From de151089cec6881a8c6c9a27ba095b1fb1637845 Mon Sep 17 00:00:00 2001 From: nl6720 Date: Wed, 8 Jun 2022 11:49:00 +0300 Subject: mkarchiso: use C.UTF-8 The glibc 2.35-6 package ships with the C.UTF-8 locale included, so mkarchiso does not need to use a non-UTF-8 locale anymore. Implements #175. --- archiso/mkarchiso | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archiso') diff --git a/archiso/mkarchiso b/archiso/mkarchiso index 3e0a86f..f8c180a 100755 --- a/archiso/mkarchiso +++ b/archiso/mkarchiso @@ -6,7 +6,7 @@ set -e -u # Control the environment umask 0022 -export LC_ALL="C" +export LC_ALL="C.UTF-8" [[ -v SOURCE_DATE_EPOCH ]] || printf -v SOURCE_DATE_EPOCH '%(%s)T' -1 export SOURCE_DATE_EPOCH -- cgit v1.2.3-70-g09d2 From 550b5be07de1fc2d4800f34d44e396ade3c7b6c0 Mon Sep 17 00:00:00 2001 From: plainlinen Date: Thu, 9 Jun 2022 22:37:10 -0700 Subject: Add *_uefi-x64.grub.* functions to mkarchiso --- archiso/mkarchiso | 272 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 251 insertions(+), 21 deletions(-) (limited to 'archiso') diff --git a/archiso/mkarchiso b/archiso/mkarchiso index f8c180a..b683d48 100755 --- a/archiso/mkarchiso +++ b/archiso/mkarchiso @@ -493,30 +493,42 @@ _make_boot_on_fat() { # Create a FAT image (efiboot.img) which will serve as the EFI system partition # $1: image size in bytes _make_efibootimg() { - local imgsize="0" + local imgsize_kib="0" + local imgsize_bytes=${1} + + if (( imgsize_bytes < 2*1024*1024 )); then + _msg_info "Validating '${bootmode}': efiboot.img size is ${imgsize_bytes} bytes is less than 2 MiB! Bumping up to 2 MiB" + imgsize_bytes=$((2*1024*1024)) + fi # Convert from bytes to KiB and round up to the next full MiB with an additional MiB for reserved sectors. - imgsize="$(awk 'function ceil(x){return int(x)+(x>int(x))} + imgsize_kib="$(awk 'function ceil(x){return int(x)+(x>int(x))} function byte_to_kib(x){return x/1024} function mib_to_kib(x){return x*1024} - END {print mib_to_kib(ceil((byte_to_kib($1)+1024)/1024))}' <<< "${1}" + END {print mib_to_kib(ceil((byte_to_kib($1)+1024)/1024))}' <<< "${imgsize_bytes}" )" # The FAT image must be created with mkfs.fat not mformat, as some systems have issues with mformat made images: # https://lists.gnu.org/archive/html/grub-devel/2019-04/msg00099.html rm -f -- "${work_dir}/efiboot.img" - _msg_info "Creating FAT image of size: ${imgsize} KiB..." + _msg_info "Creating FAT image of size: ${imgsize_kib} KiB..." if [[ "${quiet}" == "y" ]]; then # mkfs.fat does not have a -q/--quiet option, so redirect stdout to /dev/null instead # https://github.com/dosfstools/dosfstools/issues/103 - mkfs.fat -C -n ARCHISO_EFI "${work_dir}/efiboot.img" "${imgsize}" > /dev/null + mkfs.fat -C -n ARCHISO_EFI "${work_dir}/efiboot.img" "${imgsize_kib}" > /dev/null else - mkfs.fat -C -n ARCHISO_EFI "${work_dir}/efiboot.img" "${imgsize}" + mkfs.fat -C -n ARCHISO_EFI "${work_dir}/efiboot.img" "${imgsize_kib}" fi # Create the default/fallback boot path in which a boot loaders will be placed later. mmd -i "${work_dir}/efiboot.img" ::/EFI ::/EFI/BOOT } +# Copy the grub.cfg file in efiboot.img which is used by both UEFI ia32 and UEFI x64. +_make_efibootimg_grubcfg() { + mcopy -i "${work_dir}/efiboot.img" \ + "${work_dir}/grub.cfg" ::/EFI/BOOT/grub.cfg +} + _make_bootmode_uefi-ia32.grub.esp() { # Fill Grub configuration files sed "s|%ARCHISO_LABEL%|${iso_label}|g; @@ -537,16 +549,16 @@ _make_bootmode_uefi-ia32.grub.esp() { efiboot_files+=("${work_dir}/BOOTIA32.EFI" "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi") - if [[ ! " ${bootmodes[*]} " =~ uefi-x64.systemd-boot.esp ]]; then - efiboot_files+=("${pacstrap_dir}/boot/vmlinuz-"* - "${pacstrap_dir}/boot/initramfs-"*".img") - + if [[ " ${bootmodes[*]} " =~ uefi-x64.systemd-boot.esp ]]; then + # TODO: Remove this branch. + _run_once _make_bootmode_uefi-x64.systemd-boot.esp + elif [[ " ${bootmodes[*]} " =~ uefi-x64.grub.esp ]]; then + _run_once _make_bootmode_uefi-x64.grub.esp + else efiboot_imgsize="$(du -bc "${efiboot_files[@]}" \ 2>/dev/null | awk 'END { print $1 }')" # Create a FAT image for the EFI system partition _make_efibootimg "$efiboot_imgsize" - else - _run_once _make_bootmode_uefi-x64.systemd-boot.esp fi # Copy grub EFI binary to the default/fallback boot path @@ -554,10 +566,8 @@ _make_bootmode_uefi-ia32.grub.esp() { "${work_dir}/BOOTIA32.EFI" ::/EFI/BOOT/BOOTIA32.EFI # Copy GRUB configuration files - mcopy -i "${work_dir}/efiboot.img" \ - "${work_dir}/grub.cfg" ::/EFI/BOOT/grub.cfg + _run_once _make_efibootimg_grubcfg - # shellia32.efi is picked up automatically when on / if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi" ]]; then mcopy -i "${work_dir}/efiboot.img" \ "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi" ::/shellia32.efi @@ -586,7 +596,6 @@ _make_bootmode_uefi-ia32.grub.eltorito() { install -m 0644 -- "${work_dir}/grub.cfg" "${isofs_dir}/EFI/BOOT/grub.cfg" # edk2-shell based UEFI shell - # shellia32.efi is picked up automatically when on / if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi" ]]; then install -m 0644 -- "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi" \ "${isofs_dir}/shellia32.efi" @@ -595,6 +604,75 @@ _make_bootmode_uefi-ia32.grub.eltorito() { _msg_info "Done!" } +_make_bootmode_uefi-x64.grub.esp() { + # Fill Grub configuration files + sed "s|%ARCHISO_LABEL%|${iso_label}|g; + s|%INSTALL_DIR%|${install_dir}|g; + s|%ARCH%|${arch}|g" \ + "${profile}/grub/grub.cfg" > "${work_dir}/grub.cfg" + + # shellcheck disable=SC2016 + printf 'configfile ${cmdpath}/grub.cfg\n' > "${work_dir}/grub-embed.cfg" + + # Create EFI file + grub-mkstandalone -O x86_64-efi \ + --modules="part_gpt part_msdos fat iso9660" \ + --locales="en@quot" \ + --themes="" \ + -o "${work_dir}/BOOTx64.EFI" "boot/grub/grub.cfg=${work_dir}/grub-embed.cfg" + # Add GRUB to the list of files used to calculate the required FAT image size. + efiboot_files+=("${work_dir}/BOOTx64.EFI" + "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi") + + efiboot_imgsize="$(du -bc "${efiboot_files[@]}" \ + 2>/dev/null | awk 'END { print $1 }')" + + # Create a FAT image for the EFI system partition + _make_efibootimg "$efiboot_imgsize" + + # Copy grub EFI binary to the default/fallback boot path + mcopy -i "${work_dir}/efiboot.img" \ + "${work_dir}/BOOTx64.EFI" ::/EFI/BOOT/BOOTx64.EFI + + _run_once _make_efibootimg_grubcfg + + if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then + mcopy -i "${work_dir}/efiboot.img" \ + "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ::/shellx64.efi + fi + + _msg_info "Done! GRUB set up for UEFI booting successfully." +} + +# Prepare GRUB for El Torito booting +_make_bootmode_uefi-x64.grub.eltorito() { + # El Torito UEFI boot requires an image containing the EFI system partition. + # uefi-x64.grub.eltorito has the same requirements as uefi-x64.grub.esp + _run_once _make_bootmode_uefi-x64.grub.esp + + # Additionally set up system-boot in ISO 9660. This allows creating a medium for the live environment by using + # manual partitioning and simply copying the ISO 9660 file system contents. + # This is not related to El Torito booting and no firmware uses these files. + _msg_info "Preparing an /EFI directory for the ISO 9660 file system..." + install -d -m 0755 -- "${isofs_dir}/EFI/BOOT" + + # Copy GRUB EFI binary to the default/fallback boot path + install -m 0644 -- "${work_dir}/BOOTx64.EFI" \ + "${isofs_dir}/EFI/BOOT/BOOTx64.EFI" + + # Copy GRUB configuration files + # install -m 0644 -- "${work_dir}/grub.cfg" "${isofs_dir}" + # TODO: ${cmdpath} is (cd0)/EFI/BOOT, so we should put grub.cfg here? + install -m 0644 -- "${work_dir}/grub.cfg" "${isofs_dir}/EFI/BOOT" + + # edk2-shell based UEFI shell + if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then + install -m 0644 -- "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" "${isofs_dir}/shellx64.efi" + fi + + _msg_info "Done!" +} + # Prepare system-boot for booting when written to a disk (isohybrid) _make_bootmode_uefi-x64.systemd-boot.esp() { local _file efiboot_imgsize @@ -724,6 +802,11 @@ _validate_requirements_bootmode_bios.syslinux.eltorito() { } _validate_requirements_bootmode_uefi-x64.systemd-boot.esp() { + # shellcheck disable=SC2076 + if [[ " ${bootmodes[*]} " =~ ' uefi-x64.grub.esp ' ]]; then + _msg_error "Validating '${bootmode}': cannot be used with bootmode uefi-x64.grub.esp!" 0 + fi + # Check if mkfs.fat is available if ! command -v mkfs.fat &> /dev/null; then (( validation_error=validation_error+1 )) @@ -764,6 +847,11 @@ _validate_requirements_bootmode_uefi-x64.systemd-boot.esp() { } _validate_requirements_bootmode_uefi-x64.systemd-boot.eltorito() { + # shellcheck disable=SC2076 + if [[ " ${bootmodes[*]} " =~ ' uefi-x64.grub.eltorito ' ]]; then + _msg_error "Validating '${bootmode}': cannot be used with bootmode uefi-x64.grub.eltorito!" 0 + fi + # uefi-x64.systemd-boot.eltorito has the exact same requirements as uefi-x64.systemd-boot.esp _validate_requirements_bootmode_uefi-x64.systemd-boot.esp } @@ -774,7 +862,15 @@ _validate_requirements_bootmode_uefi-ia32.grub.esp() { (( validation_error=validation_error+1 )) _msg_error "Validating '${bootmode}': grub-install is not available on this host. Install 'grub'!" 0 fi - _validate_requirements_bootmode_uefi-x64.systemd-boot.esp + + # shellcheck disable=SC2076 + if [[ " ${bootmodes[*]} " =~ ' uefi-x64.systemd-boot.esp ' ]]; then + _validate_requirements_bootmode_uefi-x64.systemd-boot.esp + elif [[ " ${bootmodes[*]} " =~ ' uefi-x64.grub.esp ' ]]; then + _validate_requirements_bootmode_uefi-x64.grub.esp + else + _msg_error "Validating '${bootmode}': requires one of bootmode uefi-x64.systemd-boot.esp or uefi-x64.grub.esp" 0 + fi } _validate_requirements_bootmode_uefi-ia32.grub.eltorito() { @@ -782,6 +878,65 @@ _validate_requirements_bootmode_uefi-ia32.grub.eltorito() { _validate_requirements_bootmode_uefi-ia32.grub.esp } +_validate_requirements_bootmode_uefi-x64.grub.esp() { + # shellcheck disable=SC2076 + if [[ " ${bootmodes[*]} " =~ ' uefi-x64.systemd-boot.esp ' ]]; then + _msg_error "Validating '${bootmode}': cannot be used with bootmode uefi-x64.systemd-boot.esp!" 0 + fi + + # Check if GRUB is available + if ! command -v grub-mkstandalone &> /dev/null; then + (( validation_error=validation_error+1 )) + _msg_error "Validating '${bootmode}': grub-install is not available on this host. Install 'grub'!" 0 + fi + + # Check if mkfs.fat is available + if ! command -v mkfs.fat &> /dev/null; then + (( validation_error=validation_error+1 )) + _msg_error "Validating '${bootmode}': mkfs.fat is not available on this host. Install 'dosfstools'!" 0 + fi + + # Check if mmd and mcopy are available + if ! { command -v mmd &> /dev/null && command -v mcopy &> /dev/null; }; then + _msg_error "Validating '${bootmode}': mmd and/or mcopy are not available on this host. Install 'mtools'!" 0 + fi + + # Check if GRUB configuration files exist + if [[ ! -d "${profile}/grub" ]]; then + (( validation_error=validation_error+1 )) + _msg_error "Validating '${bootmode}': The '${profile}/grub' directory is missing!" 0 + else + if [[ ! -e "${profile}/grub/grub.cfg" ]]; then + (( validation_error=validation_error+1 )) + _msg_error "Validating '${bootmode}': File '${profile}/grub/grub.cfg' not found!" 0 + fi + local conffile + for conffile in "${profile}/grub/"*'.cfg'; do + if [[ -e "${conffile}" ]]; then + break + else + (( validation_error=validation_error+1 )) + _msg_error "Validating '${bootmode}': No configuration file found in '${profile}/grub/'!" 0 + fi + done + fi + + # Check for optional packages + # shellcheck disable=SC2076 + if [[ ! " ${pkg_list[*]} " =~ ' edk2-shell ' ]]; then + _msg_info "'edk2-shell' is not in the package list. The ISO will not contain a bootable UEFI shell." + fi +} + +_validate_requirements_bootmode_uefi-x64.grub.eltorito() { + # shellcheck disable=SC2076 + if [[ " ${bootmodes[*]} " =~ ' uefi-x64.systemd-boot.eltorito ' ]]; then + _msg_error "Validating '${bootmode}': cannot be used with bootmode uefi-x64.systemd-boot.eltorito!" 0 + fi + # uefi-x64.grub.eltorito has the exact same requirements as uefi-x64.grub.esp + _validate_requirements_bootmode_uefi-x64.grub.esp +} + # Build airootfs filesystem image _prepare_airootfs_image() { _run_once "_mkairootfs_${airootfs_image_type}" @@ -1002,17 +1157,20 @@ _add_xorrisofs_options_bios.syslinux.mbr() { # GRUB in an attached EFI system partition _add_xorrisofs_options_uefi-ia32.grub.esp() { + # TODO: how does the bootmodes systemd-boot vs x64.grub affect ${bootmodes[*]} tests in _add_xorrisofs_options_uefi-x64.systemd-boot.esp etc? # shellcheck disable=SC2076 - if [[ ! " ${bootmodes[*]} " =~ ' uefi-x64.systemd-boot.esp ' ]]; then - _add_xorrisofs_options_uefi-x64.systemd-boot.esp + if [[ ! " ${bootmodes[*]} " =~ ' uefi-x64.systemd-boot.esp ' && ! " ${bootmodes[*]} " =~ ' uefi-x64.grub.esp ' ]]; then + # _add_xorrisofs_options_uefi-x64.systemd-boot.esp + _add_xorrisofs_options_uefi-x64.grub.esp fi } # GRUB via El Torito _add_xorrisofs_options_uefi-ia32.grub.eltorito() { # shellcheck disable=SC2076 - if [[ ! " ${bootmodes[*]} " =~ ' uefi-x64.systemd-boot.eltorito ' ]]; then - _add_xorrisofs_options_uefi-x64.systemd-boot.eltorito + if [[ ! " ${bootmodes[*]} " =~ ' uefi-x64.systemd-boot.eltorito ' && ! " ${bootmodes[*]} " =~ ' uefi-x64.grub.eltorito ' ]]; then + # _add_xorrisofs_options_uefi-x64.systemd-boot.eltorito + _add_xorrisofs_options_uefi-x64.grub.eltorito fi } @@ -1086,6 +1244,78 @@ _add_xorrisofs_options_uefi-x64.systemd-boot.eltorito() { [[ " ${bootmodes[*]} " =~ ' bios.' ]] || xorrisofs_options+=('-eltorito-catalog' 'EFI/boot.cat') } +# GRUB in an attached EFI system partition. +# Same as _add_xorrisofs_options_uefi-x64.systemd-boot.esp. +_add_xorrisofs_options_uefi-x64.grub.esp() { + # Move the first partition away from the start of the ISO, otherwise the GPT will not be valid and ISO 9660 + # partition will not be mountable + # shellcheck disable=SC2076 + [[ " ${xorrisofs_options[*]} " =~ ' -partition_offset ' ]] || xorrisofs_options+=('-partition_offset' '16') + # Attach efiboot.img as a second partition and set its partition type to "EFI system partition" + xorrisofs_options+=('-append_partition' '2' 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B' "${work_dir}/efiboot.img") + # Ensure GPT is used as some systems do not support UEFI booting without it + # shellcheck disable=SC2076 + if [[ " ${bootmodes[*]} " =~ ' bios.syslinux.mbr ' ]]; then + # A valid GPT prevents BIOS booting on some systems, instead use an invalid GPT (without a protective MBR). + # The attached partition will have the EFI system partition type code in MBR, but in the invalid GPT it will + # have a Microsoft basic partition type code. + if [[ ! " ${bootmodes[*]} " =~ ' uefi-x64.grub.eltorito ' && ! " ${bootmodes[*]} " =~ ' uefi-ia32.grub.eltorito ' ]]; then + # If '-isohybrid-gpt-basdat' is specified before '-e', then the appended EFI system partition will have the + # EFI system partition type ID/GUID in both MBR and GPT. If '-isohybrid-gpt-basdat' is specified after '-e', + # the appended EFI system partition will have the Microsoft basic data type GUID in GPT. + if [[ ! " ${xorrisofs_options[*]} " =~ ' -isohybrid-gpt-basdat ' ]]; then + xorrisofs_options+=('-isohybrid-gpt-basdat') + fi + fi + else + # Use valid GPT if BIOS booting support will not be required + xorrisofs_options+=('-appended_part_as_gpt') + fi +} + +# GRUB via El Torito +# Same as _add_xorrisofs_options_uefi-x64.systemd-boot.eltorito. +_add_xorrisofs_options_uefi-x64.grub.eltorito() { + # shellcheck disable=SC2076 + if [[ " ${bootmodes[*]} " =~ ' uefi-x64.grub.esp ' || " ${bootmodes[*]} " =~ ' uefi-ia32.grub.esp ' ]]; then + # grub in an attached EFI system partition via El Torito + xorrisofs_options+=( + # Start a new El Torito boot entry for UEFI + '-eltorito-alt-boot' + # Set the second partition as the El Torito UEFI boot image + '-e' '--interval:appended_partition_2:all::' + # Boot image is not emulating floppy or hard disk; required for all known boot loaders + '-no-emul-boot' + ) + # A valid GPT prevents BIOS booting on some systems, use an invalid GPT instead. + if [[ " ${bootmodes[*]} " =~ ' bios.syslinux.mbr ' ]]; then + # If '-isohybrid-gpt-basdat' is specified before '-e', then the appended EFI system partition will have the + # EFI system partition type ID/GUID in both MBR and GPT. If '-isohybrid-gpt-basdat' is specified after '-e', + # the appended EFI system partition will have the Microsoft basic data type GUID in GPT. + if [[ ! " ${xorrisofs_options[*]} " =~ ' -isohybrid-gpt-basdat ' ]]; then + xorrisofs_options+=('-isohybrid-gpt-basdat') + fi + fi + else + # The ISO will not contain a GPT partition table, so to be able to reference efiboot.img, place it as a + # file inside the ISO 9660 file system + install -d -m 0755 -- "${isofs_dir}/EFI/archiso" + cp -a -- "${work_dir}/efiboot.img" "${isofs_dir}/EFI/archiso/efiboot.img" + # grub in an embedded efiboot.img via El Torito + xorrisofs_options+=( + # Start a new El Torito boot entry for UEFI + '-eltorito-alt-boot' + # Set efiboot.img as the El Torito UEFI boot image + '-e' 'EFI/archiso/efiboot.img' + # Boot image is not emulating floppy or hard disk; required for all known boot loaders + '-no-emul-boot' + ) + fi + # Specify where to save the El Torito boot catalog file in case it is not already set by bios.syslinux.eltorito + # shellcheck disable=SC2076 + [[ " ${bootmodes[*]} " =~ ' bios.' ]] || xorrisofs_options+=('-eltorito-catalog' 'EFI/boot.cat') +} + # Build bootstrap image _build_bootstrap_image() { local _bootstrap_parent -- cgit v1.2.3-70-g09d2 From 91b48f82f37f812e605771d42a812d7462f7cca5 Mon Sep 17 00:00:00 2001 From: nl6720 Date: Sat, 18 Jun 2022 09:02:28 +0300 Subject: mkarchiso: improve comments * Fix typos and wording, * Remove impossible TODO. --- archiso/mkarchiso | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'archiso') diff --git a/archiso/mkarchiso b/archiso/mkarchiso index b683d48..bb084f7 100755 --- a/archiso/mkarchiso +++ b/archiso/mkarchiso @@ -523,14 +523,14 @@ _make_efibootimg() { mmd -i "${work_dir}/efiboot.img" ::/EFI ::/EFI/BOOT } -# Copy the grub.cfg file in efiboot.img which is used by both UEFI ia32 and UEFI x64. +# Copy the grub.cfg file in efiboot.img which is used by both IA32 UEFI and x64 UEFI. _make_efibootimg_grubcfg() { mcopy -i "${work_dir}/efiboot.img" \ "${work_dir}/grub.cfg" ::/EFI/BOOT/grub.cfg } _make_bootmode_uefi-ia32.grub.esp() { - # Fill Grub configuration files + # Fill GRUB configuration files sed "s|%ARCHISO_LABEL%|${iso_label}|g; s|%INSTALL_DIR%|${install_dir}|g; s|%ARCH%|${arch}|g" \ @@ -539,7 +539,7 @@ _make_bootmode_uefi-ia32.grub.esp() { # shellcheck disable=SC2016 printf 'configfile ${cmdpath}/grub.cfg\n' > "${work_dir}/grub-embed.cfg" - # Create EFI file + # Create EFI binary grub-mkstandalone -O i386-efi \ --modules="part_gpt part_msdos fat iso9660" \ --locales="en@quot" \ @@ -561,7 +561,7 @@ _make_bootmode_uefi-ia32.grub.esp() { _make_efibootimg "$efiboot_imgsize" fi - # Copy grub EFI binary to the default/fallback boot path + # Copy GRUB EFI binary to the default/fallback boot path mcopy -i "${work_dir}/efiboot.img" \ "${work_dir}/BOOTIA32.EFI" ::/EFI/BOOT/BOOTIA32.EFI @@ -582,7 +582,7 @@ _make_bootmode_uefi-ia32.grub.eltorito() { # uefi-ia32.grub.eltorito has the same requirements as uefi-ia32.grub.esp _run_once _make_bootmode_uefi-ia32.grub.esp - # Additionally set up system-boot in ISO 9660. This allows creating a medium for the live environment by using + # Additionally set up systemd-boot in ISO 9660. This allows creating a medium for the live environment by using # manual partitioning and simply copying the ISO 9660 file system contents. # This is not related to El Torito booting and no firmware uses these files. _msg_info "Preparing an /EFI directory for the ISO 9660 file system..." @@ -614,7 +614,7 @@ _make_bootmode_uefi-x64.grub.esp() { # shellcheck disable=SC2016 printf 'configfile ${cmdpath}/grub.cfg\n' > "${work_dir}/grub-embed.cfg" - # Create EFI file + # Create EFI binary grub-mkstandalone -O x86_64-efi \ --modules="part_gpt part_msdos fat iso9660" \ --locales="en@quot" \ @@ -650,7 +650,7 @@ _make_bootmode_uefi-x64.grub.eltorito() { # uefi-x64.grub.eltorito has the same requirements as uefi-x64.grub.esp _run_once _make_bootmode_uefi-x64.grub.esp - # Additionally set up system-boot in ISO 9660. This allows creating a medium for the live environment by using + # Additionally set up systemd-boot in ISO 9660. This allows creating a medium for the live environment by using # manual partitioning and simply copying the ISO 9660 file system contents. # This is not related to El Torito booting and no firmware uses these files. _msg_info "Preparing an /EFI directory for the ISO 9660 file system..." @@ -661,8 +661,6 @@ _make_bootmode_uefi-x64.grub.eltorito() { "${isofs_dir}/EFI/BOOT/BOOTx64.EFI" # Copy GRUB configuration files - # install -m 0644 -- "${work_dir}/grub.cfg" "${isofs_dir}" - # TODO: ${cmdpath} is (cd0)/EFI/BOOT, so we should put grub.cfg here? install -m 0644 -- "${work_dir}/grub.cfg" "${isofs_dir}/EFI/BOOT" # edk2-shell based UEFI shell @@ -673,7 +671,7 @@ _make_bootmode_uefi-x64.grub.eltorito() { _msg_info "Done!" } -# Prepare system-boot for booting when written to a disk (isohybrid) +# Prepare systemd-boot for booting when written to a disk (isohybrid) _make_bootmode_uefi-x64.systemd-boot.esp() { local _file efiboot_imgsize local _available_ucodes=() @@ -723,13 +721,13 @@ _make_bootmode_uefi-x64.systemd-boot.esp() { _msg_info "Done! systemd-boot set up for UEFI booting successfully." } -# Prepare system-boot for El Torito booting +# Prepare systemd-boot for El Torito booting _make_bootmode_uefi-x64.systemd-boot.eltorito() { # El Torito UEFI boot requires an image containing the EFI system partition. # uefi-x64.systemd-boot.eltorito has the same requirements as uefi-x64.systemd-boot.esp _run_once _make_bootmode_uefi-x64.systemd-boot.esp - # Additionally set up system-boot in ISO 9660. This allows creating a medium for the live environment by using + # Additionally set up systemd-boot in ISO 9660. This allows creating a medium for the live environment by using # manual partitioning and simply copying the ISO 9660 file system contents. # This is not related to El Torito booting and no firmware uses these files. _msg_info "Preparing an /EFI directory for the ISO 9660 file system..." -- cgit v1.2.3-70-g09d2 From 53a3ad25af78d6399d9b605a037878ccd3179320 Mon Sep 17 00:00:00 2001 From: nl6720 Date: Sat, 18 Jun 2022 09:56:24 +0300 Subject: mkarchiso: add SBAT metadata to grub-mkstandalone created EFI binaries Even though archiso created ISOs do not support Secure Boot, having SBAT would allow users to more easily repack the files in the ISO to add a signed shim. Fixes #174 --- archiso/mkarchiso | 2 ++ 1 file changed, 2 insertions(+) (limited to 'archiso') diff --git a/archiso/mkarchiso b/archiso/mkarchiso index bb084f7..bb0524c 100755 --- a/archiso/mkarchiso +++ b/archiso/mkarchiso @@ -544,6 +544,7 @@ _make_bootmode_uefi-ia32.grub.esp() { --modules="part_gpt part_msdos fat iso9660" \ --locales="en@quot" \ --themes="" \ + --sbat=/usr/share/grub/sbat.csv \ -o "${work_dir}/BOOTIA32.EFI" "boot/grub/grub.cfg=${work_dir}/grub-embed.cfg" # Add GRUB to the list of files used to calculate the required FAT image size. efiboot_files+=("${work_dir}/BOOTIA32.EFI" @@ -619,6 +620,7 @@ _make_bootmode_uefi-x64.grub.esp() { --modules="part_gpt part_msdos fat iso9660" \ --locales="en@quot" \ --themes="" \ + --sbat=/usr/share/grub/sbat.csv \ -o "${work_dir}/BOOTx64.EFI" "boot/grub/grub.cfg=${work_dir}/grub-embed.cfg" # Add GRUB to the list of files used to calculate the required FAT image size. efiboot_files+=("${work_dir}/BOOTx64.EFI" -- cgit v1.2.3-70-g09d2 From fda19075813c40ad88d690247e167cb57096c316 Mon Sep 17 00:00:00 2001 From: nl6720 Date: Tue, 21 Jun 2022 20:45:48 +0300 Subject: mkarchiso: work arround GRUB's cmdpath having incorect case on some firmware Fixes #183 --- archiso/mkarchiso | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'archiso') diff --git a/archiso/mkarchiso b/archiso/mkarchiso index bb0524c..0c6a1ea 100755 --- a/archiso/mkarchiso +++ b/archiso/mkarchiso @@ -536,8 +536,17 @@ _make_bootmode_uefi-ia32.grub.esp() { s|%ARCH%|${arch}|g" \ "${profile}/grub/grub.cfg" > "${work_dir}/grub.cfg" - # shellcheck disable=SC2016 - printf 'configfile ${cmdpath}/grub.cfg\n' > "${work_dir}/grub-embed.cfg" + IFS='' read -r -d '' grubembedcfg <<'EOF' || true +if ! [ -d "$cmdpath" ]; then + # On some firmware, GRUB has a wrong cmdpath when booted from an optical disc. + # https://gitlab.archlinux.org/archlinux/archiso/-/issues/183 + if regexp --set=1:isodevice '^(\([^)]+\))\/?[Ee][Ff][Ii]\/[Bb][Oo][Oo][Tt]\/?$' "$cmdpath"; then + cmdpath="${isodevice}/EFI/BOOT" + fi +fi +configfile "${cmdpath}/grub.cfg" +EOF + printf '%s\n' "$grubembedcfg" > "${work_dir}/grub-embed.cfg" # Create EFI binary grub-mkstandalone -O i386-efi \ @@ -612,8 +621,17 @@ _make_bootmode_uefi-x64.grub.esp() { s|%ARCH%|${arch}|g" \ "${profile}/grub/grub.cfg" > "${work_dir}/grub.cfg" - # shellcheck disable=SC2016 - printf 'configfile ${cmdpath}/grub.cfg\n' > "${work_dir}/grub-embed.cfg" + IFS='' read -r -d '' grubembedcfg <<'EOF' || true +if ! [ -d "$cmdpath" ]; then + # On some firmware, GRUB has a wrong cmdpath when booted from an optical disc. + # https://gitlab.archlinux.org/archlinux/archiso/-/issues/183 + if regexp --set=1:isodevice '^(\([^)]+\))\/?[Ee][Ff][Ii]\/[Bb][Oo][Oo][Tt]\/?$' "$cmdpath"; then + cmdpath="${isodevice}/EFI/BOOT" + fi +fi +configfile "${cmdpath}/grub.cfg" +EOF + printf '%s\n' "$grubembedcfg" > "${work_dir}/grub-embed.cfg" # Create EFI binary grub-mkstandalone -O x86_64-efi \ -- cgit v1.2.3-70-g09d2 From 211572dda24ac13c1cb1be0093ad6cd34694e5cb Mon Sep 17 00:00:00 2001 From: Pellegrino Prevete Date: Fri, 15 Jul 2022 13:16:04 +0000 Subject: Add efibootimg variable in place of full path Update authors Update CHANGELOG --- AUTHORS.rst | 1 + CHANGELOG.rst | 2 ++ archiso/mkarchiso | 44 +++++++++++++++++++++++--------------------- 3 files changed, 26 insertions(+), 21 deletions(-) (limited to 'archiso') diff --git a/AUTHORS.rst b/AUTHORS.rst index aa287ec..b03b91e 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -35,3 +35,4 @@ Archiso Authors * nl6720 * Øyvind Heggstad * plain linen +* Pellegrino Prevete diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e1b19fa..ef5c42e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,8 @@ Changelog Added ----- +- Add ``efibootimg`` to ``mkarchiso`` to abstract the FAT image path. + Changed ------- diff --git a/archiso/mkarchiso b/archiso/mkarchiso index 0c6a1ea..9efb29f 100755 --- a/archiso/mkarchiso +++ b/archiso/mkarchiso @@ -39,6 +39,7 @@ airootfs_image_tool_options=() cert_list=() sign_netboot_artifacts="" declare -A file_permissions=() +efibootimg="" efiboot_files=() # adapted from GRUB_EARLY_INITRD_LINUX_STOCK in https://git.savannah.gnu.org/cgit/grub.git/tree/util/grub-mkconfig.in readonly ucodes=('intel-uc.img' 'intel-ucode.img' 'amd-uc.img' 'amd-ucode.img' 'early_ucode.cpio' 'microcode.cpio') @@ -475,9 +476,9 @@ _make_bootmode_bios.syslinux.eltorito() { _make_boot_on_fat() { local ucode_image all_ucode_images=() _msg_info "Preparing kernel and initramfs for the FAT file system..." - mmd -i "${work_dir}/efiboot.img" \ + mmd -i "${efibootimg}" \ "::/${install_dir}" "::/${install_dir}/boot" "::/${install_dir}/boot/${arch}" - mcopy -i "${work_dir}/efiboot.img" "${pacstrap_dir}/boot/vmlinuz-"* \ + mcopy -i "${efibootimg}" "${pacstrap_dir}/boot/vmlinuz-"* \ "${pacstrap_dir}/boot/initramfs-"*".img" "::/${install_dir}/boot/${arch}/" for ucode_image in "${ucodes[@]}"; do if [[ -e "${pacstrap_dir}/boot/${ucode_image}" ]]; then @@ -485,7 +486,7 @@ _make_boot_on_fat() { fi done if (( ${#all_ucode_images[@]} )); then - mcopy -i "${work_dir}/efiboot.img" "${all_ucode_images[@]}" "::/${install_dir}/boot/" + mcopy -i "${efibootimg}" "${all_ucode_images[@]}" "::/${install_dir}/boot/" fi _msg_info "Done!" } @@ -509,23 +510,23 @@ _make_efibootimg() { )" # The FAT image must be created with mkfs.fat not mformat, as some systems have issues with mformat made images: # https://lists.gnu.org/archive/html/grub-devel/2019-04/msg00099.html - rm -f -- "${work_dir}/efiboot.img" + rm -f -- "${efibootimg}" _msg_info "Creating FAT image of size: ${imgsize_kib} KiB..." if [[ "${quiet}" == "y" ]]; then # mkfs.fat does not have a -q/--quiet option, so redirect stdout to /dev/null instead # https://github.com/dosfstools/dosfstools/issues/103 - mkfs.fat -C -n ARCHISO_EFI "${work_dir}/efiboot.img" "${imgsize_kib}" > /dev/null + mkfs.fat -C -n ARCHISO_EFI "${efibootimg}" "${imgsize_kib}" > /dev/null else - mkfs.fat -C -n ARCHISO_EFI "${work_dir}/efiboot.img" "${imgsize_kib}" + mkfs.fat -C -n ARCHISO_EFI "${efibootimg}" "${imgsize_kib}" fi # Create the default/fallback boot path in which a boot loaders will be placed later. - mmd -i "${work_dir}/efiboot.img" ::/EFI ::/EFI/BOOT + mmd -i "${efibootimg}" ::/EFI ::/EFI/BOOT } # Copy the grub.cfg file in efiboot.img which is used by both IA32 UEFI and x64 UEFI. _make_efibootimg_grubcfg() { - mcopy -i "${work_dir}/efiboot.img" \ + mcopy -i "${efibootimg}" \ "${work_dir}/grub.cfg" ::/EFI/BOOT/grub.cfg } @@ -572,14 +573,14 @@ EOF fi # Copy GRUB EFI binary to the default/fallback boot path - mcopy -i "${work_dir}/efiboot.img" \ + mcopy -i "${efibootimg}" \ "${work_dir}/BOOTIA32.EFI" ::/EFI/BOOT/BOOTIA32.EFI # Copy GRUB configuration files _run_once _make_efibootimg_grubcfg if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi" ]]; then - mcopy -i "${work_dir}/efiboot.img" \ + mcopy -i "${efibootimg}" \ "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi" ::/shellia32.efi fi @@ -651,13 +652,13 @@ EOF _make_efibootimg "$efiboot_imgsize" # Copy grub EFI binary to the default/fallback boot path - mcopy -i "${work_dir}/efiboot.img" \ + mcopy -i "${efibootimg}" \ "${work_dir}/BOOTx64.EFI" ::/EFI/BOOT/BOOTx64.EFI _run_once _make_efibootimg_grubcfg if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then - mcopy -i "${work_dir}/efiboot.img" \ + mcopy -i "${efibootimg}" \ "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ::/shellx64.efi fi @@ -715,22 +716,22 @@ _make_bootmode_uefi-x64.systemd-boot.esp() { _make_efibootimg "$efiboot_imgsize" # Copy systemd-boot EFI binary to the default/fallback boot path - mcopy -i "${work_dir}/efiboot.img" \ + mcopy -i "${efibootimg}" \ "${pacstrap_dir}/usr/lib/systemd/boot/efi/systemd-bootx64.efi" ::/EFI/BOOT/BOOTx64.EFI # Copy systemd-boot configuration files - mmd -i "${work_dir}/efiboot.img" ::/loader ::/loader/entries - mcopy -i "${work_dir}/efiboot.img" "${profile}/efiboot/loader/loader.conf" ::/loader/ + mmd -i "${efibootimg}" ::/loader ::/loader/entries + mcopy -i "${efibootimg}" "${profile}/efiboot/loader/loader.conf" ::/loader/ for _conf in "${profile}/efiboot/loader/entries/"*".conf"; do sed "s|%ARCHISO_LABEL%|${iso_label}|g; s|%INSTALL_DIR%|${install_dir}|g; s|%ARCH%|${arch}|g" \ - "${_conf}" | mcopy -i "${work_dir}/efiboot.img" - "::/loader/entries/${_conf##*/}" + "${_conf}" | mcopy -i "${efibootimg}" - "::/loader/entries/${_conf##*/}" done # shellx64.efi is picked up automatically when on / if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then - mcopy -i "${work_dir}/efiboot.img" \ + mcopy -i "${efibootimg}" \ "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ::/shellx64.efi fi @@ -1199,7 +1200,7 @@ _add_xorrisofs_options_uefi-x64.systemd-boot.esp() { # shellcheck disable=SC2076 [[ " ${xorrisofs_options[*]} " =~ ' -partition_offset ' ]] || xorrisofs_options+=('-partition_offset' '16') # Attach efiboot.img as a second partition and set its partition type to "EFI system partition" - xorrisofs_options+=('-append_partition' '2' 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B' "${work_dir}/efiboot.img") + xorrisofs_options+=('-append_partition' '2' 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B' "${efibootimg}") # Ensure GPT is used as some systems do not support UEFI booting without it # shellcheck disable=SC2076 if [[ " ${bootmodes[*]} " =~ ' bios.syslinux.mbr ' ]]; then @@ -1246,7 +1247,7 @@ _add_xorrisofs_options_uefi-x64.systemd-boot.eltorito() { # The ISO will not contain a GPT partition table, so to be able to reference efiboot.img, place it as a # file inside the ISO 9660 file system install -d -m 0755 -- "${isofs_dir}/EFI/archiso" - cp -a -- "${work_dir}/efiboot.img" "${isofs_dir}/EFI/archiso/efiboot.img" + cp -a -- "${efibootimg}" "${isofs_dir}/EFI/archiso/efiboot.img" # systemd-boot in an embedded efiboot.img via El Torito xorrisofs_options+=( # Start a new El Torito boot entry for UEFI @@ -1270,7 +1271,7 @@ _add_xorrisofs_options_uefi-x64.grub.esp() { # shellcheck disable=SC2076 [[ " ${xorrisofs_options[*]} " =~ ' -partition_offset ' ]] || xorrisofs_options+=('-partition_offset' '16') # Attach efiboot.img as a second partition and set its partition type to "EFI system partition" - xorrisofs_options+=('-append_partition' '2' 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B' "${work_dir}/efiboot.img") + xorrisofs_options+=('-append_partition' '2' 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B' "${efibootimg}") # Ensure GPT is used as some systems do not support UEFI booting without it # shellcheck disable=SC2076 if [[ " ${bootmodes[*]} " =~ ' bios.syslinux.mbr ' ]]; then @@ -1318,7 +1319,7 @@ _add_xorrisofs_options_uefi-x64.grub.eltorito() { # The ISO will not contain a GPT partition table, so to be able to reference efiboot.img, place it as a # file inside the ISO 9660 file system install -d -m 0755 -- "${isofs_dir}/EFI/archiso" - cp -a -- "${work_dir}/efiboot.img" "${isofs_dir}/EFI/archiso/efiboot.img" + cp -a -- "${efibootimg}" "${isofs_dir}/EFI/archiso/efiboot.img" # grub in an embedded efiboot.img via El Torito xorrisofs_options+=( # Start a new El Torito boot entry for UEFI @@ -1641,6 +1642,7 @@ _build_buildmode_netboot() { _build_buildmode_iso() { local image_name="${iso_name}-${iso_version}-${arch}.iso" local run_once_mode="${buildmode}" + efibootimg="${work_dir}/efiboot.img" _build_iso_base _run_once _build_iso_image } -- cgit v1.2.3-70-g09d2 From 6ac22309530f3aa07a2b638ccde419a3a509f50c Mon Sep 17 00:00:00 2001 From: nl6720 Date: Sun, 7 Aug 2022 16:16:52 +0300 Subject: mkarchiso: unset LANGUAGE LC_ALL=C.UTF-8, unlike LC_ALL=C, does not override LANGUAGE. See https://sourceware.org/bugzilla/show_bug.cgi?id=16621 and https://savannah.gnu.org/bugs/?62815 --- archiso/mkarchiso | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'archiso') diff --git a/archiso/mkarchiso b/archiso/mkarchiso index 9efb29f..8235ddd 100755 --- a/archiso/mkarchiso +++ b/archiso/mkarchiso @@ -7,6 +7,11 @@ set -e -u # Control the environment umask 0022 export LC_ALL="C.UTF-8" +if [[ -v LANGUAGE ]]; then + # LC_ALL=C.UTF-8, unlike LC_ALL=C, does not override LANGUAGE. + # See https://sourceware.org/bugzilla/show_bug.cgi?id=16621 and https://savannah.gnu.org/bugs/?62815 + unset LANGUAGE +fi [[ -v SOURCE_DATE_EPOCH ]] || printf -v SOURCE_DATE_EPOCH '%(%s)T' -1 export SOURCE_DATE_EPOCH -- cgit v1.2.3-70-g09d2 From b13e5e3379c41b9f3b124476dc2160766554bf99 Mon Sep 17 00:00:00 2001 From: nl6720 Date: Mon, 8 Aug 2022 13:54:43 +0300 Subject: mkarchiso: copy all GRUB files to the ISO Do not limit file copying to only grub.cfg and instead copy all GRUB configuration files and assets to both the ISO9660 and FAT image. This will allow for including custom images, fonts, etc. To easily match all non-configuration files (i.e. files without the .cfg extension), bash's extended glob feature will be enabled. Actions common to multiple _make_bootmode_uefi-*.grub are split off into dedicated functions: * _make_common_bootmode_grub_copy_to_efibootimg, * _make_common_bootmode_grub_copy_to_isofs, * _make_common_bootmode_grub_cfg. Use the same du command in all efiboot_imgsize variable assignments. Fixes #185. --- CHANGELOG.rst | 1 + archiso/mkarchiso | 119 ++++++++++++++++++++++++++++++------------------------ 2 files changed, 68 insertions(+), 52 deletions(-) (limited to 'archiso') diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ef5c42e..663acbe 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,6 +9,7 @@ Added ----- - Add ``efibootimg`` to ``mkarchiso`` to abstract the FAT image path. +- Copy all files from the ``grub`` directory to ISO9660 and the FAT image, not just only ``grub.cfg``. Changed ------- diff --git a/archiso/mkarchiso b/archiso/mkarchiso index 8235ddd..149cc88 100755 --- a/archiso/mkarchiso +++ b/archiso/mkarchiso @@ -3,6 +3,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later set -e -u +shopt -s extglob # Control the environment umask 0022 @@ -529,18 +530,44 @@ _make_efibootimg() { mmd -i "${efibootimg}" ::/EFI ::/EFI/BOOT } -# Copy the grub.cfg file in efiboot.img which is used by both IA32 UEFI and x64 UEFI. -_make_efibootimg_grubcfg() { - mcopy -i "${efibootimg}" \ - "${work_dir}/grub.cfg" ::/EFI/BOOT/grub.cfg +# Copy GRUB files to efiboot.img which is used by both IA32 UEFI and x64 UEFI. +_make_common_bootmode_grub_copy_to_efibootimg() { + local files_to_copy=() + + files_to_copy+=("${work_dir}/grub/"*) + if compgen -G "${profile}/grub/!(*.cfg)" &> /dev/null; then + files_to_copy+=("${profile}/grub/"!(*.cfg)) + fi + mcopy -i "${efibootimg}" "${files_to_copy[@]}" ::/EFI/BOOT/ } -_make_bootmode_uefi-ia32.grub.esp() { +# Copy GRUB files to efiboot.img which is used by both IA32 UEFI and x64 UEFI. +_make_common_bootmode_grub_copy_to_isofs() { + local files_to_copy=() + + files_to_copy+=("${work_dir}/grub/"*) + if compgen -G "${profile}/grub/!(*.cfg)" &> /dev/null; then + files_to_copy+=("${profile}/grub/"!(*.cfg)) + fi + install -m 0644 -- "${files_to_copy[@]}" "${isofs_dir}/EFI/BOOT/" +} + +# Prepare GRUB configuration files +_make_common_bootmode_grub_cfg(){ + local _cfg + + install -d -- "${work_dir}/grub" + # Fill GRUB configuration files - sed "s|%ARCHISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g; - s|%ARCH%|${arch}|g" \ - "${profile}/grub/grub.cfg" > "${work_dir}/grub.cfg" + for _cfg in "${profile}/grub/"*'.cfg'; do + sed "s|%ARCHISO_LABEL%|${iso_label}|g; + s|%INSTALL_DIR%|${install_dir}|g; + s|%ARCH%|${arch}|g" \ + "${_cfg}" > "${work_dir}/grub/${_cfg##*/}" + done + # Add all GRUB files to the list of files used to calculate the required FAT image size. + efiboot_files+=("${work_dir}/grub/" + "${profile}/grub/"!(*.cfg)) IFS='' read -r -d '' grubembedcfg <<'EOF' || true if ! [ -d "$cmdpath" ]; then @@ -553,6 +580,11 @@ fi configfile "${cmdpath}/grub.cfg" EOF printf '%s\n' "$grubembedcfg" > "${work_dir}/grub-embed.cfg" +} + +_make_bootmode_uefi-ia32.grub.esp() { + # Prepare configuration files + _run_once _make_common_bootmode_grub_cfg # Create EFI binary grub-mkstandalone -O i386-efi \ @@ -571,22 +603,19 @@ EOF elif [[ " ${bootmodes[*]} " =~ uefi-x64.grub.esp ]]; then _run_once _make_bootmode_uefi-x64.grub.esp else - efiboot_imgsize="$(du -bc "${efiboot_files[@]}" \ - 2>/dev/null | awk 'END { print $1 }')" + efiboot_imgsize="$(du -bcs -- "${efiboot_files[@]}" 2>/dev/null | awk 'END { print $1 }')" # Create a FAT image for the EFI system partition _make_efibootimg "$efiboot_imgsize" fi # Copy GRUB EFI binary to the default/fallback boot path - mcopy -i "${efibootimg}" \ - "${work_dir}/BOOTIA32.EFI" ::/EFI/BOOT/BOOTIA32.EFI + mcopy -i "${efibootimg}" "${work_dir}/BOOTIA32.EFI" ::/EFI/BOOT/BOOTIA32.EFI - # Copy GRUB configuration files - _run_once _make_efibootimg_grubcfg + # Copy GRUB files + _run_once _make_common_bootmode_grub_copy_to_efibootimg if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi" ]]; then - mcopy -i "${efibootimg}" \ - "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi" ::/shellia32.efi + mcopy -i "${efibootimg}" "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi" ::/shellia32.efi fi _msg_info "Done! GRUB set up for UEFI booting successfully." @@ -598,6 +627,9 @@ _make_bootmode_uefi-ia32.grub.eltorito() { # uefi-ia32.grub.eltorito has the same requirements as uefi-ia32.grub.esp _run_once _make_bootmode_uefi-ia32.grub.esp + # Prepare configuration files + _run_once _make_common_bootmode_grub_cfg + # Additionally set up systemd-boot in ISO 9660. This allows creating a medium for the live environment by using # manual partitioning and simply copying the ISO 9660 file system contents. # This is not related to El Torito booting and no firmware uses these files. @@ -605,39 +637,22 @@ _make_bootmode_uefi-ia32.grub.eltorito() { install -d -m 0755 -- "${isofs_dir}/EFI/BOOT" # Copy GRUB EFI binary to the default/fallback boot path - install -m 0644 -- "${work_dir}/BOOTIA32.EFI" \ - "${isofs_dir}/EFI/BOOT/BOOTIA32.EFI" + install -m 0644 -- "${work_dir}/BOOTIA32.EFI" "${isofs_dir}/EFI/BOOT/BOOTIA32.EFI" # Copy GRUB configuration files - install -m 0644 -- "${work_dir}/grub.cfg" "${isofs_dir}/EFI/BOOT/grub.cfg" + _run_once _make_common_bootmode_grub_copy_to_isofs # edk2-shell based UEFI shell if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi" ]]; then - install -m 0644 -- "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi" \ - "${isofs_dir}/shellia32.efi" + install -m 0644 -- "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi" "${isofs_dir}/shellia32.efi" fi _msg_info "Done!" } _make_bootmode_uefi-x64.grub.esp() { - # Fill Grub configuration files - sed "s|%ARCHISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g; - s|%ARCH%|${arch}|g" \ - "${profile}/grub/grub.cfg" > "${work_dir}/grub.cfg" - - IFS='' read -r -d '' grubembedcfg <<'EOF' || true -if ! [ -d "$cmdpath" ]; then - # On some firmware, GRUB has a wrong cmdpath when booted from an optical disc. - # https://gitlab.archlinux.org/archlinux/archiso/-/issues/183 - if regexp --set=1:isodevice '^(\([^)]+\))\/?[Ee][Ff][Ii]\/[Bb][Oo][Oo][Tt]\/?$' "$cmdpath"; then - cmdpath="${isodevice}/EFI/BOOT" - fi -fi -configfile "${cmdpath}/grub.cfg" -EOF - printf '%s\n' "$grubembedcfg" > "${work_dir}/grub-embed.cfg" + # Prepare configuration files + _run_once _make_common_bootmode_grub_cfg # Create EFI binary grub-mkstandalone -O x86_64-efi \ @@ -650,21 +665,19 @@ EOF efiboot_files+=("${work_dir}/BOOTx64.EFI" "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi") - efiboot_imgsize="$(du -bc "${efiboot_files[@]}" \ - 2>/dev/null | awk 'END { print $1 }')" + efiboot_imgsize="$(du -bcs -- "${efiboot_files[@]}" 2>/dev/null | awk 'END { print $1 }')" # Create a FAT image for the EFI system partition _make_efibootimg "$efiboot_imgsize" - # Copy grub EFI binary to the default/fallback boot path - mcopy -i "${efibootimg}" \ - "${work_dir}/BOOTx64.EFI" ::/EFI/BOOT/BOOTx64.EFI + # Copy GRUB EFI binary to the default/fallback boot path + mcopy -i "${efibootimg}" "${work_dir}/BOOTx64.EFI" ::/EFI/BOOT/BOOTx64.EFI - _run_once _make_efibootimg_grubcfg + # Copy GRUB files + _run_once _make_common_bootmode_grub_copy_to_efibootimg if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then - mcopy -i "${efibootimg}" \ - "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ::/shellx64.efi + mcopy -i "${efibootimg}" "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ::/shellx64.efi fi _msg_info "Done! GRUB set up for UEFI booting successfully." @@ -676,6 +689,9 @@ _make_bootmode_uefi-x64.grub.eltorito() { # uefi-x64.grub.eltorito has the same requirements as uefi-x64.grub.esp _run_once _make_bootmode_uefi-x64.grub.esp + # Prepare configuration files + _run_once _make_common_bootmode_grub_cfg + # Additionally set up systemd-boot in ISO 9660. This allows creating a medium for the live environment by using # manual partitioning and simply copying the ISO 9660 file system contents. # This is not related to El Torito booting and no firmware uses these files. @@ -683,11 +699,10 @@ _make_bootmode_uefi-x64.grub.eltorito() { install -d -m 0755 -- "${isofs_dir}/EFI/BOOT" # Copy GRUB EFI binary to the default/fallback boot path - install -m 0644 -- "${work_dir}/BOOTx64.EFI" \ - "${isofs_dir}/EFI/BOOT/BOOTx64.EFI" + install -m 0644 -- "${work_dir}/BOOTx64.EFI" "${isofs_dir}/EFI/BOOT/BOOTx64.EFI" - # Copy GRUB configuration files - install -m 0644 -- "${work_dir}/grub.cfg" "${isofs_dir}/EFI/BOOT" + # Copy GRUB files + _run_once _make_common_bootmode_grub_copy_to_isofs # edk2-shell based UEFI shell if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then @@ -715,7 +730,7 @@ _make_bootmode_uefi-x64.systemd-boot.esp() { "${pacstrap_dir}/boot/vmlinuz-"* "${pacstrap_dir}/boot/initramfs-"*".img" "${_available_ucodes[@]}") - efiboot_imgsize="$(du -bc "${efiboot_files[@]}" \ + efiboot_imgsize="$(du -bcs -- "${efiboot_files[@]}" \ 2>/dev/null | awk 'END { print $1 }')" # Create a FAT image for the EFI system partition _make_efibootimg "$efiboot_imgsize" -- cgit v1.2.3-70-g09d2 From 7bc4c5424516c9be29b460b4fa043aa76b1c69e3 Mon Sep 17 00:00:00 2001 From: nl6720 Date: Mon, 8 Aug 2022 16:31:12 +0300 Subject: mkarchiso: preload more GRUB modules and disable shim_lock verifier --disable-shim-lock is required to support Secure Boot with custom signatures without using shim. Otherwise GRUB will trow an error when trying to boot a kernel: error: shim_lock protocol not found. error: you need to load the kernel first. The modules GRUB will use need to be preloaded otherwise the EFI binaries cannot be signed and used for Secure Boot. See https://bugs.archlinux.org/task/71382. GRUB will trow en error: error: verification requested but nobody cares These changes are done to support Secure Boot using custom keys (not shim) by simply extracting the boot loader (BOOTx64.EFI and BOOTIA32.EFI), kernel, UEFI shell, signing them and then repacking the ISO. For example. Extract the files: $ osirrox -indev archlinux-YYYY.MM.DD-x86_64.iso \ -extract_boot_images ./ \ -extract /EFI/BOOT/BOOTx64.EFI BOOTx64.EFI \ -extract /EFI/BOOT/BOOTIA32.EFI BOOTIA32.EFI \ -extract /shellx64.efi shellx64.efi \ -extract /shellia32.efi shellia32.efi \ -extract /arch/boot/x86_64/vmlinuz-linux vmlinuz-linux Make the files writable: $ chmod +w BOOTx64.EFI BOOTIA32.EFI shellx64.efi shellia32.efi vmlinuz-linux Sign the files: $ sbsign --key db.key --cert db.crt --output BOOTx64.EFI BOOTx64.EFI $ sbsign --key db.key --cert db.crt --output BOOTIA32.EFI BOOTIA32.EFI $ sbsign --key db.key --cert db.crt --output shellx64.efi shellx64.efi $ sbsign --key db.key --cert db.crt --output shellia32.efi shellia32.efi $ sbsign --key db.key --cert db.crt --output vmlinuz-linux vmlinuz-linux Copy the boot loader and UEFI shell to the EFI system partition image: $ mcopy -D oO -i eltorito_img2_uefi.img BOOTx64.EFI BOOTIA32.EFI ::/EFI/BOOT/ $ mcopy -D oO -i eltorito_img2_uefi.img shellx64.efi shellia32.efi ::/ Repack the ISO using the modified El Torito UEFI boot image and add the signed boot loader files, UEFI shell and kernel to ISO9660: $ xorriso -indev archlinux-YYYY.MM.DD-x86_64.iso \ -outdev archlinux-YYYY.MM.DD-x86_64-Secure_Boot.iso \ -boot_image any replay \ -append_partition 2 0xef eltorito_img2_uefi.img \ -map BOOTx64.EFI /EFI/BOOT/BOOTx64.EFI \ -map BOOTIA32.EFI /EFI/BOOT/BOOTIA32.EFI \ -map shellx64.efi /shellx64.efi \ -map shellia32.efi /shellia32.efi \ -map vmlinuz-linux /arch/boot/x86_64/vmlinuz-linux Boot the resulting archlinux-YYYY.MM.DD-x86_64-Secure_Boot.iso. --- CHANGELOG.rst | 3 +++ archiso/mkarchiso | 22 ++++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'archiso') diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 663acbe..cb4d5d6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,9 @@ Added Changed ------- +- Disable GRUB's shim_lock verifier and preload more modules. This allows reusing the GRUB EFI binaries when repacking + the ISO to support Secure Boot with custom signatures. + Removed ------- diff --git a/archiso/mkarchiso b/archiso/mkarchiso index 149cc88..04c1e52 100755 --- a/archiso/mkarchiso +++ b/archiso/mkarchiso @@ -583,15 +583,24 @@ EOF } _make_bootmode_uefi-ia32.grub.esp() { + local grubmodules=() + # Prepare configuration files _run_once _make_common_bootmode_grub_cfg # Create EFI binary + # Module list from https://bugs.archlinux.org/task/71382#comment202911 + grubmodules=(all_video at_keyboard boot btrfs cat chain configfile echo efifwsetup efinet ext2 f2fs fat font \ + gfxmenu gfxterm gzio halt hfsplus iso9660 jpeg keylayouts linux loadenv loopback lsefi lsefimmap \ + minicmd normal part_apple part_gpt part_msdos png read reboot regexp search search_fs_file \ + search_fs_uuid search_label serial sleep tpm usb usbserial_common usbserial_ftdi usbserial_pl2303 \ + usbserial_usbdebug video xfs zstd) grub-mkstandalone -O i386-efi \ - --modules="part_gpt part_msdos fat iso9660" \ + --modules="${grubmodules[*]}" \ --locales="en@quot" \ --themes="" \ --sbat=/usr/share/grub/sbat.csv \ + --disable-shim-lock \ -o "${work_dir}/BOOTIA32.EFI" "boot/grub/grub.cfg=${work_dir}/grub-embed.cfg" # Add GRUB to the list of files used to calculate the required FAT image size. efiboot_files+=("${work_dir}/BOOTIA32.EFI" @@ -651,15 +660,24 @@ _make_bootmode_uefi-ia32.grub.eltorito() { } _make_bootmode_uefi-x64.grub.esp() { + local grubmodules=() + # Prepare configuration files _run_once _make_common_bootmode_grub_cfg # Create EFI binary + # Module list from https://bugs.archlinux.org/task/71382#comment202911 + grubmodules=(all_video at_keyboard boot btrfs cat chain configfile echo efifwsetup efinet ext2 f2fs fat font \ + gfxmenu gfxterm gzio halt hfsplus iso9660 jpeg keylayouts linux loadenv loopback lsefi lsefimmap \ + minicmd normal part_apple part_gpt part_msdos png read reboot regexp search search_fs_file \ + search_fs_uuid search_label serial sleep tpm usb usbserial_common usbserial_ftdi usbserial_pl2303 \ + usbserial_usbdebug video xfs zstd) grub-mkstandalone -O x86_64-efi \ - --modules="part_gpt part_msdos fat iso9660" \ + --modules="${grubmodules[*]}" \ --locales="en@quot" \ --themes="" \ --sbat=/usr/share/grub/sbat.csv \ + --disable-shim-lock \ -o "${work_dir}/BOOTx64.EFI" "boot/grub/grub.cfg=${work_dir}/grub-embed.cfg" # Add GRUB to the list of files used to calculate the required FAT image size. efiboot_files+=("${work_dir}/BOOTx64.EFI" -- cgit v1.2.3-70-g09d2 From aef242720d8d17bdaf56fd573fff3c02ccc062cb Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Fri, 26 Aug 2022 11:36:03 +0200 Subject: mkarchiso: touch clock-epoch for extra hint on date and time This helps on systems with screwed or broken RTC. --- CHANGELOG.rst | 1 + archiso/mkarchiso | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'archiso') diff --git a/CHANGELOG.rst b/CHANGELOG.rst index cb4d5d6..1993cd6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,6 +10,7 @@ Added - Add ``efibootimg`` to ``mkarchiso`` to abstract the FAT image path. - Copy all files from the ``grub`` directory to ISO9660 and the FAT image, not just only ``grub.cfg``. +- Touching ``/usr/lib/clock-epoch`` to to help ``systemd`` with screwed or broken RTC. Changed ------- diff --git a/archiso/mkarchiso b/archiso/mkarchiso index 04c1e52..5f0c79b 100755 --- a/archiso/mkarchiso +++ b/archiso/mkarchiso @@ -1590,6 +1590,11 @@ _make_version() { [[ ! -e "${_os_release}" ]] || sed -i '/^IMAGE_ID=/d;/^IMAGE_VERSION=/d' "${_os_release}" printf 'IMAGE_ID=%s\nIMAGE_VERSION=%s\n' "${iso_name}" "${iso_version}" >> "${_os_release}" fi + + # Touch /usr/lib/clock-epoch to give another hint on date and time + # for systems with screwed or broken RTC. + touch -m -d"@${SOURCE_DATE_EPOCH}" -- "${pacstrap_dir}/usr/lib/clock-epoch" + _msg_info "Done!" } -- cgit v1.2.3-70-g09d2 From 326cfed7cc59af487cdae1d1a75e1e3a8f84cb67 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Wed, 18 May 2022 16:42:28 +0200 Subject: Add the ability to generate rootfs signatures using openssl CMS module if ``-c`` is given. (gitlab ci) Added a CA structure to the codesigning certificates. This to test the functionality of optional CA being in the signing message. (mkarchiso) Removed the ``sign_netboot_artifacts`` variable and instead we'll now rely on ``if [[ -v cert_list ]]; then``. Added ``ARCHISO_TLS_FD`` and ``ARCHISO_TLSCA_FD`` environment variables to override the certificates used. This is so that third party CA's can be used during building in a meaningful way without distrupting the CA trust that is shipped by default. _cms_sign_artifact() was added which signs the rootfs using OpenSSL CMS. The files will be saved as "${artifact}.cms.sig". That would be for instance "${isofs_dir}/${install_dir}/${arch}/airootfs.sfs.cms.sig". --- .gitlab/ci/build_archiso.sh | 80 ++++++++++++++++++++++++--- AUTHORS.rst | 1 + CHANGELOG.rst | 2 + archiso/mkarchiso | 130 +++++++++++++++++++++++++++++++------------- 4 files changed, 165 insertions(+), 48 deletions(-) (limited to 'archiso') diff --git a/.gitlab/ci/build_archiso.sh b/.gitlab/ci/build_archiso.sh index 5250b51..104792a 100755 --- a/.gitlab/ci/build_archiso.sh +++ b/.gitlab/ci/build_archiso.sh @@ -30,6 +30,8 @@ gnupg_homedir="" codesigning_dir="" codesigning_cert="" codesigning_key="" +ca_cert="" +ca_key="" pgp_key_id="" print_section_start() { @@ -204,43 +206,103 @@ EOF print_section_end "ephemeral_pgp_key" } -create_ephemeral_codesigning_key() { +create_ephemeral_codesigning_keys() { # create ephemeral certificates used for codesigning - print_section_start "ephemeral_codesigning_key" "Creating ephemeral codesigning key" + print_section_start "ephemeral_codesigning_key" "Creating ephemeral codesigning keys" + # The exact steps in creating a CA with Codesigning being signed was taken from + # https://jamielinux.com/docs/openssl-certificate-authority/introduction.html + # (slight modifications to the process to not disturb default values of /etc/ssl/openssl.cnf) + codesigning_dir="${tmpdir}/.codesigning/" - local codesigning_conf="${codesigning_dir}/openssl.cnf" + local ca_dir="${codesigning_dir}/ca/" + + local ca_conf="${ca_dir}/certificate_authority.cnf" + local ca_subj="/C=DE/ST=Berlin/L=Berlin/O=Arch Linux/OU=Release Engineering/CN=archlinux.org" + ca_cert="${ca_dir}/cacert.pem" + ca_key="${ca_dir}/private/cakey.pem" + + local codesigning_conf="${codesigning_dir}/code_signing.cnf" local codesigning_subj="/C=DE/ST=Berlin/L=Berlin/O=Arch Linux/OU=Release Engineering/CN=archlinux.org" codesigning_cert="${codesigning_dir}/codesign.crt" codesigning_key="${codesigning_dir}/codesign.key" + + mkdir -p "${ca_dir}/"{private,newcerts,crl} mkdir -p "${codesigning_dir}" cp -- /etc/ssl/openssl.cnf "${codesigning_conf}" - printf "\n[codesigning]\nkeyUsage=digitalSignature\nextendedKeyUsage=codeSigning\n" >> "${codesigning_conf}" + cp -- /etc/ssl/openssl.cnf "${ca_conf}" + touch "${ca_dir}/index.txt" + echo "1000" > "${ca_dir}/serial" + + # Prepare the ca configuration for the change in directory + sed -i "s#/etc/ssl#${ca_dir}#g" "${ca_conf}" + + # Create the Certificate Authority + openssl req \ + -newkey rsa:4096 \ + -sha256 \ + -nodes \ + -x509 \ + -new \ + -sha256 \ + -keyout "${ca_key}" \ + -config "${ca_conf}" \ + -subj "${ca_subj}" \ + -out "${ca_cert}" + + cat << EOF >> "${ca_conf}" + +[ v3_intermediate_ca ] +# Extensions for a typical intermediate CA ('man x509v3_config'). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +EOF + + cat << EOF >> "${codesigning_conf}" + +[codesigning] +keyUsage=digitalSignature +extendedKeyUsage=codeSigning, clientAuth, emailProtection + +EOF + openssl req \ -newkey rsa:4096 \ -keyout "${codesigning_key}" \ -nodes \ -sha256 \ - -x509 \ - -days 365 \ - -out "${codesigning_cert}" \ + -out "${codesigning_cert}.csr" \ -config "${codesigning_conf}" \ -subj "${codesigning_subj}" \ -extensions codesigning + # Sign the code signing certificate with the CA + openssl ca \ + -batch \ + -config "${ca_conf}" \ + -extensions v3_intermediate_ca \ + -days 3650 \ + -notext \ + -md sha256 \ + -in "${codesigning_cert}.csr" \ + -out "${codesigning_cert}" + print_section_end "ephemeral_codesigning_key" } run_mkarchiso() { # run mkarchiso create_ephemeral_pgp_key - create_ephemeral_codesigning_key + create_ephemeral_codesigning_keys print_section_start "mkarchiso" "Running mkarchiso" mkdir -p "${output}/" "${tmpdir}/" GNUPGHOME="${gnupg_homedir}" ./archiso/mkarchiso \ -D "${install_dir}" \ - -c "${codesigning_cert} ${codesigning_key}" \ + -c "${codesigning_cert} ${codesigning_key} ${ca_cert}" \ -g "${pgp_key_id}" \ -G "${pgp_sender}" \ -o "${output}/" \ diff --git a/AUTHORS.rst b/AUTHORS.rst index b03b91e..18207eb 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -36,3 +36,4 @@ Archiso Authors * Øyvind Heggstad * plain linen * Pellegrino Prevete +* Anton Hvornum diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 687b413..1d9eeea 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,8 @@ Changelog Added ----- +- The ability to generate rootfs signatures using openssl CMS module if ``-c`` is given. + Changed ------- diff --git a/archiso/mkarchiso b/archiso/mkarchiso index 5f0c79b..2fbbf66 100755 --- a/archiso/mkarchiso +++ b/archiso/mkarchiso @@ -43,7 +43,6 @@ bootmodes=() airootfs_image_type="" airootfs_image_tool_options=() cert_list=() -sign_netboot_artifacts="" declare -A file_permissions=() efibootimg="" efiboot_files=() @@ -94,10 +93,11 @@ usage: ${app_name} [options] Default: '${iso_label}' -P Set the ISO publisher Default: '${iso_publisher}' - -c [cert ..] Provide certificates for codesigning of netboot artifacts + -c [cert ..] Provide certificates for codesigning of netboot artifacts as + well as the rootfs artifact. Multiple files are provided as quoted, space delimited list. The first file is considered as the signing certificate, - the second as the key. + the second as the key and the third as the optional certificate authority. -g Set the PGP key ID to be used for signing the rootfs image. Passed to gpg as the value for --default-key -G Set the PGP signer (must include an email address) @@ -250,14 +250,11 @@ _mkchecksum() { } # GPG sign the root file system image. -_mksignature() { - local airootfs_image_filename gpg_options=() - _msg_info "Signing rootfs image..." - if [[ -e "${isofs_dir}/${install_dir}/${arch}/airootfs.sfs" ]]; then - airootfs_image_filename="${isofs_dir}/${install_dir}/${arch}/airootfs.sfs" - elif [[ -e "${isofs_dir}/${install_dir}/${arch}/airootfs.erofs" ]]; then - airootfs_image_filename="${isofs_dir}/${install_dir}/${arch}/airootfs.erofs" - fi +_mk_pgp_signature() { + local gpg_options=() + local airootfs_image_filename="${1}" + _msg_info "Signing rootfs image using GPG..." + rm -f -- "${airootfs_image_filename}.sig" # Add gpg sender option if the value is provided [[ -z "${gpg_sender}" ]] || gpg_options+=('--sender' "${gpg_sender}") @@ -342,6 +339,15 @@ _make_packages() { exec {ARCHISO_GNUPG_FD}<>"${work_dir}/pubkey.gpg" export ARCHISO_GNUPG_FD fi + if [[ -v cert_list[0] ]]; then + exec {ARCHISO_TLS_FD}<>"${cert_list[0]}" + export ARCHISO_TLS_FD + fi + if [[ -v cert_list[2] ]]; then + exec {ARCHISO_TLSCA_FD}<>"${cert_list[2]}" + export ARCHISO_TLSCA_FD + fi + # Unset TMPDIR to work around https://bugs.archlinux.org/task/70580 if [[ "${quiet}" = "y" ]]; then @@ -350,6 +356,14 @@ _make_packages() { env -u TMPDIR pacstrap -C "${work_dir}/${buildmode}.pacman.conf" -c -G -M -- "${pacstrap_dir}" "${buildmode_pkg_list[@]}" fi + if [[ -v cert_list[0] ]]; then + exec {ARCHISO_TLS_FD}<&- + unset ARCHISO_TLS_FD + fi + if [[ -v cert_list[2] ]]; then + exec {ARCHISO_TLSCA_FD}<&- + unset ARCHISO_TLSCA_FD + fi if [[ -n "${gpg_key}" ]]; then exec {ARCHISO_GNUPG_FD}<&- unset ARCHISO_GNUPG_FD @@ -998,8 +1012,18 @@ _validate_requirements_bootmode_uefi-x64.grub.eltorito() { _prepare_airootfs_image() { _run_once "_mkairootfs_${airootfs_image_type}" _mkchecksum + + if [[ -e "${isofs_dir}/${install_dir}/${arch}/airootfs.sfs" ]]; then + airootfs_image_filename="${isofs_dir}/${install_dir}/${arch}/airootfs.sfs" + elif [[ -e "${isofs_dir}/${install_dir}/${arch}/airootfs.erofs" ]]; then + airootfs_image_filename="${isofs_dir}/${install_dir}/${arch}/airootfs.erofs" + fi + if [[ -n "${gpg_key}" ]]; then - _mksignature + _mk_pgp_signature "${airootfs_image_filename}" + fi + if [[ -v cert_list ]]; then + _cms_sign_artifact "${airootfs_image_filename}" fi } @@ -1012,6 +1036,32 @@ _export_netboot_artifacts() { du -hs -- "${out_dir}/${install_dir}" } +_cms_sign_artifact() { + local artifact="${1}" + local openssl_flags=( + "-sign" + "-binary" + "-nocerts" + "-noattr" + "-outform" "DER" "-out" "${artifact}.cms.sig" + "-in" "${artifact}" + "-signer" "${cert_list[0]}" + "-inkey" "${cert_list[1]}" + ) + + if (( ${#cert_list[@]} > 2 )); then + openssl_flags+=("-certfile" "${cert_list[2]}") + fi + + _msg_info "Signing ${artifact} image using openssl cms..." + + rm -f -- "${artifact}.cms.sig" + + openssl cms "${openssl_flags[@]}" + + _msg_info "Done!" +} + # sign build artifacts for netboot _sign_netboot_artifacts() { local _file _dir @@ -1115,6 +1165,26 @@ _validate_common_requirements_buildmode_iso_netboot() { _msg_error "Packages file '${packages}' does not exist." 0 fi + if [[ -v cert_list ]]; then + # Check if the certificate files exist + for _cert in "${cert_list[@]}"; do + if [[ ! -e "${_cert}" ]]; then + (( validation_error=validation_error+1 )) + _msg_error "File '${_cert}' does not exist." 0 + fi + done + # Check if there are at least three certificate files to sign netboot and rootfs. + if (( ${#cert_list[@]} < 2 )); then + (( validation_error=validation_error+1 )) + _msg_error "Two certificates are required for codesigning netboot artifacts, but '${cert_list[*]}' is provided." 0 + fi + + if ! command -v openssl &> /dev/null; then + (( validation_error=validation_error+1 )) + _msg_error "Validating build mode '${_buildmode}': openssl is not available on this host. Install 'openssl'!" 0 + fi + fi + # Check if the specified airootfs_image_type is supported if typeset -f "_mkairootfs_${airootfs_image_type}" &> /dev/null; then if typeset -f "_validate_requirements_airootfs_image_type_${airootfs_image_type}" &> /dev/null; then @@ -1156,31 +1226,8 @@ _validate_requirements_buildmode_iso() { } _validate_requirements_buildmode_netboot() { - local _override_cert_list=() - - if [[ "${sign_netboot_artifacts}" == "y" ]]; then - # Check if the certificate files exist - for _cert in "${cert_list[@]}"; do - if [[ -e "${_cert}" ]]; then - _override_cert_list+=("$(realpath -- "${_cert}")") - else - (( validation_error=validation_error+1 )) - _msg_error "File '${_cert}' does not exist." 0 - fi - done - cert_list=("${_override_cert_list[@]}") - # Check if there are at least two certificate files - if (( ${#cert_list[@]} < 2 )); then - (( validation_error=validation_error+1 )) - _msg_error "Two certificates are required for codesigning, but '${cert_list[*]}' is provided." 0 - fi - fi _validate_common_requirements_buildmode_iso_netboot _validate_common_requirements_buildmode_all - if ! command -v openssl &> /dev/null; then - (( validation_error=validation_error+1 )) - _msg_error "Validating build mode '${_buildmode}': openssl is not available on this host. Install 'openssl'!" 0 - fi } # SYSLINUX El Torito @@ -1541,10 +1588,7 @@ _set_overrides() { fi [[ ! -v override_gpg_key ]] || gpg_key="$override_gpg_key" [[ ! -v override_gpg_sender ]] || gpg_sender="$override_gpg_sender" - if [[ -v override_cert_list ]]; then - sign_netboot_artifacts="y" - fi - [[ ! -v override_cert_list ]] || cert_list+=("${override_cert_list[@]}") + [[ ! -v override_cert_list ]] || mapfile -t cert_list < <(realpath -- "${override_cert_list[@]}") if [[ -v override_quiet ]]; then quiet="$override_quiet" elif [[ -z "$quiet" ]]; then @@ -1675,8 +1719,16 @@ _build_buildmode_netboot() { local run_once_mode="${buildmode}" _build_iso_base + + if [[ -e "${isofs_dir}/${install_dir}/${arch}/airootfs.sfs" ]]; then + airootfs_image_filename="${isofs_dir}/${install_dir}/${arch}/airootfs.sfs" + elif [[ -e "${isofs_dir}/${install_dir}/${arch}/airootfs.erofs" ]]; then + airootfs_image_filename="${isofs_dir}/${install_dir}/${arch}/airootfs.erofs" + fi + if [[ -v cert_list ]]; then _run_once _sign_netboot_artifacts + _cms_sign_artifact "${airootfs_image_filename}" fi _run_once _export_netboot_artifacts } -- cgit v1.2.3-70-g09d2