Page 1 of 2

A problem in my self-made boot loader

Posted: Wed Jun 04, 2014 8:18 am
by Ranger
I wrote a small piece of code to fill the MBR in order to boot different OS, but sadly my code just don't work.
The code I wrote is listed below, and I made some comment on my code to make it clarified.

Code: Select all

 .386
.model tiny
code segment byte public 'CODE' use16
  assume cs:code
  assume ds:code,es:code
start:
	xor ax,ax
	mov ss,ax
	mov sp,7c00h
	mov ds,ax
	mov es,ax
	mov si,7c00h
	mov di,0600h

	mov cx,200h

	cld
	rep movsb											;Copy itself to 0000:0600.

	push ax
	push 061ch
	retf												;Return to 0000:061c where the next insturction starts.
;--------------------------------------------------------------------------------------------
	sti
	push dx												;Save dx.
	mov cx,04h
	mov bp,07beh
CHECKPARTITIONTABLE:
	cmp byte ptr [bp+00h],00h

	jns NEXTPARTITION

	inc [BOOTABLEPARTITIONCOUNT+600h]
NEXTPARTITION:
	add bp,10h

	loop CHECKPARTITIONTABLE							;Loop 4 times to find possible bootable partition.
;--------------------------------------------------------------------------------------------
	cmp [BOOTABLEPARTITIONCOUNT+600h],'0'
	jz NOBOOTABLEPARTITIONFOUND							;If ZF=1, no bootable partition found.
	jmp BOOTABLEPARTITIONFOUND
;--------------------------------------------------------------------------------------------
GETINPUT:
	xor ah,ah
	int 16h
	cmp al,[BOOTABLEPARTITIONCOUNT+600h]
	ja ERRORLOADING
	cmp al,'1'
	jb ERRORLOADING										;Check user's input.
;--------------------------------------------------------------------------------------------
	sub al,30h
	mov cl,al
	xor ch,ch
	mov bp,07aeh 										;For later addition.
ADDBPFORNEXTENTRY:
	add bp,10h
	loop ADDBPFORNEXTENTRY								;Points to the partition table user chose.
	pop dx
LOADVBR:
	mov [bp+00],dl

	mov byte ptr [bp+11],05h 							;5 times to try to load VBR sector.
	mov ah,41h
	mov bx,55aah
	int 13h												;Check for int 13h extensions in BIOS.

	jb ERRORLOADING										;Jump if CF=1, there is no int 13h extensions.
	cmp bx,0aa55h
	jnz ERRORLOADING
	test cx,0001h
	jz ERRORLOADING										;If no int 13h extensions, fail.
EXTENDEDREAD:
;--------------------------------------------------------------------------------------------
	push dword ptr 00000000h
	push dword ptr [bp+8]
	push word ptr 0000h
	push word ptr 7c00h 
	push word ptr 0001h
	push word ptr 0010h
								; Offset Size	       Description of DISK ADDRESS PACKET's Contents
								; ------ -----  ------------------------------------------------------------
								;   00h	 BYTE	Size of packet (10h or 18h; 16 or 24 bytes).
								;   01h	 BYTE	Reserved (00).
								;   02h	 WORD	Number of blocks to transfer (Only 1 sector for this code).
								;   04h	 DWORD	Points to -> Transfer Buffer (0000 7C00 for this code).
								;   08h	 QWORD	Starting Absolute Sector (get from Partition Table entry:
								;               (00000000 + DWORD PTR [BP+08]). Remember, the Partition
								;               Table Preceding Sectors entry can only be a max. of 32 bits!
								;   10h	 QWORD  NOT USED HERE. (EDD-3.0; optional) 64-bit flat address
								;               of transfer buffer; only used if DWORD at 04h is FFFF:FFFF.
	mov ah,42h
	mov dl,[bp+00h]
	mov si,sp

	int 13h												;Try int 13h extended read.

	jc ERRORLOADING
;--------------------------------------------------------------------------------------------
	lahf
	add sp,10h 											;Remove DAP bytes from stack.
	sahf												;Discard any possible change to PSW.

	jnb CHECKMAGICNUMBER								;Jump when CF=0, indicating that extended read succeeded.
	dec byte ptr [bp+11h]
	jnz RESETDISK

	cmp byte ptr [bp+00h],80h
	jz ERRORLOADING

	mov dl,80h
	jmp LOADVBR

RESETDISK:
	xor ah,ah
	mov dl,[bp+00h]
	int 13h												;Reset disk system.

	jmp EXTENDEDREAD

CHECKMAGICNUMBER:
	mov si,7dfeh
	cmp word ptr [si],0aa55h	 						;Check the magic number where the VBR resides.
	jnz ERRORLOADING									;If we do not see it, fail.

	mov dl,[bp+00h]
	xor dh,dh

	jmp word ptr ds:[7c00h]					;Jump to Volume Boot Record(VBR) code loaded into Memory by this MBR.
;--------------------------------------------------------------------------------------------
NOBOOTABLEPARTITIONFOUND:
	mov ax,offset NOBOOTABLEPARTITIONMSG
	jmp DISPLAYMESSAGE
BOOTABLEPARTITIONFOUND:
	mov ax,offset PROMPTMSG
	jmp DISPLAYMESSAGE
SHOWBOOTABLEPARTITION:
	mov ax,offset BOOTABLEPARTITION
	inc [BOOTABLEPARTITION+601h]
	mov bl,[BOOTABLEPARTITIONCOUNT+600h]
	cmp [BOOTABLEPARTITION+601h],bl
	jbe DISPLAYMESSAGE
	jmp GETINPUT	
ERRORLOADING:
	mov ax,offset ERRORLOADINGMSG
	mov [BOOTABLEPARTITIONCOUNT+600h],'0'
DISPLAYMESSAGE:
	add ax,0600h										;Add base address to ax.
	mov si,ax
LOADNEXTBYTE:
	lodsb

	cmp al,00h
	jz THENEXTTODO

	mov bx,0007h
	mov ah,0eh
	int 10h
	jmp LOADNEXTBYTE

THENEXTTODO:
	cmp [BOOTABLEPARTITIONCOUNT+600h],'0'
	jnz SHOWBOOTABLEPARTITION
HALTCOMPUTER:
	hlt
	jmp HALTCOMPUTER

NOBOOTABLEPARTITIONMSG 	db 'No bootable partition found.',00								;No bootable partition.
ERRORLOADINGMSG 		db 0ah,0dh,'Error loading operating system.',00						;Error message.
PROMPTMSG 				db 'Input corresponding number to load OS boot record',0ah,0dh,00	;Prompt the user.
BOOTABLEPARTITION		db '(0)partition   ',00
BOOTABLEPARTITIONCOUNT  db '0'
code ends
     end start
Fortunately, I minimize my problem to a small scale. The error occurs seemingly every time while checking the magic number in
0000:7dbeh, but I just can not figure out why. The problem haunted me for a long time, any help will be appreciated.

Hum, by the way, English is not my mother tongue, so I may made some mistake in my sentences. If I did, I am sorry for it.

Re: A problem in my self-made boot loader

Posted: Wed Jun 04, 2014 9:08 am
by iansjack
What have you done in the way of debugging? Single-stepping through the code in an emulator (such as SimNow) should pinpoint the error.

Re: A problem in my self-made boot loader

Posted: Wed Jun 04, 2014 12:04 pm
by DavidCooper
Ranger wrote:I wrote a small piece of code to fill the MBR in order to boot different OS, but sadly my code just don't work.
In what way does it just don't work? Does it display any message? How many bootable partitions does it find?
inc [BOOTABLEPARTITIONCOUNT+600h]
I can't work out which byte in memory that's incrementing. Why not just increment a variable directly?
cmp [BOOTABLEPARTITIONCOUNT+600h],'0'
What is this '0' that you're then comparing it with? (ASCII '0' = 30h.)

Re: A problem in my self-made boot loader

Posted: Wed Jun 04, 2014 11:18 pm
by Ranger
iansjack wrote:What have you done in the way of debugging? Single-stepping through the code in an emulator (such as SimNow) should pinpoint the error.
I am a starter, so my way of debugging may seem rather stupid. I reboot every time to see if there is an error message.
I altered the code when debugging, made it to show different message so that I can locate where the error occurs.
My computer installed Win7 32bit, I can not use SimNow to debug, because it is 64bit.

Re: A problem in my self-made boot loader

Posted: Wed Jun 04, 2014 11:49 pm
by Ranger
Ranger wrote:I wrote a small piece of code to fill the MBR in order to boot different OS, but sadly my code just don't work.
In what way does it just don't work? Does it display any message? How many bootable partitions does it find?
1.When done int 13h extended read, it can not see the AA55 in 0000:7DFE. I am sure that int 13h extended read is successful, because I tested that CF is clear after the procedure. I do not know what is wrong.
I installed Win 7 32-bit on my laptop. I have only one OS, and the code finds one OS as I excepted.
inc [BOOTABLEPARTITIONCOUNT+600h]
I can't work out which byte in memory that's incrementing. Why not just increment a variable directly?
2.That is my fault, I do not mean confusing. The code copies itself to 0000:0600, so I have to add 600h to make it points to a correct location.
cmp [BOOTABLEPARTITIONCOUNT+600h],'0'
What is this '0' that you're then comparing it with? (ASCII '0' = 30h.)
3.I test if there are available OS to boot, if the [BOOTABLEPARTITIONCOUNT+600h] is '0', which means there is not OS or other error occurred. In such case, the code will display a message and then halt the computer.

Re: A problem in my self-made boot loader

Posted: Thu Jun 05, 2014 12:07 am
by iansjack
Ranger wrote:
iansjack wrote:What have you done in the way of debugging? Single-stepping through the code in an emulator (such as SimNow) should pinpoint the error.
I am a starter, so my way of debugging may seem rather stupid. I reboot every time to see if there is an error message.
I altered the code when debugging, made it to show different message so that I can locate where the error occurs.
My computer installed Win7 32bit, I can not use SimNow to debug, because it is 64bit.
Other emulator/debugger combinations are available (e.g. Bochs or qemu + gdb). It is well worth learning how to use one. Nothing beats actually inspecting the code, memory, and registers as the program runs. Once you can do that it becomes trivial to track this sort of problem. Clearly your code is not doing what you think it is; your problem is that you can't see what it is doing.

Re: A problem in my self-made boot loader

Posted: Thu Jun 05, 2014 12:13 am
by Ranger
I do not if there are some protection mechanism in Win 7 32-bit prohibiting me from loading the VBR(Volume Boot Record). I tried to replace my MBR's first 446 bytes with a standard MBR, it prompts me that the software(or hardware, I do not remember) configuration has changed and failed to load Win 7. I then filled the MBR code area with 90h to each byte(90h means NOP in machine code), and booted my computer from another boot program that is installed in my USB drive, it prompts the same message again.

I do not have TPM in my computer, I am sure that won't be the reason why I can not boot my computer.

Re: A problem in my self-made boot loader

Posted: Thu Jun 05, 2014 12:15 am
by Ranger
iansjack wrote:
Ranger wrote:
iansjack wrote:What have you done in the way of debugging? Single-stepping through the code in an emulator (such as SimNow) should pinpoint the error.
I am a starter, so my way of debugging may seem rather stupid. I reboot every time to see if there is an error message.
I altered the code when debugging, made it to show different message so that I can locate where the error occurs.
My computer installed Win7 32bit, I can not use SimNow to debug, because it is 64bit.
Other emulator/debugger combinations are available (e.g. Bochs or qemu + gdb). It is well worth learning how to use one. Nothing beats actually inspecting the code, memory, and registers as the program runs. Once you can do that it becomes trivial to track this sort of problem. Clearly your code is not doing what you think it is; your problem is that you can't see what it is doing.
Thank you for your help, I will try to learn more.

Re: A problem in my self-made boot loader

Posted: Thu Jun 05, 2014 9:12 am
by Candy
Ranger wrote:I do not if there are some protection mechanism in Win 7 32-bit prohibiting me from loading the VBR(Volume Boot Record). I tried to replace my MBR's first 446 bytes with a standard MBR, it prompts me that the software(or hardware, I do not remember) configuration has changed and failed to load Win 7. I then filled the MBR code area with 90h to each byte(90h means NOP in machine code), and booted my computer from another boot program that is installed in my USB drive, it prompts the same message again.
Are you sure that it's starting that code? Doesn't make sense to get that error then, unless you do have some form of "secure boot" enabled.

Re: A problem in my self-made boot loader

Posted: Thu Jun 05, 2014 9:39 am
by Ranger
Candy wrote:
Ranger wrote:I do not if there are some protection mechanism in Win 7 32-bit prohibiting me from loading the VBR(Volume Boot Record). I tried to replace my MBR's first 446 bytes with a standard MBR, it prompts me that the software(or hardware, I do not remember) configuration has changed and failed to load Win 7. I then filled the MBR code area with 90h to each byte(90h means NOP in machine code), and booted my computer from another boot program that is installed in my USB drive, it prompts the same message again.
Are you sure that it's starting that code? Doesn't make sense to get that error then, unless you do have some form of "secure boot" enabled.
I don't know, may be I should learn more about booting stuff. It is more complicated than I thought, and I found myself know little about it.

Re: A problem in my self-made boot loader

Posted: Thu Jun 05, 2014 12:14 pm
by DavidCooper
Ranger wrote:1.When done int 13h extended read, it can not see the AA55 in 0000:7DFE. I am sure that int 13h extended read is successful, because I tested that CF is clear after the procedure. I do not know what is wrong.
So when you said in your original post "The error occurs seemingly every time while checking the magic number in 0000:7dbeh, but I just can not figure out why", it now appears that you meant 7dfeh.
3.I test if there are available OS to boot, if the [BOOTABLEPARTITIONCOUNT+600h] is '0', which means there is not OS or other error occurred. In such case, the code will display a message and then halt the computer.
I don't use assembler, so I may be wrong, but I'd have thought you'd want to compare the variable with 0 rather than '0'. I see you doing the same thing with

Code: Select all

cmp al,'1'
so I just want to check whether that's correct coding or if it will compare al with 31h.

I'm going to give up on trying to follow your code though as it's too much effort for me to try to work out if it's coded correctly, but if your problem persists and you can't work out how to debug it, just paste the hex of your MBR here and I'll then be able to see the faults in it. (Though that obviously isn't relevant if your machine can't be booted by any MBR.)

Re: A problem in my self-made boot loader

Posted: Fri Jun 06, 2014 5:44 am
by Ranger
The hex of my self-made MBR is given by the attachment. I can not paste the hex here because it is too long.

Thank you for your help, I don't have time to debug recently, because I am busy preparing the coming examinations. I will return back on this code when I have time.

Re: A problem in my self-made boot loader

Posted: Fri Jun 06, 2014 5:10 pm
by DavidCooper
If you'd commented your code in detail it would have been a lot easier to follow, but the mystery tour has been fun, and the quality of the code isn't bad either. Not what I was expecting.

Code: Select all

mov byte ptr [bp+11],05h                      ;5 times to try to load VBR sector.
Should be [bp+11h]. You've messed up the LBA address in the partition table, so the wrong sector's being loaded in. (You later read the retry count correctly from [bp+11h].)

Re: A problem in my self-made boot loader

Posted: Tue Jun 10, 2014 8:20 am
by Ranger
Thank you for your patience. After reading your post, I am aware of my problem now. I fixed the bug and my code can load the right sector into memory now.
But windows boot manager prompts me an error message. It says that the hardware or software configuration has been changed; device is inaccessible. Hum, this may be the protection mechanism of Win 7.
I know I have to figure out how Win 7 boot manager works, or otherwise I can not get my code work with Win 7. #-o
Thank you for your help! :D I will continue my work.

Re: A problem in my self-made boot loader

Posted: Tue Jun 10, 2014 2:23 pm
by DavidCooper
Judging by http://www.techrepublic.com/article/get ... hitecture/, it looks as if writing your own MBR won't work if Windows Vista/7/8 is on that drive. I assume that the BIOS is be programmed to look for a file called Bootmgr.exe and to run that instead of the MBR. You'd have to put details of the other OS you want to run in the Boot Configuration Data database so that the Windows Bootmanager can work out how to boot it, and it's the Windows Bootmanager that will offer the choice of OSes rather than allowing your MBR to do so.

Please correct me if I've got that wrong (anyone reading this who knows how it should be done)