Bootloader / int 13h and USB problem

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Richy
Member
Member
Posts: 41
Joined: Wed Nov 19, 2008 10:03 am

Bootloader / int 13h and USB problem

Post by Richy »

So I have a working (if very basic) OS. I developed it a few years ago to run from a floppy disk. Today I decided the time had come to migrate it to a USB stick. I decided to take it step by step, getting small pieces working one by one. Hopefully the first pieces will be the hardest and the rest will fall into place nicely.

So anyway, the first piece is obviously the bootloader, and getting the PC to boot from USB using my code. Stage 1 bootloader works, it displays a nice welcome message. Problems arise when I try to load the stage 2 bootloader. It doesn't display the stage-2 message, only a character of garbage.

This is the stage 1:

Code: Select all

[BITS 16]	;16-bits real mode
[ORG 0x7C00]	;Origin, tell the assembler that where the code will be in memory after it is been loaded

jmp main

;Included functions
%include "PrintScreen.inc"

;Data
LoadString db 'Stage 1 Bootloader Starting...', 10, 13, 0	;HelloWorld string ending with 0


main:
MOV AX, CS
MOV DS, AX
MOV ES, AX

MOV SI, LoadString 	;Store string pointer to SI
CALL PrintString	;Call print string procedure


    reset:                      ; Reset the floppy drive
            mov ax, 0           ;
            mov dl, 81h           ; Drive: 0=first floppy, 80h = first HDD
            int 13h             ;
            jc reset            ; ERROR => reset again


    read:
            mov ax, 1000h       ; ES:BX = 1000:0000
            mov es, ax          ;
            mov bx, 0           ;

            mov ah, 2           ; Load disk data to ES:BX
            mov al, 1           ; Load 1 sectors
            mov ch, 0           ; Cylinder=0
            mov cl, 2           ; Sector=2
            mov dh, 0           ; Head=0
            mov dl, 81h         ; Drive
            int 13h             ; Read!

            jc read             ; ERROR => Try again


            jmp 1000h:0000      ; Jump to the program



TIMES 510 - ($ - $$) db 0	;Fill the rest of sector with 0
DW 0xAA55			;Add boot signature at the end of bootloader
And this is the stage 2:

Code: Select all

[BITS 16]	;16-bits real mode
[ORG 0x0000]	;Origin, tell the assembler that where the code will be in memory after it is been loaded

jmp main

;Included functions
%include "PrintScreen.inc"

;Data
HelloString db "Hello World",10,13,0


main:
MOV AX, CS
MOV DS, AX
MOV ES, AX
MOV BX, 0

MOV SI, HelloString 	;Store string pointer to SI
CALL PrintString	;Call print string procedure
JMP $       		;Infinite loop
The code for PrintScreen.inc works, so I won't bother putting it up here unless someone asks for it.

I've copied both files on with DD:

Code: Select all

dd if=part1.bin of=\\.\d: bs=512 count=1
dd if=part2.bin of=\\.\d: seek=1 bs=512 count=1
Where part1 and part2 refer to stage 1 and stage 2 respectively.

Like I said, all the code worked on the floppy, and here I just changed the drive number in Stage 1 from 0 to 81h.

My best guesses for the problems are something wrong in my using int 13h or not copying correctly with DD. But I've read over all the documentation I could find for each of these and find nothing wrong. It could be a third problem I do not suspect, but then how would I find it.

Can anyone help? See something wrong somewhere that I'm missing?
Nable
Member
Member
Posts: 453
Joined: Tue Nov 08, 2011 11:35 am

Re: Bootloader / int 13h and USB problem

Post by Nable »

Richy wrote:Like I said, all the code worked on the floppy, and here I just changed the drive number in Stage 1 from 0 to 81h.
AFAIR, you should never hardcode this number - BIOS passes the right value to your first-stage bootloader (in DL register).
One more thing: if your BIOS decides to emulate USB stick as USB-HDD (instead of USB-FDD), it can check whether you have correct partition table in MBR and refuse to boot if you don't have one.
Octocontrabass
Member
Member
Posts: 5590
Joined: Mon Mar 25, 2013 7:01 pm

Re: Bootloader / int 13h and USB problem

Post by Octocontrabass »

Richy wrote:

Code: Select all

MOV AX, CS
MOV DS, AX
MOV ES, AX
Careful. Your code currently assumes CS will always be 0 at this point, but the BIOS may load your code at 0x07C0:0000 instead of 0x0000:7C00.
Richy wrote:

Code: Select all

            mov dl, 81h           ; Drive: 0=first floppy, 80h = first HDD
This is wrong for a few reasons.

First, the correct value will be in DL when your code begins executing. You should always use it, especially since your code may be chain loaded from another bootloader.

Second, the BIOS will almost always assign 0x80 to the boot hard disk, whether it is "first" or not.

Finally, you probably aren't even using USB-HDD emulation. Most BIOSes will check your disk for a "valid" partition table and use USB-FDD emulation if you don't have one. What counts as "valid" is different between BIOSes, but having a single bootable partition is most likely to work. Unfortunately, if you mark a partition as bootable, some BIOSes will skip your first stage and attempt to boot that partition instead.
Richy
Member
Member
Posts: 41
Joined: Wed Nov 19, 2008 10:03 am

Re: Bootloader / int 13h and USB problem

Post by Richy »

Well I've tried saving the drive number at the beginning of the code:

Code: Select all

DriveNumber db 0x00
mov [DriveNumber], dl
Then replacing the two lines where I set dl with that value:

Code: Select all

mov dl, [DriveNumber]
I'm sorry to report no improvement on fetching my stage-2 bootloader.
M2004
Member
Member
Posts: 65
Joined: Sun Mar 07, 2010 2:12 am

Re: Bootloader / int 13h and USB problem

Post by M2004 »

Richy: You fail to setup stack properly before using it.


regards
M2004
Richy
Member
Member
Posts: 41
Joined: Wed Nov 19, 2008 10:03 am

Re: Bootloader / int 13h and USB problem

Post by Richy »

Alright, I added the lines to setup the stack. The stage 1 code now looks like this:

Code: Select all

[BITS 16]	;16-bits real mode
[ORG 0x7C00]	;Origin, tell the assembler that where the code will be in memory after it is been loaded

jmp main

;Included functions
%include "PrintScreen.inc"

;Data
LoadString db 'Stage 1 Bootloader Starting...', 10, 13, 0	;HelloWorld string ending with 0
DriveNumber db 0x00


main:
xor AX, AX
MOV DS, AX
MOV ES, AX
mov ss, ax
mov sp, 7C00h

mov [DriveNumber], dl

MOV SI, LoadString 	;Store string pointer to SI
CALL PrintString	;Call print string procedure


    reset:                      ; Reset the floppy drive
            mov ax, 0           ;
            mov dl, 81h           ; Drive: 0=first floppy, 80h = first HDD
	    ;mov dl, [DriveNumber] ; drive
            int 13h             ;
            jc reset            ; ERROR => reset again


    read:
            mov ax, 1000h       ; ES:BX = 1000:0000
            mov es, ax          ;
            mov bx, 0           ;

            mov ah, 2           ; Load disk data to ES:BX
            mov al, 1           ; Load 1 sectors
            mov ch, 0           ; Cylinder=0
            mov cl, 2           ; Sector=2
            mov dh, 0           ; Head=0
            mov dl, 81h         ; Drive
	    ;mov dl, [DriveNumber] ; drive
            int 13h             ; Read!

            jc read             ; ERROR => Try again


            jmp 1000h:0000      ; Jump to the program



TIMES 510 - ($ - $$) db 0	;Fill the rest of sector with 0
DW 0xAA55			;Add boot signature at the end of bootloader
Still doesn't work. But it gets weirder... if I use the two lines "mov dl, [DriveNumber]" the message from the first-stage bootloader doesn't display at all. If I use the lines "mov dl, 81h" the stage-1 message displays along with a character of garbage like before. Now that's weird because the LoadString message is displayed in the code before the drive reset and read, so it should be displayed either way!
Richy
Member
Member
Posts: 41
Joined: Wed Nov 19, 2008 10:03 am

Re: Bootloader / int 13h and USB problem

Post by Richy »

For reference I've tried using different values of dl as well. dl = 0 causes my floppy drive to go crazy, so we know what that one is. dl = 1, dl = 80h, dl = 82h, or removing the line assigning a value to dl altogether causes the line of the stage-1 to display and nothing else. dl = 81h, as I said, gives a character of garbage, but at least that means it's loading and running something in memory, so it is getting to the jump...

FYI, the computer I'm running this on has a floppy drive and a hard drive, in addition to the USB.
Richy
Member
Member
Posts: 41
Joined: Wed Nov 19, 2008 10:03 am

Re: Bootloader / int 13h and USB problem

Post by Richy »

grrr... whatever I do, now I can see the bootloader get as far as the jmp 1000h:0000 line, but after that nothing. Either it did not load the stage-2 in memory for some reason, or there's something wrong with the stage 2.
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: Bootloader / int 13h and USB problem

Post by SpyderTL »

Some suggestions:

Try printing the value passed to you in DL to the screen so that you will know for sure which drive to use, and whether it is a floppy drive (0x00) or a hard drive (0x80).

If it is a hard drive, you will probably need to rewrite your code to use int 13h AH = 42h instead of 02h.

Let us know what you find.

- Joshua
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
Richy
Member
Member
Posts: 41
Joined: Wed Nov 19, 2008 10:03 am

Re: Bootloader / int 13h and USB problem

Post by Richy »

SpyderTL wrote:Some suggestions:

Try printing the value passed to you in DL to the screen so that you will know for sure which drive to use, and whether it is a floppy drive (0x00) or a hard drive (0x80).

If it is a hard drive, you will probably need to rewrite your code to use int 13h AH = 42h instead of 02h.

Let us know what you find.

- Joshua
It's 0x80, the first hard drive.
Richy
Member
Member
Posts: 41
Joined: Wed Nov 19, 2008 10:03 am

Re: Bootloader / int 13h and USB problem

Post by Richy »

But I'm still having the same problem with int 13h ah=42h. I've tried multiple variations of calling the command, but they boil down to having this in my data section:

Code: Select all

DiskAddressPacket:        
   .Size      DB 0x10
   .NULL      DB 0x00
   .Sectors   DW 0x01
   .Offset      DW 0x00
   .Segment   DW 0x1000
   .LBA      DQ 0x01
And this in the read section:

Code: Select all

    read:
            mov ah, 42h           ; Load disk data to ES:BX
            mov dl, byte [DriveNumber] ; drive
            MOV SI,DiskAddressPacket
            int 13h             ; Read!
            jc read             ; ERROR => Try again

            jmp 1000h:0000      ; Jump to the program
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Bootloader / int 13h and USB problem

Post by Brendan »

Hi,

The bug is here:

Code: Select all

            int 13h             ; Read!
            jc read             ; ERROR => Try again
It needs to be:

Code: Select all

            int 13h             ; Read!
            jc error_hander     ; ERROR => Display the error so you know what went wrong
Note: You can find a list of error codes that the BIOS may be returning here. Sadly, they aren't sequential, so you'd need something slightly more complicated than a lookup table to display the right string (e.g. maybe a list of "value + string" pairs and a linear search for the entry with the right value).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Richy
Member
Member
Posts: 41
Joined: Wed Nov 19, 2008 10:03 am

Re: Bootloader / int 13h and USB problem

Post by Richy »

Brendan wrote:Hi,

The bug is here:
Actually, no. It's getting through the read function correctly, and never does the JC.

The problem seems to be that it's reading all zeros... the stage-2 was never copied I think. Everything worked fine when I used the HxD tool and manually copy-pasted the binary in. But that's still weird... wasn't DD copying the file? It was telling me it was. Can anyone check my DD commands in the OP?
User avatar
Minoto
Member
Member
Posts: 89
Joined: Thu May 12, 2011 7:24 pm

Re: Bootloader / int 13h and USB problem

Post by Minoto »

Richy wrote:The problem seems to be that it's reading all zeros... the stage-2 was never copied I think. Everything worked fine when I used the HxD tool and manually copy-pasted the binary in. But that's still weird... wasn't DD copying the file? It was telling me it was. Can anyone check my DD commands in the OP?
Were you using HxD to copy the files to your floppy disk, or to your USB drive? It sounds like your USB drive is partitioned like a hard drive, and your dd commands may have copied your stage 1 and stage 2 to the first two sectors of the partition, rather than the first two sectors of the actual device. In that case, the MBR should be loaded first, then it would load and execute your stage 1 from the first sector of the partition, then your stage 1 would read sector 2 of the device, which very well could be all zeroes.
Those who understand Unix are doomed to copy it, poorly.
Richy
Member
Member
Posts: 41
Joined: Wed Nov 19, 2008 10:03 am

Re: Bootloader / int 13h and USB problem

Post by Richy »

Minoto wrote:
Richy wrote:The problem seems to be that it's reading all zeros... the stage-2 was never copied I think. Everything worked fine when I used the HxD tool and manually copy-pasted the binary in. But that's still weird... wasn't DD copying the file? It was telling me it was. Can anyone check my DD commands in the OP?
Were you using HxD to copy the files to your floppy disk, or to your USB drive? It sounds like your USB drive is partitioned like a hard drive, and your dd commands may have copied your stage 1 and stage 2 to the first two sectors of the partition, rather than the first two sectors of the actual device. In that case, the MBR should be loaded first, then it would load and execute your stage 1 from the first sector of the partition, then your stage 1 would read sector 2 of the device, which very well could be all zeroes.

Back when I was using a floppy, I used partcopy.

For my USB drive, I was using DD to copy the two bootloaders. Stage-1 was working but couldn't load Stage-2. HxD showed me that neither bootloaders were on the first two sectors where I had told DD to put them. When I copy-pasted the two bootloaders onto the right sectors using HxD, they both worked. So your partition idea might be correct...
Post Reply