X86 Boot Loader

A x86-boot loader for danrlOS (a tiny kernel written in C) using Disk Address Packets for boot-media access.

Why this one is different

Contrary to popular belief, the BIOS can address blocks on a hard drive beyond common limits. BIOS interrupt 0x13 with register AH set to 0x42 allows extended reading of sectors from a drive. This method allows a boot loader to load data from a drive without calculating head and track numbers. Moreover, it is possible to boot a kernel that resides at the end of a large drive. Unfortunately, most boot loaders still use the old and limited method interrupt 0x13 with AH set to 0x02. This boot loader is different and makes use of Disk Address Packets. Since it is part of my self-written operating system, it is optimized for the corresponding filesystem, but any filesystem that can be read-implemented within the limits of assembler and sectors-size could be integrated easily.


The screenshot shows booting an early, multi-stage version of danrlOS-MBR.

Behind the scenes

The most interesting part are the disk address packets. With logical block addressing (LBA) we can address up to 2^64 sectors. dap_lba_0 and dap_lba_1 represent one 64-bit integer, but since the processor can not handle 64-bit wide variables at this early stage, we must treat them separately. A disk address packet is created as documented in the following listing:

; disk address packet
db       0x10                            ; size of packet
db       0x00                            ; reserved
dw       0x01                            ; number of blocks to transfer
dw       BLOCKBUFFER                     ; buffer destination address
dw       0x00                            ; in page 0
db       0x01                            ; start block number byte 1/4
db       0x00                            ; start block number byte 2/4
db       0x00                            ; start block number byte 3/4
db       0x00                            ; start block number byte 4/4

Then BIOS Interrupt 0x13 with register AH set to 0x42 is invoked.

mov      dl, [boot_device]
mov      si, disk_address_packet
mov      ah, 0x42                        ; extended disk access
int      0x13

As long as the carry flag is not set after this operation, everything went fine (a set carry flag indicates an error). We can find the requested data at the address defined by BLOCKBUFFER (see above listings) in the system’s RAM. Voilà!