Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(#2180787) Dynamically calculate UEFI sections offset #63

Merged
merged 3 commits into from
Jul 24, 2023
Merged
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 dracut-functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -995,3 +995,44 @@ get_dev_module() {
fi
echo "$dev_drivers"
}

# Check if file is in PE format
pe_file_format() {
if [[ $# -eq 1 ]]; then
local magic
magic=$(objdump -p "$1" \
| gawk '{if ($1 == "Magic"){print strtonum("0x"$2)}}')
magic=$(printf "0x%x" "$magic")
# 0x10b (PE32), 0x20b (PE32+)
[[ $magic == 0x20b || $magic == 0x10b ]] && return 0
fi
return 1
}

# Get specific data from the PE header
pe_get_header_data() {
local data_header
[[ $# -ne "2" ]] && return 1
[[ $(pe_file_format "$1") -eq 1 ]] && return 1
data_header=$(objdump -p "$1" \
| awk -v data="$2" '{if ($1 == data){print $2}}')
echo "$data_header"
}

# Get the SectionAlignment data from the PE header
pe_get_section_align() {
local align_hex
[[ $# -ne "1" ]] && return 1
align_hex=$(pe_get_header_data "$1" "SectionAlignment")
[[ $? -eq 1 ]] && return 1
echo "$((16#$align_hex))"
}

# Get the ImageBase data from the PE header
pe_get_image_base() {
local base_image
[[ $# -ne "1" ]] && return 1
base_image=$(pe_get_header_data "$1" "ImageBase")
[[ $? -eq 1 ]] && return 1
echo "$((16#$base_image))"
}
52 changes: 42 additions & 10 deletions dracut.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1433,7 +1433,6 @@
exit 1
fi
unset EFI_MACHINE_TYPE_NAME
EFI_SECTION_VMA_INITRD=0x3000000
case $(uname -m) in
x86_64)
EFI_MACHINE_TYPE_NAME=x64
Expand All @@ -1443,8 +1442,6 @@
;;
aarch64)
EFI_MACHINE_TYPE_NAME=aa64
# aarch64 kernels are uncompressed and thus larger, so we need a bigger gap between vma sections
EFI_SECTION_VMA_INITRD=0x4000000
;;
*)
dfatal "Architecture '$(uname -m)' not supported to create a UEFI executable"
Expand Down Expand Up @@ -2596,29 +2593,64 @@
done
fi

offs=$(objdump -h "$uefi_stub" 2> /dev/null | gawk 'NF==7 {size=strtonum("0x"$3);\
Dismissed Show dismissed Hide dismissed
offset=strtonum("0x"$4)} END {print size + offset}')
if [[ $offs -eq 0 ]]; then
dfatal "Failed to get the size of $uefi_stub to create UEFI image file"
exit 1
fi
align=$(pe_get_section_align "$uefi_stub")
if [[ $? -eq 1 ]]; then
dfatal "Failed to get the SectionAlignment of the stub PE header to create the UEFI image file"
exit 1
fi
offs=$((offs + "$align" - offs % "$align"))
[[ -s $dracutsysrootdir/usr/lib/os-release ]] && uefi_osrelease="$dracutsysrootdir/usr/lib/os-release"
[[ -s $dracutsysrootdir/etc/os-release ]] && uefi_osrelease="$dracutsysrootdir/etc/os-release"
[[ -s $uefi_osrelease ]] \
&& uefi_osrelease_offs=${offs} \
&& offs=$((offs + $(stat -Lc%s "$uefi_osrelease"))) \
&& offs=$((offs + "$align" - offs % "$align"))

if [[ $kernel_cmdline ]] || [[ $hostonly_cmdline == yes && -d "$initdir/etc/cmdline.d" ]]; then
echo -ne "\x00" >> "$uefi_outdir/cmdline.txt"
dinfo "Using UEFI kernel cmdline:"
dinfo "$(tr -d '\000' < "$uefi_outdir/cmdline.txt")"
uefi_cmdline="${uefi_outdir}/cmdline.txt"
uefi_cmdline_offs=${offs}
offs=$((offs + $(stat -Lc%s "$uefi_cmdline")))
offs=$((offs + "$align" - offs % "$align"))
else
unset uefi_cmdline
fi

[[ -s $dracutsysrootdir/usr/lib/os-release ]] && uefi_osrelease="$dracutsysrootdir/usr/lib/os-release"
[[ -s $dracutsysrootdir/etc/os-release ]] && uefi_osrelease="$dracutsysrootdir/etc/os-release"
if [[ -s ${dracutsysrootdir}${uefi_splash_image} ]]; then
uefi_splash_image="${dracutsysrootdir}${uefi_splash_image}"
uefi_splash_offs=${offs}
offs=$((offs + $(stat -Lc%s "$uefi_splash_image")))
offs=$((offs + "$align" - offs % "$align"))
else
unset uefi_splash_image
fi

uefi_linux_offs="${offs}"
offs=$((offs + $(stat -Lc%s "$kernel_image")))
offs=$((offs + "$align" - offs % "$align"))
uefi_initrd_offs="${offs}"

base_image=$(pe_get_image_base "$uefi_stub")
if [[ $? -eq 1 ]]; then
dfatal "Failed to get ImageBase data of $uefi_stub to create UEFI image file"
exit 1
fi

if objcopy \
${uefi_osrelease:+--add-section .osrel="$uefi_osrelease" --change-section-vma .osrel=0x20000} \
${uefi_cmdline:+--add-section .cmdline="$uefi_cmdline" --change-section-vma .cmdline=0x30000} \
${uefi_splash_image:+--add-section .splash="$uefi_splash_image" --change-section-vma .splash=0x40000} \
--add-section .linux="$kernel_image" --change-section-vma .linux=0x2000000 \
--add-section .initrd="${DRACUT_TMPDIR}/initramfs.img" --change-section-vma .initrd="${EFI_SECTION_VMA_INITRD}" \
${uefi_osrelease:+--add-section .osrel="$uefi_osrelease" --change-section-vma .osrel=$(printf 0x%x "$uefi_osrelease_offs")} \
${uefi_cmdline:+--add-section .cmdline="$uefi_cmdline" --change-section-vma .cmdline=$(printf 0x%x "$uefi_cmdline_offs")} \
${uefi_splash_image:+--add-section .splash="$uefi_splash_image" --change-section-vma .splash=$(printf 0x%x "$uefi_splash_offs")} \
--add-section .linux="$kernel_image" --change-section-vma .linux="$(printf 0x%x "$uefi_linux_offs")" \
--add-section .initrd="${DRACUT_TMPDIR}/initramfs.img" --change-section-vma .initrd="$(printf 0x%x "$uefi_initrd_offs")" \
--image-base="$(printf 0x%x "$base_image")" \
"$uefi_stub" "${uefi_outdir}/linux.efi"; then
if [[ -n ${uefi_secureboot_key} && -n ${uefi_secureboot_cert} ]]; then
if sbsign \
Expand Down
Loading