diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | AUTHORS.rst | 1 | ||||
-rw-r--r-- | CHANGELOG.rst | 11 | ||||
-rw-r--r-- | configs/baseline/airootfs/etc/locale.conf | 1 | ||||
-rw-r--r-- | configs/baseline/grub/grub.cfg | 10 | ||||
-rw-r--r-- | configs/baseline/profiledef.sh | 2 | ||||
-rw-r--r-- | configs/releng/airootfs/etc/locale.conf | 2 | ||||
-rw-r--r-- | configs/releng/airootfs/etc/pacman.d/hooks/40-locale-gen.hook | 13 | ||||
-rw-r--r-- | configs/releng/grub/grub.cfg | 51 | ||||
-rw-r--r-- | docs/README.profile.rst | 11 | ||||
-rwxr-xr-x | parabolaiso/mkparabolaiso | 312 |
11 files changed, 352 insertions, 67 deletions
@@ -3,5 +3,10 @@ parabolaiso-*.tar.gz* work/ out/ *.iso +*.img +*.cer +*.crt +*.key +*.pem user-data meta-data diff --git a/AUTHORS.rst b/AUTHORS.rst index 9dc5520..8085882 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -33,6 +33,7 @@ Archiso Authors * Yu Li-Yu <afg984@gmail.com> * nl6720 <nl6720@gmail.com> * Øyvind Heggstad <heggstad@gmail.com> +* plain linen <bcdedit@hotmail.com> =================== Parabolaiso Authors diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 12f6c6c..2759e3d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,12 +8,23 @@ Changelog Added ----- +- Configure the locale for the baseline profile to ``C.UTF-8`` so that a UTF-8 locale is used. +- Add ``uefi-x64.grub.esp`` and ``uefi-x64.grub.eltorito`` boot mode to support x86_64 UEFI boot on x86_64 machines. +- Use ``mkfs.erofs``'s ``ztailpacking`` option in the baseline profile to reduce the image size. + Changed ------- +- Change the releng profile's locale from ``en_US.UTF-8`` to ``C.UTF-8``. +- Set ``LC_ALL`` to ``C.UTF-8`` instead of ``C`` in mkparabolaiso since it is now available and non-UTF-8 locales should be + avoided. + Removed ------- +- Remove the custom pacman hook that ran ``locale-gen`` on glibc install from the releng profile. The used locale now + ships with the glibc package itself. + [64] - 2022-05-30 ================= diff --git a/configs/baseline/airootfs/etc/locale.conf b/configs/baseline/airootfs/etc/locale.conf new file mode 100644 index 0000000..f9c983c --- /dev/null +++ b/configs/baseline/airootfs/etc/locale.conf @@ -0,0 +1 @@ +LANG=C.UTF-8 diff --git a/configs/baseline/grub/grub.cfg b/configs/baseline/grub/grub.cfg index 3d0234a..6b7db5c 100644 --- a/configs/baseline/grub/grub.cfg +++ b/configs/baseline/grub/grub.cfg @@ -14,14 +14,18 @@ if loadfont "${prefix}/fonts/unicode.pf2" ; then terminal_output gfxterm fi -menuentry "Parabola GNU/Linux-libre (x86_64, UEFI)" { +default=parabola +timeout=15 +timeout_style=menu + +menuentry "Parabola GNU/Linux-libre (x86_64, UEFI)" --class arch --class gnu-linux --class gnu --class os --id 'parabola' { set gfxpayload=keep search --no-floppy --set=root --label %PARABOLAISO_LABEL% - linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% + linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img } -menuentry "Parabola GNU/Linux-libre (x86_64, UEFI) Copy to RAM" { ++menuentry "Parabola GNU/Linux-libre (x86_64, UEFI) Copy to RAM" --class arch --class gnu-linux --class gnu --class os --id 'parabola-copy-to-ram' { set gfxpayload=keep search --no-floppy --set=root --label %PARABOLAISO_LABEL% linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% copytoram diff --git a/configs/baseline/profiledef.sh b/configs/baseline/profiledef.sh index 95c1364..7e714ef 100644 --- a/configs/baseline/profiledef.sh +++ b/configs/baseline/profiledef.sh @@ -14,7 +14,7 @@ bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito' arch="x86_64" pacman_conf="pacman.conf" airootfs_image_type="erofs" -airootfs_image_tool_options=('-zlz4hc,12') +airootfs_image_tool_options=('-zlz4hc,12' -E ztailpacking) file_permissions=( ["/etc/shadow"]="0:0:400" ) diff --git a/configs/releng/airootfs/etc/locale.conf b/configs/releng/airootfs/etc/locale.conf index 01ec548..f9c983c 100644 --- a/configs/releng/airootfs/etc/locale.conf +++ b/configs/releng/airootfs/etc/locale.conf @@ -1 +1 @@ -LANG=en_US.UTF-8 +LANG=C.UTF-8 diff --git a/configs/releng/airootfs/etc/pacman.d/hooks/40-locale-gen.hook b/configs/releng/airootfs/etc/pacman.d/hooks/40-locale-gen.hook deleted file mode 100644 index 82dd199..0000000 --- a/configs/releng/airootfs/etc/pacman.d/hooks/40-locale-gen.hook +++ /dev/null @@ -1,13 +0,0 @@ -# remove from airootfs! -[Trigger] -Operation = Install -Type = Package -Target = glibc - -[Action] -Description = Uncommenting en_US.UTF-8 locale and running locale-gen... -When = PostTransaction -Depends = glibc -Depends = sed -Depends = sh -Exec = /bin/sh -c "sed -i 's/#\(en_US\.UTF-8\)/\1/' /etc/locale.gen && locale-gen" diff --git a/configs/releng/grub/grub.cfg b/configs/releng/grub/grub.cfg index 80b0d72..d3ed9d2 100644 --- a/configs/releng/grub/grub.cfg +++ b/configs/releng/grub/grub.cfg @@ -14,33 +14,54 @@ if loadfont "${prefix}/fonts/unicode.pf2" ; then terminal_output gfxterm fi +default=parabola +timeout=15 +timeout_style=menu + # GRUB init tune for accessibility # -# Morse translation table: -# "." is "500 1 300 1" -# "-" is "600 3 300 1" -# " " is "100 2" -# "/" is "100 5" -# -# Message: "s for blind" -play 500 500 1 300 1 500 1 300 1 500 1 300 1 100 5 500 1 300 1 500 1 300 1 100 2 500 1 300 1 500 1 300 1 600 3 300 1 500 1 300 1 100 5 600 3 300 1 500 1 300 1 500 1 300 1 500 1 300 1 100 2 500 1 300 1 600 3 300 1 500 1 300 1 500 1 300 1 100 2 500 1 300 1 500 1 300 1 100 2 500 1 300 1 500 1 300 1 100 2 600 3 300 1 500 1 300 1 100 2 600 3 300 1 500 1 300 1 500 1 300 1 +play 600 988 1 1319 4 -menuentry "Parabola GNU/Linux-libre install medium (x86_64, UEFI)" { +menuentry "Parabola GNU/Linux-libre install medium (x86_64, UEFI)" --class arch --class gnu-linux --class gnu --class os --id 'parabola' { set gfxpayload=keep search --no-floppy --set=root --label %PARABOLAISO_LABEL% - linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% + linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux.img } -menuentry "Parabola GNU/Linux-libre install medium with speakup screen reader (x86_64, UEFI)" --hotkey=s { +menuentry "Parabola GNU/Linux-libre install medium with speakup screen reader (x86_64, UEFI)" --hotkey s --class arch --class gnu-linux --class gnu --class os --id 'parabola-accessibility' { set gfxpayload=keep search --no-floppy --set=root --label %PARABOLAISO_LABEL% linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% accessibility=on initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img } -menuentry "UEFI Shell" { - insmod chain - search --no-floppy --set=root --label %PARABOLAISO_LABEL% - chainloader /shellia32.efi +if [ "${grub_platform}" == "efi" ]; then + if [ "${grub_cpu}" == "x86_64" ]; then + menuentry "UEFI Shell" { + insmod chain + search --no-floppy --set=root --label %PARABOLAISO_LABEL% + chainloader /shellx64.efi + } + elif [ "${grub_cpu}" == "i386" ]; then + menuentry "UEFI Shell" { + insmod chain + search --no-floppy --set=root --label %PARABOLAISO_LABEL% + chainloader /shellia32.efi + } + fi + + menuentry 'UEFI Firmware Settings' --id 'uefi-firmware' { + fwsetup + } +fi + +menuentry "System shutdown" --class shutdown --class poweroff { + echo "System shutting down..." + halt +} + +menuentry "System restart" --class reboot --class restart { + echo "System rebooting..." + reboot } diff --git a/docs/README.profile.rst b/docs/README.profile.rst index f2ba5e6..2da996d 100644 --- a/docs/README.profile.rst +++ b/docs/README.profile.rst @@ -48,6 +48,8 @@ The image file is constructed from some of the variables in ``profiledef.sh``: ` - ``bios.syslinux.eltorito``: Syslinux for x86 BIOS booting from an optical disc - ``uefi-ia32.grub.esp``: GRUB for IA32 UEFI booting from a disk - ``uefi-ia32.grub.eltorito``: GRUB for IA32 UEFI booting from an optical disc + - ``uefi-x64.grub.esp``: GRUB for x86_64 UEFI booting from a disk + - ``uefi-x64.grub.eltorito``: GRUB for x86_64 UEFI booting from an optical disc - ``uefi-x64.systemd-boot.esp``: systemd-boot for x86_64 UEFI booting from a disk - ``uefi-x64.systemd-boot.eltorito``: systemd-boot for x86_64 UEFI booting from an optical disc - ``uefi-x64.refind.esp``: rEFInd for x86_64 UEFI booting from a disk @@ -173,7 +175,12 @@ The *custom template identifiers* are understood in all `.cfg` files in this dir grub ---- -This directory is mandatory when the ``uefi-ia32.grub.esp`` or ``uefi-ia32.grub.eltorito`` bootmodes are selected in -``profiledef.sh``. +This directory is mandatory when any of the following bootmodes is used in ``profiledef.sh``: + +- ``uefi-ia32.grub.esp`` or +- ``uefi-ia32.grub.eltorito`` or +- ``uefi-x64.grub.esp`` or +- ``uefi-x64.grub.eltorito`` + It contains configuration files for `GRUB <https://www.gnu.org/software/grub/>`_ used in the resulting image. diff --git a/parabolaiso/mkparabolaiso b/parabolaiso/mkparabolaiso index 6af74b7..94fc352 100755 --- a/parabolaiso/mkparabolaiso +++ b/parabolaiso/mkparabolaiso @@ -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 @@ -257,7 +257,7 @@ _mksignature() { rm -f -- "${airootfs_image_filename}.sig" # Add gpg sender option if the value is provided [[ -z "${gpg_sender}" ]] || gpg_options+=('--sender' "${gpg_sender}") - # always use the .sig file extension, as that is what mkinitcpio-archiso's hooks expect + # always use the .sig file extension, as that is what mkinitcpio-parabolaiso's hooks expect gpg --batch --no-armor --no-include-key-block --output "${airootfs_image_filename}.sig" --detach-sign \ --default-key "${gpg_key}" "${gpg_options[@]}" "${airootfs_image_filename}" _msg_info "Done!" @@ -518,71 +518,91 @@ _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 PARAISO_EFI "${work_dir}/efiboot.img" "${imgsize}" > /dev/null + mkfs.fat -C -n PARAISO_EFI "${work_dir}/efiboot.img" "${imgsize_kib}" > /dev/null else - mkfs.fat -C -n PARAISO_EFI "${work_dir}/efiboot.img" "${imgsize}" + mkfs.fat -C -n PARAISO_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 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|%PARABOLAISO_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" + 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 file + # Create EFI binary grub-mkstandalone -O i386-efi \ --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" "${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 + # Copy GRUB EFI binary to the default/fallback boot path mcopy -i "${work_dir}/efiboot.img" \ "${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 @@ -597,7 +617,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..." @@ -611,7 +631,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" @@ -620,7 +639,84 @@ _make_bootmode_uefi-ia32.grub.eltorito() { _msg_info "Done!" } -# Prepare system-boot for booting when written to a disk (isohybrid) +_make_bootmode_uefi-x64.grub.esp() { + # Fill Grub configuration files + sed "s|%PARABOLAISO_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" + + # Create EFI binary + grub-mkstandalone -O x86_64-efi \ + --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" + "${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 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..." + 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}/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 systemd-boot for booting when written to a disk (isohybrid) _make_bootmode_uefi-x64.systemd-boot.esp() { local efiboot_imgsize _msg_info "Setting up systemd-boot for UEFI booting..." @@ -664,13 +760,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..." @@ -845,6 +941,11 @@ _validate_common_requirements_bootmode_uefi-x64() { } _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 + _validate_common_requirements_bootmode_uefi-x64 # Check if systemd-boot configuration files exist if [[ ! -d "${profile}/efiboot/loader/entries" ]]; then @@ -868,6 +969,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 } @@ -878,7 +984,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() { @@ -914,6 +1028,65 @@ _validate_requirements_bootmode_uefi-x64.refind.eltorito() { _validate_requirements_bootmode_uefi-x64.refind.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}" @@ -1183,17 +1356,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 } @@ -1267,6 +1443,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/parabolaiso" + cp -a -- "${work_dir}/efiboot.img" "${isofs_dir}/EFI/parabolaiso/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/parabolaiso/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') +} + # rEFInd in an attached EFI system partition _add_xorrisofs_options_uefi-x64.refind.esp() { # _add_xorrisofs_options_uefi-x64.refind.esp does the exact same thing as _add_xorrisofs_options_uefi-x64.systemd-boot.esp |