From 9cc35234a5ddccc51bcd9dffc756490155f1355c Mon Sep 17 00:00:00 2001 From: Morten Linderud Date: Sun, 17 Nov 2019 15:58:38 +0100 Subject: [PATCH 01/12] [mkinitcpio] Create UEFI executables Implement UEFI executable generation in mkinitcpio by utilizing UEFI stubs provided by systemd/gummiboot. This allows us to create a unified boot image we can boot from UEFI with. These are practical for secure boot as we can sign initramfs, kernel cmdline and the kernel all at once. By utilizing the BOOT_LOADER_SPECIFICATION we can also drop new images into the correct patch and have systemd-boot/gummiboot pick up the images. The code does several things and does a fair amount of guessing to figure out all the inputs needed. We use `/etc/kernel/cmdline` to localize the kernel cmdline options we want for the image. This is inherited from the `kernel-install` hook system which might double as some form of standard. We also do a dance to get the correct kernel image. We do a lookup into /lib/modules and /boot for both versioned and unversioned kernels (mainly Arch Linux). There is an attempt to support both 32bit and 64bit lookup paths for the stub images, but only 64bit is tested. Gummiboot is also not tested. https://www.freedesktop.org/software/systemd/man/kernel-install.html https://systemd.io/BOOT_LOADER_SPECIFICATION/#type-2-efi-unified-kernel-images Signed-off-by: Morten Linderud --- mkinitcpio | 111 +++++++++++++++++++++++++++++++++++- mkinitcpio.d/example.preset | 3 + 2 files changed, 112 insertions(+), 2 deletions(-) diff --git a/mkinitcpio b/mkinitcpio index 1f6a499b..da1d8cd9 100755 --- a/mkinitcpio +++ b/mkinitcpio @@ -22,6 +22,8 @@ _d_presets=mkinitcpio.d # options and runtime data _optmoduleroot= _optgenimg= _optcompress= _opttargetdir= +_optosrelease="/usr/lib/os-release" +_optuefi= _optmicrocode= _optcmdline= _optsplash= _optkernelimage= _optuefistub= _optshowautomods=0 _optsavetree=0 _optshowmods=0 _optquiet=1 _optcolor=1 _optskiphooks=() _optaddhooks=() _hooks=() _optpreset=() @@ -44,6 +46,7 @@ usage: ${0##*/} [options] Options: -A, --addhooks Add specified hooks, comma separated, to image -c, --config Use alternate config file. (default: /etc/mkinitcpio.conf) + -C, --cmdline Set kernel line. (default content: /etc/kernel/cmdline, /proc/cmdline) -g, --generate Generate cpio image and write to specified path -H, --hookhelp Display help for given hook and exit -h, --help Display this message and exit @@ -59,6 +62,12 @@ usage: ${0##*/} [options] -d, --generatedir Write generated image into -t, --builddir Use DIR as the temporary build directory -D, --hookdir Specify where to look for hooks. + -U, --uefi Build EFI image + -m, --microcode Location of microcode for UEFI executable + -R, --osrelease Include os-release (default: /usr/lib/os-release) + -l, --splash Include bitmap splash for UEFI executable + -i, --kernelimage Kernel image for UEFI executable + -I, --uefistub Location of UEFI stub loader -V, --version Display version information and exit -v, --verbose Verbose output (default: no) -z, --compress Use an alternate compressor on the image @@ -251,6 +260,56 @@ build_image() { fi } +build_uefi(){ + set -x + local out=$1 microcode=$2 initramfs=$3 cmdline=$4 osrelease=$5 splash=$6 kernelimg=$7 uefistub=$8 errmsg= + OBJCOPYARGS=() + + if [[ -z "$uefistub" ]]; then + for stub in {/usr,}/lib/systemd/boot/efi/linux{x64,ia32}.efi.stub {/usr,}/lib/gummiboot/linux{x64,ia32}.efi.stub; do + if [[ -f "$stub" ]]; then + uefistub="$stub" + break + fi + done + fi + + if [[ -z "$kernelimg" ]]; then + for img in "/lib/modules/$KERNELIMAGE" "/boot/vmlinuz-$KERNELIMAGE" "/boot/vmlinuz-linuz"; do + if [[ -f "$img" ]]; then + KERNELIMAGE="$img" + break + fi + done + fi + + if [[ -z "$cmdline" ]]; then + if [[ -f "/etc/kernel/cmdline" ]]; then + cmdline="/etc/kernel/cmdline" + else + cmdline="/proc/cmdline" + fi + fi + + if [[ -n "$splash" ]]; then + OBJCOPYARGS+=("--add-section .splash=$splash --change-section-vma .splash=0x40000") + fi + msg "Creating EFI image: %s" "$out" + objcopy \ + --add-section .osrel="$osrelease" --change-section-vma .osrel=0x20000 \ + --add-section .cmdline="$cmdline" --change-section-vma .cmdline=0x30000 \ + --add-section .linux="$kernelimg" --change-section-vma .linux=0x2000000 \ + --add-section .initrd=<(cat "$microcode" "$initramfs" ) --change-section-vma .initrd=0x3000000 \ + ${OBJCOPYARGS[@]} "$uefistub" "$out" + + status=$? + if (( $status )) ; then + error "EFI image generation FAILED" + else + msg "EFI image generation successful" + fi +} + process_preset() ( local preset=$1 preset_image= preset_options= local -a preset_mkopts preset_cmd @@ -307,6 +366,16 @@ process_preset() ( preset_cmd+=(${!preset_options}) # intentional word splitting fi + preset_efi_image=${p}_efi_image + if [[ ${!preset_efi_image:-$ALL_efi_image} ]]; then + preset_cmd+=(-U "${!preset_efi_image:-$ALL_efi_image}") + fi + + preset_microcode=${p}_microcode + if [[ ${!preset_microcode:-$ALL_microcode} ]]; then + preset_cmd+=(-m "${!preset_microcode:-$ALL_microcode}") + fi + msg2 "${preset_cmd[*]}" MKINITCPIO_PROCESS_PRESET=1 "$0" "${preset_cmd[@]}" (( $? )) && ret=1 @@ -345,10 +414,11 @@ preload_builtin_modules() { trap 'cleanup 130' INT trap 'cleanup 143' TERM -_opt_short='A:c:D:g:H:hk:nLMPp:r:S:sd:t:Vvz:' +_opt_short='A:c:D:g:H:hk:I:i:nLl:Mm:Pp:r:S:sd:t:U:Vvz:' _opt_long=('add:' 'addhooks:' 'config:' 'generate:' 'hookdir': 'hookhelp:' 'help' 'kernel:' 'listhooks' 'automods' 'moduleroot:' 'nocolor' 'allpresets' - 'preset:' 'skiphooks:' 'save' 'generatedir:' 'builddir:' 'version' 'verbose' 'compress:') + 'preset:' 'skiphooks:' 'save' 'generatedir:' 'builddir:' 'version' 'verbose' 'compress:' + 'uefi:' 'microcode:' 'splash:' 'kernelimage:' 'uefistub:') parseopts "$_opt_short" "${_opt_long[@]}" -- "$@" || exit 1 set -- "${OPTRET[@]}" @@ -367,6 +437,10 @@ while :; do shift _f_config=$1 ;; + -C|--cmdline) + shift + _optcmdline=$1 + ;; -k|--kernel) shift KERNELVERSION=$1 @@ -400,6 +474,13 @@ while :; do -n|--nocolor) _optcolor=0 ;; + -U|--uefi) + shift + [[ -d $1 ]] && die "Invalid image path -- must not be a directory" + if ! _optuefi=$(readlink -f "$1") || [[ ! -e ${_optgenimg%/*} ]]; then + die "Unable to write to path: \`%s'" "$1" + fi + ;; -v|--verbose) _optquiet=0 ;; @@ -418,13 +499,35 @@ while :; do hook_list exit 0 ;; + -l|--splash) + shift + [[ -f $1 ]] || die "Invalid file -- must be a file" + _optsplash=$1 + ;; + -i|--kernelimage) + shift + _optkernelimage=$1 + ;; + -I|--uefistub) + shift + _optkernelimage=$1 + ;; -M|--automods) _optshowautomods=1 ;; + -m|--microcode) + shift + _optmicrocode=$1 + ;; -P|--allpresets) _optpreset=("$_d_presets"/*.preset) [[ -e ${_optpreset[0]} ]] || die "No presets found in $_d_presets" ;; + -R|--osrelease) + shift + [[ ! -f $1 ]] && die "Invalid file -- must be a file" + _optosrelease=$1 + ;; -t|--builddir) shift export TMPDIR=$1 @@ -556,6 +659,10 @@ else msg "Dry run complete, use -g IMAGE to generate a real image" fi +if [[ $_optuefi && $_optgenimg ]]; then + build_uefi "$_optuefi" "$_optmicrocode" "$_optgenimg" "$_optcmdline" "$_optosrelease" "$_optkernelimage" "$_optsplash" "$_optuefistub" +fi + cleanup $(( !!_builderrors )) # vim: set ft=sh ts=4 sw=4 et: diff --git a/mkinitcpio.d/example.preset b/mkinitcpio.d/example.preset index a0479d22..341d57d0 100644 --- a/mkinitcpio.d/example.preset +++ b/mkinitcpio.d/example.preset @@ -8,6 +8,7 @@ PRESETS=('default' 'fallback') # as the path to an kernel image. ALL_kver='/boot/vmlinuz-linux' ALL_config='/etc/mkinitcpio.conf' +ALL_microcode="/boot/intel-ucode.img" # presetname_kver - the kernel version (omit if ALL_kver should be used) # presetname_config - the configuration file (omit if ALL_config should be used) @@ -17,9 +18,11 @@ ALL_config='/etc/mkinitcpio.conf' #default_kver="3.0-ARCH" #default_config="/etc/mkinitcpio.conf" default_image="/tmp/initramfs-linux.img" +default_efi_image="/efi/EFI/Linux/linux.efi" default_options="" #fallback_kver="3.0-ARCH" #fallback_config="/etc/mkinitcpio.conf" fallback_image="/tmp/initramfs-linux-fallback.img" +fallback_efi_image="/efi/EFI/Linux/linux-fallback.efi" fallback_options="-S autodetect" From 4d29a7e208856d0d98a92b010476a5ed2bbb5aae Mon Sep 17 00:00:00 2001 From: Morten Linderud Date: Tue, 6 Apr 2021 20:54:01 +0200 Subject: [PATCH 02/12] fixup! [mkinitcpio] Create UEFI executables Signed-off-by: Morten Linderud --- mkinitcpio | 56 ++++++++++++++++++++++++++----------- mkinitcpio.d/example.preset | 2 +- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/mkinitcpio b/mkinitcpio index da1d8cd9..dd15585f 100755 --- a/mkinitcpio +++ b/mkinitcpio @@ -22,8 +22,8 @@ _d_presets=mkinitcpio.d # options and runtime data _optmoduleroot= _optgenimg= _optcompress= _opttargetdir= -_optosrelease="/usr/lib/os-release" -_optuefi= _optmicrocode= _optcmdline= _optsplash= _optkernelimage= _optuefistub= +_optosrelease="/etc/os-release" +_optuefi= _optmicrocode=() _optcmdline= _optsplash= _optkernelimage= _optuefistub= _optshowautomods=0 _optsavetree=0 _optshowmods=0 _optquiet=1 _optcolor=1 _optskiphooks=() _optaddhooks=() _hooks=() _optpreset=() @@ -261,52 +261,73 @@ build_image() { } build_uefi(){ - set -x - local out=$1 microcode=$2 initramfs=$3 cmdline=$4 osrelease=$5 splash=$6 kernelimg=$7 uefistub=$8 errmsg= + local out=$1 initramfs=$2 cmdline=$3 osrelease=$4 splash=$5 kernelimg=$6 uefistub=$7 microcode=(${@:7}) errmsg= OBJCOPYARGS=() + msg "Creating UEFI executable: %s" "$out" + if [[ -z "$uefistub" ]]; then for stub in {/usr,}/lib/systemd/boot/efi/linux{x64,ia32}.efi.stub {/usr,}/lib/gummiboot/linux{x64,ia32}.efi.stub; do if [[ -f "$stub" ]]; then uefistub="$stub" + msg2 "Using UEFI stub: %s" "$uefistub" break fi done + elif [[ ! -f "$uefisub" ]]; then + error "UEFI stub '%s' not found" "$uefistub" + return 1 fi if [[ -z "$kernelimg" ]]; then - for img in "/lib/modules/$KERNELIMAGE" "/boot/vmlinuz-$KERNELIMAGE" "/boot/vmlinuz-linuz"; do + for img in "/lib/modules/$KERNELVERSION/vmlinuz" "/boot/vmlinuz-$KERNELVERSION" "/boot/vmlinuz-linux"; do if [[ -f "$img" ]]; then - KERNELIMAGE="$img" + kernelimg="$img" + msg2 "Using kernel image: %s" "$kernelimg" break fi done fi + if [[ ! -f "$kernelimg" ]]; then + error "Kernel image '%s' not found" "$kernelimage" + return 1 + fi if [[ -z "$cmdline" ]]; then if [[ -f "/etc/kernel/cmdline" ]]; then cmdline="/etc/kernel/cmdline" + elif [[ -f "/usr/lib/kernel/cmdline" ]]; then + cmdline="/usr/lib/kernel/cmdline" else cmdline="/proc/cmdline" fi + msg2 "Using cmdline file %s" "$cmdline" + fi + if [[ ! -f "$cmdline" ]]; then + error "Kernel cmdline file '%s' not found" "$cmdline" + return 1 + fi + + if [[ -z "$initramfs" ]]; then + error "Initramfs '%s' not found" "$initramfs" + return 1 fi if [[ -n "$splash" ]]; then - OBJCOPYARGS+=("--add-section .splash=$splash --change-section-vma .splash=0x40000") + OBJCOPYARGS+=(--add-section .splash="$splash" --change-section-vma .splash=0x40000) fi - msg "Creating EFI image: %s" "$out" objcopy \ --add-section .osrel="$osrelease" --change-section-vma .osrel=0x20000 \ --add-section .cmdline="$cmdline" --change-section-vma .cmdline=0x30000 \ --add-section .linux="$kernelimg" --change-section-vma .linux=0x2000000 \ - --add-section .initrd=<(cat "$microcode" "$initramfs" ) --change-section-vma .initrd=0x3000000 \ + --add-section .initrd=<(cat ${microcode[@]} "$initramfs") --change-section-vma .initrd=0x3000000 \ ${OBJCOPYARGS[@]} "$uefistub" "$out" status=$? if (( $status )) ; then - error "EFI image generation FAILED" + error "UEFI executable generation FAILED" else - msg "EFI image generation successful" + msg "UEFI executable generation successful" fi } @@ -371,11 +392,12 @@ process_preset() ( preset_cmd+=(-U "${!preset_efi_image:-$ALL_efi_image}") fi - preset_microcode=${p}_microcode + preset_microcode=${p}_microcode[@] if [[ ${!preset_microcode:-$ALL_microcode} ]]; then - preset_cmd+=(-m "${!preset_microcode:-$ALL_microcode}") + for mc in "${!preset_microcode:-${ALL_microcode[@]}}"; do + preset_cmd+=(-m "$mc") + done fi - msg2 "${preset_cmd[*]}" MKINITCPIO_PROCESS_PRESET=1 "$0" "${preset_cmd[@]}" (( $? )) && ret=1 @@ -414,7 +436,7 @@ preload_builtin_modules() { trap 'cleanup 130' INT trap 'cleanup 143' TERM -_opt_short='A:c:D:g:H:hk:I:i:nLl:Mm:Pp:r:S:sd:t:U:Vvz:' +_opt_short='A:C:c:D:g:H:hk:I:i:nLl:Mm:Pp:R:r:S:sd:t:U:Vvz:' _opt_long=('add:' 'addhooks:' 'config:' 'generate:' 'hookdir': 'hookhelp:' 'help' 'kernel:' 'listhooks' 'automods' 'moduleroot:' 'nocolor' 'allpresets' 'preset:' 'skiphooks:' 'save' 'generatedir:' 'builddir:' 'version' 'verbose' 'compress:' @@ -517,7 +539,7 @@ while :; do ;; -m|--microcode) shift - _optmicrocode=$1 + _optmicrocode+=($1) ;; -P|--allpresets) _optpreset=("$_d_presets"/*.preset) @@ -660,7 +682,7 @@ else fi if [[ $_optuefi && $_optgenimg ]]; then - build_uefi "$_optuefi" "$_optmicrocode" "$_optgenimg" "$_optcmdline" "$_optosrelease" "$_optkernelimage" "$_optsplash" "$_optuefistub" + build_uefi "$_optuefi" "$_optgenimg" "$_optcmdline" "$_optosrelease" "$_optsplash" "$_optkernelimage" "$_optuefistub" "${_optmicrocode[@]}" fi cleanup $(( !!_builderrors )) diff --git a/mkinitcpio.d/example.preset b/mkinitcpio.d/example.preset index 341d57d0..3fb1db17 100644 --- a/mkinitcpio.d/example.preset +++ b/mkinitcpio.d/example.preset @@ -8,7 +8,7 @@ PRESETS=('default' 'fallback') # as the path to an kernel image. ALL_kver='/boot/vmlinuz-linux' ALL_config='/etc/mkinitcpio.conf' -ALL_microcode="/boot/intel-ucode.img" +ALL_microcode=(/boot/*-ucode.img) # presetname_kver - the kernel version (omit if ALL_kver should be used) # presetname_config - the configuration file (omit if ALL_config should be used) From 9f738410688ba7c9a1298704e7b5ad9dc67e905d Mon Sep 17 00:00:00 2001 From: Morten Linderud Date: Tue, 6 Apr 2021 20:59:56 +0200 Subject: [PATCH 03/12] fixup! fixup! [mkinitcpio] Create UEFI executables Signed-off-by: Morten Linderud --- mkinitcpio | 4 +++- mkinitcpio.d/example.preset | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mkinitcpio b/mkinitcpio index dd15585f..18a99f52 100755 --- a/mkinitcpio +++ b/mkinitcpio @@ -267,7 +267,7 @@ build_uefi(){ msg "Creating UEFI executable: %s" "$out" if [[ -z "$uefistub" ]]; then - for stub in {/usr,}/lib/systemd/boot/efi/linux{x64,ia32}.efi.stub {/usr,}/lib/gummiboot/linux{x64,ia32}.efi.stub; do + for stub in {/usr,}/lib/{systemd/boot/efi,gummiboot}/linux{x64,ia32}.efi.stub; do if [[ -f "$stub" ]]; then uefistub="$stub" msg2 "Using UEFI stub: %s" "$uefistub" @@ -299,7 +299,9 @@ build_uefi(){ elif [[ -f "/usr/lib/kernel/cmdline" ]]; then cmdline="/usr/lib/kernel/cmdline" else + warning "Note: /etc/kernel/cmdline does not exist and --cmdline is unset!" cmdline="/proc/cmdline" + warning "Reusing current kernel cmdline from $cmdline" fi msg2 "Using cmdline file %s" "$cmdline" fi diff --git a/mkinitcpio.d/example.preset b/mkinitcpio.d/example.preset index 3fb1db17..d46a074b 100644 --- a/mkinitcpio.d/example.preset +++ b/mkinitcpio.d/example.preset @@ -18,11 +18,11 @@ ALL_microcode=(/boot/*-ucode.img) #default_kver="3.0-ARCH" #default_config="/etc/mkinitcpio.conf" default_image="/tmp/initramfs-linux.img" -default_efi_image="/efi/EFI/Linux/linux.efi" +default_efi_image="/efi/EFI/Linux/arch-linux.efi" default_options="" #fallback_kver="3.0-ARCH" #fallback_config="/etc/mkinitcpio.conf" fallback_image="/tmp/initramfs-linux-fallback.img" -fallback_efi_image="/efi/EFI/Linux/linux-fallback.efi" +fallback_efi_image="/efi/EFI/Linux/arch-linux-fallback.efi" fallback_options="-S autodetect" From 2acb0cbfce277f89052f887c18a635ac7af489e4 Mon Sep 17 00:00:00 2001 From: Morten Linderud Date: Thu, 8 Apr 2021 01:04:40 +0200 Subject: [PATCH 04/12] fixup! fixup! fixup! [mkinitcpio] Create UEFI executables Signed-off-by: Morten Linderud --- mkinitcpio | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mkinitcpio b/mkinitcpio index 18a99f52..ce7792f0 100755 --- a/mkinitcpio +++ b/mkinitcpio @@ -61,8 +61,8 @@ usage: ${0##*/} [options] -s, --save Save build directory. (default: no) -d, --generatedir Write generated image into -t, --builddir Use DIR as the temporary build directory - -D, --hookdir Specify where to look for hooks. - -U, --uefi Build EFI image + -D, --hookdir Specify where to look for hooks + -U, --uefi Build an UEFI executable -m, --microcode Location of microcode for UEFI executable -R, --osrelease Include os-release (default: /usr/lib/os-release) -l, --splash Include bitmap splash for UEFI executable @@ -501,7 +501,7 @@ while :; do -U|--uefi) shift [[ -d $1 ]] && die "Invalid image path -- must not be a directory" - if ! _optuefi=$(readlink -f "$1") || [[ ! -e ${_optgenimg%/*} ]]; then + if ! _optuefi=$(readlink -f "$1") || [[ ! -e ${_optuefi%/*} ]]; then die "Unable to write to path: \`%s'" "$1" fi ;; From 0e6c8d35cad28f2562184b80f1e29223bb38e3f1 Mon Sep 17 00:00:00 2001 From: Morten Linderud Date: Mon, 12 Apr 2021 00:21:26 +0200 Subject: [PATCH 05/12] fixup! fixup! fixup! fixup! [mkinitcpio] Create UEFI executables Signed-off-by: Morten Linderud --- mkinitcpio | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/mkinitcpio b/mkinitcpio index ce7792f0..e7a8967d 100755 --- a/mkinitcpio +++ b/mkinitcpio @@ -22,7 +22,7 @@ _d_presets=mkinitcpio.d # options and runtime data _optmoduleroot= _optgenimg= _optcompress= _opttargetdir= -_optosrelease="/etc/os-release" +_optosrelease= _optuefi= _optmicrocode=() _optcmdline= _optsplash= _optkernelimage= _optuefistub= _optshowautomods=0 _optsavetree=0 _optshowmods=0 _optquiet=1 _optcolor=1 @@ -64,7 +64,7 @@ usage: ${0##*/} [options] -D, --hookdir Specify where to look for hooks -U, --uefi Build an UEFI executable -m, --microcode Location of microcode for UEFI executable - -R, --osrelease Include os-release (default: /usr/lib/os-release) + -R, --osrelease Include os-release (default: /etc/os-release) -l, --splash Include bitmap splash for UEFI executable -i, --kernelimage Kernel image for UEFI executable -I, --uefistub Location of UEFI stub loader @@ -310,6 +310,19 @@ build_uefi(){ return 1 fi + if [[ -z "$osrelease" ]]; then + if [[ -f "/etc/os-release" ]]; then + osrelease="/etc/os-release" + elif [[ -f "/usr/lib/os-release" ]]; then + osrelease="/usr/lib/os-release" + fi + msg2 "Using os-release file %s" "$osrelease" + fi + if [[ ! -f "$osrelease" ]]; then + error "os-release file '%s' not found" "$osrelease" + return 1 + fi + if [[ -z "$initramfs" ]]; then error "Initramfs '%s' not found" "$initramfs" return 1 From 655f3085fa1f12be765b4baa346c4f5cbe04c9b2 Mon Sep 17 00:00:00 2001 From: Morten Linderud Date: Mon, 12 Apr 2021 00:21:38 +0200 Subject: [PATCH 06/12] fixup! fixup! fixup! fixup! fixup! [mkinitcpio] Create UEFI executables Signed-off-by: Morten Linderud --- mkinitcpio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkinitcpio b/mkinitcpio index e7a8967d..0111f809 100755 --- a/mkinitcpio +++ b/mkinitcpio @@ -333,7 +333,7 @@ build_uefi(){ fi objcopy \ --add-section .osrel="$osrelease" --change-section-vma .osrel=0x20000 \ - --add-section .cmdline="$cmdline" --change-section-vma .cmdline=0x30000 \ + --add-section .cmdline=<(grep '^[^#]' "$cmdline" | tr -s '\n' ' ') --change-section-vma .cmdline=0x30000 \ --add-section .linux="$kernelimg" --change-section-vma .linux=0x2000000 \ --add-section .initrd=<(cat ${microcode[@]} "$initramfs") --change-section-vma .initrd=0x3000000 \ ${OBJCOPYARGS[@]} "$uefistub" "$out" From 70eb8a50e3be0843a645469794829b25eb9843be Mon Sep 17 00:00:00 2001 From: Morten Linderud Date: Thu, 8 Apr 2021 01:04:48 +0200 Subject: [PATCH 07/12] Added manpage Signed-off-by: Morten Linderud --- man/mkinitcpio.8.txt | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/man/mkinitcpio.8.txt b/man/mkinitcpio.8.txt index 46ff0670..cda079b0 100644 --- a/man/mkinitcpio.8.txt +++ b/man/mkinitcpio.8.txt @@ -29,8 +29,13 @@ Options after all other hooks from the config file. Multiple hooks should be comma-separated. This option can be specified multiple times. +*-C, \--cmdline* 'config':: + Use kernel cmdline with UEFI executable. If none is specified it will + try find one of the files '/etc/kernel/cmdline', '/usr/share/kernel/cmdline' + or `/proc/cmdline`. Only used along with '--uefi'. + *-c, \--config* 'config':: - Use 'config' file to generate the ramdisk. Default: /etc/mkinitcpio.conf + Use 'config' file to generate the ramdisk. Default: '/etc/mkinitcpio.conf' *-d, \--generatedir* 'directory':: Set 'directory' as the location where the initramfs is built. This might be @@ -59,14 +64,39 @@ Options *-L, \--listhooks*:: List all available hooks. +*-l, \--splash* 'filename':: + UEFI executables can show a bitmap file on boot. + +*-I, \--uefistub* 'filename':: + UEFI stub image used for UEFI executable generation. Only used if '--uefi' + is specified. Default: Attempts to look for a systemd-boot or gummiboot + stub loader. + +*-i, \--kernelimage* 'filename':: + Include a kernel image for the UEFI executable. This is only used if + '--uefi' is specified. Default: one of + '/lib/modules/$KERNELVERSION/vmlinuz', '/boot/vmlinuz-$KERNELVERSION', or + '/boot/vmlinuz-linux'. + *-M, \--automods*:: Display modules found via autodetection. mkinitcpio will automatically try to determine which kernel modules are needed to start your computer. This option lists which modules were detected. +*-m, \--microcode* 'filename':: + Include microcode into the UEFI executable. This option is only used if + '--uefi' is specified. Default: no. + *-n, \--nocolor*:: Disable color output. +*-U, \--uefi* 'filename':: + Generate a UEFI executable as 'filename'. If a CPIO image is successfully + built, it will be used to generate a UEFI executable stub image for UEFI + booting. This combines the initramfs, the kernel, any specified microcode + and the kernel cmdline into one executable. This is useful for boot chain + integrity where the file is signed. Default: no. + *-P, \--allpresets*:: Process all presets contained in '/etc/mkinitcpio.d'. See the '-p' option for more detail about presets. @@ -79,6 +109,10 @@ Options *-r, \--moduleroot* 'root':: Specifies the root directory to find modules in, defaulting to '/'. +*-R, \--osrelease* 'filename';; + Include a os-release file for the UEFI executable. Only used if '--uefi' is + specified. Default: '/etc/os-release' or '/usr/lib/os-release'. + *-S, \--skiphooks* 'hooks':: Skip 'hooks' when generating the image. Multiple hooks should be comma-separated. This option can be specified multiple times. From 4e9d26390c452d7188e46b0b0c6316348120c833 Mon Sep 17 00:00:00 2001 From: Morten Linderud Date: Thu, 8 Apr 2021 01:10:13 +0200 Subject: [PATCH 08/12] fixup! Added manpage Signed-off-by: Morten Linderud --- man/mkinitcpio.8.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/mkinitcpio.8.txt b/man/mkinitcpio.8.txt index cda079b0..e06f7a3d 100644 --- a/man/mkinitcpio.8.txt +++ b/man/mkinitcpio.8.txt @@ -32,7 +32,7 @@ Options *-C, \--cmdline* 'config':: Use kernel cmdline with UEFI executable. If none is specified it will try find one of the files '/etc/kernel/cmdline', '/usr/share/kernel/cmdline' - or `/proc/cmdline`. Only used along with '--uefi'. + or '/proc/cmdline'. Only used along with '--uefi'. *-c, \--config* 'config':: Use 'config' file to generate the ramdisk. Default: '/etc/mkinitcpio.conf' From 34be8f70d5a25116c279b6ad9246de4769513dd4 Mon Sep 17 00:00:00 2001 From: Morten Linderud Date: Fri, 9 Apr 2021 00:34:12 +0200 Subject: [PATCH 09/12] man/mkinitcio.8: Added examples to the manpage Signed-off-by: Morten Linderud --- man/mkinitcpio.8.txt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/man/mkinitcpio.8.txt b/man/mkinitcpio.8.txt index e06f7a3d..b1a1c15f 100644 --- a/man/mkinitcpio.8.txt +++ b/man/mkinitcpio.8.txt @@ -35,7 +35,7 @@ Options or '/proc/cmdline'. Only used along with '--uefi'. *-c, \--config* 'config':: - Use 'config' file to generate the ramdisk. Default: '/etc/mkinitcpio.conf' + Use 'config' file to generate the ramdisk. Default: '/etc/mkinitcpio.conf'. *-d, \--generatedir* 'directory':: Set 'directory' as the location where the initramfs is built. This might be @@ -109,7 +109,7 @@ Options *-r, \--moduleroot* 'root':: Specifies the root directory to find modules in, defaulting to '/'. -*-R, \--osrelease* 'filename';; +*-R, \--osrelease* 'filename':: Include a os-release file for the UEFI executable. Only used if '--uefi' is specified. Default: '/etc/os-release' or '/usr/lib/os-release'. @@ -383,6 +383,15 @@ Examples Create an initial ramdisk for the kernel at /boot/vmlinuz-linux. The resulting image will be written to /boot/initramfs-linux.img. +*mkinitcpio -g /boot/initramfs-linux.img -k /boot/vmlinuz-linux --uefi /efi/EFI/Linux/systemd-linux.efi*:: + Create an initial ramdisk for the kernel along with a UEFI executable. + The resuling executable will be written to /efi/EFI/Linux/systemd-linux.efi. + +*mkinitcpio -g /boot/initramfs-linux.img -k /boot/vmlinuz-linux -U /efi/EFI/Linux/systemd-linux.efi -M /boot/intel-ucode.img -l /usr/share/systemd/bootctl/splash-arch.bmp*:: + Create an initial ramdisk for the kernel and an UEFI executable. This + also includes the Intel CPU microcode and a splash image which will be + used during boot. + See also -------- A more thorough article on configuring mkinitcpio: From e14d024d4f22b18c10040d45ded761030214e762 Mon Sep 17 00:00:00 2001 From: Morten Linderud Date: Tue, 6 Jul 2021 00:28:35 +0200 Subject: [PATCH 10/12] mkinitcpio: remove short options, restructure docs and help Signed-off-by: Morten Linderud --- man/mkinitcpio.8.txt | 60 +++++++++++++++++++++++--------------------- mkinitcpio | 26 ++++++++++--------- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/man/mkinitcpio.8.txt b/man/mkinitcpio.8.txt index b1a1c15f..5d987cef 100644 --- a/man/mkinitcpio.8.txt +++ b/man/mkinitcpio.8.txt @@ -29,11 +29,6 @@ Options after all other hooks from the config file. Multiple hooks should be comma-separated. This option can be specified multiple times. -*-C, \--cmdline* 'config':: - Use kernel cmdline with UEFI executable. If none is specified it will - try find one of the files '/etc/kernel/cmdline', '/usr/share/kernel/cmdline' - or '/proc/cmdline'. Only used along with '--uefi'. - *-c, \--config* 'config':: Use 'config' file to generate the ramdisk. Default: '/etc/mkinitcpio.conf'. @@ -64,29 +59,11 @@ Options *-L, \--listhooks*:: List all available hooks. -*-l, \--splash* 'filename':: - UEFI executables can show a bitmap file on boot. - -*-I, \--uefistub* 'filename':: - UEFI stub image used for UEFI executable generation. Only used if '--uefi' - is specified. Default: Attempts to look for a systemd-boot or gummiboot - stub loader. - -*-i, \--kernelimage* 'filename':: - Include a kernel image for the UEFI executable. This is only used if - '--uefi' is specified. Default: one of - '/lib/modules/$KERNELVERSION/vmlinuz', '/boot/vmlinuz-$KERNELVERSION', or - '/boot/vmlinuz-linux'. - *-M, \--automods*:: Display modules found via autodetection. mkinitcpio will automatically try to determine which kernel modules are needed to start your computer. This option lists which modules were detected. -*-m, \--microcode* 'filename':: - Include microcode into the UEFI executable. This option is only used if - '--uefi' is specified. Default: no. - *-n, \--nocolor*:: Disable color output. @@ -96,6 +73,7 @@ Options booting. This combines the initramfs, the kernel, any specified microcode and the kernel cmdline into one executable. This is useful for boot chain integrity where the file is signed. Default: no. + For a list of relevant options see 'Options for UEFi executable' below. *-P, \--allpresets*:: Process all presets contained in '/etc/mkinitcpio.d'. See the '-p' option for @@ -109,10 +87,6 @@ Options *-r, \--moduleroot* 'root':: Specifies the root directory to find modules in, defaulting to '/'. -*-R, \--osrelease* 'filename':: - Include a os-release file for the UEFI executable. Only used if '--uefi' is - specified. Default: '/etc/os-release' or '/usr/lib/os-release'. - *-S, \--skiphooks* 'hooks':: Skip 'hooks' when generating the image. Multiple hooks should be comma-separated. This option can be specified multiple times. @@ -137,6 +111,34 @@ Options *-z, \--compress* 'compress':: Override the compression method with the 'compress' program. +Options for UEFi executable +--------------------------- + +*--cmdline* 'config':: + Use kernel cmdline with UEFI executable. If none is specified it will + try find one of the files '/etc/kernel/cmdline', '/usr/share/kernel/cmdline' + or '/proc/cmdline'. + +*--splash* 'filename':: + UEFI executables can show a bitmap file on boot. + +*--uefistub* 'filename':: + UEFI stub image used for UEFI executable generation. + Default: Attempts to look for a systemd-boot or gummiboot + stub loader. + +*--kernelimage* 'filename':: + Include a kernel image for the UEFI executable. Default: one of + '/lib/modules/$KERNELVERSION/vmlinuz', '/boot/vmlinuz-$KERNELVERSION', or + '/boot/vmlinuz-linux'. + +*--microcode* 'filename':: + Include microcode into the UEFI executable. Default: no. + +*--osrelease* 'filename':: + Include a os-release file for the UEFI executable. + Default: '/etc/os-release' or '/usr/lib/os-release'. + About Presets ------------- A preset is a pre-defined definition on how to create an initial ramdisk. @@ -383,11 +385,11 @@ Examples Create an initial ramdisk for the kernel at /boot/vmlinuz-linux. The resulting image will be written to /boot/initramfs-linux.img. -*mkinitcpio -g /boot/initramfs-linux.img -k /boot/vmlinuz-linux --uefi /efi/EFI/Linux/systemd-linux.efi*:: +*mkinitcpio -U /efi/EFI/Linux/systemd-linux.efi*:: Create an initial ramdisk for the kernel along with a UEFI executable. The resuling executable will be written to /efi/EFI/Linux/systemd-linux.efi. -*mkinitcpio -g /boot/initramfs-linux.img -k /boot/vmlinuz-linux -U /efi/EFI/Linux/systemd-linux.efi -M /boot/intel-ucode.img -l /usr/share/systemd/bootctl/splash-arch.bmp*:: +*mkinitcpio -U /efi/EFI/Linux/systemd-linux.efi --microcode /boot/intel-ucode.img --splash /usr/share/systemd/bootctl/splash-arch.bmp*:: Create an initial ramdisk for the kernel and an UEFI executable. This also includes the Intel CPU microcode and a splash image which will be used during boot. diff --git a/mkinitcpio b/mkinitcpio index 0111f809..fe5929e5 100755 --- a/mkinitcpio +++ b/mkinitcpio @@ -46,7 +46,6 @@ usage: ${0##*/} [options] Options: -A, --addhooks Add specified hooks, comma separated, to image -c, --config Use alternate config file. (default: /etc/mkinitcpio.conf) - -C, --cmdline Set kernel line. (default content: /etc/kernel/cmdline, /proc/cmdline) -g, --generate Generate cpio image and write to specified path -H, --hookhelp Display help for given hook and exit -h, --help Display this message and exit @@ -63,15 +62,18 @@ usage: ${0##*/} [options] -t, --builddir Use DIR as the temporary build directory -D, --hookdir Specify where to look for hooks -U, --uefi Build an UEFI executable - -m, --microcode Location of microcode for UEFI executable - -R, --osrelease Include os-release (default: /etc/os-release) - -l, --splash Include bitmap splash for UEFI executable - -i, --kernelimage Kernel image for UEFI executable - -I, --uefistub Location of UEFI stub loader -V, --version Display version information and exit -v, --verbose Verbose output (default: no) -z, --compress Use an alternate compressor on the image + Options for UEFI executable (-U, --uefi): + --cmdline Set kernel line (default content: /etc/kernel/cmdline, /proc/cmdline) + --microcode Location of microcode + --osrelease Include os-release (default: /etc/os-release) + --splash Include bitmap splash + --kernelimage Kernel image + --uefistub Location of UEFI stub loader + EOF } @@ -474,7 +476,7 @@ while :; do shift _f_config=$1 ;; - -C|--cmdline) + --cmdline) shift _optcmdline=$1 ;; @@ -536,23 +538,23 @@ while :; do hook_list exit 0 ;; - -l|--splash) + --splash) shift [[ -f $1 ]] || die "Invalid file -- must be a file" _optsplash=$1 ;; - -i|--kernelimage) + --kernelimage) shift _optkernelimage=$1 ;; - -I|--uefistub) + --uefistub) shift _optkernelimage=$1 ;; -M|--automods) _optshowautomods=1 ;; - -m|--microcode) + --microcode) shift _optmicrocode+=($1) ;; @@ -560,7 +562,7 @@ while :; do _optpreset=("$_d_presets"/*.preset) [[ -e ${_optpreset[0]} ]] || die "No presets found in $_d_presets" ;; - -R|--osrelease) + --osrelease) shift [[ ! -f $1 ]] && die "Invalid file -- must be a file" _optosrelease=$1 From 4187cd0f54ade618161394c6d434718a637def44 Mon Sep 17 00:00:00 2001 From: Morten Linderud Date: Tue, 6 Jul 2021 00:28:54 +0200 Subject: [PATCH 11/12] mkinitcpio: Create tmp initramfs when -U is used Preferably we shouldn't need to have a dry run when `mkinitcpio -U` is invoked, instead create a temporary initramfs we use for the UEFI executable. Signed-off-by: Morten Linderud --- mkinitcpio | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mkinitcpio b/mkinitcpio index fe5929e5..c4d4c223 100755 --- a/mkinitcpio +++ b/mkinitcpio @@ -601,6 +601,14 @@ if [[ -n $_d_flag_hooks && -n $_d_flag_install ]]; then _d_install=${_d_flag_install%:} fi + +# If we specified --uefi but no -g we want to create a temporary initramfs which will be used with the efi executable. +if [[ $_optuefi && $_optgenimg == "" ]]; then + tmpfile=$(mktemp -t mkinitcpio.XXXXXX) + trap "rm $tmpfile" EXIT + _optgenimg="$tmpfile" +fi + # insist that /proc and /dev be mounted (important for chroots) # NOTE: avoid using mountpoint for this -- look for the paths that we actually # use in mkinitcpio. Avoids issues like FS#26344. From d9298e9d5cc1761d1fd26c85abbb00a5f7917f9c Mon Sep 17 00:00:00 2001 From: Morten Linderud Date: Tue, 6 Jul 2021 00:56:21 +0200 Subject: [PATCH 12/12] mkinitcpio: fix _opt_short Signed-off-by: Morten Linderud --- mkinitcpio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkinitcpio b/mkinitcpio index c4d4c223..692c7554 100755 --- a/mkinitcpio +++ b/mkinitcpio @@ -453,7 +453,7 @@ preload_builtin_modules() { trap 'cleanup 130' INT trap 'cleanup 143' TERM -_opt_short='A:C:c:D:g:H:hk:I:i:nLl:Mm:Pp:R:r:S:sd:t:U:Vvz:' +_opt_short='A:c:D:g:H:hk:nLMPp:r:S:sd:t:U:Vvz:' _opt_long=('add:' 'addhooks:' 'config:' 'generate:' 'hookdir': 'hookhelp:' 'help' 'kernel:' 'listhooks' 'automods' 'moduleroot:' 'nocolor' 'allpresets' 'preset:' 'skiphooks:' 'save' 'generatedir:' 'builddir:' 'version' 'verbose' 'compress:'