Skip to content

Commit ace1403

Browse files
committed
Replace ukify with objcopy for UKI creation to fix overlapping PE sections
- Replace ukify with manual objcopy implementation to avoid overlapping PE sections that cause "Boot may fail due to image memory corruption!" errors - Extract UKI build logic into separate bash script (hack/uki/build-uki.sh) for better maintainability - Calculate section offsets dynamically to ensure proper alignment - Remove ukify dependency from build container, add binutils for objcopy - Update documentation to reflect the change from ukify to objcopy This resolves boot failures caused by memory corruption from overlapping PE sections in the generated UKI files.
1 parent d9e1833 commit ace1403

File tree

4 files changed

+57
-12
lines changed

4 files changed

+57
-12
lines changed

docs/boot-image/uki.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ Unified Kernel Images
22
=====================
33

44
Have a look at the [Arch Documentation - Unified Kernel Images](https://wiki.archlinux.org/title/Unified_kernel_image).
5-
It also describes how to build a UKI with `objcopy` instead of `ukify`.
5+
6+
FeOS uses `objcopy` to build UKIs instead of `ukify` to avoid overlapping PE sections that can cause boot failures. The UKI creation process dynamically calculates section offsets to ensure proper alignment and prevent memory corruption.
67

78
## Boot from USB Stick
89
Booting FeOS from USB is quite easy. You just need to prepare a USB stick with a bootable UEFI partition and insert the FeOS UKI.

hack/build-container/Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ RUN apt-get update && apt-get upgrade -y && apt-get install -y \
77
ninja-build \
88
protobuf-compiler \
99
libprotobuf-dev \
10-
sbsigntool python3-pefile systemd-boot \
10+
sbsigntool systemd-boot \
1111
musl-tools \
12-
ca-certificates
12+
ca-certificates \
13+
binutils
1314

1415
RUN cargo new xyz; cd xyz; cargo fetch; cd ..; rm -rf xyz
1516
RUN rustup component add clippy
1617
RUN rustup component add rustfmt
1718
RUN rustup target add x86_64-unknown-linux-musl
1819
RUN mkdir /feos
1920
RUN mkdir /target
20-
RUN wget https://raw.githubusercontent.com/systemd/systemd/main/src/ukify/ukify.py -O /usr/bin/ukify && chmod +x /usr/bin/ukify
2121
WORKDIR /feos

hack/uki/build-uki.sh

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/bin/bash
2+
set -e
3+
4+
echo "Building UKI with objcopy..."
5+
6+
# Calculate section alignment from systemd stub
7+
echo "Calculating section offsets..."
8+
align="$(objdump -p /usr/lib/systemd/boot/efi/linuxx64.efi.stub | awk '/SectionAlignment/ {print $2}')"
9+
align_dec=$((16#$align))
10+
echo "Section alignment: $align ($align_dec bytes)"
11+
12+
# Calculate the end of the systemd stub to determine where our sections can start
13+
stub_size="$(objdump -h /usr/lib/systemd/boot/efi/linuxx64.efi.stub | tail -n +2 | awk '{if(NF==7) {size=$3; offset=$4; printf "%d\n", ("0x" size) + ("0x" offset)}}' | sort -n | tail -1)"
14+
15+
# Calculate properly aligned offsets for each section
16+
osrel_offs=$((stub_size + align_dec - stub_size % align_dec))
17+
cmdline_offs=$((osrel_offs + $(stat -Lc%s "/usr/lib/os-release")))
18+
cmdline_offs=$((cmdline_offs + align_dec - cmdline_offs % align_dec))
19+
initrd_offs=$((cmdline_offs + $(stat -Lc%s "/feos/target/cmdline")))
20+
initrd_offs=$((initrd_offs + align_dec - initrd_offs % align_dec))
21+
linux_offs=$((initrd_offs + $(stat -Lc%s "/feos/target/initramfs.zst")))
22+
linux_offs=$((linux_offs + align_dec - linux_offs % align_dec))
23+
24+
echo "Calculated offsets:"
25+
echo " .osrel: 0x$(printf %x $osrel_offs)"
26+
echo " .cmdline: 0x$(printf %x $cmdline_offs)"
27+
echo " .initrd: 0x$(printf %x $initrd_offs)"
28+
echo " .linux: 0x$(printf %x $linux_offs)"
29+
30+
# Create UKI using objcopy with calculated offsets
31+
echo "Creating UKI with objcopy..."
32+
objcopy \
33+
--add-section .osrel=/feos/hack/uki/os-release.txt \
34+
--change-section-vma .osrel=$(printf 0x%x $osrel_offs) \
35+
--add-section .cmdline=/feos/target/cmdline \
36+
--change-section-vma .cmdline=$(printf 0x%x $cmdline_offs) \
37+
--add-section .initrd=/feos/target/initramfs.zst \
38+
--change-section-vma .initrd=$(printf 0x%x $initrd_offs) \
39+
--add-section .linux=/feos/target/kernel/vmlinuz \
40+
--change-section-vma .linux=$(printf 0x%x $linux_offs) \
41+
/usr/lib/systemd/boot/efi/linuxx64.efi.stub /feos/target/uki.efi
42+
43+
# Sign the UKI with secureboot key
44+
echo "Signing UKI with secureboot key..."
45+
sbsign \
46+
--key /feos/keys/secureboot.key \
47+
--cert /feos/keys/secureboot.pem \
48+
--output /feos/target/uki.efi \
49+
/feos/target/uki.efi
50+
51+
echo "UKI created successfully at target/uki.efi"

hack/uki/make.mk

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,4 @@ keys:
77
openssl x509 -in keys/secureboot.pem -out keys/secureboot.der -outform DER
88

99
uki: keys
10-
docker run --rm -u $${UID} -v "`pwd`:/feos" feos-builder ukify build \
11-
--os-release @/feos/hack/uki/os-release.txt \
12-
--linux /feos/target/kernel/vmlinuz \
13-
--initrd /feos/target/initramfs.zst \
14-
--cmdline @/feos/target/cmdline \
15-
--secureboot-private-key /feos/keys/secureboot.key \
16-
--secureboot-certificate /feos/keys/secureboot.pem \
17-
--output /feos/target/uki.efi
10+
docker run --rm -u $${UID} -v "`pwd`:/feos" feos-builder /feos/hack/uki/build-uki.sh

0 commit comments

Comments
 (0)