mirror of
https://github.com/dracutdevs/dracut.git
synced 2024-10-26 16:25:20 +03:00
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>
This commit is contained in:
parent
e9b4774239
commit
f32e95bcad
@ -1023,3 +1023,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))"
|
||||
}
|
||||
|
45
dracut.sh
45
dracut.sh
@ -1506,7 +1506,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
|
||||
@ -1516,8 +1515,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"
|
||||
@ -2467,29 +2464,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 \
|
||||
|
Loading…
Reference in New Issue
Block a user