How to use systemboot - Telecominfraproject/OpenCellular GitHub Wiki

systemboot

SystemBoot is a distribution for LinuxBoot to create a system firmware + bootloader. It is based on LinuxBoot u-root. The provided programs are:

  • netboot: a network boot client that uses DHCP and HTTP to get a boot program based on Linux, and uses kexec to run it
  • localboot: a tool that finds bootable kernel configurations on the local disks and boots them
  • verifiedboot: a tool that boots a systemboot boot configuration including verified/measured boot procedure.
  • uinit: a wrapper around netboot and localboot that just mimicks a BIOS/UEFI BDS behaviour, by looping between network booting and local booting. The name uinit is necessary to be picked up as boot program by u-root.

This work is similar to the pxeboot and boot commands that are already part of u-root, but approach and implementation are slightly different. Thanks to Chris Koch and Jean-Marie Verdun for pioneering in this area.

This project started as a personal experiment under github.com/insomniacslk/systemboot but it is now an effort of a broader community and graduated to a real project for system firmwares.

The next sections go into further details.

verifiedboot

Is a booter tool which loads a boot configuration by given NVRAM variables and executes into the OS in a secure manner. This is done by using verified and measured boot process.

Boot options

Boot options are stored inside the firmware NVRAM and dynamically probed by systemboot. Those options can be written as map where the key is the string identifier and the value is the responding json matching the booter (e.g. verifiedbooter):

[ "Boot0000": {"device_path": "/dev/sda1", "bc_file": "/boot/bc.img", "bc_name": "test"} ]

Each key is unique and RO NVRAM precedes RW entries. So they overwrite them. Boot order is in reverse order which leads to follong boot procedure.

Boot9999
...
Boot0003 ----|
Boot0002 <---|----|
Boot0001 <--------|
Boot0000 <- RO fallback

If newly written RW entries break the boot procedure the RO entry will give the a fallback option for booting the system.

Boot Configuration

During boot phase systemboot tries to find the boot configuration file by using the NVRAM boot options. If it is found then it gets executed by systemboot as part of the boot process.

1) Generate signing keys

Needed to sign the the boot configuration file

configtool genkeys --passphrase=thisisnotasecurepassword private_key.pem public_key.pem
2) Create a manifest.json

Which can have multiple boot configurations in an array. It offers the following config items:

commandline

Is the kernel commandline for the linux kernel to boot.

initrd

Is the initramfs file name in the initrd directory.

kernel

Is the kernel file name in the kernel directory.

dt

Is the device-tree file name in the dt directory.

name

Is a unique identifier for the boot configuration.

{
  "configs": [
    {
      "commandline": "root=/dev/mapper/sys-root ro root_trim=yes crypt_root=UUID=597ca453-ddb4-499b-8385-aa1383133249 keymap=de dolvm init=/lib/systemd/systemd net.ifnames=0 intel_iommu=igfx_off",
      "initrd": "initrd",
      "kernel": "kernel",
      "name": "test"
    }
  ]
}
3) Pack configuration + arbitrary files

Now we merging everything into one zip file and attaching a signature at the end.

configtool pack --passphrase=thisisnotasecurepassword --kernel-dir=kernelDir --initrd-dir=initrdDir --dt-dir=deviceTreeDir manifest.json bc.file private_key.pem

Afterwards copy the boot file to the boot directory with the file path location stored inside the NVRAM vars.