Skip to content

Instantly share code, notes, and snippets.

@gustingonzalez
Last active October 1, 2022 23:58
Show Gist options
  • Save gustingonzalez/d92338c63396f0a34b01d9da781735cb to your computer and use it in GitHub Desktop.
Save gustingonzalez/d92338c63396f0a34b01d9da781735cb to your computer and use it in GitHub Desktop.
Generates an EFI unified kernel image based on a systemd stub
#!/bin/bash
# Generates an EFI image based on a systemd stub.
OUTPUT_PATH=$1
OSREL_PATH=$2
CMDLINE_PATH=$3
SPLASH_PATH=$4
INITRD_PATH=$5
LINUX_PATH=$6
# List of components that must be placed into the image. Each pair of items
# refers to the name of the component and its associated path. IMPORTANT: these
# components will be incorporated in the order in which they appear here! The
# arrangement of each one is based on the comments in the following commit:
# https://github.com/systemd/systemd/commit/0fa2cac4f0cdefaf1addd7f1fe0fd8113db9360b.
ORDERED_EFI_ITEMS=(
"osrel" $OSREL_PATH
"cmdline" $CMDLINE_PATH
"splash" $SPLASH_PATH
"initrd" $INITRD_PATH
"linux" $LINUX_PATH
)
# systemd stub, used to build the image.
STUB=/usr/lib/systemd/boot/efi/linuxx64.efi.stub
# Based on the stub, computes the placement of the first EFI component.
LAST_STUB_COMPONENT_INFO=$(objdump -h $STUB | tail -2 | head -1)
LAST_STUB_COMPONENT_SIZE=0x$(echo "$LAST_STUB_COMPONENT_INFO" | awk '{print $3}')
LAST_STUB_COMPONENT_OFFSET=0x$(echo "$LAST_STUB_COMPONENT_INFO" | awk '{print $4}')
START_OFFSET=$(($LAST_STUB_COMPONENT_OFFSET + $LAST_STUB_COMPONENT_SIZE))
curr_offset=$START_OFFSET
for ((efi_item_number=0; efi_item_number<${#ORDERED_EFI_ITEMS[@]}; efi_item_number+=2)) ; do
efi_component_name=${ORDERED_EFI_ITEMS[$efi_item_number]}
efi_component_file=${ORDERED_EFI_ITEMS[$efi_item_number+1]}
# Creates a variable storing the offset (in hexa) of the current component.
# Its name is assigned based on the name of the latter. E.g., the variable
# indicating the 'linux' offset will be named 'linux_offset'.
declare "$efi_component_name"_offset=0x$(printf "%x\n" $curr_offset)
echo "The component '$efi_component_name' ('$efi_component_file') has been asigned to the section $curr_offset."
# Recalculates the offset to be used in the next component.
efi_component_size=$(stat -c%s $efi_component_file)
curr_offset=$(($curr_offset + $efi_component_size))
done
# Builds the EFI image with the specified stub and components.
objcopy \
--add-section .osrel=$OSREL_PATH --change-section-vma .osrel=$osrel_offset \
--add-section .cmdline=$CMDLINE_PATH --change-section-vma .cmdline=$cmdline_offset \
--add-section .splash=$SPLASH_PATH --change-section-vma .splash=$splash_offset \
--add-section .initrd=$INITRD_PATH --change-section-vma .initrd=$initrd_offset \
--add-section .linux=$LINUX_PATH --change-section-vma .linux=$linux_offset \
$STUB $OUTPUT_PATH
@gustingonzalez
Copy link
Author

Example of usage:
create-systemd-efi-image.sh BOOTx64.efi os-release.txt cmdline.txt splash.bmp initrd.lz vmlinuz

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment