Disk Tutorial · 02

Partition Tables

A block device is only a numbered span of sectors. A partition table is the map that says which ranges are meant to be used, which filesystem probably lives there, and which parts of the medium are intentionally empty.

[o-o] |=| /_\

A filesystem should never wake up on the whole card by accident. First we draw the borders. Then we let the filesystem read inside them.

Goal

Extend the first disk program so disk partitions prints more than the four raw MBR slots. The command should show the start and end of each partition, its size, its type, and the unused ranges between valid partitions. That makes the partition table visible as a map of the whole device, not just a list of entries.

The runtime around the disk program also matters: the ACT LED is driven by a normal heartbeat task, and direct LED checks use led on, led off, or led toggle. Low-level register tools are still available through debug, but the main lesson should be readable from the normal shell commands.

Disks Without Tables

An SD card may have a partition table, but it does not have to. A small embedded image can place one filesystem directly at LBA 0. A bootloader can use a raw region with no filesystem at all. Some flash layouts are fixed by firmware and never carry an MBR or GPT. The driver must therefore separate three questions:

In this tutorial we treat a missing table as a reported condition, not as a driver crash. Later modules can decide whether they accept a raw device or require a partition device.

Kinds of Partition Tables

The first implementation understands MBR because it is tiny and visible in one sector. MBR has four primary slots and a two-byte signature at the end of sector zero. It can also point to extended partition chains, but this tutorial does not implement those yet.

GPT is the modern layout. A GPT disk usually still has a protective MBR entry of type 0xEE so old tools do not mistake the disk for empty space. Real GPT parsing reads a header, validates CRCs, and then walks an array of partition entries. That belongs after the MBR lesson, once the block and partition-device boundary is stable.

There are also platform-specific maps, raw boot layouts, and flash-oriented arrangements. The universal rule is the same: a partition table is metadata that divides one block device into bounded child block devices.

An MBR Entry

MBR entries begin at byte 446 in sector zero. Each entry is 16 bytes:

offset size meaning
0      1    boot flag, usually 0x00 or 0x80
1      3    starting CHS address, historical
4      1    partition type byte
5      3    ending CHS address, historical
8      4    first LBA, little-endian
12     4    sector count, little-endian

Alquist reads the LBA fields by hand instead of casting the bytes to a structure. The CHS fields are kept on disk for compatibility, but the driver uses first_lba and sector_count. From those two numbers it derives last_lba = first_lba + sector_count - 1.

Unused Space

Not every sector belongs to a partition. LBA 0 is occupied by the MBR itself. There is often padding before the first partition so filesystems begin on an alignment boundary. There can be gaps between partitions, and there can be spare space after the last partition. None of that is automatically bad.

Printing unused ranges is useful because it teaches the driver to see the whole medium. It also prepares the later write path: a partition editor, filesystem grow operation, or diagnostic tool must know which sectors are unowned before it changes anything.

The Code Change

The parser still records the four MBR entries. The display code now derives last_lba, sorts valid partitions by start LBA, and prints gaps from LBA 1 through the end of the medium.

Partitions:
  #1 boot=no  type=0x0C FAT32 LBA first_lba=16384 last_lba=1064959 sectors=1048576 size=512 MiB ok (ok)
  #2 boot=no  type=0x83 Linux first_lba=1064960 last_lba=62333951 sectors=61268992 size=29.21 GiB ok (ok)
Unused ranges:
  unused first_lba=1 last_lba=16383 sectors=16383 size=7 MiB
  media size unknown; end after last partition not shown

The output is still read-only. It does not claim, format, erase, or write unused sectors. It only names them.

Try It

make
make test-mbr

On hardware, boot the example and run:

help
tasks
led toggle
partitions
disk partitions

The command should show each detected partition with first_lba, last_lba, sector count, size, validity, and a list of unused ranges. Use debug only when you want the raw register-level tools such as readblk or disk dump0.

Next

With hardware reads and partition boundaries visible, the next storage lesson can mount the first FAT32 partition read-only, walk a subdirectory, and print a small file on the console.