fix(dracut.sh): use dynamically uefi's sections offset

This commit is contained in:
Lukas Nykryn 2023-08-02 12:28:18 +02:00
parent 6aee126537
commit 7341377917
2 changed files with 151 additions and 1 deletions

View File

@ -0,0 +1,143 @@
From ec6972ab724c23edb47394e1211c4d3dc635ea8f Mon Sep 17 00:00:00 2001
From: Valentin Lefebvre <valentin.lefebvre@suse.com>
Date: Mon, 13 Mar 2023 12:06:13 +0100
Subject: [PATCH] fix(dracut.sh): use dynamically uefi's sections offset
* Uefi section are creating by `objcopy` with hardcoded sections
offset. This commit allow to have the correct offset between
each part of the efi file, needed to create an UKI. Offsets
are simply calculated so no sections overlap, as recommended
in https://wiki.archlinux.org/title/Unified_kernel_image#Manually
Moreover, efi stub file's header is parsed to apply the correct
offsets according the section alignment factor.
* Remove EFI_SECTION_VMA_INITRD, no need anymore as initrd
section offset dynamically calculated
Fixes dracutdevs#2275
Signed-off-by: Valentin Lefebvre <valentin.lefebvre@suse.com>
---
dracut-functions.sh | 23 +++++++++++++++++++++++
dracut.sh | 45 +++++++++++++++++++++++++++++++++++----------
2 files changed, 58 insertions(+), 10 deletions(-)
diff --git a/dracut-functions.sh b/dracut-functions.sh
index 280e4e7..78547f3 100755
--- a/dracut-functions.sh
+++ b/dracut-functions.sh
@@ -1011,3 +1011,26 @@ 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" \
+ | awk '{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 the sectionAlignment data from the PE header
+pe_get_section_align() {
+ local align_hex
+ [[ $# -ne "1" ]] && return 1
+ [[ $(pe_file_format "$1") -eq 1 ]] && return 1
+ align_hex=$(objdump -p "$1" \
+ | awk '{if ($1 == "SectionAlignment"){print $2}}')
+ echo "$((16#$align_hex))"
+}
diff --git a/dracut.sh b/dracut.sh
index 031dd85..f42ef89 100755
--- a/dracut.sh
+++ b/dracut.sh
@@ -1447,7 +1447,6 @@ if [[ ! $print_cmdline ]]; then
exit 1
fi
unset EFI_MACHINE_TYPE_NAME
- EFI_SECTION_VMA_INITRD=0x3000000
case "${DRACUT_ARCH:-$(uname -m)}" in
x86_64)
EFI_MACHINE_TYPE_NAME=x64
@@ -1457,8 +1456,6 @@ if [[ ! $print_cmdline ]]; then
;;
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 '${DRACUT_ARCH:-$(uname -m)}' not supported to create a UEFI executable"
@@ -2617,29 +2614,57 @@ if [[ $uefi == yes ]]; then
fi
fi
+ offs=$(objdump -h "$uefi_stub" 2> /dev/null | awk 'NF==7 {size=strtonum("0x"$3);\
+ 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 && -e "${uefi_outdir}/cmdline.txt" ]]; 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}"
+
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")" \
"$uefi_stub" "${uefi_outdir}/linux.efi"; then
if [[ -n ${uefi_secureboot_key} && -n ${uefi_secureboot_cert} ]]; then
if sbsign \
--
2.39.2

View File

@ -7,7 +7,7 @@
%global __requires_exclude pkg-config
# rpmdev-bumpspec and releng automation compatible variable
%global baserelease 10
%global baserelease 11
Name: dracut
Version: 059
@ -70,6 +70,10 @@ Patch9: 2377-fix-kernel-modules-add-interconnect-drivers.patch
# https://github.com/dracutdevs/dracut/pull/2184
Patch10: 2184-add-nvmeof-module.patch
# fix(dracut.sh): use dynamically uefi's sections offset
# https://github.com/dracutdevs/dracut/pull/2277
Patch11: 0001-fix-dracut.sh-use-dynamically-uefi-s-sections-offset.patch
BuildRequires: bash
BuildRequires: git-core
BuildRequires: pkgconfig(libkmod) >= 23
@ -476,6 +480,9 @@ echo 'dracut_rescue_image="yes"' > $RPM_BUILD_ROOT%{dracutlibdir}/dracut.conf.d/
%{_prefix}/lib/kernel/install.d/51-dracut-rescue.install
%changelog
* Mon Jul 24 2023 Lukáš Nykrýn <lnykryn@redhat.com> - 059-11
- fix(dracut.sh): use dynamically uefi's sections offset
* Mon Jul 24 2023 Pavel Valena <pvalena@redhat.com> - 059-10
- feat(nvmf): support for NVMeoF