Step 1 of 5 · Reading · ~4 min
Read
Boot & Memory
Boot Process
Between the power button and your kernel's first instruction lies a fixed choreography. Every stage exists because the previous one was too small to do the next job. In this lesson you will read the first thing that choreography touches on a BIOS machine: the 512-byte master boot record. Your program will take a real sector as hex, check it, decode its partition table and say which partition the BIOS would boot.
The chain, in order
- Reset vector. The CPU starts at
0xFFFFFFF0, 16 bytes below 4 GiB, where the firmware ROM is mapped, in real mode: the 16-bit mode of the 1978 8086. Every x86 chip still wakes up pretending to be one. - Firmware (BIOS POST). It tests RAM, discovers devices, picks a boot disk and reads exactly one sector (the first 512 bytes) to physical address
0x7C00. If the last two bytes of that sector are55 AAit jumps to0x7C00. That is the entire BIOS-to-OS interface: 512 bytes at a fixed address, no filesystem, no negotiation. - Bootloader. 446 bytes cannot hold a filesystem driver, so stage 1 only loads a larger stage 2 (GRUB's core image) from a fixed place. Stage 2 can read files, loads your kernel ELF, and records the E820 memory map, the hardware's one-time list of which RAM ranges are usable. A Multiboot kernel is entered with a pointer to that information.
- Mode switches. Enable the A20 line, load a GDT, set
CR0.PEfor protected mode; for 64-bit build page tables, setEFER.LMEand turn on paging. - Kernel early init. Zero
.bss, set a stack, bring up a console, load your own GDT and IDT, parse the memory map, then allocator, paging, scheduler, and finally start PID 1.
UEFI replaces steps 2 and 3 with a FAT "EFI System Partition" holding the bootloader as an ordinary executable, but the handshake (memory map in, kernel entry out) is the same.
Anatomy of the sector
offset size field
0 440 bootstrap code
440 4 disk signature (little-endian, e.g. what fdisk calls "Disk identifier")
444 2 usually 00 00
446 16 partition entry 1
462 16 partition entry 2
478 16 partition entry 3
494 16 partition entry 4
510 2 boot signature: bytes 55 AA
Read the last two bytes in order: the byte at 510 is 0x55, the byte at 511 is 0xAA. As a little-endian 16-bit word that is 0xAA55, which is why you see both spellings.
Each 16-byte partition entry:
| Offset | Size | Meaning |
|---|---|---|
| 0 | 1 | boot flag: 0x80 active, 0x00 inactive, anything else is invalid |
| 1 | 3 | CHS address of the first sector (obsolete) |
| 4 | 1 | partition type (0x83 Linux, 0x07 NTFS, 0xEE GPT protective, 0x00 empty slot) |
| 5 | 3 | CHS address of the last sector (obsolete) |
| 8 | 4 | LBA of the first sector, little-endian |
| 12 | 4 | number of sectors, little-endian |
Worked example, one real entry:
80 20 21 00 83 FE FF FF 00 08 00 00 00 20 03 00
Flag 80 is active, type 83 is Linux. The start field is the bytes 00 08 00 00; reversed they are 0x00000800 = 2048 (the 1 MiB alignment every modern partitioner uses). The count 00 20 03 00 reverses to 0x00032000 = 204800 sectors = 100 MiB. Read it big-endian by mistake and the start becomes 0x00080000 = 524288. The last sector is start + count - 1 = 206847.
Common mistakes
- Reading the LBA or count most-significant byte first.
- Treating the signature as
0x55AAinstead of the bytes55 AA(a word of0x55AAmeans the bytes were swapped and the BIOS refuses the disk). - Computing
lastin 32 bits: a GPT protective entry (type0xEE) has start 1 and count0xFFFFFFFF, sostart + count - 1needs more than 32 bits of room before you subtract. - Counting an entry with an invalid flag as bootable.
Your exercise
The program receives the sector as hex text and prints the report described in the exercise. The starter parses the hex into a 512-byte array for you; you write the decoding.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…