Add an example recipe (based on configs/pc_x86_64_efi_defconfig) to
generate an x86-64 image which boots the system using the efibootguard
bootloader. The recipe is an example of how to create an image using
efibootguard, including how to create the disk image & how to configure
efibootguard.
The created example image contains two boot slots; one of which contains
the kernel and the other is a dummy slot (e.g. cannot be booted from).
Also add instructions (and a silly script) to boot the example image
with QEMU.
DEVELOPERS | 2 +
board/pc-efibootguard/genimage.cfg | 59 ++++++++++++++++++++++++++++
board/pc-efibootguard/linux-efistub.fragment | 4 ++
board/pc-efibootguard/post-build.sh | 35 +++++++++++++++++
board/pc-efibootguard/post-image.sh | 7 ++++
board/pc-efibootguard/readme.txt | 30 ++++++++++++++
board/pc-efibootguard/run-image-qemu.sh | 9 +++++
configs/pc_x86_64_efibootguard_defconfig | 51 ++++++++++++++++++++++++
8 files changed, 197 insertions(+)
diff --git a/DEVELOPERS b/DEVELOPERS
index f64a5d6370..1b8d27bcf1 100644
--- a/DEVELOPERS
+++ b/DEVELOPERS
@@ -699,6 +699,8 @@ F: package/perl-x10/
N: Christopher Obbard <
obb...@gmail.com>
F: boot/efibootguard/
+F: board/pc-efibootguard/
+F: configs/pc_x86_64_efibootguard_defconfig
diff --git a/board/pc-efibootguard/genimage.cfg b/board/pc-efibootguard/genimage.cfg
new file mode 100644
index 0000000000..2437a89b63
--- /dev/null
+++ b/board/pc-efibootguard/genimage.cfg
@@ -0,0 +1,59 @@
+image EFI.vfat {
+ vfat {
+ file EFI/BOOT/BOOTX64.EFI {
+ image = "efibootguard/efibootguardx64.efi"
+ }
+ }
+
+ size = 16352K # 16MB - 32KB
+}
+
+image boot-a.vfat {
+ vfat {}
+
+ size = 128M
+ srcpath = "output/images/boot-a-part"
+}
+
+# # boot-b is a placeholder
+image boot-b.vfat {
+ vfat {}
+
+ size = 128M
+ srcpath = "output/images/boot-b-part"
+}
+
+image disk.img {
+ hdimage {
+ partition-table-type = "gpt"
+ }
+
+ partition EFI {
+ image = "EFI.vfat"
+ partition-type-uuid = esp
+ offset = 32K
+ bootable = true
+ }
+
+ partition boot-a {
+ partition-type-uuid = fat32
+ image = "boot-a.vfat"
+ }
+
+ partition boot-b {
+ partition-type-uuid = fat32
+ image = "boot-b.vfat"
+ }
+
+ partition system-a {
+ partition-type-uuid = root-x86-64
+ image = "rootfs.ext4"
+ size = 2G
+ }
+
+ # system-b is a placeholder
+ partition system-b {
+ partition-type-uuid = root-x86-64
+ size = 2G
+ }
+}
diff --git a/board/pc-efibootguard/linux-efistub.fragment b/board/pc-efibootguard/linux-efistub.fragment
new file mode 100644
index 0000000000..82f757b098
--- /dev/null
+++ b/board/pc-efibootguard/linux-efistub.fragment
@@ -0,0 +1,4 @@
+CONFIG_EFI=y
+CONFIG_EFI_STUB=y
+CONFIG_EFIVAR_FS=y
+CONFIG_EFI_PARTITION=y
diff --git a/board/pc-efibootguard/post-build.sh b/board/pc-efibootguard/post-build.sh
new file mode 100755
index 0000000000..7f5973cd39
--- /dev/null
+++ b/board/pc-efibootguard/post-build.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+set -e
+
+BOARD_DIR=$(dirname "$0")
+
+# Kernel cmdline to append
+KERNEL_CMDLINE=""
+
+# Create efibootguard boot-a slot configuration
+mkdir -p ${BINARIES_DIR}/boot-a-part
+echo -n "boot-a" | iconv -f ascii -t UTF-16LE > ${BINARIES_DIR}/boot-a-part/EFILABEL
+${HOST_DIR}/bin/bg_setenv \
+ --verbose \
+ --watchdog=0 \
+ --filepath=${BINARIES_DIR}/boot-a-part/BGENV.DAT \
+ --revision=2 \
+ --ustate=OK \
+ --kernel="C:boot-a:bzImage" \
+ --args="root=PARTLABEL=system-a $KERNEL_CMDLINE"
+
+# Create efibootguard boot-a slot configuration (unbootable)
+mkdir -p ${BINARIES_DIR}/boot-b-part
+echo -n "boot-b" | iconv -f ascii -t UTF-16LE > ${BINARIES_DIR}/boot-b-part/EFILABEL
+${HOST_DIR}/bin/bg_setenv \
+ --verbose \
+ --watchdog=0 \
+ --filepath=${BINARIES_DIR}/boot-b-part/BGENV.DAT \
+ --revision=1 \
+ --ustate=FAILED \
+ --kernel="C:boot-b:bzImage" \
+ --args="root=PARTLABEL=system-b $KERNEL_CMDLINE"
+
+# Copy kernel into boot-a.
+cp ${BINARIES_DIR}/bzImage ${BINARIES_DIR}/boot-a-part/
diff --git a/board/pc-efibootguard/post-image.sh b/board/pc-efibootguard/post-image.sh
new file mode 100755
index 0000000000..eec88f707d
--- /dev/null
+++ b/board/pc-efibootguard/post-image.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+set -e
+
+UUID=$(dumpe2fs "$BINARIES_DIR/rootfs.ext2" 2>/dev/null | sed -n 's/^Filesystem UUID: *\(.*\)/\1/p')
+sed "s/UUID_TMP/$UUID/g" board/pc-efibootguard/genimage.cfg > "$BINARIES_DIR/genimage.cfg"
+support/scripts/genimage.sh -c "$BINARIES_DIR/genimage.cfg"
diff --git a/board/pc-efibootguard/readme.txt b/board/pc-efibootguard/readme.txt
new file mode 100644
index 0000000000..d3eeb9793a
--- /dev/null
+++ b/board/pc-efibootguard/readme.txt
@@ -0,0 +1,30 @@
+EFI Boot Guard Example Recipe
+=============================
+
+1. Build
+
+ Build the image:
+
+ $ make pc_x86_64_efibootguard_defconfig
+
+ Add any additional packages required and build:
+
+ $ make
+
+Emulation in qemu
+=================
+
+Run the emulation with:
+
+qemu-system-x86_64 \
+ -M pc \
+ -drive if=pflash,format=raw,readonly=on,file=</path/to/OVMF_CODE.fd> \
+ -drive file=output/images/disk.img,if=virtio,format=raw \
+ -boot menu=on \
+ -net nic,model=virtio \
+ -net user
+
+Note that </path/to/OVMF.fd> needs to point to a valid x86_64 UEFI
+firmware image for qemu. It may be provided by your distribution as a
+edk2 or OVMF package, in a path such as /usr/share/OVMF/OVMF_CODE_4M.fd
+(for Debian).
diff --git a/board/pc-efibootguard/run-image-qemu.sh b/board/pc-efibootguard/run-image-qemu.sh
new file mode 100755
index 0000000000..32be727c3e
--- /dev/null
+++ b/board/pc-efibootguard/run-image-qemu.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+qemu-system-x86_64 \
+ -M pc \
+ -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \
+ -drive file=output/images/disk.img,if=virtio,format=raw \
+ -boot menu=on \
+ -net nic,model=virtio \
+ -net user
diff --git a/configs/pc_x86_64_efibootguard_defconfig b/configs/pc_x86_64_efibootguard_defconfig
new file mode 100644
index 0000000000..276c628e18
--- /dev/null
+++ b/configs/pc_x86_64_efibootguard_defconfig
@@ -0,0 +1,51 @@
+BR2_x86_64=y
+BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_6_12=y
+BR2_GLOBAL_PATCH_DIR="board/pc/patches"
+BR2_DOWNLOAD_FORCE_CHECK_HASHES=y
+BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
+BR2_TARGET_GENERIC_GETTY_PORT="tty1"
+BR2_ROOTFS_POST_BUILD_SCRIPT="board/pc-efibootguard/post-build.sh"
+BR2_ROOTFS_POST_IMAGE_SCRIPT="board/pc-efibootguard/post-image.sh"
+BR2_LINUX_KERNEL=y
+BR2_LINUX_KERNEL_CUSTOM_VERSION=y
+BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.47"
+BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
+BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/pc/linux.config"
+BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="board/pc-efibootguard/linux-efistub.fragment"
+BR2_LINUX_KERNEL_INSTALL_TARGET=y
+BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
+BR2_LINUX_KERNEL_NEEDS_HOST_LIBELF=y
+BR2_PACKAGE_LINUX_FIRMWARE=y
+BR2_PACKAGE_LINUX_FIRMWARE_ATHEROS_9170=y
+BR2_PACKAGE_LINUX_FIRMWARE_ATHEROS_9271=y
+BR2_PACKAGE_LINUX_FIRMWARE_IWLWIFI_3160=y
+BR2_PACKAGE_LINUX_FIRMWARE_IWLWIFI_3168=y
+BR2_PACKAGE_LINUX_FIRMWARE_IWLWIFI_5000=y
+BR2_PACKAGE_LINUX_FIRMWARE_IWLWIFI_6000G2A=y
+BR2_PACKAGE_LINUX_FIRMWARE_IWLWIFI_6000G2B=y
+BR2_PACKAGE_LINUX_FIRMWARE_IWLWIFI_7260=y
+BR2_PACKAGE_LINUX_FIRMWARE_IWLWIFI_7265D=y
+BR2_PACKAGE_LINUX_FIRMWARE_IWLWIFI_8000C=y
+BR2_PACKAGE_LINUX_FIRMWARE_IWLWIFI_8265=y
+BR2_PACKAGE_LINUX_FIRMWARE_RALINK_RT73=y
+BR2_PACKAGE_LINUX_FIRMWARE_RALINK_RT2XX=y
+BR2_PACKAGE_LINUX_FIRMWARE_RTL_81XX=y
+BR2_PACKAGE_LINUX_FIRMWARE_RTL_87XX=y
+BR2_PACKAGE_LINUX_FIRMWARE_RTL_88XX=y
+BR2_PACKAGE_LINUX_FIRMWARE_RTL_8169=y
+BR2_PACKAGE_ACPID=y
+BR2_PACKAGE_CONNMAN=y
+BR2_PACKAGE_CONNMAN_WIFI=y
+BR2_PACKAGE_CONNMAN_CLIENT=y
+BR2_PACKAGE_WIRELESS_REGDB=y
+BR2_TARGET_ROOTFS_EXT2=y
+BR2_TARGET_ROOTFS_EXT2_4=y
+BR2_TARGET_ROOTFS_EXT2_SIZE="120M"
+# BR2_TARGET_ROOTFS_TAR is not set
+BR2_TARGET_EFIBOOTGUARD=y
+BR2_TARGET_EFIBOOTGUARD_X86_64=y
+BR2_TARGET_EFIBOOTGUARD_INSTALL_TOOLS=y
+BR2_TARGET_HOST_EFIBOOTGUARD=y
+BR2_PACKAGE_HOST_DOSFSTOOLS=y
+BR2_PACKAGE_HOST_GENIMAGE=y
+BR2_PACKAGE_HOST_MTOOLS=y
--
2.53.0