Page 1 of 1

Writing my first bootloader. 0x13 paramenters?

Posted: Fri Nov 16, 2012 11:41 am
by nickie
Hello,
I'm new in this forum so please correct me if I'm wrong :P. I'm actually game programmer and I believe I'm coding quite well in C++ with around 3 years of non-stop coding(no social life). However I have no solid knowledge of x86 assembly(though I've played some time with dissassemblers and have made small things in it)
So... I decided to learn how my pc work. I need to write a bootloader. I've been trying to do it for 1 week.(reading ebooks, forums articles, etc)
I'm using nasm and managed to run some code in VirtualBox.

First of all, this is part of the virtual machine's log:
00:00:04.968130 PIIX3 ATA: Ctl#0: RESET, DevSel=1 AIOIf=1 CmdIf0=0xa1 (-1 usec ago) CmdIf1=0xc4 (-1 usec ago)
00:00:04.968161 PIIX3 ATA: Ctl#0: finished processing RESET
00:00:04.968732 Guest Log: BIOS: int13_harddisk: function 02, disk 80, parameters out of range 0000/0020/0021!
This is the master boot record of my virtual hard disk. (You can ingore my code, as I'll post it in a second, just to see the parameters which were generated when I formatted it with a third party software through ubuntu). Its the modern MBR standart
EB 00 FA B8 00 00 8E D8 8E C0 8E E0 8E E8 B8 00 04 8E D0 BC 00 00 FB BE 2E 7D E8 F9 00 B2 80 E8 E1 00 BE 41 7D E8 EE 00 B0 01 8A 0E C0 7D 8A 2E C1 7D 8A 36 BF 7D B2 80 E8 CF 00 BE 2E 7D E8 D5 00 E9 BC 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 31 D2 5B F7 37 FE C2 88 16 28 7D 31 D2 5B F7 37 88 16 2A 7D A2 2C 7D C3 83 E8 02 31 C9 5B 8A 0F F7 E1 C3 B4 00 CD 13 72 FA C3 B4 02 CD 13 72 01 C3 E8 EF FF EB F4 AC 08 C0 74 06 B4 0E CD 10 EB F5 C3 00 00 00 00 00 00 00 00 00 00 00 00 4C 61 75 6E 63 68 20 53 75 63 63 65 73 73 66 75 6C 21 00 4F 4B 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8E 55 08 00 00 00 00 20 21 00 0B 28 20 08 00 08 00 00 00 F8 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA
and this is my code:

Code: Select all

[BITS 16]

[ORG 0x0000]



jmp loader

;db 0x00



;Function:*****************************************************************

;NAME: loader

;Parameters:***************

;NO

;**************************************************************************

loader:

cli ; clear interrupts

mov ax, 0x07C0

mov ds, ax

mov es, ax

mov fs, ax

mov gs, ax



mov ax, 0x800

mov ss, ax

mov sp, 0

sti ; enable interrupts



mov si, msg

call Print





;Reset the hard disk

mov dl, 80h

call Reset





mov si, succ

call Print


;set read params
mov al, 1
mov cl, [SSector1]
mov ch, [STrack1]
mov dh, [SHead1]
mov bx, 0x400
mov dl, 80h

call Read



mov si, msg

call Print



jmp 0x400









times 218 - ($-$$) db 0





;End of a function*********************************************************

;**************************************************************************









;Parameter Block:**********************************************************

;NAME: Disk Timestamp

;Size:***************

;6 bytes

;**************************************************************************



dw 0xFFFF ; reserved

HardDrive: db 0xEE ; not mapped in the hard drive. In other words, not used and I don't need it

db 0xCC ; not used

db 0xBB ; not used

db 0xAA ; not used



;End of a param block******************************************************

;**************************************************************************









;Parameters:***************

;Input: dl -> DriveNumber

;**************************

Reset:

;first reset the reader

mov ah, 0x00

int 0x13

jc Reset

ret



;Parameters:***************

;ax - address to read in, dl - drive number

;al - sectors to read(count), ch - track, cl - sector

;dh - head

;**************************

Read:

;now read in the file

mov ah, 0x02 ; what are we doing?

int 0x13 ; call bios

jc GoToReset

ret



GoToReset:

call Reset

jmp Read



;Parameters:***************

;0

;**************************



Print:

lodsb

or al, al

jz PrintDone

mov ah, 0eh

int 10h

jmp Print

PrintDone:

ret









;Variables:****************
;NOT USED; JUST COPIED FROM ONE TUTORIAL
;**************************

first_data_sector: dw 0x0000

working_lba: dd 0x00000000

absoluteSector: dw 0x0000

absoluteHead: dw 0x0000

absoluteTrack: dw 0x0000



msg	db	"Launch Successful!", 0 ; had some problems with the segments, so I used this to test if its going ok for now.

succ db "OK!",0 ; printing it from time to time to check where the problem is

;**************************



times 440 - ($-$$) db 0







;Parameter Block:**********************************************************

;NAME: Partition Tables

;Size:***************

;72 bytes

;**************************************************************************



DiskSignature: dd 0x00000000

dw 0x0000 ; not used

;Partition Table 1



DiskDrive1: db 0xFF

SHead1: db 0x00 

SSector1: db 0x00

STrack1: db 0x00

PartitionType1: db 0x00

EHead1: db 0x00 

ESectorTack1: dw 0x0000

StartSector1: dd 0x00000000

SectorCount1: dd 0x00000000



;Partition Table 2

;Partition Table 3

;Partition Table 4

;End of partition tables



times 510 - ($-$$) db 0



dw 0x55AA



;End of a param block******************************************************

;**************************************************************************



Thats it.
So my question is: how do I read the sector at SSector1, STrack1 and SHead1 to 7C00:0x400?

If I haven't given information you need, please ask and I'll answer as soon as I can

Re: Writing my first bootloader. 0x13 paramenters?

Posted: Fri Nov 16, 2012 11:57 am
by bluemoon
SSector1: db 0x00
For BIOS INT13/AH=02, CL = sector number 1-63 (bits 0-5), high two bits of cylinder (bits 6-7, hard disk only).
Search for Ralf Brown's Interrupt List for detail.

Re: Writing my first bootloader. 0x13 paramenters?

Posted: Fri Nov 16, 2012 12:06 pm
by nickie
I'm actually just mapping the correct byte. This value is already written in the hard drive's boot sector by a third party partitioner. WHen I need to put my own code, I just copy the bytecode itself. This was the idea :D I think I have achieved it because the virtual machine code is telling me the parameters it was asked to use. And I know that the sector's byte are actually 6 bits and the high 2 bits are part of the track's number. However the number I have here is 0x21 or 0x20(don't remember) which in binary is 00100000(the first 2 bits are 00, they do not change anything)

Also thanks for the note. I'll keep it in mind after I actually read something=

Re: Writing my first bootloader. 0x13 paramenters?

Posted: Fri Nov 16, 2012 1:29 pm
by Brendan
Hi,
nickie wrote:So my question is: how do I read the sector at SSector1, STrack1 and SHead1 to 7C00:0x400?
You don't. For hard disks you should be using an LBA address and "int 0x13 extensions" and should never use CHS at all.
nickie wrote:Its the modern MBR standart
That random infestation of bytes actually means this:
00 20 21 00 0B 28 20 08 00 08 00 00 00 F8 01 00 = first partition table entry
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 = second partition table entry
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 = third partition table entry
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 = fourth partition table entry
55 AA = end of sector

The first partition table entry decodes as:
0x00 = not active, not bootable
0x20 = trash ("starting head 32")
0x21 0x00 = trash ("starting sector 33, starting cylinder 0")
0x0B = partition type (should be 0x0C)
0x28 = trash ("ending head 40")
0x20 0x08 = trash ("ending sector 32, ending cylinder 8")
0x00 0x08 0x00 0x00 = starting sector LBA 0x00000800
0x00 0xF8 0x01 0x00 = size of partition is 0x0001F800 or 63 MiB.

From this you can see that Ubuntu thought "sector 32, head 40, cylinder 8" is LBA sector 131072, which probably means that Ubuntu thought there are 63 sectors per track and 255 heads (because 8*255*63 + 40*63 + 32 = 131072). However, this has nothing to do with how many sectors per track or how many heads the BIOS thinks there are. For example, the BIOS could think there are 8 sectors per track and 64 heads (and a lot more cylinders). Ubuntu doesn't use the BIOS and doesn't know what the BIOS thinks, and therefore it just guesses (and probably guesses wrong, and screws up all of the CHS fields).

Of course it's worse than this. Because CHS is bad, if you plug the exact same hard drive into different computers, the different BIOSs in those computers may do "fake CHS->LBA" conversion differently, and may decide to use different values for sectors per track and number of heads.

Now; there is one problem with using the LBA address. If the computer is ancient (e.g. 80386 or older) then it might not support "int 0x13 extensions". In this case, you ask the BIOS what it currently thinks the number of sectors per track and number of heads is, and then use this information to convert the starting/ending LBA addresses from the partition table into CHS values (you do not use the CHS values from the partition table for anything under any circumstances).


Cheers,

Brendan

Re: Writing my first bootloader. 0x13 paramenters?

Posted: Fri Nov 16, 2012 1:44 pm
by bluemoon
As a side note, the CHS value can be set to "invalid" (e.g. FF FF FF) by some utility, in that case you will be forced to look at LBA fields.

Re: Writing my first bootloader. 0x13 paramenters?

Posted: Fri Nov 16, 2012 2:30 pm
by nickie
Brendar and bluemoon, thank you both for the answers. They was quite helpful. I'll go for the LBA address, int 0x13 and ah = 0x42.