OSDev.org

The Place to Start for Operating System Developers
It is currently Fri May 07, 2021 5:37 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: FAT16 bootloader
PostPosted: Thu Apr 15, 2021 11:43 am 
Offline
User avatar

Joined: Thu Jun 16, 2016 9:35 am
Posts: 24
Hello!
I'm trying to figure out a problem I'm having with a two-stage bootloader designated to be used on a FAT16 disk.
Bochs throws this error constantly: int13_harddisk: function 42. LBA out of range
So my initial guess is that something is going up either with the DAP setup or with the way I'm setting up the stack (I've read somewhere it needs to be aligned for this to work) or if segments are going crazy (I really hate Real Mode, but everyday I try doing my best to embrace it hahah) or if my BPB is wrong so I'll try to give as much info as I can.

I'm using i386-elf-as for compiling (AT%T Syntax)

For the initial code setup (Including the BPB) I do it this way:

Code:
.code16
.global boot0
.global init0_fat16
.section .text
init0_fat16:   
# TODO/HACK: Do we really need: .intel_syntax noprefix and .att_syntax prefix in jmp short boot0 ? (EDIT for osdev forum, I've inspected both outcomes jmp short & normal jmp on a dissasembler and they both seem to produce 0xEB instead of 0xEE; so I'm debating on what to leave this like)
.intel_syntax noprefix
   jmp short boot0
.att_syntax prefix
   nop

bpb:
  oem_string:            .ascii   "INITIUM1"
  sector_size:            .word   0x200
  sectors_per_cluster:            .byte   4
  reserved_sectors:         .word   4
  number_of_fats:            .byte   2
  total_fat_directory_entries:         .word   512
  total_sectors:         .word   20160
  media_descriptor_type:         .byte   0xF8
  sectors_per_fat:               .word   20
  spt:                  .word   63
  heads_count:            .word   16
  hidden_sector_count:      .int   0
  high_sector_count:      .int   0
  bios_boot_drive:         .byte   0x80
  reserved:               .byte   0
  extended_bpb_signature:   .byte   0x29
  volumeid_name:         .int   0xd7450e5
  volume_label:            .ascii   "BOOTLOAD   "
  fs_type:               .ascii   "FAT16   "

boot0:
   xor %ax, %ax
   mov %ax, %ds
   mov %ax, %es
   mov $0x0900, %bx
   cli
   mov %bx, %ss
   mov %ax, %sp
   mov %sp, %bp
   sti
   cld

   mov %dl, bios_boot_drive

   xor %dx, %dx
   xor %ax, %ax
   
   mov bios_boot_drive, %dl
   
   mov number_of_fats, %ax
   mulw sectors_per_fat
   add reserved_sectors, %ax
   mov %ax, root_dir_offset

   xchg %bx, %ax

   mov sector_size, %ax
   mov $0x20, %cx
   div %cx

   xchg %cx, %ax
   mov total_fat_directory_entries, %ax
   div %cx
   add %bx, %ax
   mov %ax, data_cluster_offset

   xor %dx, %dx

.loop:
   xchg %bx, %bx
   mov root_dir_offset, %ax
   add %dx, %ax
   mov $0x200, %bx
   mov $0x01, %cx
   push %dx
   call read_sectors

   mov $0x200, %bx
   mov %bx, %ax
   add sector_size, %ax
.loop_dir_entries:
   mov stage2_name, %di
   mov $0x06, %cx
   mov %bx, %si
   rep cmpsb
   je .match

   add $0x20, %bx
   cmp %bx, %ax
   jne .loop_dir_entries

   pop %dx
   inc %dx
   cmp $0x80, %dx
   jne .loop
   jmp error

.match:
   movw 0x1A(%bx),%ax

   sub $0x02, %ax
   mulb sectors_per_cluster
   add data_cluster_offset, %ax

   mov $1, %cx # STAGE 2 Size, hardcoded for now
   mov $0x0400, %bx

   call read_sectors
   jmp $0x0, $0x1000


error:
   cli
   hlt

read_sectors:
   pusha
   mov %eax, dap_sector_low
   mov %es, dap_segment
   mov %bx, dap_offset
.extended_read:
   mov $0x42, %ah
   mov bios_boot_drive, %dl
   mov dap, %si
   int $0x13
   jnc .read_ok

   mov $0x0e, %ah
   mov $0x41, %al
   int $0x10

   xor %ax, %ax
   int $0x13
   jmp .extended_read

.read_ok:
   popa
   inc %eax
   add $0x200, %bx
   jnc .no_carry

   mov %es, %dx
   add $0x10, %dh
   mov %dx, %es
.no_carry:
   dec %cx
   jz read_sectors_exit
   jmp read_sectors

read_sectors_exit:
   ret


root_dir_offset: .word 0x0000
data_cluster_offset: .word 0x0000
stage2_name:    .ascii "STAGE2"
stage2_cur_offset: .word 0x0000
stage2_cur_segment: .word 0x0000

.align 4
dap:
dap_size:      .byte 0x10
dap_reserved:      .byte 0x00   
dap_block_count:   .word 0x01
dap_offset:      .word 0x1000
dap_segment:      .word 0x00
dap_sector_low:      .int 0x01
dap_sector_high:   .int 0x00

.fill 510-(.-init0_fat16), 1, 0
.word 0xAA55


My link script goes like this:
Code:
ENTRY(init0_fat16)

OUTPUT_FORMAT(elf32-i386)

OUTPUT_ARCH(i386)

SECTIONS {

    . = 0x7C00;

    .text :
    {
        *(.text)
    }

    .rodata :
    {
        *(.rodata)
    }

    .data :
    {
        *(.data)
    }

    .bss :
    {
        *(.bss)
    }
}


And I build the image like this (In case this messes up something):
bximage -mode=create -hd=10M -q hdd.img
mkfs.fat -F 16 hdd.img
mkdir disk/
dd conv=notrunc if=bootloader/boot0.bin of=hdd.img bs=512 seek=0 status=none
sudo mount -t msdos -o loop hdd.img disk/
sudo cp bootloader/boot1.bin disk/STAGE2
sudo umount disk/
rm -r disk/

I really can't figure exactly what's wrong, but I've double-checked the BPB info using Ultimate64 and a few bits more that I don't remember as of writing but still, same output.

Any directions you guys recommend?
Thanks for your time!
Hope you have a nice day!


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Thu Apr 15, 2021 1:56 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 2991
cakehonolulu wrote:
Bochs throws this error constantly: int13_harddisk: function 42. LBA out of range

Since you're using Bochs, try using its debugger. Set a breakpoint (or insert a magic breakpoint) at the "int $0x13" instruction, then dump all of the registers and the contents of your DAP. Don't forget segment registers!

If you don't see the problem in the register dump, post it here.


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Fri Apr 16, 2021 1:20 am 
Offline
User avatar

Joined: Thu Jun 16, 2016 9:35 am
Posts: 24
Octocontrabass wrote:
cakehonolulu wrote:
Bochs throws this error constantly: int13_harddisk: function 42. LBA out of range

Since you're using Bochs, try using its debugger. Set a breakpoint (or insert a magic breakpoint) at the "int $0x13" instruction, then dump all of the registers and the contents of your DAP. Don't forget segment registers!

If you don't see the problem in the register dump, post it here.


Before int13
Code:
rax: 00000000_0000422c
rbx: 00000000_00000200
rcx: 00000000_00090001
rdx: 00000000_00000080
rsp: 00000000_0000ffec
rbp: 00000000_00000000
rsi: 00000000_000e0010
rdi: 00000000_0000ffac
r8 : 00000000_00000000
r9 : 00000000_00000000
r10: 00000000_00000000
r11: 00000000_00000000
r12: 00000000_00000000
r13: 00000000_00000000
r14: 00000000_00000000
r15: 00000000_00000000
rip: 00000000_00007cf4
eflags 0x00000202: id vip vif ac vm rf nt IOPL=0 of df IF tf sf zf af pf cf


Before calling int13, I can see that ah=42 (Extended Read), dl contains the bios drive number, and i have the buffer prepared, but something looks wrong to me, the buffer, am I right?

After calling int13:
Code:
rax: 00000000_0000012c
rbx: 00000000_00000200
rcx: 00000000_00090001
rdx: 00000000_00000080
rsp: 00000000_0000ffec
rbp: 00000000_00000000
rsi: 00000000_000e0010
rdi: 00000000_0000ffac
r8 : 00000000_00000000
r9 : 00000000_00000000
r10: 00000000_00000000
r11: 00000000_00000000
r12: 00000000_00000000
r13: 00000000_00000000
r14: 00000000_00000000
r15: 00000000_00000000
rip: 00000000_00007cf8
eflags 0x00000203: id vip vif ac vm rf nt IOPL=0 of df IF tf sf zf af pf CF


ah shows the error code "01", according to ralph's interrupt list, 01 stands for "invalid function in AH or invalid parameter"; which kinda confirms that the issue is with how I setup the buffer.

But by the looks of it, I don't exactly know how to fix it, to me, it looks good; but again, I could 100% be missing something about real mode segment:offset addressing which is a pain for me.

Any inputs?

Thanks for your previous answer and for your time!


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Fri Apr 16, 2021 4:17 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 611
Seems to me:
Code:
mov dap, %si
should be
Code:
mov $dap, %si
since you want the address of DAP in SI not the word value stored at memory location DAP in SI.


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Fri Apr 16, 2021 5:23 am 
Offline
User avatar

Joined: Thu Jun 16, 2016 9:35 am
Posts: 24
MichaelPetch wrote:
Seems to me:
Code:
mov dap, %si
should be
Code:
mov $dap, %si
since you want the address of DAP in SI not the word value stored at memory location DAP in SI.


After carefully changing that line of code, bochs now complains about a different error:

int13_harddisk: function 42, error 01 !

Which suggests that I've fixed one bug that I didn't take into account at first glance but the main and bigger one remains, my guess remains the same, to me, it looks like something is wrong with the buffer.


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Fri Apr 16, 2021 8:46 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 2991
Use the Bochs debugger to dump the registers (including segment registers) and the contents of the DAP and post them here.


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Fri Apr 16, 2021 8:49 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 611
I'm just eyeballing things and have no intention to run it. But what I told you is a problem but looking at it a bit further this appears to be a problem too:
Code:
mov $0x0400, %bx
You seem to be starting at 0x0000:0x0400 . 0x0000:0x0400 is on top of the BDA (BIOS Data Area). Clobbering that could very well cause Int 13h to fail after the first read. Try starting at 0x600 (or 0x500 on almost all systems will be safe).


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Fri Apr 16, 2021 11:04 am 
Offline
User avatar

Joined: Thu Jun 16, 2016 9:35 am
Posts: 24
MichaelPetch wrote:
I'm just eyeballing things and have no intention to run it. But what I told you is a problem but looking at it a bit further this appears to be a problem too:
Code:
mov $0x0400, %bx
You seem to be starting at 0x0000:0x0400 . 0x0000:0x0400 is on top of the BDA (BIOS Data Area). Clobbering that could very well cause Int 13h to fail after the first read. Try starting at 0x600 (or 0x500 on almost all systems will be safe).


Same result, but a step in the right direction


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Fri Apr 16, 2021 11:10 am 
Offline
User avatar

Joined: Thu Jun 16, 2016 9:35 am
Posts: 24
Octocontrabass wrote:
Use the Bochs debugger to dump the registers (including segment registers) and the contents of the DAP and post them here.


Segment registers:
Code:
es:0x0000, dh=0x00009300, dl=0x0000ffff, valid=3                                                                                Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed                                           cs:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1                                                                                Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed                                           ss:0x0900, dh=0x00009300, dl=0x9000ffff, valid=7                                                                                Data segment, base=0x00009000, limit=0x0000ffff, Read/Write, Accessed                                           ds:0x0000, dh=0x00009300, dl=0x0000ffff, valid=3                                                                                Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed                                           fs:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1                                                                                Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed                                           gs:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1                                                                                Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed                                           ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1                                                                      tr:0x0000, dh=0x00008b00, dl=0x0000ffff, valid=1                                                                        gdtr:base=0x00000000000f9af7, limit=0x30                                                                                idtr:base=0x0000000000000000, limit=0x3ff


Regular registers:
Code:
rax: 00000000_00000444
rbx: 00000000_00000600
rcx: 00000000_00090001
rdx: 00000000_00000000
rsp: 00000000_0000fffe
rbp: 00000000_00000000
rsi: 00000000_000e0226
rdi: 00000000_00005459
r8 : 00000000_00000000
r9 : 00000000_00000000
r10: 00000000_00000000
r11: 00000000_00000000
r12: 00000000_00000000
r13: 00000000_00000000
r14: 00000000_00000000
r15: 00000000_00000000
rip: 00000000_00007cd3


DAP:
Code:
<bochs:12> x /16bx 0x7D29
[bochs]:
0x0000000000007d29 <bogus+       0>:    0x00    0x01    0x00    0x00    0x02    0x00    0x00    0x2c
0x0000000000007d31 <bogus+       8>:    0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Fri Apr 16, 2021 11:28 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 2991
cakehonolulu wrote:
Code:
rax: 00000000_00000444

Perhaps I wasn't specific enough... I want to see the registers and DAP immediately before you call INT 0x13.

cakehonolulu wrote:
Code:
<bochs:12> x /16bx 0x7D29

Are you sure that's the right address for your DAP?


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Fri Apr 16, 2021 11:48 am 
Offline
User avatar

Joined: Thu Jun 16, 2016 9:35 am
Posts: 24
Octocontrabass wrote:
cakehonolulu wrote:
Code:
rax: 00000000_00000444

Perhaps I wasn't specific enough... I want to see the registers and DAP immediately before you call INT 0x13.

cakehonolulu wrote:
Code:
<bochs:12> x /16bx 0x7D29

Are you sure that's the right address for your DAP?


Registers before int13:
Code:
rax: 00000000_0000422c
rbx: 00000000_00000200
rcx: 00000000_00090001
rdx: 00000000_00000080
rsp: 00000000_0000ffec
rbp: 00000000_00000000
rsi: 00000000_000e7d28
rdi: 00000000_0000ffac
r8 : 00000000_00000000
r9 : 00000000_00000000
r10: 00000000_00000000
r11: 00000000_00000000
r12: 00000000_00000000
r13: 00000000_00000000
r14: 00000000_00000000
r15: 00000000_00000000
rip: 00000000_00007cf1
eflags 0x00000202: id vip vif ac vm rf nt IOPL=0 of df IF tf sf zf af pf cf


Segment registers:
Code:
es:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1                                                                                Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed                                           cs:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1                                                                                Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed                                           ss:0x0900, dh=0x00009300, dl=0x9000ffff, valid=7                                                                                Data segment, base=0x00009000, limit=0x0000ffff, Read/Write, Accessed                                           ds:0x0000, dh=0x00009300, dl=0x0000ffff, valid=7                                                                                Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed                                           fs:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1                                                                                Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed                                           gs:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1                                                                                Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed                                           ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1                                                                      tr:0x0000, dh=0x00008b00, dl=0x0000ffff, valid=1                                                                        gdtr:base=0x00000000000f9af7, limit=0x30                                                                                idtr:base=0x0000000000000000, limit=0x3ff


DAP:
Code:
0x0000000000007d28 <bogus+       0>:    0x10    0x00    0x01    0x00    0x00    0x02    0x00    0x00
0x0000000000007d30 <bogus+       8>:    0x2c    0x00    0x00    0x00    0x00    0x00    0x00    0x00


DAP should be at offset 128h after inspecting the resulting binary file of the loader. 0x7C00 + 0x128 = 0x7D28
DAP is 16 byte long so x /16bx 0x7D28 should do the job


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Fri Apr 16, 2021 12:01 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 611
In your DAP the segment and offset is "0x00 0x02 0x00 0x00" . That translates to 0x0000:0x0200 which is not where you want to be loading. Is it possible this DAP we are seeing here is not the one used for the first Int 13h call? How many times did Int 13h get called to do reads before reaching this far? I assume this wasn't from the first call to Int 13h.


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Fri Apr 16, 2021 12:04 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 611
For example in .loop you do:
Code:
   mov $0x200, %bx
   mov $0x01, %cx
   push %dx
   call read_sectors
. You move 0x200 into BX and that then gets placed into the DAP as the dap_offset.


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Sun Apr 18, 2021 1:18 pm 
Offline
User avatar

Joined: Thu Jun 16, 2016 9:35 am
Posts: 24
MichaelPetch wrote:
For example in .loop you do:
Code:
   mov $0x200, %bx
   mov $0x01, %cx
   push %dx
   call read_sectors
. You move 0x200 into BX and that then gets placed into the DAP as the dap_offset.


Changed that, but to no avail... I must be missing something

EDIT:

Code:
.loop:
   mov root_dir_offset, %ax
   add %dx, %ax
   mov $0x0600, %bx // CHANGED THIS
   mov $0x01, %cx
   push %dx
   call read_sectors


DAP (Before first INT13):
Code:
0x0000000000007d28 <bogus+       0>:    0x00    0x00    0x00    0x90    0x10    0x00    0x01    0x00
0x0000000000007d30 <bogus+       8>:    0x00    0x10    0x00    0x00    0x01    0x00    0x00    0x00


Top
 Profile  
 
 Post subject: Re: FAT16 bootloader
PostPosted: Sun Apr 18, 2021 2:11 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 611
Your DAP has moved. The bytes you are displaying no longer represent where your DAP now resides. I assume it has moved because you have made modifications to the code and data shifting the location.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 15 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group