File System as Partition Table

If you squint really hard – a partition table is basically a filesystem with only a handful of files – a partition table of, say, 4 partitions, is conceptually pretty much the same as a filesystem with only 4 files in it – the filesystem labels are the filenames, and the partitions are just the files.

So why don’t we use a filesystem as a partition table and boot a OS from it? The pros of doing that is quite obvious: All partitioning operations previously done using fdisk or parted can now be done with file managers, or common UNIX utilities like cp and truncate. To add a new partition, add a new file; to remove a partition, delete the file; to make a partition larger, simply extend the file – no more moving other partition around like playing Klotski.

This is especially true for beginners – one big hurdle to jump using a Raspberry Pi – is to prepare a SD card. Without prior knowledge of MBR or GPT, this process is quite error prone. If we’re using a filesystem as a partition table, the provisioning process is just copying some files into a FAT32 disk, which comes standard on most SD cards. Upgrading the OS is no different from copying files – which can be easily done in any OS.

Proof-of-Concept

Let’s get a proof of concept running – we want to prepare a SD card with a single partition, have a image file root.img in there, and boot off of it. In linux terms – mount the root.img as a loop device, and use that as root.

Linux itself, does not have the capability of directly booting from a image file as root. We have to do it in a more roundabout way.

  1. Boot to a initramfs
  2. Mount devtmpfs, proc, and sys.
  3. Mount the filesystem containing the image file, in the case of Raspberry Pis, this is /dev/mmcblk0p1.
  4. Mount the image file using a loop device.
  5. switch_root to the actual rootfs.

For the initramfs, we use BusyBox with a custom init file, with a few extra utilities written in shell script.

The boot process is roughly the following:

  1. Linux starts /init in the initramfs.
  2. Wait 5 seconds, if the user interrupts, offer options to use a rescue shell, reboot or shutdown.
  3. Mount /dev/mmcblk0p1 to /boot and give control to /boot/init. We do this because initramfs is not persistent, and we want to boot process to be configurable.
  4. Wait 5 seconds, if the user interrupts, let the user select a image to boot.
  5. Mount the image (default /boot/root.img) and switch_root
  6. Raspbian takes over.

By Yifan Gu

aka. Frank, aka. 顾屹凡

Leave a comment