[Solved] BIOS Int 13/02h hangs the bootloader

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.
PaulAche
Posts: 8
Joined: Sat Jan 27, 2018 2:02 pm

[Solved] BIOS Int 13/02h hangs the bootloader

Post by PaulAche »

I am writing a simple bootloader and currently having a problem loading the kernel into the memory from disk. When I try to read disk sectors, int13/02h never returns and hangs the execution of the program. I managed to make the bootloader print a hello-message prior to making the interrupt (int 10/Eh), so the boot signature is ok and the bootloader code is being run.

I'd like to read 1 sector, and here are my registers at the execution address of int13/02h (checked with debugging):

ax: 0x201
bx: 0x8000 (my kernel offset)
cx: 0x02
dx: 0x80
sp: 0xffff

ss: 0x9000
ds: 0x07c0 (will set to 0x0 before ljumping to kernel)
es: 0x0

It seems like I am experiencing something similar to this, except that I am setting up the es:bx buffer correctly, so the correct answer doesn't really help me.

Code: Select all

	movw  $0x0, %bx
	movw  %bx, %es
	movw  $0x8000, %bx
Needless to say, I am pretty new to this. I hope anyone can point me in the right direction, and hopefully the information I've provided is sufficient.

Edit
ss: 0x9000 (previously 0x7000)
Last edited by PaulAche on Sun Jan 28, 2018 10:34 pm, edited 3 times in total.
User avatar
TightCoderEx
Member
Member
Posts: 90
Joined: Sun Jan 13, 2013 6:24 pm
Location: Grande Prairie AB

Re: BIOS Int 13/02h hangs the bootloader

Post by TightCoderEx »

Post your entire code, that way those of us helping won't have to make so many assumptions about what it might be.
PaulAche
Posts: 8
Joined: Sat Jan 27, 2018 2:02 pm

Re: BIOS Int 13/02h hangs the bootloader

Post by PaulAche »

Edit: The code served no purpose in solving this issue. This was caused by the stack segment overriding the EBDA sector.
Last edited by PaulAche on Mon Jan 29, 2018 10:43 am, edited 2 times in total.
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: BIOS Int 13/02h hangs the bootloader

Post by iansjack »

What's the return code from the BIOS call?
PaulAche
Posts: 8
Joined: Sat Jan 27, 2018 2:02 pm

Re: BIOS Int 13/02h hangs the bootloader

Post by PaulAche »

iansjack wrote:What's the return code from the BIOS call?
That is what I am getting at. There is no return, the bootloader just hangs when it tries to execute the int13/02h line.
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: BIOS Int 13/02h hangs the bootloader

Post by iansjack »

How do you know it is "hanging"?
PaulAche
Posts: 8
Joined: Sat Jan 27, 2018 2:02 pm

Re: BIOS Int 13/02h hangs the bootloader

Post by PaulAche »

iansjack wrote:How do you know it is "hanging"?
I've run bochs with gdb and set 2 breakpoints, one at

Code: Select all

 int $0x13 
and another at

Code: Select all

cmpb $0x0, %ah
(the instruction right after int13/2h).

It hits the first breakpoint at

Code: Select all

 int $0x13 
I am able to interact with the debugger, e.g. "info registers", "continue". However, when I type "continue" to resume the execution, bochs hangs and the gdb becomes irresponsive. It never reaches the 2nd breakpoint:

Code: Select all

cmpb $0x0, %ah
Bochs hangs without the gdb as well.
PaulAche
Posts: 8
Joined: Sat Jan 27, 2018 2:02 pm

Re: BIOS Int 13/02h hangs the bootloader

Post by PaulAche »

PaulAche wrote: Edit
ss: 0x9000 (previously 0x7000)
I am very sorry for confusing everyone. I had my %ss register set to 0x9000, not 0x7000 as stated previously. After actually changing it to 0x7000 the bootloader no longer hanged and I was able to read the sector (returned ah=0). My initial thought was that my read was somehow overwriting the stack. However, I was only reading 1 sector (512 bytes) at the address 0x8000, so that can't be the case. Could anyone explain?
davidv1992
Member
Member
Posts: 223
Joined: Thu Jul 05, 2007 8:58 am

Re: BIOS Int 13/02h hangs the bootloader

Post by davidv1992 »

After the complete read, you have only 512 bytes of stack space left. It is very well possible that your bios uses more than that internally.
User avatar
TightCoderEx
Member
Member
Posts: 90
Joined: Sun Jan 13, 2013 6:24 pm
Location: Grande Prairie AB

Re: BIOS Int 13/02h hangs the bootloader

Post by TightCoderEx »

#1: Your string is not NULL terminated
#2: Don't hardcode DL, what it needs to be has already been passed by BIOS
#3: Trace into the code @ 8000H, cause that's probably where the problem is.

In Boch's, just single step to next instruction after BIOS function and see what's returned in AH or set your breakpoint @ cmp $0x0, %ah
Octocontrabass
Member
Member
Posts: 5586
Joined: Mon Mar 25, 2013 7:01 pm

Re: BIOS Int 13/02h hangs the bootloader

Post by Octocontrabass »

PaulAche wrote:Could anyone explain?
Your stack was colliding with the EBDA. Take a look at this memory map for example.

(You should also be setting SP to 0, not 0xFFFF.)
PaulAche
Posts: 8
Joined: Sat Jan 27, 2018 2:02 pm

Re: BIOS Int 13/02h hangs the bootloader

Post by PaulAche »

Octocontrabass wrote:
PaulAche wrote:Could anyone explain?
Your stack was colliding with the EBDA. Take a look at this memory map for example.

(You should also be setting SP to 0, not 0xFFFF.)
Could you please elaborate a bit more? I fail to grasp how changing my stack segment to 0x7000 will prevent EBDA collision. Also, why should the sp be set to 0?
PaulAche
Posts: 8
Joined: Sat Jan 27, 2018 2:02 pm

Re: BIOS Int 13/02h hangs the bootloader

Post by PaulAche »

TightCoderEx wrote:#1: Your string is not NULL terminated
#2: Don't hardcode DL, what it needs to be has already been passed by BIOS
#3: Trace into the code @ 8000H, cause that's probably where the problem is.
#1. asciz, z stands for zero. They are null terminated.
#2. I was taught never to assume any register values in bootblock, DL included. Hardcoding 80h shouldn't be a problem, I am not trying to boot from a CD-ROM.
#3. It would be nice if I could, but the gdb hangs during the execution.
TightCoderEx wrote: In Boch's, just single step to next instruction after BIOS function and see what's returned in AH or set your breakpoint @ cmp $0x0, %ah
I couldn't single step/trace/info registers because both Bochs and the GDB hung during (not after) the execution of 0x13.
Octocontrabass
Member
Member
Posts: 5586
Joined: Mon Mar 25, 2013 7:01 pm

Re: BIOS Int 13/02h hangs the bootloader

Post by Octocontrabass »

PaulAche wrote:Could you please elaborate a bit more? I fail to grasp how changing my stack segment to 0x7000 will prevent EBDA collision.
With SS set to 0x9000, your stack segment covers the entire (linear) address range from 0x90000 to 0x9FFFF, which includes the small section reserved for use by the EBDA. You put your stack right at the top, where the EBDA goes.
PaulAche wrote:Also, why should the sp be set to 0?
In the x86 architecture, SP always points to the item at the top of the stack. When the stack is completely empty, SP should point just past the topmost space in the stack. If the first byte to be filled by a push is at 0xFFFF, then SP should point to one byte higher: 0.

Wasting one byte of stack space is no big deal, but having the stack misaligned can be a big performance hit, and compiled code requires the stack to be aligned.

(For contrast, some non-x86 CPU architectures have their equivalent of SP pointing to the empty space at the top of the stack. In these architectures, setting the stack pointer to 0xFFFF would be correct.)
PaulAche wrote:#2. I was taught never to assume any register values in bootblock, DL included. Hardcoding 80h shouldn't be a problem, I am not trying to boot from a CD-ROM.
Almost all BIOSes will set DL for you, including every PnP BIOS (which is everything from the mid-90s onward). Hardcoding it means you'll have problems the first time you encounter a BIOS that doesn't assign 0x80 to your boot disk.
PaulAche
Posts: 8
Joined: Sat Jan 27, 2018 2:02 pm

Re: BIOS Int 13/02h hangs the bootloader

Post by PaulAche »

Octocontrabass wrote:
PaulAche wrote:Could you please elaborate a bit more? I fail to grasp how changing my stack segment to 0x7000 will prevent EBDA collision.
With SS set to 0x9000, your stack segment covers the entire (linear) address range from 0x90000 to 0x9FFFF, which includes the small section reserved for use by the EBDA. You put your stack right at the top, where the EBDA goes.
PaulAche wrote:Also, why should the sp be set to 0?
In the x86 architecture, SP always points to the item at the top of the stack. When the stack is completely empty, SP should point just past the topmost space in the stack. If the first byte to be filled by a push is at 0xFFFF, then SP should point to one byte higher: 0.

Wasting one byte of stack space is no big deal, but having the stack misaligned can be a big performance hit, and compiled code requires the stack to be aligned.

(For contrast, some non-x86 CPU architectures have their equivalent of SP pointing to the empty space at the top of the stack. In these architectures, setting the stack pointer to 0xFFFF would be correct.)
PaulAche wrote:#2. I was taught never to assume any register values in bootblock, DL included. Hardcoding 80h shouldn't be a problem, I am not trying to boot from a CD-ROM.
Almost all BIOSes will set DL for you, including every PnP BIOS (which is everything from the mid-90s onward). Hardcoding it means you'll have problems the first time you encounter a BIOS that doesn't assign 0x80 to your boot disk.
Your explanation makes perfect sense! The only thing I'm struggling with is understanding how you got the linear address range from 0x9000. If I remember correctly, I can get the linear address by SS * 16 + SP. That would make the address range start at (0h * 16h) + 9000h = 0x90000 (20-bit value). How did you get the upper range value 0x9FFFF?
Post Reply