Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/test-x86-lilo-qemu.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: X86 LILO (legacy BIOS/MBR) QEMU test

on:
pull_request:
branches: [ '*' ]
jobs:
lilo_qemu_test:
runs-on: ubuntu-latest
container:
image: ghcr.io/wolfssl/wolfboot-ci-x86:v1.29
timeout-minutes: 20

steps:
- uses: actions/checkout@v4
with:
submodules: true

- name: Trust workspace
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"

- name: install req
run: |
apt-get update -o Acquire::Retries=3
apt-get install --no-install-recommends -y -q -o Acquire::Retries=3 dosfstools fdisk cpio
# A stock distribution bzImage to boot, without installing it. The
# kernel itself ships in linux-binary-<abi>, under /usr/lib/modules.
mkdir -p /tmp/kernel && chmod 777 /tmp/kernel && cd /tmp/kernel
abi=$(apt-cache depends linux-image-amd64 | awk '/Depends: linux-image-/ {sub("linux-image-", "", $2); print $2; exit}')
apt-get download linux-binary-$abi
dpkg-deb -x linux-binary-${abi}_*.deb .
cp usr/lib/modules/$abi/vmlinuz /tmp/vmlinuz

- name: build
run: |
cp config/examples/x86_64_lilo.config .config
make keytools
make

- name: run test
run: |
python3 tools/lilo/test/run-qemu.py -k /tmp/vmlinuz
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -667,3 +667,7 @@ tools/unit-tests/stm32wb_write_extract.h
tools/unit-tests/t10xx_flash_status_extract.h
tools/unit-tests/ti_hercules_erase_extract.h
tools/unit-tests/versal_host_write.c

# x86_64_lilo
tools/lilo/lilo
tools/lilo/test/out
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,10 @@ ifeq ($(TARGET),aarch64_efi)
MAIN_TARGET:=wolfboot.efi
endif

ifeq ($(TARGET),x86_64_lilo)
MAIN_TARGET:=wolfboot.bin
endif

ifeq ($(FSP), 1)
MAIN_TARGET:=wolfboot_stage1.bin
endif
Expand Down
23 changes: 23 additions & 0 deletions arch.mk
Original file line number Diff line number Diff line change
Expand Up @@ -2476,6 +2476,29 @@ ifneq ($(CROSS_COMPILE_PATH),)
endif


ifeq ($(TARGET),x86_64_lilo)
# Legacy BIOS/MBR boot, LILO style: no EFI and no FSP. wolfBoot runs in
# flat 32-bit protected mode and drops back to real mode for BIOS disk,
# keyboard and video services. tools/lilo installs it on a disk.
USE_GCC_HEADLESS=0
DISK_FS?=fat32
LD := ld
CFLAGS += -m32 -ffreestanding -fno-stack-protector -fno-PIC -fno-pie \
-mno-mmx -mno-sse -mno-red-zone -fno-asynchronous-unwind-tables \
-ffunction-sections -fdata-sections -U_FORTIFY_SOURCE -Os
# gnu11: keeps the host glibc headers from turning memchr & co. into
# C23 _Generic macros that collide with src/string.c
CFLAGS += -std=gnu11
CFLAGS += -DWOLFBOOT_LILO -DDEBUG_UART -DWOLFBOOT_NO_LOAD_ADDRESS
LDFLAGS = -m elf_i386 --gc-sections --entry=_mbr_start -T $(LSCRIPT) \
-Map=wolfboot.map
LD_START_GROUP =
LD_END_GROUP = $(shell $(CC) -m32 -print-libgcc-file-name)
OBJS += src/boot_x86_bios_mbr.o src/boot_x86_bios_start.o src/x86/bios.o
OBJS += src/disk.o src/gpt.o
UPDATE_OBJS := src/update_lilo.o
endif

ifeq ($(TARGET),x86_64_efi)
USE_GCC_HEADLESS=0
GNU_EFI_LIB_PATH?=/usr/lib
Expand Down
11 changes: 11 additions & 0 deletions config/examples/x86_64_lilo.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
ARCH=x86_64
TARGET=x86_64_lilo
SIGN=NONE
HASH=SHA256
DEBUG=0
SPMATH=0
FORCE_32BIT=1
DISK_FS=fat32
WOLFBOOT_NO_PARTITIONS=1
# required for keytools
WOLFBOOT_SECTOR_SIZE?=0x1000
134 changes: 134 additions & 0 deletions docs/Targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ This README describes configuration of supported targets.
* [NXP T10xx PPC (T1024 / T1040)](#nxp-qoriq-t10xx-ppc-t1024--t1040)
* [NXP T2080 PPC](#nxp-qoriq-t2080-ppc)
* [Qemu x86-64 UEFI](#qemu-x86-64-uefi)
* [x86-64 legacy BIOS/MBR, LILO style (x86_64_lilo)](#x86-64-legacy-biosmbr-lilo-style-x86_64_lilo)
* [NVIDIA Jetson Orin (aarch64_efi)](#nvidia-jetson-orin-aarch64_efi)
* [NVIDIA Jetson Orin (NVIDIA Tegra234) BL33 firmware](#nvidia-jetson-orin-nvidia-tegra234-bl33-firmware)
* [Raspberry Pi pico 2 (rp2350)](#raspberry-pi-pico-rp2350)
Expand Down Expand Up @@ -8189,6 +8190,139 @@ To pass an authenticated Linux kernel command line, sign the kernel with `--cmdl



## x86-64 legacy BIOS/MBR, LILO style (x86_64_lilo)

The third x86-64 port, next to [UEFI](#qemu-x86-64-uefi) and
[Intel FSP](#intel-x86_64-with-intel-fsp-support): no EFI stage and no FSP.
wolfBoot boots from the MBR of a legacy BIOS machine and is installed, the
way LILO was, by a `lilo` tool that reads `/etc/lilo.conf`.

### Boot flow

1. The BIOS loads the MBR (`src/boot_x86_bios_mbr.S`) at `0x7C00`. It reads
wolfBoot from the sectors between the MBR and the first partition
(INT 13h extensions, LBA) to `0x7E00`.
2. wolfBoot (`src/boot_x86_bios_start.S`) enables A20 and switches to flat
32-bit protected mode. Disk, keyboard, video and memory-map services are
BIOS calls, made by dropping back to real mode for each one
(`src/x86/bios.c`), so wolfBoot needs no disk driver of its own: it
reads the disk the BIOS booted from (tested on QEMU with IDE, AHCI on
q35, and virtio-blk).
3. It reads the boot map written by `lilo` and, LILO-style, shows a `boot:`
prompt over the configured labels (`src/update_lilo.c`).
4. The selected kernel is read from a FAT32 partition with wolfBoot's own
FAT32 reader, staged in RAM and checked with the regular wolfBoot image
verification (with `SIGN=NONE`, the SHA-256 integrity check).
5. The kernel is started through the Linux real-mode boot protocol: setup at
`0x90000`, protected-mode kernel at `0x100000`, initrd high in RAM. The
kernel's own setup code then queries the BIOS (E820, EDD, video), as it
did under LILO. A 64-bit (x86_64) kernel boots this way like any other.
`other=` entries chain-load a partition boot sector instead.

The progress letters are LILO's: `L` (MBR running), `LI` (wolfBoot loaded),
`LIL` (wolfBoot running), `LILO` (map loaded). A failure in the MBR prints
the BIOS error code after the letters (`E0`: not installed, `E1`: no LBA
support in the BIOS).

As with LILO the MBR code is BIOS-only, and the disk must use MBR (not GPT)
partitioning. Unlike LILO, the map names files instead of listing their
sectors, so a kernel can be replaced in the FAT32 partition without running
`lilo` again; run it again when `lilo.conf` changes.

Disk layout written by `lilo` (all of it in front of the first partition,
which usually starts at sector 2048):

| LBA | Content |
|-----------|----------------------------------------------------------|
| 0 | MBR boot code and descriptor; disk signature and partition table preserved |
| 1 - 33 | boot map (`include/lilo_map.h`) |
| 34 - | wolfBoot (about 40 sectors) |

### Configuration and build

An example configuration is in
[config/examples/x86_64_lilo.config](../config/examples/x86_64_lilo.config).
The build needs a 32-bit capable gcc (`gcc-multilib` on Debian/Ubuntu).

```
cp config/examples/x86_64_lilo.config .config
make keytools
make
make -C tools/lilo
```

`wolfboot.bin` is the MBR sector followed by wolfBoot. Kernels are wolfBoot
images:

```
tools/keytools/sign --no-sign --sha256 bzImage 1
```

### Installing

`tools/lilo/lilo` takes the usual `lilo` options (`-C`, `-b`, `-i`, `-D`,
`-s`, `-t`, `-q`, `-u`, `-v`) and the usual `lilo.conf` keywords; see
[tools/lilo/README.md](../tools/lilo/README.md). For example:

```
boot=/dev/sda
install=/boot/wolfboot.bin
prompt
timeout=50
default=linux
serial=0,115200n8

image=/boot/vmlinuz_v1_signed.bin
label=linux
initrd=/boot/initrd.img
root=/dev/sda2
read-only
append="console=ttyS0,115200"

other=/dev/sda3
label=dos
```

`/boot` is taken to be where the FAT32 partition is mounted, so
`/boot/vmlinuz_v1_signed.bin` is `/vmlinuz_v1_signed.bin` on the partition
(see `fat-mount=` to change it). `lilo` checks every image with wolfBoot's
own partition and FAT32 code before writing anything.

### Running on QEMU

[tools/lilo/test/run-qemu.py](../tools/lilo/test/run-qemu.py) builds a disk
image (MBR, a FAT32 partition and a partition with a test boot sector),
signs a kernel (by default the newest `/boot/vmlinuz-*`), installs wolfBoot
with `lilo`, and boots it on `qemu-system-x86_64` with the stock SeaBIOS:
default boot after the timeout, a label and extra parameters typed at the
prompt, recovery from an unknown label and from a corrupted image, and
`other=` chain loading.

```
python3 tools/lilo/test/run-qemu.py [-k bzImage] [-a kvm|tcg]
```

```
LILO
wolfBoot: 639 KB low, 510 MB extended memory
...
boot: linux
Loading linux
Boot partition: 0xF00000 (sz 14546880, ver 0x1, type 0xFF01)
..............
Verified /vmlinuz-wolfboot-v1.bin, version 1
Loading initrd.
Booting kernel: BOOT_IMAGE=linux ro console=ttyS0,115200 panic=-1
[ 0.000000] Linux version 7.2.11+deb14-amd64 ...
```

`SIGN=NONE` authenticates nothing: anyone who can write the disk can replace
the kernel. The image check only catches corruption. The port uses the
generic image verification, so a signing configuration (with a keystore)
builds the same way, but the MBR code and the map are not authenticated by
anything in a legacy BIOS boot.


## NVIDIA Jetson Orin (aarch64_efi)

The `aarch64_efi` target builds wolfBoot as an AArch64 UEFI application (`wolfboot.efi`), the direct counterpart of the [Qemu x86-64 UEFI](#qemu-x86-64-uefi) target. It uses only UEFI Boot Services (no SoC-specific registers), so the same binary runs on any AArch64 UEFI platform. It has been validated on the NVIDIA Jetson Orin Nano Developer Kit (Tegra234), where the on-module UEFI firmware (edk2-nvidia) launches it after the NVIDIA-signed early boot chain (BootROM -> MB1 -> MB2 -> UEFI). wolfBoot reads the next-stage image from the EFI Simple File System, authenticates it with wolfCrypt, and boots it via the UEFI `LoadImage`/`StartImage` services (an AArch64 Linux `Image` is itself a PE/COFF EFI-stub application).
Expand Down
Loading
Loading