diff options
68 files changed, 1687 insertions, 1040 deletions
diff --git a/.editorconfig b/.editorconfig index 7bc540f..6ef3c82 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,6 +16,10 @@ charset = utf-8 indent_style = space indent_size = 4 max_line_length = 120 +# for shfmt +switch_case_indent = true +binary_next_line = true + [*.{yml,yaml}] end_of_line = lf @@ -32,3 +36,6 @@ trim_trailing_whitespace = true charset = utf-8 indent_style = space indent_size = 2 + +[Makefile] +indent_style = tab @@ -3,5 +3,10 @@ parabolaiso-*.tar.gz* work/ out/ *.iso +*.img +*.cer +*.crt +*.key +*.pem user-data meta-data diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 0000000..75aca74 --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1,11 @@ +# Suggest explicitly using -n in `[ $var ]` +enable=avoid-nullary-conditions + +# Suggest 'command -v' instead of 'which' +enable=deprecate-which + +# Suggest quoting variables without metacharacters +enable=quote-safe-variables + +# Require [[ and warn about [ in Bash/Ksh +enable=require-double-brackets diff --git a/AUTHORS.rst b/AUTHORS.rst index 9dc5520..f3da577 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -2,36 +2,60 @@ Archiso Authors =============== +* 2hexed <2hexed@protonmail.com> * Aaron Griffin <aaron@archlinux.org> * Adam Purkrt <adam@purkrt.net> * Alexander Epaneshnikov <aarnaarn2@gmail.com> +* Alexander Speshilov <speshuric@gmail.com> +* Anton Hvornum <anton@hvornum.se> +* Antonio V <crazysnob@live.it> * Chandan Singh <cks071g2@gmail.com> * Charles Vejnar <ce@vejnar.org> * Christian Hesse <mail@eworm.de> * Christopher Brannon <cmbrannon79@gmail.com> * Dan McGee <dan@archlinux.org> +* Darren Ng <un1gfn@gmail.com> * David Runge <dvzrv@archlinux.org> * David Thurstenson <thurstylark@gmail.com> * Dieter Plaetinck <dieter@plaetinck.be> * Eli Schwartz <eschwartz@archlinux.org> +* Eric Toombs <567-ewtoombs@users.noreply.gitlab.archlinux.org> * Florian Pritz <bluewind@xinu.at> +* Francois Dupoux <fdupoux@users.sourceforge.net> * Gerardo Exequiel Pozzi <vmlinuz386@gmail.com> * Gerhard Brauer <gerbra@archlinux.de> +* Giancarlo Razzolini <grazzolini@archlinux.org> +* Howard Hicks <deimosian@gmail.com> * James Sitegen <jamesm.sitegen@gmail.com> +* Jonathan Liu <net147@gmail.com> +* Jonathon Fernyhough <jonathon@m2x.dev> * Justin Kromlinger <hashworks@archlinux.org> * Keshav Amburay <the.ridikulus.rat@gmail.com> +* Kristian Klausen <kristian@klausen.dk> * Loui Chang <louipc.ist@gmail.com> * Lukas Fleischer <archlinux@cryptocrack.de> * Martin Damian Fernandez <martin.damian.fernandez@gmail.com> +* Michael Gilchrist <michaelgilch@gmail.com> * Michael Vorburger <mike@vorburger.ch> +* Pellegrino Prevete <pellegrinoprevete@gmail.com> * Pierre Schmitz <pierre@archlinux.de> * Sean Enck <enckse@voidedtech.com> * Simo Leone <simo@archlinux.org> +* Simon Wilper <sxw@chronowerks.de> +* Sorin Pânca <sorin.panca@gmail.com> * Steffen Bönigk <boenki@gmx.de> * Sven-Hendrik Haase <svenstaro@gmail.com> * Thomas Bächler <thomas@archlinux.org> +* Tobias Powalowski <tpowa@archlinux.org> +* Tom Yan <tom.ty89@gmail.com> * Yu Li-Yu <afg984@gmail.com> +* Zig Globulin <zig@zigsystem.com> +* hayao <hayao@fascode.net> +* mono wock <aaronleemorrison@protonmail.com> * nl6720 <nl6720@gmail.com> +* plain linen <bcdedit@hotmail.com> +* shivanandvp <shivanandvp.oss@gmail.com> +* weltio weltio <weltio@web.de> * Øyvind Heggstad <heggstad@gmail.com> =================== @@ -39,11 +63,11 @@ Parabolaiso Authors =================== * Andreas Grapentin <andreas@grapentin.org> -* André Fabian Silva Delgado <emulatorman@parabola.nu> +* André Fabian Silva Delgado <emulatorman@hyperbola.info> * David P <megver83@parabola.nu> * Drtan Samos <drtan@lavabit.com> * Esteban Carnevale <alfplayer@mailoo.org> * Jorge Lopez <jorginho@riseup.net> * bill-auger <mr.j.spam.me@gmail.com> * chandan <cks071g2@gmail.com> -* Márcio Alexandre Silva Delgado <coadde@parabola.nu> +* Márcio Alexandre Silva Delgado <coadde@hyperbola.info> diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 12f6c6c..b2f9dc3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -11,9 +11,237 @@ Added Changed ------- +Deprecated +---------- + +Fixed +----- + Removed ------- +[74] - 2023-12-21 +================= + +Added +----- + +- Add bcachefs-tools to releng for access to bcachefs userspace tools. +- Add tftp as a valid protocol for downloading automated boot script. + +Changed +------- + +- Set ``RequiredForOnline=routable`` in systemd-networkd configuration files to improve the chances that the network + really is *online* when ``network-online.target`` is reached. + +Fixed +----- + +- Add missing replacement for the UUID variable in systemd-boot configuration files on ISO 9660. + +[73] - 2023-09-29 +================= + +Added +----- + +- Add bolt to releng for authorizing and otherwise managing Thunderbolt and USB4 devices. +- Add ``uefi-ia32.systemd-boot.esp`` and ``uefi-ia32.systemd-boot.eltorito`` boot modes that use systemd-boot for IA32 + UEFI. The boot modes of baseline and releng are not changed. +- Add GRUB configuration file ``/boot/grub/loopback.cfg`` to the releng and baseline profiles. It sets the necessary + boot parameters required for booting the ISO image as a file on a file system. + +Fixed +----- + +- Add ``/etc/localtime`` to the baseline profile to ensure the ISO can be booted successfully without triggering + questions from systemd-firstboot. + +[72] - 2023-08-29 +================= + +Added +----- + +- Add tpm2-tools to releng to allow clearing, creating and reading keys on the TPM. +- Add sequoia-sq and openpgp-card-tools as additional tooling for working with OpenPGP certificates and smartcards. + +Changed +------- + +- Moved custom ``mkinitcpio.conf`` files to ``/etc/mkinitcpio.conf.d/parabolaiso.conf``. +- Mount ``/etc/pacman.d/gnupg`` on tmpfs with option ``noswap`` instead of using ramfs. This ensures there is a limit to + the file system size. +- Enable systemd-networkd's support for IPv6 Privacy Extensions globally instead of per-connection. +- Moved custom ``sshd_config`` files to ``/ssh/sshd_config.d/10-parabolaiso.conf`` +- Use pcsclite for interfacing with smartcards, since both gnupg and opgpcard support it. + +Fixed +----- + +- Sign the root file system image only once. +- Make sure xorriso does not read its configuration files to prevent interference and unintended behavior. + +[71] - 2023-05-28 +================= + +Added +----- + +- Added classes for Memtest86+ and UEFI Shell menuentries. +- Add foot-terminfo and wezterm-terminfo packages to releng to support terminal emulators using them. E.g. when + installing via SSH. +- Add a new ``-r`` option to ``mkparabolaiso`` that deletes the working directly after the build. +- Add support for mDNS announce and resolve. + +Changed +------- + +- Increase EROFS compression for the baseline profile by using an extreme LZMA compression level and enabling the + experimental compressed fragments and data deduplication features. +- Identify the ISO volume via a UUID instead of a file system label in all boot loader configuration files. +- Update ``pacman.conf`` to match the one shipped with pacman 6.0.2-7 (from Arch) which removes the community repository. + +Fixed +----- + +- Wait for ``network-online.target`` to become active before trying to download the script passed via the ``script=`` + boot parameter. +- Subdirectories from ``grub/`` are copied to the ISO. +- Modify the commandline options to a ``cp`` command in ``mkparabolaiso`` so that the entire script does not exit with + failure when a custom ``.bashrc`` file is supplied with the parabolaiso configuration. This fix was needed after + **GNU Coreutils** recently changed the behaviour of the ``-n`` (or ``--no-clobber``) commandline option to the ``cp`` + command. +- Ensure ``SOURCE_DATE_EPOCH`` is read from the ``build_date`` file before ``profiledef.sh`` is sourced to ensure the + variable has a correct value when used inside ``profiledef.sh``. + + +[70] - 2023-02-27 +================= + +Added +----- + +- Support *file system transposition* to simplify boot medium preparation for UEFI boot via extracting the ISO image + contents to a drive. ``grub.cfg`` does not hardcode the ISO volume label anymore, instead GRUB will search for volume + with a ``/boot/grub/YYYY-mm-dd-HH-MM-SS-00.uuid`` file on it. +- Preload GRUB's NTFS modules for UEFI that allegedly have native NTFS support. GRUB's exFAT and UDF modules are also + preloaded in case someone finds them useful. + +Changed +------- + +- Identify the ISO volume via a UUID instead of a file system label to avoid collisions of multiple ISOs created in the + same month. +- Honor ``SOURCE_DATE_EPOCH`` in the ``date`` command used by ``profiledef.sh`` of the shipped profiles. +- Do not duplicate ``grub.cfg`` in both ISO 9660 and the EFI system partition / El Torito image. GRUB will search for + the ISO volume and load the ``grub.cfg`` from there. +- Moved GRUB files on ISO 9660 from ``/EFI/BOOT/`` to a boot-platform neutral place ``/boot/grub/``. This does not apply + to the EFI binaries that remain in the default/fallback boot path. +- Move ``grubenv`` to ``/boot/grub/grubenv`` on ISO 9660 so that it is together with the rest of GRUB-specific files. + Additionally write more variables in it. The previous ``/${install_dir}/grubenv`` (``/parabola/grubenv`` for releng) + is deprecated and a future parabolaiso release will not create this file anymore. +- Moved syslinux directory from ``/syslinux/`` to ``/boot/syslinux/`` to keep most boot loader files in ``/boot/``. +- Update ``README.transfer`` documentation and convert it to reStructuredText. +- Use ``console`` as grub's ``terminal_output``, as ``gfxterm`` leads to a blank screen on some hardware. + +Removed +------- + +- Do not place memtest86+ in netboot artifacts. + +[69] - 2022-12-24 +================= + +Added +----- + +- Add Memtest86+ to x86_64 UEFI GRUB boot menu. + +Changed +------- + +- Check if the GPG public key file was successfully placed in the work directory before trying to use it. +- Open the file descriptors for code signing certificates and GPG public key as read only. Nothing from the within the + ``pacstrap`` invoked chroot should ever be allowed to write outside of it. +- Error out early if any of the code signing certificate files passed with option ``-c`` do not exist. +- Use LZMA compressed EROFS image for the baseline profile. Now that xz 5.4 is out and erofs-utils is built with LZMA + support, using a higher compression is possible. +- Add ``/etc/machine-id`` with special value ``uninitialized``. The final id is generated at boot time, and systemd's + first-boot mechanim (see ``First Boot Semantics`` in ``machine-id(5)``) applies. No functional change unless that + ``ConditionFirstBoot=yes`` is true and passive unit ``first-boot-complete.target`` activates for ordering. + +[68] - 2022-10-30 +================= + +Changed +------- + +- Do not explicitly enable ``qemu-guest-agent.service`` as it will be started by a udev rule. +- Remove existing signature (``.sig``) files and do not sign them when signing netboot artifacts. This is mostly + applicable when re-running ``mkparabolaiso`` after a failure. +- Replace ``parabolaiso_kms`` with ``kms`` in ``mkinitcpio.conf``. The hook is available in mkinitcpio since version 32. + +[67] - 2022-09-25 +================= + +Added +----- + +- The ability to generate rootfs signatures using openssl CMS module if ``-c`` is given. + +Changed +------- + +- Order ``pacman-init.service`` before ``archlinux-keyring-wkd-sync.service`` since + ``archlinux-keyring-wkd-sync.service`` needs an initialized pacman keyring. +- Order ``pacman-init.service`` after ``time-sync.target`` since ``pacman-init.service`` may otherwise create local + signatures that are not valid on target systems after installation. + +[66] - 2022-08-28 +================= + +Added +----- + +- Add ``efibootimg`` to ``mkarchiso`` to abstract the FAT image path. +- Unset ``LANGUAGE`` since ``LC_ALL=C.UTF-8``, unlike ``LC_ALL=C``, does not override ``LANGUAGE``. +- 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 +------- + +- 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. + +[65] - 2022-06-30 +================= + +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. +- Remove "Copy to RAM" boot entries since the ``parabolaiso`` mkinitcpio hook enables it automatically when there is enough + free RAM. +- Drop parabolaiso rEFInd support in favor of upstream archiso GRUB EFI bootmode. + [64] - 2022-05-30 ================= @@ -148,7 +376,7 @@ Removed ------- - Remove all files related to ``mkinitcpio`` integration, as they now live in - https://gitlab.archlinux.org/mkinitcpio/mkinitcpio-archiso + https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio-archiso [57] - 2021-07-30 ================= @@ -130,7 +130,7 @@ boot the iso image from GRUB with a version specific cow directory to mitigate o .. code:: sh loopback loop parabola.iso - load_env -f (loop)/parabola/grubenv + load_env -f (loop)/boot/grub/grubenv linux (loop)/parabola/boot/x86_64/vmlinuz-linux-libre ... \ cow_directory=parabola/${VERSION} ... initrd (loop)/parabola/boot/x86_64/initramfs-linux-libre-lts.img 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/airootfs/etc/localtime b/configs/baseline/airootfs/etc/localtime Binary files differnew file mode 100644 index 0000000..91558be --- /dev/null +++ b/configs/baseline/airootfs/etc/localtime diff --git a/configs/baseline/airootfs/etc/mkinitcpio.conf b/configs/baseline/airootfs/etc/mkinitcpio.conf deleted file mode 100644 index 9a851c9..0000000 --- a/configs/baseline/airootfs/etc/mkinitcpio.conf +++ /dev/null @@ -1,67 +0,0 @@ -# vim:set ft=sh -# MODULES -# The following modules are loaded before any boot hooks are -# run. Advanced users may wish to specify all system modules -# in this array. For instance: -# MODULES=(piix ide_disk reiserfs) -MODULES=() - -# BINARIES -# This setting includes any additional binaries a given user may -# wish into the CPIO image. This is run last, so it may be used to -# override the actual binaries included by a given hook -# BINARIES are dependency parsed, so you may safely ignore libraries -BINARIES=() - -# FILES -# This setting is similar to BINARIES above, however, files are added -# as-is and are not parsed in any way. This is useful for config files. -FILES=() - -# HOOKS -# This is the most important setting in this file. The HOOKS control the -# modules and scripts added to the image, and what happens at boot time. -# Order is important, and it is recommended that you do not change the -# order in which HOOKS are added. Run 'mkinitcpio -H <hook name>' for -# help on a given hook. -# 'base' is _required_ unless you know precisely what you are doing. -# 'udev' is _required_ in order to automatically load modules -# 'filesystems' is _required_ unless you specify your fs modules in MODULES -# Examples: -## This setup specifies all modules in the MODULES setting above. -## No raid, lvm2, or encrypted root is needed. -# HOOKS=(base) -# -## This setup will autodetect all modules for your system and should -## work as a sane default -# HOOKS=(base udev autodetect block filesystems) -# -## This setup will generate a 'full' image which supports most systems. -## No autodetection is done. -# HOOKS=(base udev block filesystems) -# -## This setup assembles a pata mdadm array with an encrypted root FS. -## Note: See 'mkinitcpio -H mdadm' for more information on raid devices. -# HOOKS=(base udev block mdadm encrypt filesystems) -# -## This setup loads an lvm2 volume group on a usb device. -# HOOKS=(base udev block lvm2 filesystems) -# -## NOTE: If you have /usr on a separate partition, you MUST include the -# usr, fsck and shutdown hooks. -HOOKS=(base udev modconf parabolaiso block filesystems) - -# COMPRESSION -# Use this to compress the initramfs image. By default, gzip compression -# is used. Use 'cat' to create an uncompressed image. -#COMPRESSION="gzip" -#COMPRESSION="bzip2" -#COMPRESSION="lzma" -#COMPRESSION="xz" -#COMPRESSION="lzop" -#COMPRESSION="lz4" -#COMPRESSION="zstd" - -# COMPRESSION_OPTIONS -# Additional options for the compressor -#COMPRESSION_OPTIONS=() diff --git a/configs/baseline/airootfs/etc/mkinitcpio.conf.d/parabolaiso.conf b/configs/baseline/airootfs/etc/mkinitcpio.conf.d/parabolaiso.conf new file mode 100644 index 0000000..9d4877e --- /dev/null +++ b/configs/baseline/airootfs/etc/mkinitcpio.conf.d/parabolaiso.conf @@ -0,0 +1 @@ +HOOKS=(base udev modconf parabolaiso block filesystems) diff --git a/configs/baseline/airootfs/etc/mkinitcpio.d/linux-libre.preset b/configs/baseline/airootfs/etc/mkinitcpio.d/linux-libre.preset index 625a03d..282bcde 100644 --- a/configs/baseline/airootfs/etc/mkinitcpio.d/linux-libre.preset +++ b/configs/baseline/airootfs/etc/mkinitcpio.d/linux-libre.preset @@ -3,6 +3,6 @@ PRESETS=('parabolaiso') ALL_kver='/boot/vmlinuz-linux-libre' -ALL_config='/etc/mkinitcpio.conf' +parabolaiso_config='/etc/mkinitcpio.conf.d/parabolaiso.conf' parabolaiso_image="/boot/initramfs-linux-libre.img" diff --git a/configs/baseline/airootfs/etc/ssh/sshd_config b/configs/baseline/airootfs/etc/ssh/sshd_config deleted file mode 100644 index 93f7d63..0000000 --- a/configs/baseline/airootfs/etc/ssh/sshd_config +++ /dev/null @@ -1,116 +0,0 @@ -# $OpenBSD: sshd_config,v 1.104 2021/07/02 05:11:21 dtucker Exp $ - -# This is the sshd server system-wide configuration file. See -# sshd_config(5) for more information. - -# This sshd was compiled with PATH=/usr/local/sbin:/usr/local/bin:/usr/bin - -# The strategy used for options in the default sshd_config shipped with -# OpenSSH is to specify options with their default value where -# possible, but leave them commented. Uncommented options override the -# default value. - -#Port 22 -#AddressFamily any -#ListenAddress 0.0.0.0 -#ListenAddress :: - -#HostKey /etc/ssh/ssh_host_rsa_key -#HostKey /etc/ssh/ssh_host_ecdsa_key -#HostKey /etc/ssh/ssh_host_ed25519_key - -# Ciphers and keying -#RekeyLimit default none - -# Logging -#SyslogFacility AUTH -#LogLevel INFO - -# Authentication: - -#LoginGraceTime 2m -PermitRootLogin yes -#StrictModes yes -#MaxAuthTries 6 -#MaxSessions 10 - -#PubkeyAuthentication yes - -# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2 -# but this is overridden so installations will only check .ssh/authorized_keys -AuthorizedKeysFile .ssh/authorized_keys - -#AuthorizedPrincipalsFile none - -#AuthorizedKeysCommand none -#AuthorizedKeysCommandUser nobody - -# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts -#HostbasedAuthentication no -# Change to yes if you don't trust ~/.ssh/known_hosts for -# HostbasedAuthentication -#IgnoreUserKnownHosts no -# Don't read the user's ~/.rhosts and ~/.shosts files -#IgnoreRhosts yes - -# To disable tunneled clear text passwords, change to no here! -#PasswordAuthentication yes -#PermitEmptyPasswords no - -# Change to no to disable s/key passwords -#KbdInteractiveAuthentication yes - -# Kerberos options -#KerberosAuthentication no -#KerberosOrLocalPasswd yes -#KerberosTicketCleanup yes -#KerberosGetAFSToken no - -# GSSAPI options -#GSSAPIAuthentication no -#GSSAPICleanupCredentials yes - -# Set this to 'yes' to enable PAM authentication, account processing, -# and session processing. If this is enabled, PAM authentication will -# be allowed through the KbdInteractiveAuthentication and -# PasswordAuthentication. Depending on your PAM configuration, -# PAM authentication via KbdInteractiveAuthentication may bypass -# the setting of "PermitRootLogin without-password". -# If you just want the PAM account and session checks to run without -# PAM authentication, then enable this but set PasswordAuthentication -# and KbdInteractiveAuthentication to 'no'. -UsePAM yes - -#AllowAgentForwarding yes -#AllowTcpForwarding yes -#GatewayPorts no -#X11Forwarding no -#X11DisplayOffset 10 -#X11UseLocalhost yes -#PermitTTY yes -PrintMotd no # pam does that -#PrintLastLog yes -#TCPKeepAlive yes -#PermitUserEnvironment no -#Compression delayed -#ClientAliveInterval 0 -#ClientAliveCountMax 3 -#UseDNS no -#PidFile /run/sshd.pid -#MaxStartups 10:30:100 -#PermitTunnel no -#ChrootDirectory none -#VersionAddendum none - -# no default banner path -#Banner none - -# override default of no subsystems -Subsystem sftp /usr/lib/ssh/sftp-server - -# Example of overriding settings on a per-user basis -#Match User anoncvs -# X11Forwarding no -# AllowTcpForwarding no -# PermitTTY no -# ForceCommand cvs server diff --git a/configs/baseline/airootfs/etc/ssh/sshd_config.d/10-parabolaiso.conf b/configs/baseline/airootfs/etc/ssh/sshd_config.d/10-parabolaiso.conf new file mode 100644 index 0000000..6ea7b41 --- /dev/null +++ b/configs/baseline/airootfs/etc/ssh/sshd_config.d/10-parabolaiso.conf @@ -0,0 +1,3 @@ +# Allow root login using password authentication +PasswordAuthentication yes +PermitRootLogin yes diff --git a/configs/baseline/airootfs/etc/systemd/network.conf.d/ipv6-privacy-extensions.conf b/configs/baseline/airootfs/etc/systemd/network.conf.d/ipv6-privacy-extensions.conf new file mode 100644 index 0000000..0e9ceb4 --- /dev/null +++ b/configs/baseline/airootfs/etc/systemd/network.conf.d/ipv6-privacy-extensions.conf @@ -0,0 +1,2 @@ +[Network] +IPv6PrivacyExtensions=yes diff --git a/configs/baseline/airootfs/etc/systemd/network/20-ethernet.network b/configs/baseline/airootfs/etc/systemd/network/20-ethernet.network index 4b6a2ab..0e4287b 100644 --- a/configs/baseline/airootfs/etc/systemd/network/20-ethernet.network +++ b/configs/baseline/airootfs/etc/systemd/network/20-ethernet.network @@ -5,6 +5,9 @@ Name=en* Name=eth* +[Link] +RequiredForOnline=routable + [Network] DHCP=yes -IPv6PrivacyExtensions=yes +MulticastDNS=yes diff --git a/configs/baseline/airootfs/etc/systemd/resolved.conf.d/parabolaiso.conf b/configs/baseline/airootfs/etc/systemd/resolved.conf.d/parabolaiso.conf new file mode 100644 index 0000000..5d64185 --- /dev/null +++ b/configs/baseline/airootfs/etc/systemd/resolved.conf.d/parabolaiso.conf @@ -0,0 +1,4 @@ +# Default systemd-resolved configuration for parabolaiso + +[Resolve] +MulticastDNS=yes diff --git a/configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service b/configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service deleted file mode 120000 index 8e3ff80..0000000 --- a/configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/systemd/system/qemu-guest-agent.service
\ No newline at end of file diff --git a/configs/baseline/efiboot/loader/entries/01-parabolaiso-x86_64-linux-libre.conf b/configs/baseline/efiboot/loader/entries/01-parabolaiso-x86_64-linux-libre.conf index e89de03..dcfa3a9 100644 --- a/configs/baseline/efiboot/loader/entries/01-parabolaiso-x86_64-linux-libre.conf +++ b/configs/baseline/efiboot/loader/entries/01-parabolaiso-x86_64-linux-libre.conf @@ -1,4 +1,4 @@ title Parabola GNU/Linux-libre (x86_64, UEFI) linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img -options parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% +options parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=%PARABOLAISO_UUID% diff --git a/configs/baseline/efiboot/loader/entries/02-parabolaiso-x86_64-ram-linux-libre.conf b/configs/baseline/efiboot/loader/entries/02-parabolaiso-x86_64-ram-linux-libre.conf deleted file mode 100644 index 630af00..0000000 --- a/configs/baseline/efiboot/loader/entries/02-parabolaiso-x86_64-ram-linux-libre.conf +++ /dev/null @@ -1,4 +0,0 @@ -title Parabola GNU/Linux-libre (x86_64, UEFI) Copy to RAM -linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre -initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img -options parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% copytoram diff --git a/configs/baseline/grub/grub.cfg b/configs/baseline/grub/grub.cfg index 3d0234a..540ba68 100644 --- a/configs/baseline/grub/grub.cfg +++ b/configs/baseline/grub/grub.cfg @@ -1,29 +1,104 @@ +# Load partition table and file system modules insmod part_gpt insmod part_msdos insmod fat insmod iso9660 +insmod ntfs +insmod ntfscomp +insmod exfat +insmod udf -insmod all_video - -insmod font - +# Use graphics-mode output if loadfont "${prefix}/fonts/unicode.pf2" ; then - insmod gfxterm + insmod all_video set gfxmode="auto" terminal_input console - terminal_output gfxterm + terminal_output console fi -menuentry "Parabola GNU/Linux-libre (x86_64, UEFI)" { +# Enable serial console +insmod serial +insmod usbserial_common +insmod usbserial_ftdi +insmod usbserial_pl2303 +insmod usbserial_usbdebug +if serial --unit=0 --speed=115200; then + terminal_input --append serial + terminal_output --append serial +fi + +# Search for the ISO volume +if [ -z "${PARABOLAISO_UUID}" ]; then + if [ -z "${PARABOLAISO_HINT}" ]; then + regexp --set=1:PARABOLAISO_HINT '^\(([^)]+)\)' "${cmdpath}" + fi + search --no-floppy --set=root --file '%PARABOLAISO_SEARCH_FILENAME%' --hint "${PARABOLAISO_HINT}" + probe --set PARABOLAISO_UUID --fs-uuid "${root}" +fi + +# Get a human readable platform identifier +if [ "${grub_platform}" == 'efi' ]; then + parabolaiso_platform='UEFI' + if [ "${grub_cpu}" == 'x86_64' ]; then + parabolaiso_platform="x64 ${parabolaiso_platform}" + elif [ "${grub_cpu}" == 'i386' ]; then + parabolaiso_platform="IA32 ${parabolaiso_platform}" + else + parabolaiso_platform="${grub_cpu} ${parabolaiso_platform}" + fi +elif [ "${grub_platform}" == 'pc' ]; then + parabolaiso_platform='BIOS' +else + parabolaiso_platform="${grub_cpu} ${grub_platform}" +fi + +# Set default menu entry +default=parabola +timeout=15 +timeout_style=menu + +# Menu entries + +menuentry "Parabola GNU/Linux-libre (%ARCH%, ${parabolaiso_platform})" --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% - initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img + linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-libre parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=${PARABOLAISO_UUID} + initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-libre.img } -menuentry "Parabola GNU/Linux-libre (x86_64, UEFI) 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 - initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img +if [ "${grub_platform}" == 'efi' -a "${grub_cpu}" == 'x86_64' -a -f '/boot/memtest86+/memtest.efi' ]; then + menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class gnu --class tool { + set gfxpayload=800x600,1024x768 + linux /boot/memtest86+/memtest.efi + } +fi +if [ "${grub_platform}" == 'pc' -a -f '/boot/memtest86+/memtest' ]; then + menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class gnu --class tool { + set gfxpayload=800x600,1024x768 + linux /boot/memtest86+/memtest + } +fi +if [ "${grub_platform}" == 'efi' ]; then + if [ "${grub_cpu}" == 'x86_64' -a -f '/shellx64.efi' ]; then + menuentry 'UEFI Shell' { + chainloader /shellx64.efi + } + elif [ "${grub_cpu}" == "i386" -a -f '/shellia32.efi' ]; then + menuentry 'UEFI Shell' { + 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/configs/baseline/grub/loopback.cfg b/configs/baseline/grub/loopback.cfg new file mode 100644 index 0000000..149c879 --- /dev/null +++ b/configs/baseline/grub/loopback.cfg @@ -0,0 +1,73 @@ +# https://www.supergrubdisk.org/wiki/Loopback.cfg + +# Search for the ISO volume +search --no-floppy --set=parabolaiso_img_dev --file "${iso_path}" +probe --set parabolaiso_img_dev_uuid --fs-uuid "${parabolaiso_img_dev}" + +# Get a human readable platform identifier +if [ "${grub_platform}" == 'efi' ]; then + parabolaiso_platform='UEFI' + if [ "${grub_cpu}" == 'x86_64' ]; then + parabolaiso_platform="x64 ${parabolaiso_platform}" + elif [ "${grub_cpu}" == 'i386' ]; then + parabolaiso_platform="IA32 ${parabolaiso_platform}" + else + parabolaiso_platform="${grub_cpu} ${parabolaiso_platform}" + fi +elif [ "${grub_platform}" == 'pc' ]; then + parabolaiso_platform='BIOS' +else + parabolaiso_platform="${grub_cpu} ${grub_platform}" +fi + +# Set default menu entry +default=parabola +timeout=15 +timeout_style=menu + + +# Menu entries + +menuentry "Parabola GNU/Linux-libre (%ARCH%, ${parabolaiso_platform})" --class arch --class gnu-linux --class gnu --class os --id 'parabola' { + set gfxpayload=keep + linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-libre parabolaisobasedir=%INSTALL_DIR% img_dev=UUID=${parabolaiso_img_dev_uuid} img_loop="${iso_path}" + initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-libre.img +} + +if [ "${grub_platform}" == 'efi' -a "${grub_cpu}" == 'x86_64' -a -f '/boot/memtest86+/memtest.efi' ]; then + menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class gnu --class tool { + set gfxpayload=800x600,1024x768 + linux /boot/memtest86+/memtest.efi + } +fi +if [ "${grub_platform}" == 'pc' -a -f '/boot/memtest86+/memtest' ]; then + menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class gnu --class tool { + set gfxpayload=800x600,1024x768 + linux /boot/memtest86+/memtest + } +fi +if [ "${grub_platform}" == 'efi' ]; then + if [ "${grub_cpu}" == 'x86_64' -a -f '/shellx64.efi' ]; then + menuentry 'UEFI Shell' { + chainloader /shellx64.efi + } + elif [ "${grub_cpu}" == "i386" -a -f '/shellia32.efi' ]; then + menuentry 'UEFI Shell' { + 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/configs/baseline/pacman.conf b/configs/baseline/pacman.conf index 7bcfccb..59821bc 100644 --- a/configs/baseline/pacman.conf +++ b/configs/baseline/pacman.conf @@ -77,21 +77,12 @@ LocalFileSigLevel = Optional [libre] Include = /etc/pacman.d/mirrorlist -#[testing] -#Include = /etc/pacman.d/mirrorlist - [core] Include = /etc/pacman.d/mirrorlist [extra] Include = /etc/pacman.d/mirrorlist -#[community-testing] -#Include = /etc/pacman.d/mirrorlist - -[community] -Include = /etc/pacman.d/mirrorlist - #[pcr-testing] #Include = /etc/pacman.d/mirrorlist diff --git a/configs/baseline/profiledef.sh b/configs/baseline/profiledef.sh index 95c1364..7c35814 100644 --- a/configs/baseline/profiledef.sh +++ b/configs/baseline/profiledef.sh @@ -2,10 +2,10 @@ # shellcheck disable=SC2034 iso_name="parabola-baseline" -iso_label="PARA_$(date +%Y%m)" +iso_label="PARA_$(date --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y%m)" iso_publisher="Parabola GNU/Linux-libre <https://parabola.nu>" iso_application="Parabola GNU/Linux-libre baseline" -iso_version="$(date +%Y.%m.%d)" +iso_version="$(date --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y.%m.%d)" install_dir="parabola" buildmodes=('iso') bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito' @@ -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=('-zlzma,109' -E 'ztailpacking,fragments,dedupe') file_permissions=( ["/etc/shadow"]="0:0:400" ) diff --git a/configs/baseline/syslinux/syslinux-linux-libre.cfg b/configs/baseline/syslinux/syslinux-linux-libre.cfg index 47ac1e7..458bfe4 100644 --- a/configs/baseline/syslinux/syslinux-linux-libre.cfg +++ b/configs/baseline/syslinux/syslinux-linux-libre.cfg @@ -2,10 +2,4 @@ LABEL parabola MENU LABEL Parabola GNU/Linux-libre (x86_64, BIOS) LINUX /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-libre INITRD /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% - -LABEL parabola-ram -MENU LABEL Parabola GNU/Linux-libre (x86_64, BIOS) Copy to RAM -LINUX /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-libre -INITRD /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% copytoram +APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=%PARABOLAISO_UUID% 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/mkinitcpio.conf b/configs/releng/airootfs/etc/mkinitcpio.conf deleted file mode 100644 index f1d34eb..0000000 --- a/configs/releng/airootfs/etc/mkinitcpio.conf +++ /dev/null @@ -1,67 +0,0 @@ -# vim:set ft=sh -# MODULES -# The following modules are loaded before any boot hooks are -# run. Advanced users may wish to specify all system modules -# in this array. For instance: -# MODULES=(piix ide_disk reiserfs) -MODULES=() - -# BINARIES -# This setting includes any additional binaries a given user may -# wish into the CPIO image. This is run last, so it may be used to -# override the actual binaries included by a given hook -# BINARIES are dependency parsed, so you may safely ignore libraries -BINARIES=() - -# FILES -# This setting is similar to BINARIES above, however, files are added -# as-is and are not parsed in any way. This is useful for config files. -FILES=() - -# HOOKS -# This is the most important setting in this file. The HOOKS control the -# modules and scripts added to the image, and what happens at boot time. -# Order is important, and it is recommended that you do not change the -# order in which HOOKS are added. Run 'mkinitcpio -H <hook name>' for -# help on a given hook. -# 'base' is _required_ unless you know precisely what you are doing. -# 'udev' is _required_ in order to automatically load modules -# 'filesystems' is _required_ unless you specify your fs modules in MODULES -# Examples: -## This setup specifies all modules in the MODULES setting above. -## No raid, lvm2, or encrypted root is needed. -# HOOKS=(base) -# -## This setup will autodetect all modules for your system and should -## work as a sane default -# HOOKS=(base udev autodetect block filesystems) -# -## This setup will generate a 'full' image which supports most systems. -## No autodetection is done. -# HOOKS=(base udev block filesystems) -# -## This setup assembles a pata mdadm array with an encrypted root FS. -## Note: See 'mkinitcpio -H mdadm' for more information on raid devices. -# HOOKS=(base udev block mdadm encrypt filesystems) -# -## This setup loads an lvm2 volume group on a usb device. -# HOOKS=(base udev block lvm2 filesystems) -# -## NOTE: If you have /usr on a separate partition, you MUST include the -# usr, fsck and shutdown hooks. -HOOKS=(base udev modconf memdisk parabolaiso parabolaiso_loop_mnt parabolaiso_pxe_common parabolaiso_pxe_nbd parabolaiso_pxe_http parabolaiso_pxe_nfs parabolaiso_kms block filesystems keyboard) - -# COMPRESSION -# Use this to compress the initramfs image. By default, gzip compression -# is used. Use 'cat' to create an uncompressed image. -#COMPRESSION="gzip" -#COMPRESSION="bzip2" -#COMPRESSION="lzma" -COMPRESSION="xz" -#COMPRESSION="lzop" -#COMPRESSION="lz4" -#COMPRESSION="zstd" - -# COMPRESSION_OPTIONS -# Additional options for the compressor -#COMPRESSION_OPTIONS=() diff --git a/configs/releng/airootfs/etc/mkinitcpio.conf.d/parabolaiso.conf b/configs/releng/airootfs/etc/mkinitcpio.conf.d/parabolaiso.conf new file mode 100644 index 0000000..26c74ea --- /dev/null +++ b/configs/releng/airootfs/etc/mkinitcpio.conf.d/parabolaiso.conf @@ -0,0 +1,2 @@ +HOOKS=(base udev modconf kms memdisk parabolaiso parabolaiso_loop_mnt parabolaiso_pxe_common parabolaiso_pxe_nbd parabolaiso_pxe_http parabolaiso_pxe_nfs block filesystems keyboard) +COMPRESSION="xz" diff --git a/configs/releng/airootfs/etc/mkinitcpio.d/linux-libre.preset b/configs/releng/airootfs/etc/mkinitcpio.d/linux-libre.preset index 625a03d..282bcde 100644 --- a/configs/releng/airootfs/etc/mkinitcpio.d/linux-libre.preset +++ b/configs/releng/airootfs/etc/mkinitcpio.d/linux-libre.preset @@ -3,6 +3,6 @@ PRESETS=('parabolaiso') ALL_kver='/boot/vmlinuz-linux-libre' -ALL_config='/etc/mkinitcpio.conf' +parabolaiso_config='/etc/mkinitcpio.conf.d/parabolaiso.conf' parabolaiso_image="/boot/initramfs-linux-libre.img" 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/airootfs/etc/ssh/sshd_config b/configs/releng/airootfs/etc/ssh/sshd_config deleted file mode 100644 index 93f7d63..0000000 --- a/configs/releng/airootfs/etc/ssh/sshd_config +++ /dev/null @@ -1,116 +0,0 @@ -# $OpenBSD: sshd_config,v 1.104 2021/07/02 05:11:21 dtucker Exp $ - -# This is the sshd server system-wide configuration file. See -# sshd_config(5) for more information. - -# This sshd was compiled with PATH=/usr/local/sbin:/usr/local/bin:/usr/bin - -# The strategy used for options in the default sshd_config shipped with -# OpenSSH is to specify options with their default value where -# possible, but leave them commented. Uncommented options override the -# default value. - -#Port 22 -#AddressFamily any -#ListenAddress 0.0.0.0 -#ListenAddress :: - -#HostKey /etc/ssh/ssh_host_rsa_key -#HostKey /etc/ssh/ssh_host_ecdsa_key -#HostKey /etc/ssh/ssh_host_ed25519_key - -# Ciphers and keying -#RekeyLimit default none - -# Logging -#SyslogFacility AUTH -#LogLevel INFO - -# Authentication: - -#LoginGraceTime 2m -PermitRootLogin yes -#StrictModes yes -#MaxAuthTries 6 -#MaxSessions 10 - -#PubkeyAuthentication yes - -# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2 -# but this is overridden so installations will only check .ssh/authorized_keys -AuthorizedKeysFile .ssh/authorized_keys - -#AuthorizedPrincipalsFile none - -#AuthorizedKeysCommand none -#AuthorizedKeysCommandUser nobody - -# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts -#HostbasedAuthentication no -# Change to yes if you don't trust ~/.ssh/known_hosts for -# HostbasedAuthentication -#IgnoreUserKnownHosts no -# Don't read the user's ~/.rhosts and ~/.shosts files -#IgnoreRhosts yes - -# To disable tunneled clear text passwords, change to no here! -#PasswordAuthentication yes -#PermitEmptyPasswords no - -# Change to no to disable s/key passwords -#KbdInteractiveAuthentication yes - -# Kerberos options -#KerberosAuthentication no -#KerberosOrLocalPasswd yes -#KerberosTicketCleanup yes -#KerberosGetAFSToken no - -# GSSAPI options -#GSSAPIAuthentication no -#GSSAPICleanupCredentials yes - -# Set this to 'yes' to enable PAM authentication, account processing, -# and session processing. If this is enabled, PAM authentication will -# be allowed through the KbdInteractiveAuthentication and -# PasswordAuthentication. Depending on your PAM configuration, -# PAM authentication via KbdInteractiveAuthentication may bypass -# the setting of "PermitRootLogin without-password". -# If you just want the PAM account and session checks to run without -# PAM authentication, then enable this but set PasswordAuthentication -# and KbdInteractiveAuthentication to 'no'. -UsePAM yes - -#AllowAgentForwarding yes -#AllowTcpForwarding yes -#GatewayPorts no -#X11Forwarding no -#X11DisplayOffset 10 -#X11UseLocalhost yes -#PermitTTY yes -PrintMotd no # pam does that -#PrintLastLog yes -#TCPKeepAlive yes -#PermitUserEnvironment no -#Compression delayed -#ClientAliveInterval 0 -#ClientAliveCountMax 3 -#UseDNS no -#PidFile /run/sshd.pid -#MaxStartups 10:30:100 -#PermitTunnel no -#ChrootDirectory none -#VersionAddendum none - -# no default banner path -#Banner none - -# override default of no subsystems -Subsystem sftp /usr/lib/ssh/sftp-server - -# Example of overriding settings on a per-user basis -#Match User anoncvs -# X11Forwarding no -# AllowTcpForwarding no -# PermitTTY no -# ForceCommand cvs server diff --git a/configs/releng/airootfs/etc/ssh/sshd_config.d/10-parabolaiso.conf b/configs/releng/airootfs/etc/ssh/sshd_config.d/10-parabolaiso.conf new file mode 100644 index 0000000..6ea7b41 --- /dev/null +++ b/configs/releng/airootfs/etc/ssh/sshd_config.d/10-parabolaiso.conf @@ -0,0 +1,3 @@ +# Allow root login using password authentication +PasswordAuthentication yes +PermitRootLogin yes diff --git a/configs/releng/airootfs/etc/systemd/network.conf.d/ipv6-privacy-extensions.conf b/configs/releng/airootfs/etc/systemd/network.conf.d/ipv6-privacy-extensions.conf new file mode 100644 index 0000000..0e9ceb4 --- /dev/null +++ b/configs/releng/airootfs/etc/systemd/network.conf.d/ipv6-privacy-extensions.conf @@ -0,0 +1,2 @@ +[Network] +IPv6PrivacyExtensions=yes diff --git a/configs/releng/airootfs/etc/systemd/network/20-ethernet.network b/configs/releng/airootfs/etc/systemd/network/20-ethernet.network index 9ada778..d3a3271 100644 --- a/configs/releng/airootfs/etc/systemd/network/20-ethernet.network +++ b/configs/releng/airootfs/etc/systemd/network/20-ethernet.network @@ -5,9 +5,12 @@ Name=en* Name=eth* +[Link] +RequiredForOnline=routable + [Network] DHCP=yes -IPv6PrivacyExtensions=yes +MulticastDNS=yes # systemd-networkd does not set per-interface-type default route metrics # https://github.com/systemd/systemd/issues/17698 diff --git a/configs/releng/airootfs/etc/systemd/network/20-wlan.network b/configs/releng/airootfs/etc/systemd/network/20-wlan.network index 601d5b8..8b70a95 100644 --- a/configs/releng/airootfs/etc/systemd/network/20-wlan.network +++ b/configs/releng/airootfs/etc/systemd/network/20-wlan.network @@ -1,9 +1,12 @@ [Match] Name=wl* +[Link] +RequiredForOnline=routable + [Network] DHCP=yes -IPv6PrivacyExtensions=yes +MulticastDNS=yes # systemd-networkd does not set per-interface-type default route metrics # https://github.com/systemd/systemd/issues/17698 diff --git a/configs/releng/airootfs/etc/systemd/network/20-wwan.network b/configs/releng/airootfs/etc/systemd/network/20-wwan.network index 55dadc2..6e1c8dd 100644 --- a/configs/releng/airootfs/etc/systemd/network/20-wwan.network +++ b/configs/releng/airootfs/etc/systemd/network/20-wwan.network @@ -1,9 +1,11 @@ [Match] -Type=ww* +Name=ww* + +[Link] +RequiredForOnline=routable [Network] DHCP=yes -IPv6PrivacyExtensions=yes # systemd-networkd does not set per-interface-type default route metrics # https://github.com/systemd/systemd/issues/17698 @@ -11,7 +13,7 @@ IPv6PrivacyExtensions=yes # Use values from NetworkManager. From nm_device_get_route_metric_default in # https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c [DHCPv4] -RouteMetric=2048 +RouteMetric=700 [IPv6AcceptRA] RouteMetric=700 diff --git a/configs/releng/airootfs/etc/systemd/resolved.conf.d/parabolaiso.conf b/configs/releng/airootfs/etc/systemd/resolved.conf.d/parabolaiso.conf new file mode 100644 index 0000000..5d64185 --- /dev/null +++ b/configs/releng/airootfs/etc/systemd/resolved.conf.d/parabolaiso.conf @@ -0,0 +1,4 @@ +# Default systemd-resolved configuration for parabolaiso + +[Resolve] +MulticastDNS=yes diff --git a/configs/releng/airootfs/etc/systemd/system/dbus-org.freedesktop.timesync1.service b/configs/releng/airootfs/etc/systemd/system/dbus-org.freedesktop.timesync1.service new file mode 120000 index 0000000..cd00411 --- /dev/null +++ b/configs/releng/airootfs/etc/systemd/system/dbus-org.freedesktop.timesync1.service @@ -0,0 +1 @@ +/usr/lib/systemd/system/systemd-timesyncd.service
\ No newline at end of file diff --git a/configs/releng/airootfs/etc/systemd/system/etc-pacman.d-gnupg.mount b/configs/releng/airootfs/etc/systemd/system/etc-pacman.d-gnupg.mount index 0ba0e67..038961e 100644 --- a/configs/releng/airootfs/etc/systemd/system/etc-pacman.d-gnupg.mount +++ b/configs/releng/airootfs/etc/systemd/system/etc-pacman.d-gnupg.mount @@ -2,7 +2,7 @@ Description=Temporary /etc/pacman.d/gnupg directory [Mount] -What=ramfs +What=tmpfs Where=/etc/pacman.d/gnupg -Type=ramfs -Options=mode=0755 +Type=tmpfs +Options=mode=0755,noswap diff --git a/configs/releng/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service b/configs/releng/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service deleted file mode 120000 index 8e3ff80..0000000 --- a/configs/releng/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/systemd/system/qemu-guest-agent.service
\ No newline at end of file diff --git a/configs/releng/airootfs/etc/systemd/system/pacman-init.service b/configs/releng/airootfs/etc/systemd/system/pacman-init.service index b18f7f8..b824884 100644 --- a/configs/releng/airootfs/etc/systemd/system/pacman-init.service +++ b/configs/releng/airootfs/etc/systemd/system/pacman-init.service @@ -1,7 +1,9 @@ [Unit] Description=Initializes Pacman keyring Requires=etc-pacman.d-gnupg.mount -After=etc-pacman.d-gnupg.mount +After=etc-pacman.d-gnupg.mount time-sync.target +BindsTo=etc-pacman.d-gnupg.mount +Before=archlinux-keyring-wkd-sync.service [Service] Type=oneshot diff --git a/configs/releng/airootfs/etc/systemd/system/sockets.target.wants/pcscd.socket b/configs/releng/airootfs/etc/systemd/system/sockets.target.wants/pcscd.socket new file mode 120000 index 0000000..3897c63 --- /dev/null +++ b/configs/releng/airootfs/etc/systemd/system/sockets.target.wants/pcscd.socket @@ -0,0 +1 @@ +/usr/lib/systemd/system/pcscd.socket
\ No newline at end of file diff --git a/configs/releng/airootfs/etc/systemd/system/sysinit.target.wants/systemd-time-wait-sync.service b/configs/releng/airootfs/etc/systemd/system/sysinit.target.wants/systemd-time-wait-sync.service new file mode 120000 index 0000000..cabf28b --- /dev/null +++ b/configs/releng/airootfs/etc/systemd/system/sysinit.target.wants/systemd-time-wait-sync.service @@ -0,0 +1 @@ +/usr/lib/systemd/system/systemd-time-wait-sync.service
\ No newline at end of file diff --git a/configs/releng/airootfs/etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service b/configs/releng/airootfs/etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service new file mode 120000 index 0000000..cd00411 --- /dev/null +++ b/configs/releng/airootfs/etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service @@ -0,0 +1 @@ +/usr/lib/systemd/system/systemd-timesyncd.service
\ No newline at end of file diff --git a/configs/releng/airootfs/root/.automated_script.sh b/configs/releng/airootfs/root/.automated_script.sh index 52c47e6..0d95012 100755 --- a/configs/releng/airootfs/root/.automated_script.sh +++ b/configs/releng/airootfs/root/.automated_script.sh @@ -1,22 +1,29 @@ #!/usr/bin/env bash -script_cmdline () -{ +script_cmdline() { local param - for param in $(< /proc/cmdline); do + for param in $(</proc/cmdline); do case "${param}" in - script=*) echo "${param#*=}" ; return 0 ;; + script=*) + echo "${param#*=}" + return 0 + ;; esac done } -automated_script () -{ +automated_script() { local script rt script="$(script_cmdline)" if [[ -n "${script}" && ! -x /tmp/startup_script ]]; then - if [[ "${script}" =~ ^((http|https|ftp)://) ]]; then - curl "${script}" --location --retry-connrefused --retry 10 -s -o /tmp/startup_script >/dev/null + if [[ "${script}" =~ ^((http|https|ftp|tftp)://) ]]; then + # there's no synchronization for network availability before executing this script + printf '%s: waiting for network-online.target\n' "$0" + until systemctl --quiet is-active network-online.target; do + sleep 1 + done + printf '%s: downloading %s\n' "$0" "${script}" + curl "${script}" --location --retry-connrefused --retry 10 -s -o /tmp/startup_script rt=$? else cp "${script}" /tmp/startup_script @@ -24,6 +31,9 @@ automated_script () fi if [[ ${rt} -eq 0 ]]; then chmod +x /tmp/startup_script + printf '%s: executing automated script\n' "$0" + # note that script is executed when other services (like pacman-init) may be still in progress, please + # synchronize to "systemctl is-system-running --wait" when your script depends on other services /tmp/startup_script fi fi diff --git a/configs/releng/airootfs/root/.gnupg/scdaemon.conf b/configs/releng/airootfs/root/.gnupg/scdaemon.conf new file mode 100644 index 0000000..e1f3d1f --- /dev/null +++ b/configs/releng/airootfs/root/.gnupg/scdaemon.conf @@ -0,0 +1,4 @@ +disable-ccid +disable-pinpad +pcsc-driver /usr/lib/libpcsclite.so +pcsc-shared diff --git a/configs/releng/airootfs/root/.zlogin b/configs/releng/airootfs/root/.zlogin index 0fb119d..bf6bc8f 100644 --- a/configs/releng/airootfs/root/.zlogin +++ b/configs/releng/airootfs/root/.zlogin @@ -1,5 +1,5 @@ # fix for screen readers -if grep -Fq 'accessibility=' /proc/cmdline &> /dev/null; then +if grep -Fqa 'accessibility=' /proc/cmdline &> /dev/null; then setopt SINGLE_LINE_ZLE fi diff --git a/configs/releng/airootfs/usr/local/bin/choose-mirror b/configs/releng/airootfs/usr/local/bin/choose-mirror index e8f8254..2f881e4 100755 --- a/configs/releng/airootfs/usr/local/bin/choose-mirror +++ b/configs/releng/airootfs/usr/local/bin/choose-mirror @@ -4,21 +4,22 @@ get_cmdline() { local param - for param in $(< /proc/cmdline); do + for param in $(</proc/cmdline); do case "${param}" in - $1=*) echo "${param##*=}"; - return 0 - ;; + "${1}="*) + echo "${param##*=}" + return 0 + ;; esac done } -mirror=$(get_cmdline mirror) -[[ $mirror = auto ]] && mirror=$(get_cmdline parabolaiso_http_srv) -[[ $mirror ]] || exit 0 +mirror="$(get_cmdline mirror)" +[[ "$mirror" == 'auto' ]] && mirror="$(get_cmdline parabolaiso_http_srv)" +[[ -n "$mirror" ]] || exit 0 mv /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.orig -cat >/etc/pacman.d/mirrorlist << EOF +cat >/etc/pacman.d/mirrorlist <<EOF # # Parabola GNU/Linux-libre repository mirrorlist # Generated by parabolaiso diff --git a/configs/releng/airootfs/usr/local/bin/livecd-sound b/configs/releng/airootfs/usr/local/bin/livecd-sound index baae0d2..b92fcf2 100755 --- a/configs/releng/airootfs/usr/local/bin/livecd-sound +++ b/configs/releng/airootfs/usr/local/bin/livecd-sound @@ -3,7 +3,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later usage() { - cat <<- _EOF_ + cat <<-_EOF_ live cd sound helper script. Usage: livecdsound [OPTION] OPTIONS @@ -14,14 +14,13 @@ usage() { _EOF_ } -bugout () { +bugout() { printf "/usr/local/bin/livecdsound: programming error" stat_fail } -echo_card_indices() -{ - if [ -f /proc/asound/cards ] ; then +echo_card_indices() { + if [[ -f /proc/asound/cards ]]; then sed -n -e's/^[[:space:]]*\([0-7]\)[[:space:]].*/\1/p' /proc/asound/cards fi } @@ -33,8 +32,8 @@ echo_card_indices() # $1 <card id> # $2 <control> # $3 <level> -unmute_and_set_level(){ - { [ "$3" ] &&[ "$2" ] && [ "$1" ] ; } || bugout +unmute_and_set_level() { + [[ -n "$3" && -n "$2" && -n "$1" ]] || bugout systemd-cat -t "livecdsound" printf "Setting: %s on card: %s to %s\n" "$2" "$1" "$3" systemd-cat -t "livecdsound" amixer -c "$1" set "$2" "$3" unmute return 0 @@ -42,9 +41,8 @@ unmute_and_set_level(){ # $1 <card id> # $2 <control> -mute_and_zero_level() -{ - { [ "$1" ] && [ "$2" ] ; } || bugout +mute_and_zero_level() { + [[ -n "$1" && -n "$2" ]] || bugout systemd-cat -t "livecdsound" printf "Muting control: %s on card: %s\n" "$2" "$1" systemd-cat -t "livecdsound" amixer -c "$1" set "$2" "0%" mute return 0 @@ -53,17 +51,15 @@ mute_and_zero_level() # $1 <card ID> # $2 <control> # $3 "on" | "off" -switch_control() -{ - { [ "$3" ] && [ "$1" ] ; } || bugout +switch_control() { + [[ -n "$3" && -n "$1" ]] || bugout systemd-cat -t "livecdsound" printf "Switching control: %s on card: %s to %s\n" "$2" "$1" "$3" systemd-cat -t "livecdsound" amixer -c "$1" set "$2" "$3" return 0 } # $1 <card ID> -sanify_levels_on_card() -{ +sanify_levels_on_card() { unmute_and_set_level "$1" "Front" "80%" unmute_and_set_level "$1" "Master" "80%" unmute_and_set_level "$1" "Master Mono" "80%" @@ -134,94 +130,89 @@ sanify_levels_on_card() } # $1 <card ID> | "all" -sanify_levels() -{ +sanify_levels() { local ttsdml_returnstatus=0 local card case "$1" in - all) - for card in $(echo_card_indices) ; do - sanify_levels_on_card "$card" || ttsdml_returnstatus=1 - done - ;; - *) - sanify_levels_on_card "$1" || ttsdml_returnstatus=1 - ;; + all) + for card in $(echo_card_indices); do + sanify_levels_on_card "$card" || ttsdml_returnstatus=1 + done + ;; + *) + sanify_levels_on_card "$1" || ttsdml_returnstatus=1 + ;; esac - return $ttsdml_returnstatus + return "$ttsdml_returnstatus" } # List all cards that *should* be usable for PCM audio. In my experience, # the console speaker (handled by the pcsp driver) isn't a suitable playback # device, so we'll exclude it. -list_non_pcsp_cards() -{ +list_non_pcsp_cards() { for card in $(echo_card_indices); do local cardfile="/proc/asound/card${card}/id" - if [ -r "$cardfile" ] && [ -f "$cardfile" ] && \ - [ "$(cat "$cardfile")" != pcsp ]; then + if [[ -r "$cardfile" && -f "$cardfile" && "$(cat "$cardfile")" != pcsp ]]; then echo "$card" fi done } # Properly initialize the sound card so that we have audio at boot. -unmute_all_cards() -{ +unmute_all_cards() { sanify_levels all } is_numeric() { - local str=$1 + local str="$1" [[ "$str" =~ ^[0-9]+$ ]] } set_default_card() { - local card=$1 - sed -e "s/%card%/$card/g" < /usr/local/share/livecd-sound/asound.conf.in \ - > /etc/asound.conf + local card="$1" + sed -e "s/%card%/$card/g" </usr/local/share/livecd-sound/asound.conf.in \ + >/etc/asound.conf } play_on_card() { - local card=$1 file=$2 + local card="$1" file="$2" aplay -q "-Dplughw:$card,0" "$file" } # If there are multiple usable sound cards, prompt the user to choose one, # using auditory feedback. -pick_a_card() -{ +pick_a_card() { set -f usable_cards="$(list_non_pcsp_cards)" - num_usable_cards="$(wc -w <<< "$usable_cards")" + num_usable_cards="$(wc -w <<<"$usable_cards")" - if [ "$num_usable_cards" -eq 1 ]; then + if (( num_usable_cards == 1 )); then systemd-cat -t "livecdsound" printf "Only one sound card is detected\n" exit 0 fi systemd-cat -t "livecdsound" printf "multiple sound cards detected\n" - for card in $usable_cards; do + for card in "${usable_cards[@]}"; do if ! is_numeric "$card"; then continue fi - play_on_card "$card" /usr/share/livecd-sounds/pick-a-card.wav& + play_on_card "$card" /usr/share/livecd-sounds/pick-a-card.wav & done wait sleep 1 - for card in $usable_cards; do + for card in "${usable_cards[@]}"; do if ! is_numeric "$card"; then continue - fi - play_on_card "$card" /usr/share/livecd-sounds/beep.wav - if read -r -t 10; then - systemd-cat -t "livecdsound" printf "Selecting %s sound card as default\n" "$card" - set_default_card "$card" - break - fi -done + fi + play_on_card "$card" /usr/share/livecd-sounds/beep.wav + if read -r -t 10; then + systemd-cat -t "livecdsound" printf "Selecting %s sound card as default\n" "$card" + set_default_card "$card" + break + fi + done } -if [[ $# -eq 0 ]]; then +if (( $# == 0 )); then echo "error: No argument passed." exit 1 fi diff --git a/configs/releng/efiboot/loader/entries/01-parabolaiso-x86_64-linux-libre.conf b/configs/releng/efiboot/loader/entries/01-parabolaiso-x86_64-linux-libre.conf index 925962a..1af7867 100644 --- a/configs/releng/efiboot/loader/entries/01-parabolaiso-x86_64-linux-libre.conf +++ b/configs/releng/efiboot/loader/entries/01-parabolaiso-x86_64-linux-libre.conf @@ -2,4 +2,4 @@ title Parabola GNU/Linux-libre install medium (x86_64, UEFI) sort-key 01 linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img -options parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% +options parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=%PARABOLAISO_UUID% diff --git a/configs/releng/efiboot/loader/entries/02-parabolaiso-x86_64-speech-linux-libre.conf b/configs/releng/efiboot/loader/entries/02-parabolaiso-x86_64-speech-linux-libre.conf index e2f3cbe..3bb7725 100644 --- a/configs/releng/efiboot/loader/entries/02-parabolaiso-x86_64-speech-linux-libre.conf +++ b/configs/releng/efiboot/loader/entries/02-parabolaiso-x86_64-speech-linux-libre.conf @@ -2,4 +2,4 @@ title Parabola GNU/Linux-libre install medium (x86_64, UEFI) with speech sort-key 02 linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img -options parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% accessibility=on +options parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=%PARABOLAISO_UUID% accessibility=on diff --git a/configs/releng/efiboot/loader/entries/03-parabolaiso-x86_64-ram-linux-libre.conf b/configs/releng/efiboot/loader/entries/03-parabolaiso-x86_64-ram-linux-libre.conf deleted file mode 100644 index ea54bc3..0000000 --- a/configs/releng/efiboot/loader/entries/03-parabolaiso-x86_64-ram-linux-libre.conf +++ /dev/null @@ -1,5 +0,0 @@ -title Parabola GNU/Linux-libre install medium (x86_64, UEFI, Copy to RAM) -sort-key 03 -linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre -initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img -options parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% copytoram diff --git a/configs/releng/efiboot/loader/entries/04-parabolaiso-x86_64-ram-speech-linux-libre.conf b/configs/releng/efiboot/loader/entries/04-parabolaiso-x86_64-ram-speech-linux-libre.conf deleted file mode 100644 index 9a5b99b..0000000 --- a/configs/releng/efiboot/loader/entries/04-parabolaiso-x86_64-ram-speech-linux-libre.conf +++ /dev/null @@ -1,5 +0,0 @@ -title Parabola GNU/Linux-libre install medium (x86_64, UEFI, Copy to RAM) with speech -sort-key 04 -linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre -initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img -options parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% copytoram accessibility=on diff --git a/configs/releng/grub/grub.cfg b/configs/releng/grub/grub.cfg index 80b0d72..4266ef3 100644 --- a/configs/releng/grub/grub.cfg +++ b/configs/releng/grub/grub.cfg @@ -1,46 +1,87 @@ +# Load partition table and file system modules insmod part_gpt insmod part_msdos insmod fat insmod iso9660 +insmod ntfs +insmod ntfscomp +insmod exfat +insmod udf +# Use graphics-mode output insmod all_video - insmod font - if loadfont "${prefix}/fonts/unicode.pf2" ; then - insmod gfxterm set gfxmode="auto" terminal_input console - terminal_output gfxterm + terminal_output console +fi + +# Enable serial console +if serial --unit=0 --speed=115200; then + terminal_input --append serial + terminal_output --append serial fi +# Search for the ISO volume +if [ -z "${PARABOLAISO_UUID}" ]; then + if [ -z "${PARABOLAISO_HINT}" ]; then + regexp --set=1:PARABOLAISO_HINT '^\(([^)]+)\)' "${cmdpath}" + fi + search --no-floppy --set=root --file '%PARABOLAISO_SEARCH_FILENAME%' --hint "${PARABOLAISO_HINT}" + probe --set PARABOLAISO_UUID --fs-uuid "${root}" +fi + +# Set default menu entry +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 - -menuentry "Parabola GNU/Linux-libre install medium (x86_64, UEFI)" { +play 600 988 1 1319 4 + +# Menu entries + +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% - initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux.img + linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=${PARABOLAISO_UUID} + initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.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 + linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=${PARABOLAISO_UUID} 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 "Run Memtest86+ (RAM test)" --class memtest86 --class memtest --class gnu --class tool { + set gfxpayload=800x600,1024x768 + linux /boot/memtest86+/memtest.efi + } + menuentry "UEFI Shell" --class efi { + insmod chain + chainloader /shellx64.efi + } + elif [ "${grub_cpu}" == "i386" ]; then + menuentry "UEFI Shell" --class efi { + insmod chain + 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/configs/releng/grub/loopback.cfg b/configs/releng/grub/loopback.cfg new file mode 100644 index 0000000..6ac328c --- /dev/null +++ b/configs/releng/grub/loopback.cfg @@ -0,0 +1,80 @@ +# https://www.supergrubdisk.org/wiki/Loopback.cfg + +# Search for the ISO volume +search --no-floppy --set=parabolaiso_img_dev --file "${iso_path}" +probe --set parabolaiso_img_dev_uuid --fs-uuid "${parabolaiso_img_dev}" + +# Get a human readable platform identifier +if [ "${grub_platform}" == 'efi' ]; then + parabolaiso_platform='UEFI' + if [ "${grub_cpu}" == 'x86_64' ]; then + parabolaiso_platform="x64 ${parabolaiso_platform}" + elif [ "${grub_cpu}" == 'i386' ]; then + parabolaiso_platform="IA32 ${parabolaiso_platform}" + else + parabolaiso_platform="${grub_cpu} ${parabolaiso_platform}" + fi +elif [ "${grub_platform}" == 'pc' ]; then + parabolaiso_platform='BIOS' +else + parabolaiso_platform="${grub_cpu} ${grub_platform}" +fi + +# Set default menu entry +default=parabola +timeout=15 +timeout_style=menu + + +# Menu entries + +menuentry "Parabola GNU/Linux-libre install medium (%ARCH%, ${parabolaiso_platform})" --class arch --class gnu-linux --class gnu --class os --id 'parabola' { + set gfxpayload=keep + linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-libre parabolaisobasedir=%INSTALL_DIR% img_dev=UUID=${parabolaiso_img_dev_uuid} img_loop="${iso_path}" + initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-libre.img +} + +menuentry "Parabola GNU/Linux-libre install medium with speakup screen reader (%ARCH%, ${parabolaiso_platform})" --hotkey s --class arch --class gnu-linux --class gnu --class os --id 'parabola-accessibility' { + set gfxpayload=keep + linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-libre parabolaisobasedir=%INSTALL_DIR% img_dev=UUID=${parabolaiso_img_dev_uuid} img_loop="${iso_path}" accessibility=on + initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-libre.img +} + + +if [ "${grub_platform}" == 'efi' -a "${grub_cpu}" == 'x86_64' -a -f '/boot/memtest86+/memtest.efi' ]; then + menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class memtest --class gnu --class tool { + set gfxpayload=800x600,1024x768 + linux /boot/memtest86+/memtest.efi + } +fi +if [ "${grub_platform}" == 'pc' -a -f '/boot/memtest86+/memtest' ]; then + menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class memtest --class gnu --class tool { + set gfxpayload=800x600,1024x768 + linux /boot/memtest86+/memtest + } +fi +if [ "${grub_platform}" == 'efi' ]; then + if [ "${grub_cpu}" == 'x86_64' -a -f '/shellx64.efi' ]; then + menuentry 'UEFI Shell' --class efi { + chainloader /shellx64.efi + } + elif [ "${grub_cpu}" == "i386" -a -f '/shellia32.efi' ]; then + menuentry 'UEFI Shell' --class efi { + 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/configs/releng/packages.both b/configs/releng/packages.both index aabb1e6..9828871 100644 --- a/configs/releng/packages.both +++ b/configs/releng/packages.both @@ -1,7 +1,9 @@ alsa-utils arch-install-scripts base +bcachefs-tools bind +bolt brltty btrfs-progs cloud-init @@ -23,6 +25,7 @@ ethtool exfatprogs f2fs-tools fatresize +foot-terminfo fsarchiver gnu-netcat gpart @@ -53,6 +56,7 @@ man-pages mc mdadm memtest86+ +memtest86+-efi mkinitcpio mkinitcpio-parabolaiso mkinitcpio-nfs-utils @@ -67,6 +71,7 @@ ntfs-3g nvme-cli open-iscsi openconnect +openpgp-card-tools openssh openvpn partclone @@ -84,10 +89,10 @@ rp-pppoe rsync rxvt-unicode-terminfo screen +sequoia-sq sdparm sg3_utils smartmontools -sof-firmware squashfs-tools sudo syslinux @@ -96,6 +101,7 @@ tcpdump terminus-font testdisk tmux +tpm2-tools tpm2-tss udftools usb_modeswitch @@ -103,6 +109,7 @@ usbmuxd usbutils vim vpnc +wezterm-terminfo wireless-regdb wireless_tools wpa_supplicant diff --git a/configs/releng/pacman.conf b/configs/releng/pacman.conf index 79a8f69..4469abc 100644 --- a/configs/releng/pacman.conf +++ b/configs/releng/pacman.conf @@ -76,21 +76,12 @@ LocalFileSigLevel = Optional [libre] Include = /etc/pacman.d/mirrorlist -#[testing] -#Include = /etc/pacman.d/mirrorlist - [core] Include = /etc/pacman.d/mirrorlist [extra] Include = /etc/pacman.d/mirrorlist -#[community-testing] -#Include = /etc/pacman.d/mirrorlist - -[community] -Include = /etc/pacman.d/mirrorlist - #[pcr-testing] #Include = /etc/pacman.d/mirrorlist diff --git a/configs/releng/profiledef.sh b/configs/releng/profiledef.sh index 12df102..5ac639e 100644 --- a/configs/releng/profiledef.sh +++ b/configs/releng/profiledef.sh @@ -2,10 +2,10 @@ # shellcheck disable=SC2034 iso_name="parabola" -iso_label="PARA_$(date +%Y%m)" +iso_label="PARA_$(date --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y%m)" iso_publisher="Parabola GNU/Linux-libre <https://parabola.nu>" iso_application="Parabola GNU/Linux-libre Live/Rescue CD" -iso_version="$(date +%Y.%m.%d)" +iso_version="$(date --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y.%m.%d)" install_dir="parabola" buildmodes=('iso') bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito' @@ -19,6 +19,7 @@ file_permissions=( ["/etc/shadow"]="0:0:400" ["/root"]="0:0:750" ["/root/.automated_script.sh"]="0:0:755" + ["/root/.gnupg"]="0:0:700" ["/usr/local/bin/choose-mirror"]="0:0:755" ["/usr/local/bin/Installation_guide"]="0:0:755" ["/usr/local/bin/livecd-sound"]="0:0:755" diff --git a/configs/releng/syslinux/parabolaiso_head.cfg b/configs/releng/syslinux/parabolaiso_head.cfg index 591097e..4f56858 100644 --- a/configs/releng/syslinux/parabolaiso_head.cfg +++ b/configs/releng/syslinux/parabolaiso_head.cfg @@ -12,7 +12,7 @@ MENU CMDLINEROW 14 MENU HELPMSGROW 16 MENU HELPMSGENDROW 29 -# Refer to http://syslinux.zytor.com/wiki/index.php/Doc/menu +# Refer to https://wiki.syslinux.org/wiki/index.php/Comboot/menu.c32 MENU COLOR border 35;40 #ff777caa #a0000000 std MENU COLOR title 1;35;40 #ff777caa #a0000000 std diff --git a/configs/releng/syslinux/parabolaiso_pxe32-linux-libre.cfg b/configs/releng/syslinux/parabolaiso_pxe32-linux-libre.cfg index 5e44dc9..fa629f1 100644 --- a/configs/releng/syslinux/parabolaiso_pxe32-linux-libre.cfg +++ b/configs/releng/syslinux/parabolaiso_pxe32-linux-libre.cfg @@ -6,7 +6,7 @@ ENDTEXT MENU LABEL Boot Parabola GNU/Linux-libre (i686) (NBD) LINUX ::/%INSTALL_DIR%/boot/i686/vmlinuz-linux-libre INITRD ::/%INSTALL_DIR%/boot/i686/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% parabolaiso_nbd_srv=${pxeserver} checksum verify +APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=%PARABOLAISO_UUID% parabolaiso_nbd_srv=${pxeserver} cms_verify=y SYSAPPEND 3 LABEL parabola32_nfs @@ -17,7 +17,7 @@ ENDTEXT MENU LABEL Boot Parabola GNU/Linux-libre (i686) (NFS) LINUX ::/%INSTALL_DIR%/boot/i686/vmlinuz-linux-libre INITRD ::/%INSTALL_DIR%/boot/i686/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaiso_nfs_srv=${pxeserver}:/run/parabolaiso/bootmnt checksum verify +APPEND parabolaisobasedir=%INSTALL_DIR% parabolaiso_nfs_srv=${pxeserver}:/run/parabolaiso/bootmnt cms_verify=y SYSAPPEND 3 LABEL parabola32_http @@ -28,5 +28,5 @@ ENDTEXT MENU LABEL Boot Parabola GNU/Linux-libre (i686) (HTTP) LINUX ::/%INSTALL_DIR%/boot/i686/vmlinuz-linux-libre INITRD ::/%INSTALL_DIR%/boot/i686/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaiso_http_srv=http://${pxeserver}/ checksum verify +APPEND parabolaisobasedir=%INSTALL_DIR% parabolaiso_http_srv=http://${pxeserver}/ cms_verify=y SYSAPPEND 3 diff --git a/configs/releng/syslinux/parabolaiso_pxe64-linux-libre.cfg b/configs/releng/syslinux/parabolaiso_pxe64-linux-libre.cfg index 9868ea9..44531ab 100644 --- a/configs/releng/syslinux/parabolaiso_pxe64-linux-libre.cfg +++ b/configs/releng/syslinux/parabolaiso_pxe64-linux-libre.cfg @@ -6,7 +6,7 @@ ENDTEXT MENU LABEL Boot Parabola GNU/Linux-libre (x86_64) (NBD) LINUX ::/%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre INITRD ::/%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% parabolaiso_nbd_srv=${pxeserver} checksum verify +APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=%PARABOLAISO_UUID% parabolaiso_nbd_srv=${pxeserver} cms_verify=y SYSAPPEND 3 LABEL parabola64_nfs @@ -17,7 +17,7 @@ ENDTEXT MENU LABEL Boot Parabola GNU/Linux-libre (x86_64) (NFS) LINUX ::/%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre INITRD ::/%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaiso_nfs_srv=${pxeserver}:/run/parabolaiso/bootmnt checksum verify +APPEND parabolaisobasedir=%INSTALL_DIR% parabolaiso_nfs_srv=${pxeserver}:/run/parabolaiso/bootmnt cms_verify=y SYSAPPEND 3 LABEL parabola64_http @@ -28,5 +28,5 @@ ENDTEXT MENU LABEL Boot Parabola GNU/Linux-libre (x86_64) (HTTP) LINUX ::/%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre INITRD ::/%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaiso_http_srv=http://${pxeserver}/ checksum verify +APPEND parabolaisobasedir=%INSTALL_DIR% parabolaiso_http_srv=http://${pxeserver}/ cms_verify=y SYSAPPEND 3 diff --git a/configs/releng/syslinux/parabolaiso_sys32-linux-libre.cfg b/configs/releng/syslinux/parabolaiso_sys32-linux-libre.cfg index 4f0acb1..d15cac6 100644 --- a/configs/releng/syslinux/parabolaiso_sys32-linux-libre.cfg +++ b/configs/releng/syslinux/parabolaiso_sys32-linux-libre.cfg @@ -8,7 +8,7 @@ ENDTEXT MENU LABEL Parabola GNU/Linux-libre install medium (i686, BIOS) LINUX /%INSTALL_DIR%/boot/i686/vmlinuz-linux-libre INITRD /%INSTALL_DIR%/boot/i686/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% +APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=%PARABOLAISO_UUID% # Accessibility boot option LABEL parabola32speech @@ -19,7 +19,7 @@ ENDTEXT MENU LABEL Parabola GNU/Linux-libre install medium (i686, BIOS) with ^speech LINUX /%INSTALL_DIR%/boot/i686/vmlinuz-linux-libre INITRD /%INSTALL_DIR%/boot/i686/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% accessibility=on +APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=%PARABOLAISO_UUID% accessibility=on # Copy to RAM boot option LABEL parabola32ram @@ -30,4 +30,4 @@ ENDTEXT MENU LABEL Parabola GNU/Linux-libre install medium (i686, BIOS, Copy to RAM) LINUX /%INSTALL_DIR%/boot/i686/vmlinuz-linux-libre INITRD /%INSTALL_DIR%/boot/i686/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% copytoram +APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=%PARABOLAISO_UUID% copytoram diff --git a/configs/releng/syslinux/parabolaiso_sys64-linux-libre.cfg b/configs/releng/syslinux/parabolaiso_sys64-linux-libre.cfg index cbf736e..9750687 100644 --- a/configs/releng/syslinux/parabolaiso_sys64-linux-libre.cfg +++ b/configs/releng/syslinux/parabolaiso_sys64-linux-libre.cfg @@ -6,7 +6,7 @@ ENDTEXT MENU LABEL Parabola GNU/Linux-libre install medium (x86_64, BIOS) LINUX /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre INITRD /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% +APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=%PARABOLAISO_UUID% # Accessibility boot option LABEL parabola64speech @@ -17,15 +17,4 @@ ENDTEXT MENU LABEL Parabola GNU/Linux-libre install medium (x86_64, BIOS) with ^speech LINUX /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre INITRD /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% accessibility=on - -# Copy to RAM boot option -LABEL parabola64ram -TEXT HELP -Boot the Parabola GNU/Linux-libre install medium on BIOS with Copy-to-RAM option -It allows you to install Parabola GNU/Linux-libre or perform system maintenance. -ENDTEXT -MENU LABEL Parabola GNU/Linux-libre install medium (x86_64, BIOS, Copy to RAM) -LINUX /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux-libre -INITRD /%INSTALL_DIR%/boot/x86_64/initramfs-linux-libre.img -APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisolabel=%PARABOLAISO_LABEL% copytoram +APPEND parabolaisobasedir=%INSTALL_DIR% parabolaisodevice=UUID=%PARABOLAISO_UUID% accessibility=on diff --git a/configs/releng/syslinux/parabolaiso_tail.cfg b/configs/releng/syslinux/parabolaiso_tail.cfg index e5339a2..dcbb413 100644 --- a/configs/releng/syslinux/parabolaiso_tail.cfg +++ b/configs/releng/syslinux/parabolaiso_tail.cfg @@ -7,12 +7,12 @@ MENU LABEL Boot existing OS COM32 chain.c32 APPEND hd0 0 -# http://www.memtest.org/ +# https://www.memtest.org/ LABEL memtest MENU LABEL Run Memtest86+ (RAM test) LINUX /%INSTALL_DIR%/boot/memtest -# http://hdt-project.org/ +# https://wiki.syslinux.org/wiki/index.php/Hdt_(Hardware_Detection_Tool) LABEL hdt MENU LABEL Hardware Information (HDT) COM32 hdt.c32 diff --git a/docs/README.profile.rst b/docs/README.profile.rst index f2ba5e6..ec76ede 100644 --- a/docs/README.profile.rst +++ b/docs/README.profile.rst @@ -48,10 +48,12 @@ 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.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 - - ``uefi-x64.refind.eltorito``: rEFInd for x86_64 UEFI booting from an optical disc + - ``uefi-x64.grub.esp``: GRUB for x64 UEFI booting from a disk + - ``uefi-x64.grub.eltorito``: GRUB for x64 UEFI booting from an optical disc + - ``uefi-ia32.systemd-boot.esp``: systemd-boot for IA32 UEFI booting from a disk + - ``uefi-ia32.systemd-boot.eltorito``: systemd-boot for IA32UEFI booting from an optical disc + - ``uefi-x64.systemd-boot.esp``: systemd-boot for x64 UEFI booting from a disk + - ``uefi-x64.systemd-boot.eltorito``: systemd-boot for x64 UEFI booting from an optical disc Note that BIOS El Torito boot mode must always be listed before UEFI El Torito boot mode. * ``arch``: The architecture (e.g. ``x86_64``) to build the image for. This is also used to resolve the name of the packages file (e.g. ``packages.x86_64``) @@ -137,9 +139,16 @@ The following *custom template identifiers* are understood and will be replaced respective variables in ``profiledef.sh``: * ``%PARABOLAISO_LABEL%``: Set this using the ``iso_label`` variable in ``profiledef.sh``. -* ``%INSTALL_DIR%``: Set this using the ``iso_label`` variable in ``profiledef.sh``. +* ``%INSTALL_DIR%``: Set this using the ``install_dir`` variable in ``profiledef.sh``. * ``%ARCH%``: Set this using the ``arch`` variable in ``profiledef.sh``. +Additionally there are also *custom template identifiers* have harcoded values set by ``mkparabolaiso`` that cannot be +overridden: + +* ``%PARABOLAISO_UUID%``: the ISO 9660 modification date in UTC, i.e. its "UUID", +* ``%PARABOLAISO_SEARCH_FILENAME%``: file path on ISO 9660 that can be used by GRUB to find the ISO volume + (**for GRUB ``.cfg`` files only**). + efiboot ------- @@ -173,7 +182,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/docs/README.transfer b/docs/README.transfer deleted file mode 100644 index 2cf28e3..0000000 --- a/docs/README.transfer +++ /dev/null @@ -1,133 +0,0 @@ -INDEX ------ - -* Transfer ISO file to target medium (configs/releng) - * To -> CD / DVD / BD - * To -> USB-key / SD / HDD / SSD - * PC-BIOS (MBR) - * PC-BIOS (ISOHYBRID-MBR) - * PC-EFI (GPT) [x86_64 only] - * PC-EFI (ISOHYBRID-GPT) [x86_64 only] - - - -*** Transfer ISO image to target medium (configs/releng) - -ISO images names consist of: parabola-<YYYY>.<MM>.<DD>-dual.iso - -Where: - <YYYY> Year - <MM> Month - <DD> Day - - -** To -> CD / DVD / BD - -Note: All ISO images are booteable on a PC-BIOS via "El Torito" in no-emulation mode, - All x86_64 ISO images are booteable on a PC-EFI via "El Torito" in no-emulation mode. - -Nomeclature: - <B> scsibus number - <T> target number - <L> lun number - (Note: see cdrecord -scanbus, for these numbers) - - -1) Write it directly using your favorite recording program. -# cdrecord dev=<B>,<T>,<L> -dao parabola-<YYYY>.<MM>.<DD>-dual.iso - - -** To -> USB Flash Drive (USB-key) / Memory card (SD) / - Hard-Disk Drive (HDD) / Solid-State Drive (SSD) - -Note: These steps are the general workflow, you can skip some of them, - using another filesystem if your bootloader supports it, - installing to another directory than "parabola/" or using more than - one partition. Just ensure that main boot params options - (parabolaisolabel= and parabolaisobasedir=) are set correctly according to your setup. - -Nomeclature: -<DEV-TARGET>: Device node of the drive where ISO contents should be copied - (example: /dev/sdx) -<DEV-TARGET-N>: Device node of the partition on <DEV-TARGET> - (example: /dev/sdx1) -<MNT-TARGET-N>: Mount point path where <DEV-TARGET-N> is mounted - (example: /mnt/sdx/1) -<ISO-SOURCE>: Path to the ISO file parabola-<YYYY>.<MM>.<DD>-dual.iso - (example: ~/parabola-2012.07.22-dual.iso) -<FS-LABEL>: Represents the filesystem label of the <ISO-SOURCE> - (example: PARA_201302) - - -* PC-BIOS (MBR): - -Note: Using here a MBR partition mode as example, but GPT should also works - if machine firmware is not broken. - Just ensure that partition is set with attribute "2: legacy BIOS bootable" - and use gptmbr.bin instead of mbr.bin for syslinux. - -1) Create one partition entry in MBR and mark it as "active" (booteable). -Note: Type "b" for FAT32, "83" for EXTFS or "7" for NTFS. -# fdisk <DEV-TARGET> - -2) Create a FAT32, EXTFS or NTFS filesystem on such partition and setup a label. -Note: COW is not supported on NTFS. -# mkfs.fat -F 32 -n <FS-LABEL> <DEV-TARGET-N> -# mkfs.ext4 -L <FS-LABEL> <DEV-TARGET-N> -# mkfs.ntfs -L <FS-LABEL> <DEV-TARGET-N> - -3) Mount target filesystem. -# mount <DEV-TARGET-N> <MNT-TARGET-N> - -4) Extract ISO image on target filesystem. -# bsdtar -x --exclude=isolinux/ --exclude=EFI/ --exclude=loader/ -f <ISO-SOURCE> -C <MNT-TARGET-N> - -5) Install syslinux bootloader on target filesystem. -# extlinux -i <MNT-TARGET-N>/parabola/boot/syslinux - -6) Unmount target filesystem. -# umount <MNT-TARGET-N> - -7) Install syslinux MBR boot code on target drive. -# dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/bios/mbr.bin of=<DEV-TARGET> - - -* PC-BIOS (ISOHYBRID-MBR): - -Note: This method is the most easily, quick and dirty, but is the most limited - if you want to use your target medium for other purposes. - If using this does not work, use PC-BIOS (MBR) method instead. - -1) Dump ISO file to target medium. -# dd if=<ISO-SOURCE> of=<DEV-TARGET> - - -* PC-EFI (GPT) [x86_64 only] - -Note: Using here a GPT partition mode as example, but MBR should also works - if machine firmware is not broken. - -1) Create one partition entry in GPT (of type "ef00") -# gdisk <DEV-TARGET> - -2) Create a FAT32 filesystem on such partition and setup a label. -# mkfs.fat -F 32 -n <FS-LABEL> <DEV-TARGET-N> - -3) Mount target filesystem. -# mount <DEV-TARGET-N> <MNT-TARGET-N> - -4) Extract ISO image on target filesystem. -# bsdtar -x --exclude=isolinux/ --exclude=EFI/parabolaiso/ --exclude=parabola/boot/syslinux/ -f <ISO-SOURCE> -C <MNT-TARGET-N> - -5) Unmount target filesystem. -# umount <MNT-TARGET-N> - - -* PC-EFI (ISOHYBRID-GPT) [x86_64 only] - -Note: This method is the most easily, quick and dirty, but is the most limited - if you want to use your target medium for other purposes. - If using this does not work, use PC-EFI (GPT) method instead. - -1) Dump ISO file to target medium. -# dd if=<ISO-SOURCE> of=<DEV-TARGET> diff --git a/docs/README.transfer.rst b/docs/README.transfer.rst new file mode 100644 index 0000000..c09b41d --- /dev/null +++ b/docs/README.transfer.rst @@ -0,0 +1,165 @@ +============================================== +Transfer ISO to target medium (configs/releng) +============================================== + +ISO images names consist of: ``parabola-YYYY.MM.DD-x86_64.iso``. + +Where: ``YYYY`` is the year, ``MM`` the month and ``DD`` the day. + +.. contents:: + +Burn to an optical disc +======================= + + .. note:: + All ISO images are BIOS and UEFI bootable via "El Torito" in no-emulation mode. + +Burn the ISO using your favorite disc burning program. + +For example: + +.. code:: sh + + xorriso -as cdrecord -v -sao dev=/dev/sr0 parabola-YYYY.MM.DD-x86_64.iso + +Write to an USB flash drive / memory card / hard disk drive / solid state drive / etc. +====================================================================================== + + .. tip:: + See https://wiki.archlinux.org/title/USB_flash_installation_medium for more detailed instructions. + +Nomeclature: + +``<DEV-TARGET>`` + Device node of the drive where ISO contents should be copied (example: ``/dev/sdx``). +``<DEV-TARGET-N>`` + Device node of the partition on ``<DEV-TARGET>`` (example: ``/dev/sdx1``). +``<FS-LABEL>`` + Represents the file system label of the ``parabola-YYYY.MM.DD-x86_64.iso`` (example: ``ARCH_201703``). + +ISOHYBRID (BIOS and UEFI) +------------------------- + + .. note:: + This method is the most easily, quick and dirty, but is the most limited if you want to use your target medium + for other purposes. If using this does not work, use the `File system transposition (UEFI only)`_ method instead. + +Directly write the ISO file to the target medium: + +.. code:: sh + + dd bs=4M if=parabola-YYYY.MM.DD-x86_64.iso of=<DEV-TARGET> conv=fsync oflag=direct status=progress + +File system transposition (UEFI only) +-------------------------------- + +This method extracts the contents of the ISO onto a prepared UEFI-bootable volume. + +If your drive is already partitioned and formatted, skip to the "Mount the target file system" step. + + .. note:: + Using MBR with one FAT formatted active partition is the most compatible method. + +1. Partition the drive with *fdisk*. + + .. code:: sh + + fdisk <DEV-TARGET> + + 1) Create a new MBR partition table with command ``o``. + + .. warning:: + This will destroy all data on the drive. + + 2) Create a new primary partition with command ``n`` and set its type code to ``0c`` with command ``t``. + + 3) Mark the partition as bootable with the ``a`` command. + + 4) Write the changes and exit with ``w``. + +2. Format the newly created partition to FAT32 + + .. code:: sh + + mkfs.fat -F 32 /dev/disk/by-id/<TARGET-DEVICE>-part1 + +3. Mount the target file system + + .. code:: sh + + mount <DEV-TARGET-N> /mnt + +4. Extract the ISO image on the target file system. + + .. code:: sh + + bsdtar -x --exclude=boot/syslinux/ -f parabola-YYYY.MM.DD-x86_64.iso -C /mnt + +5. Unmount the target file system. + + .. code:: sh + + umount /mnt + +Manual formatting (BIOS only) +----------------------------- + + .. note:: + These steps are the general workflow, you can skip some of them, using another file system if your boot loader + supports it, installing to another directory than ``arch/`` or using more than one partition. Just ensure that + main boot parameters (``archisolabel=`` and ``archisobasedir=``) are set correctly according to your setup. + + Using here a MBR partition mode as example, but GPT should also work if the machine firmware is not broken. Just + ensure that partition is set with attribute ``2: legacy BIOS bootable`` and use ``gptmbr.bin`` instead of + ``mbr.bin`` for syslinux. + +1) Create one partition entry in MBR and mark it as "active" (bootable). + + .. note:: + Type ``b`` for FAT32, ``83`` for EXTFS or ``7`` for NTFS. + + .. code:: sh + + fdisk <DEV-TARGET> + +2) Create a FAT32, EXTFS or NTFS file system on such partition and setup a label. + + .. note:: + COW is not supported on NTFS. + + .. code:: sh + + mkfs.fat -F 32 -n <FS-LABEL> <DEV-TARGET-N> + mkfs.ext4 -L <FS-LABEL> <DEV-TARGET-N> + mkfs.ntfs -L <FS-LABEL> <DEV-TARGET-N> + +3) Mount the target file system. + + .. code:: sh + + mount <DEV-TARGET-N> /mnt + +4) Extract the ISO image on the target file system. + + .. code:: sh + + bsdtar -x --exclude=boot/grub/ --exclude=EFI/ -f parabola-YYYY.MM.DD-x86_64.iso -C /mnt + +5) Install the syslinux boot loader on the target file system. + + .. code:: sh + + extlinux -i /mnt/boot/syslinux + +6) Unmount the target file system. + + .. code:: sh + + umount /mnt + +7) Install syslinux MBR boot code on the target drive. + + .. code:: sh + + dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/bios/mbr.bin of=<DEV-TARGET> + diff --git a/parabolaiso/mkparabolaiso b/parabolaiso/mkparabolaiso index 6af74b7..3beb237 100755 --- a/parabolaiso/mkparabolaiso +++ b/parabolaiso/mkparabolaiso @@ -3,10 +3,16 @@ # SPDX-License-Identifier: GPL-3.0-or-later set -e -u +shopt -s extglob # Control the environment umask 0022 -export LC_ALL="C" +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 @@ -23,6 +29,7 @@ gpg_key="" gpg_sender="" iso_name="" iso_label="" +iso_uuid="" iso_publisher="" iso_application="" iso_version="" @@ -34,13 +41,14 @@ packages_dual="" bootstrap_packages="" bootstrap_packages_dual="" pacstrap_dir="" +declare -i rm_work_dir=0 buildmodes=() bootmodes=() airootfs_image_type="" airootfs_image_tool_options=() cert_list=() -sign_netboot_artifacts="" declare -A file_permissions=() +efibootimg="" efiboot_files=() # Show an INFO message @@ -79,14 +87,15 @@ usage: ${app_name} [options] <profile_dir> Default: '${iso_application}' -C <file> pacman configuration file. Default: '${pacman_conf}' - -D <install_dir> Set an install_dir. All files will by located here. + -D <install_dir> Set an install_dir. All files will be located here. Default: '${install_dir}' NOTE: Max 8 characters, use only [a-z0-9] -L <label> Set the ISO volume label Default: '${iso_label}' -P <publisher> 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. @@ -101,6 +110,7 @@ usage: ${app_name} [options] <profile_dir> Default: '${out_dir}' -p [package ..] Package(s) to install. Multiple packages are provided as quoted, space delimited list. + -r Delete the working directory at the end. -v Enable verbose output -w <work_dir> Set the working directory Default: '${work_dir}' @@ -159,9 +169,10 @@ _cleanup_pacstrap_dir() { [[ -d "${pacstrap_dir}/var/tmp" ]] && find "${pacstrap_dir}/var/tmp" -mindepth 1 -delete # Delete package pacman related files. find "${work_dir}" \( -name '*.pacnew' -o -name '*.pacsave' -o -name '*.pacorig' \) -delete - # Create an empty /etc/machine-id + # Create /etc/machine-id with special value 'uninitialized': the final id is + # generated on first boot, systemd's first-boot mechanism applies (see machine-id(5)) rm -f -- "${pacstrap_dir}/etc/machine-id" - printf '' > "${pacstrap_dir}/etc/machine-id" + printf 'uninitialized\n' >"${pacstrap_dir}/etc/machine-id" _msg_info "Done!" } @@ -196,7 +207,7 @@ _mkairootfs_ext4+squashfs() { [[ ! "${quiet}" == "y" ]] || mkfs_ext4_options+=('-q') rm -f -- "${pacstrap_dir}.img" E2FSPROGS_FAKE_TIME="${SOURCE_DATE_EPOCH}" mkfs.ext4 "${mkfs_ext4_options[@]}" -- "${pacstrap_dir}.img" 32G - tune2fs -c 0 -i 0 -- "${pacstrap_dir}.img" > /dev/null + tune2fs -c 0 -i 0 -- "${pacstrap_dir}.img" >/dev/null _msg_info "Done!" install -d -m 0755 -- "${isofs_dir}/${install_dir}/${arch}" @@ -237,27 +248,24 @@ _mkchecksum() { _msg_info "Creating checksum file for self-test..." cd -- "${isofs_dir}/${install_dir}/${arch}" if [[ -e "${isofs_dir}/${install_dir}/${arch}/airootfs.sfs" ]]; then - sha512sum airootfs.sfs > airootfs.sha512 + sha512sum airootfs.sfs >airootfs.sha512 elif [[ -e "${isofs_dir}/${install_dir}/${arch}/airootfs.erofs" ]]; then - sha512sum airootfs.erofs > airootfs.sha512 + sha512sum airootfs.erofs >airootfs.sha512 fi cd -- "${OLDPWD}" _msg_info "Done!" } # GPG sign the root file system image. -_mksignature() { - local airootfs_image_filename gpg_options=() - _msg_info "Signing ${arch} 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}") - # 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!" @@ -297,12 +305,12 @@ _run_dual() { # Set up custom pacman.conf with custom cache and pacman hook directories. _make_pacman_conf() { local _cache_dirs _system_cache_dirs _profile_cache_dirs - _system_cache_dirs="$(pacman-conf CacheDir| tr '\n' ' ')" - _profile_cache_dirs="$(pacman-conf --config "${pacman_conf}" CacheDir| tr '\n' ' ')" + _system_cache_dirs="$(pacman-conf CacheDir | tr '\n' ' ')" + _profile_cache_dirs="$(pacman-conf --config "${pacman_conf}" CacheDir | tr '\n' ' ')" # Only use the profile's CacheDir, if it is not the default and not the same as the system cache dir. - if [[ "${_profile_cache_dirs}" != "/var/cache/pacman/pkg" ]] && \ - [[ "${_system_cache_dirs}" != "${_profile_cache_dirs}" ]]; then + if [[ "${_profile_cache_dirs}" != "/var/cache/pacman/pkg" ]] \ + && [[ "${_system_cache_dirs}" != "${_profile_cache_dirs}" ]]; then _cache_dirs="${_profile_cache_dirs}" else _cache_dirs="${_system_cache_dirs}" @@ -315,9 +323,9 @@ _make_pacman_conf() { # HookDir is *always* set to the airootfs' override directory # see `man 8 pacman` for further info sed "/Architecture/d;/\[options\]/a Architecture = ${arch}" "${pacman_conf}" | \ - pacman-conf --config /dev/stdin | \ - sed "/CacheDir/d;/DBPath/d;/HookDir/d;/LogFile/d;/RootDir/d;/\[options\]/a CacheDir = ${_cache_dirs} - /\[options\]/a HookDir = ${pacstrap_dir}/etc/pacman.d/hooks/" > "${work_dir}/${buildmode}.pacman.conf.${arch}" + pacman-conf --config /dev/stdin \ + | sed "/CacheDir/d;/DBPath/d;/HookDir/d;/LogFile/d;/RootDir/d;/\[options\]/a CacheDir = ${_cache_dirs} + /\[options\]/a HookDir = ${pacstrap_dir}/etc/pacman.d/hooks/" >"${work_dir}/${buildmode}.pacman.conf.${arch}" } # Prepare working directory and copy custom root file system files. @@ -332,7 +340,7 @@ _make_custom_airootfs() { cp -af --no-preserve=ownership,mode -- "${profile}/airootfs/." "${pacstrap_dir}" # Set ownership and mode for files and directories for filename in "${!file_permissions[@]}"; do - IFS=':' read -ra permissions <<< "${file_permissions["${filename}"]}" + IFS=':' read -ra permissions <<<"${file_permissions["${filename}"]}" # Prevent file path traversal outside of $pacstrap_dir if [[ "$(realpath -q -- "${pacstrap_dir}${filename}")" != "${pacstrap_dir}"* ]]; then _msg_error "Failed to set permissions on '${pacstrap_dir}${filename}'. Outside of valid path." 1 @@ -360,40 +368,59 @@ _make_packages() { local buildmode_pkg_list_arch eval "buildmode_pkg_list_arch=(\${buildmode_pkg_list_${arch}[@]})" + if [[ -v gpg_publickey ]]; then + exec {PARABOLAISO_GNUPG_FD}<"$gpg_publickey" + export PARABOLAISO_GNUPG_FD + fi + if [[ -v cert_list[0] ]]; then + exec {PARABOLAISO_TLS_FD}<"${cert_list[0]}" + export PARABOLAISO_TLS_FD + fi + if [[ -v cert_list[2] ]]; then + exec {PARABOLAISO_TLSCA_FD}<"${cert_list[2]}" + export PARABOLAISO_TLSCA_FD + fi + + # Install the qemu-arm-static binary if [[ "${arch}" == "armv7h" ]] && ! setarch armv7l /bin/true 2>/dev/null; then # Make sure that qemu-static is set up with binfmt_misc if [[ -z $(grep -l -xF \ -e "interpreter /usr/bin/qemu-arm-static" \ - -r -- /proc/sys/fs/binfmt_misc 2> /dev/null \ + -r -- /proc/sys/fs/binfmt_misc 2>/dev/null \ | xargs -r grep -xF 'enabled') ]]; then # Register the qemu-arm-static as an ARM interpreter in the kernel (using binfmt_misc kernel module) - echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm-static:' > /proc/sys/fs/binfmt_misc/register + printf ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm-static:' >/proc/sys/fs/binfmt_misc/register fi install -d -m 0755 -- "${pacstrap_dir}/usr/bin" install -m 0755 -- /usr/bin/qemu-arm-static "${pacstrap_dir}/usr/bin" fi - if [[ -n "${gpg_key}" ]]; then - exec {PARABOLAISO_GNUPG_FD}<>"${work_dir}/pubkey.gpg" - export PARABOLAISO_GNUPG_FD - fi - # Unset TMPDIR to work around https://bugs.archlinux.org/task/70580 if [[ "${quiet}" = "y" ]]; then - env -u TMPDIR pacstrap -C "${work_dir}/${buildmode}.pacman.conf.${arch}" -c -G -M -- "${pacstrap_dir}" "${buildmode_pkg_list[@]}" "${buildmode_pkg_list_arch[@]}" &> /dev/null + env -u TMPDIR pacstrap -C "${work_dir}/${buildmode}.pacman.conf.${arch}" -c -G -M -- "${pacstrap_dir}" "${buildmode_pkg_list[@]}" "${buildmode_pkg_list_arch[@]}" &>/dev/null else env -u TMPDIR pacstrap -C "${work_dir}/${buildmode}.pacman.conf.${arch}" -c -G -M -- "${pacstrap_dir}" "${buildmode_pkg_list[@]}" "${buildmode_pkg_list_arch[@]}" fi - if [[ -n "${gpg_key}" ]]; then + # Delete the qemu-arm-static binary + if [[ "${arch}" == "armv7h" ]] && ! setarch armv7l /bin/true 2>/dev/null; then + rm -f -- "${pacstrap_dir}/usr/bin/qemu-arm-static" + fi + + if [[ -v cert_list[0] ]]; then + exec {PARABOLAISO_TLS_FD}<&- + unset PARABOLAISO_TLS_FD + fi + if [[ -v cert_list[2] ]]; then + exec {PARABOLAISO_TLSCA_FD}<&- + unset PARABOLAISO_TLSCA_FD + fi + if [[ -v gpg_publickey ]]; then exec {PARABOLAISO_GNUPG_FD}<&- unset PARABOLAISO_GNUPG_FD fi - # Delete the qemu-arm-static binary - rm -f -- "${pacstrap_dir}/usr/bin/qemu-arm-static" - _msg_info "Done! Packages installed successfully." } @@ -414,13 +441,13 @@ _make_customize_airootfs() { if [[ ! -d "${pacstrap_dir}${passwd[5]}" ]]; then install -d -m 0750 -o "${passwd[2]}" -g "${passwd[3]}" -- "${pacstrap_dir}${passwd[5]}" fi - cp -dnRT --preserve=mode,timestamps,links -- "${pacstrap_dir}/etc/skel/." "${pacstrap_dir}${passwd[5]}" + cp -dRT --update=none --preserve=mode,timestamps,links -- "${pacstrap_dir}/etc/skel/." "${pacstrap_dir}${passwd[5]}" chmod -f 0750 -- "${pacstrap_dir}${passwd[5]}" chown -hR -- "${passwd[2]}:${passwd[3]}" "${pacstrap_dir}${passwd[5]}" else _msg_error "Failed to set permissions on '${pacstrap_dir}${passwd[5]}'. Outside of valid path." 1 fi - done < "${profile}/airootfs/etc/passwd" + done <"${profile}/airootfs/etc/passwd" _msg_info "Done!" fi @@ -441,6 +468,10 @@ _make_bootmodes() { for bootmode in "${bootmodes[@]}"; do _run_once "_make_bootmode_${bootmode}" done + + if [[ "${bootmodes[*]}" != *grub* ]]; then + _run_once _make_common_grubenv_and_loopbackcfg + fi } # Copy kernel and initramfs to ISO 9660 @@ -455,39 +486,39 @@ _make_boot_on_iso9660() { # Prepare syslinux for booting from MBR (isohybrid) _make_bootmode_bios.syslinux.mbr() { _msg_info "Setting up SYSLINUX for BIOS booting from a disk..." - install -d -m 0755 -- "${isofs_dir}/syslinux" + install -d -m 0755 -- "${isofs_dir}/boot/syslinux" for _cfg in "${profile}/syslinux/"*.cfg; do sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; + s|%PARABOLAISO_UUID%|${iso_uuid}|g; s|%INSTALL_DIR%|${install_dir}|g; s|%ARCH%|${arch}|g" \ - "${_cfg}" > "${isofs_dir}/syslinux/${_cfg##*/}" + "${_cfg}" >"${isofs_dir}/boot/syslinux/${_cfg##*/}" done if [[ -e "${profile}/syslinux/splash.png" ]]; then - install -m 0644 -- "${profile}/syslinux/splash.png" "${isofs_dir}/syslinux/" + install -m 0644 -- "${profile}/syslinux/splash.png" "${isofs_dir}/boot/syslinux/" fi - install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/"*.c32 "${isofs_dir}/syslinux/" - install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/lpxelinux.0" "${isofs_dir}/syslinux/" - install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/memdisk" "${isofs_dir}/syslinux/" + install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/"*.c32 "${isofs_dir}/boot/syslinux/" + install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/lpxelinux.0" "${isofs_dir}/boot/syslinux/" + install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/memdisk" "${isofs_dir}/boot/syslinux/" _run_dual '_run_once _make_boot_on_iso9660' - if [[ -e "${isofs_dir}/syslinux/hdt.c32" ]]; then - install -d -m 0755 -- "${isofs_dir}/syslinux/hdt" + if [[ -e "${isofs_dir}/boot/syslinux/hdt.c32" ]]; then + install -d -m 0755 -- "${isofs_dir}/boot/syslinux/hdt" if [[ -e "${pacstrap_dir}/usr/share/hwdata/pci.ids" ]]; then gzip -cn9 "${pacstrap_dir}/usr/share/hwdata/pci.ids" > \ - "${isofs_dir}/syslinux/hdt/pciids.gz" + "${isofs_dir}/boot/syslinux/hdt/pciids.gz" fi find "${pacstrap_dir}/usr/lib/modules" -name 'modules.alias' -print -exec gzip -cn9 '{}' ';' -quit > \ - "${isofs_dir}/syslinux/hdt/modalias.gz" + "${isofs_dir}/boot/syslinux/hdt/modalias.gz" fi # Add other aditional/extra files to ${install_dir}/boot/ if [[ -e "${pacstrap_dir}/boot/memtest86+/memtest.bin" ]]; then + install -d -m 0755 -- "${isofs_dir}/boot/memtest86+/" # rename for PXE: https://wiki.parabola.nu/index.php/Syslinux#Using_memtest - install -m 0644 -- "${pacstrap_dir}/boot/memtest86+/memtest.bin" "${isofs_dir}/${install_dir}/boot/memtest" - install -d -m 0755 -- "${isofs_dir}/${install_dir}/boot/licenses/memtest86+/" - install -m 0644 -- "${pacstrap_dir}/usr/share/licenses/common/GPL2/license.txt" \ - "${isofs_dir}/${install_dir}/boot/licenses/memtest86+/" + install -m 0644 -- "${pacstrap_dir}/boot/memtest86+/memtest.bin" "${isofs_dir}/boot/memtest86+/memtest" + install -m 0644 -- "${pacstrap_dir}/usr/share/licenses/common/GPL2/license.txt" "${isofs_dir}/boot/memtest86+/" fi _msg_info "Done! SYSLINUX set up for BIOS booting from a disk successfully." } @@ -495,9 +526,9 @@ _make_bootmode_bios.syslinux.mbr() { # Prepare syslinux for El-Torito booting _make_bootmode_bios.syslinux.eltorito() { _msg_info "Setting up SYSLINUX for BIOS booting from an optical disc..." - install -d -m 0755 -- "${isofs_dir}/syslinux" - install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/isolinux.bin" "${isofs_dir}/syslinux/" - install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/isohdpfx.bin" "${isofs_dir}/syslinux/" + install -d -m 0755 -- "${isofs_dir}/boot/syslinux" + install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/isolinux.bin" "${isofs_dir}/boot/syslinux/" + install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/isohdpfx.bin" "${isofs_dir}/boot/syslinux/" # ISOLINUX and SYSLINUX installation is shared _run_once _make_bootmode_bios.syslinux.mbr @@ -508,9 +539,9 @@ _make_bootmode_bios.syslinux.eltorito() { # Copy kernel and initramfs to FAT image _make_boot_on_fat() { _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/x86_64" - 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/x86_64/" _msg_info "Done!" } @@ -518,74 +549,202 @@ _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..." + 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 PARAISO_EFI "${work_dir}/efiboot.img" "${imgsize}" > /dev/null + mkfs.fat -C -n PARAISO_EFI "${efibootimg}" "${imgsize_kib}" >/dev/null else - mkfs.fat -C -n PARAISO_EFI "${work_dir}/efiboot.img" "${imgsize}" + mkfs.fat -C -n PARAISO_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 } -_make_bootmode_uefi-ia32.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" +# Copy GRUB files to ISO 9660 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 -d -m 0755 -- "${isofs_dir}/boot/grub" + cp -r --remove-destination -- "${files_to_copy[@]}" "${isofs_dir}/boot/grub/" +} + +# Prepare GRUB configuration files +_make_common_bootmode_grub_cfg() { + local _cfg search_filename + + install -d -- "${work_dir}/grub" + + # Create a /boot/grub/YYYY-mm-dd-HH-MM-SS-00.uuid file on ISO 9660. GRUB will search for it to find the ISO + # volume. This is similar to what grub-mkrescue does, except it places the file in /.disk/, but we opt to use a + # directory that does not start with a dot to avoid it being accidentally missed when copying the ISO's contents. + : >"${work_dir}/grub/${iso_uuid}.uuid" + search_filename="/boot/grub/${iso_uuid}.uuid" + + # Fill GRUB configuration files + for _cfg in "${profile}/grub/"*'.cfg'; do + sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; + s|%PARABOLAISO_UUID%|${iso_uuid}|g; + s|%INSTALL_DIR%|${install_dir}|g; + s|%ARCH%|${arch}|g; + s|%PARABOLAISO_SEARCH_FILENAME%|${search_filename}|g" \ + "${_cfg}" >"${work_dir}/grub/${_cfg##*/}" + done + + # Prepare grub.cfg that will be embedded inside the GRUB binaries + 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. During El Torito boot, GRUB is + # launched from a case-insensitive FAT-formatted EFI system partition, but it seemingly cannot access that partition + # and sets cmdpath to the whole cd# device which has case-sensitive ISO 9660 + Rock Ridge + Joliet file systems. + # See https://gitlab.archlinux.org/archlinux/archiso/-/issues/183 and https://savannah.gnu.org/bugs/?62886 + if regexp --set=1:parabolaiso_bootdevice '^\(([^)]+)\)\/?[Ee][Ff][Ii]\/[Bb][Oo][Oo][Tt]\/?$' "${cmdpath}"; then + set cmdpath="(${parabolaiso_bootdevice})/EFI/BOOT" + set PARABOLAISO_HINT="${parabolaiso_bootdevice}" + fi +fi + +# Prepare a hint for the search command using the device in cmdpath +if [ -z "${PARABOLAISO_HINT}" ]; then + regexp --set=1:PARABOLAISO_HINT '^\(([^)]+)\)' "${cmdpath}" +fi - # shellcheck disable=SC2016 - printf 'configfile ${cmdpath}/grub.cfg\n' > "${work_dir}/grub-embed.cfg" +# Search for the ISO volume +if search --no-floppy --set=parabolaiso_device --file '%PARABOLAISO_SEARCH_FILENAME%' --hint "${PARABOLAISO_HINT}"; then + set PARABOLAISO_HINT="${parabolaiso_device}" + if probe --set PARABOLAISO_UUID --fs-uuid "${PARABOLAISO_HINT}"; then + export PARABOLAISO_UUID + fi +else + echo "Could not find a volume with a '%PARABOLAISO_SEARCH_FILENAME%' file on it!" +fi - # Create EFI file +# Load grub.cfg +if [ "${PARABOLAISO_HINT}" == 'memdisk' -o -z "${PARABOLAISO_HINT}" ]; then + echo 'Could not find the ISO volume!' +elif [ -e "(${PARABOLAISO_HINT})/boot/grub/grub.cfg" ]; then + export PARABOLAISO_HINT + set root="${PARABOLAISO_HINT}" + configfile "(${PARABOLAISO_HINT})/boot/grub/grub.cfg" +else + echo "File '(${PARABOLAISO_HINT})/boot/grub/grub.cfg' not found!" +fi +EOF + grubembedcfg="${grubembedcfg//'%PARABOLAISO_SEARCH_FILENAME%'/"${search_filename}"}" + printf '%s\n' "$grubembedcfg" >"${work_dir}/grub-embed.cfg" + + # Write grubenv + printf '%.1024s' \ + "$(printf '# GRUB Environment Block\nNAME=%s\nVERSION=%s\nPARABOLAISO_LABEL=%s\nINSTALL_DIR=%s\nARCH=%s\nPARABOLAISO_SEARCH_FILENAME=%s\n%s' \ + "${iso_name}" \ + "${iso_version}" \ + "${iso_label}" \ + "${install_dir}" \ + "${arch}" \ + "${search_filename}" \ + "$(printf '%0.1s' "#"{1..1024})")" \ + >"${work_dir}/grub/grubenv" +} + +# Create GRUB specific configuration files when GRUB is not used as a boot loader +_make_common_grubenv_and_loopbackcfg() { + local search_filename + + install -d -m 0755 -- "${isofs_dir}/boot/grub" + # Create a /boot/grub/YYYY-mm-dd-HH-MM-SS-00.uuid file on ISO 9660. GRUB will search for it to find the ISO + # volume. This is similar to what grub-mkrescue does, except it places the file in /.disk/, but we opt to use a + # directory that does not start with a dot to avoid it being accidentally missed when copying the ISO's contents. + search_filename="/boot/grub/${iso_uuid}.uuid" + : >"${isofs_dir}/${search_filename}" + + # Write grubenv + printf '%.1024s' \ + "$(printf '# GRUB Environment Block\nNAME=%s\nVERSION=%s\nPARABOLAISO_LABEL=%s\nINSTALL_DIR=%s\nARCH=%s\nPARABOLAISO_SEARCH_FILENAME=%s\n%s' \ + "${iso_name}" \ + "${iso_version}" \ + "${iso_label}" \ + "${install_dir}" \ + "${arch}" \ + "${search_filename}" \ + "$(printf '%0.1s' "#"{1..1024})")" \ + >"${isofs_dir}/boot/grub/grubenv" + + # Copy loopback.cfg to /boot/grub/ on ISO 9660 + if [[ -e "${profile}/grub/loopback.cfg" ]]; then + sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; + s|%PARABOLAISO_UUID%|${iso_uuid}|g; + s|%INSTALL_DIR%|${install_dir}|g; + s|%ARCH%|${arch}|g; + s|%PARABOLAISO_SEARCH_FILENAME%|${search_filename}|g" \ + "${profile}/grub/loopback.cfg" >"${isofs_dir}/boot/grub/loopback.cfg" + fi +} + +_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 exfat ext2 f2fs fat font \ + gfxmenu gfxterm gzio halt hfsplus iso9660 jpeg keylayouts linux loadenv loopback lsefi lsefimmap \ + minicmd normal ntfs ntfscomp part_apple part_gpt part_msdos png read reboot regexp search \ + search_fs_file search_fs_uuid search_label serial sleep tpm udf usb usbserial_common usbserial_ftdi \ + usbserial_pl2303 usbserial_usbdebug video xfs zstd) grub-mkstandalone -O i386-efi \ - --modules="part_gpt part_msdos fat iso9660" \ - --locales="en@quot" \ - --themes="" \ - -o "${work_dir}/BOOTIA32.EFI" "boot/grub/grub.cfg=${work_dir}/grub-embed.cfg" + --modules="${grubmodules[*]}" \ + --locales="en@quot" \ + --themes="" \ + --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" "${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") - - efiboot_imgsize="$(du -bc "${efiboot_files[@]}" \ - 2>/dev/null | awk 'END { print $1 }')" + 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 -bcs -- "${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 - mcopy -i "${work_dir}/efiboot.img" \ - "${work_dir}/BOOTIA32.EFI" ::/EFI/BOOT/BOOTIA32.EFI + # Copy GRUB EFI binary to the default/fallback boot path + mcopy -i "${efibootimg}" "${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 + # Copy GRUB files + _run_once _make_common_bootmode_grub_copy_to_isofs - # 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 + 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." @@ -597,80 +756,193 @@ _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 + # 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. _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}/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 - # 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" + install -m 0644 -- "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi" "${isofs_dir}/shellia32.efi" fi _msg_info "Done!" } -# Prepare system-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..." +_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="${grubmodules[*]}" \ + --locales="en@quot" \ + --themes="" \ + --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" + "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi") + + 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 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 + fi + + # Add other aditional/extra files to ${install_dir}/boot/ + if [[ -e "${pacstrap_dir}/boot/memtest86+/memtest.efi" ]]; then + install -d -m 0755 -- "${isofs_dir}/boot/memtest86+/" + install -m 0644 -- "${pacstrap_dir}/boot/memtest86+/memtest.efi" "${isofs_dir}/boot/memtest86+/memtest.efi" + install -m 0644 -- "${pacstrap_dir}/usr/share/licenses/common/GPL2/license.txt" "${isofs_dir}/boot/memtest86+/" + 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 + + # 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. + _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 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 + install -m 0644 -- "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" "${isofs_dir}/shellx64.efi" + fi + + _msg_info "Done!" +} + +_make_common_bootmode_systemd-boot() { + local _file efiboot_imgsize # Calculate the required FAT image size in bytes - efiboot_files+=("${pacstrap_dir}/usr/lib/systemd/boot/efi/systemd-bootx64.efi" - "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" - "${profile}/efiboot/" + # shellcheck disable=SC2076 + if [[ " ${bootmodes[*]} " =~ ' uefi-x64.systemd-boot.esp ' || " ${bootmodes[*]} " =~ ' uefi-x64.systemd-boot.eltorito ' ]]; then + efiboot_files+=("${pacstrap_dir}/usr/lib/systemd/boot/efi/systemd-bootx64.efi" + "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi") + fi + # shellcheck disable=SC2076 + if [[ " ${bootmodes[*]} " =~ ' uefi-ia32.systemd-boot.esp ' || " ${bootmodes[*]} " =~ ' uefi-ia32.systemd-boot.eltorito ' ]]; then + efiboot_files+=("${pacstrap_dir}/usr/lib/systemd/boot/efi/systemd-bootia32.efi" + "${pacstrap_dir}/usr/share/edk2-shell/ia32/Shell_Full.efi") + fi + efiboot_files+=("${work_dir}/loader/" "${pacstrap_dir}/boot/vmlinuz-"* - "${pacstrap_dir}/boot/initramfs-"*".img" - "${_available_ucodes[@]}") - efiboot_imgsize="$(du -bc "${efiboot_files[@]}" \ - 2>/dev/null | awk 'END { print $1 }')" + "${pacstrap_dir}/boot/initramfs-"*".img") + 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 systemd-boot EFI binary to the default/fallback boot path - mcopy -i "${work_dir}/efiboot.img" \ - "${pacstrap_dir}/usr/lib/systemd/boot/efi/systemd-bootx64.efi" ::/EFI/BOOT/BOOTx64.EFI +_make_common_bootmode_systemd-boot_conf() { + local _conf - # 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/ + install -d -m 0755 -- "${work_dir}/loader" "${work_dir}/loader/entries" + + install -m 0644 -- "${profile}/efiboot/loader/loader.conf" "${work_dir}/loader" for _conf in "${profile}/efiboot/loader/entries/"*".conf"; do sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; + s|%PARABOLAISO_UUID%|${iso_uuid}|g; s|%INSTALL_DIR%|${install_dir}|g; s|%ARCH%|${arch}|g" \ - "${_conf}" | mcopy -i "${work_dir}/efiboot.img" - "::/loader/entries/${_conf##*/}" + "${_conf}" >"${work_dir}/loader/entries/${_conf##*/}" done +} + +# Copy systemd-boot configuration files to ISO 9660 +_make_common_bootmode_systemd-boot_conf.isofs() { + cp -r --remove-destination -- "${work_dir}/loader" "${isofs_dir}/" +} + +# Copy systemd-boot configuration files to FAT image +_make_common_bootmode_systemd-boot_conf.esp() { + mcopy -i "${efibootimg}" -s "${work_dir}/loader" ::/ +} + +# Prepare systemd-boot for booting when written to a disk (isohybrid) +_make_bootmode_uefi-x64.systemd-boot.esp() { + _msg_info "Setting up systemd-boot for x64 UEFI booting..." + + # Prepare configuration files + _run_once _make_common_bootmode_systemd-boot_conf + + # Prepare a FAT image for the EFI system partition + _run_once _make_common_bootmode_systemd-boot + + # Copy systemd-boot EFI binary to the default/fallback boot path + mcopy -i "${efibootimg}" \ + "${pacstrap_dir}/usr/lib/systemd/boot/efi/systemd-bootx64.efi" ::/EFI/BOOT/BOOTx64.EFI + + # Copy systemd-boot configuration files + _run_once _make_common_bootmode_systemd-boot_conf.esp # 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 # Copy kernel and initramfs to FAT image. # systemd-boot can only access files from the EFI system partition it was launched from. - _make_boot_on_fat + _run_once _make_boot_on_fat - _msg_info "Done! systemd-boot set up for UEFI booting successfully." + _msg_info "Done! systemd-boot set up for x64 UEFI booting successfully." } -# Prepare system-boot for El Torito booting +# Prepare systemd-boot for El Torito booting _make_bootmode_uefi-x64.systemd-boot.eltorito() { + # Prepare configuration files + _run_once _make_common_bootmode_systemd-boot_conf + # 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..." @@ -681,14 +953,7 @@ _make_bootmode_uefi-x64.systemd-boot.eltorito() { "${isofs_dir}/EFI/BOOT/BOOTx64.EFI" # Copy systemd-boot configuration files - install -d -m 0755 -- "${isofs_dir}/loader/entries" - install -m 0644 -- "${profile}/efiboot/loader/loader.conf" "${isofs_dir}/loader/" - for _conf in "${profile}/efiboot/loader/entries/"*".conf"; do - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g; - s|%ARCH%|${arch}|g" \ - "${_conf}" > "${isofs_dir}/loader/entries/${_conf##*/}" - done + _run_once _make_common_bootmode_systemd-boot_conf.isofs # edk2-shell based UEFI shell # shellx64.efi is picked up automatically when on / @@ -699,78 +964,60 @@ _make_bootmode_uefi-x64.systemd-boot.eltorito() { _msg_info "Done!" } -# Prepare rEFInd for booting when written to a disk (isohybrid) -_make_bootmode_uefi-x64.refind.esp() { - local efiboot_imgsize - _msg_info "Setting up rEFInd for UEFI booting..." +_make_bootmode_uefi-ia32.systemd-boot.esp() { + _msg_info "Setting up systemd-boot for IA32 UEFI booting..." - # Calculate the required FAT image size in bytes - efiboot_files+=("${pacstrap_dir}/usr/share/refind/refind_x64.efi" \ - "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" \ - "${profile}/efiboot/" \ - "${pacstrap_dir}/boot/vmlinuz-"* \ - "${pacstrap_dir}/boot/initramfs-"*".img") - 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" + # Prepare configuration files + _run_once _make_common_bootmode_systemd-boot_conf - # Copy rEFInd EFI binary to the default/fallback boot path - mcopy -i "${work_dir}/efiboot.img" \ - "${pacstrap_dir}/usr/share/refind/refind_x64.efi" ::/EFI/BOOT/BOOTx64.EFI + # Prepare a FAT image for the EFI system partition + _run_once _make_common_bootmode_systemd-boot - # Copy rEFInd configuration files - mmd -i "${work_dir}/efiboot.img" ::/EFI/BOOT/entries - mcopy -i "${work_dir}/efiboot.img" "${profile}/efiboot/refind.conf" ::/EFI/BOOT/ - for _conf in "${profile}/efiboot/entries/"*".conf"; do - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g; - s|%ARCH%|${arch}|g" \ - "${_conf}" | mcopy -i "${work_dir}/efiboot.img" - "::/EFI/BOOT/entries/${_conf##*/}" - done + # Copy systemd-boot EFI binary to the default/fallback boot path + mcopy -i "${efibootimg}" \ + "${pacstrap_dir}/usr/lib/systemd/boot/efi/systemd-bootia32.efi" ::/EFI/BOOT/BOOTIA32.EFI - # 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" \ - "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ::/shellx64.efi + # Copy systemd-boot configuration files + _run_once _make_common_bootmode_systemd-boot_conf.esp + + # shellia32.efi is picked up automatically when on / + 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 fi # Copy kernel and initramfs to FAT image. - _make_boot_on_fat + # systemd-boot can only access files from the EFI system partition it was launched from. + _run_once _make_boot_on_fat - _msg_info "Done! rEFInd set up for UEFI booting successfully." + _msg_info "Done! systemd-boot set up for IA32 UEFI booting successfully." } -# Prepare rEFInd for El Torito booting -_make_bootmode_uefi-x64.refind.eltorito() { +_make_bootmode_uefi-ia32.systemd-boot.eltorito() { + # Prepare configuration files + _run_once _make_common_bootmode_systemd-boot_conf + # El Torito UEFI boot requires an image containing the EFI system partition. - # uefi-x64.refind.eltorito has the same requirements as uefi-x64.refind.esp - _run_once _make_bootmode_uefi-x64.refind.esp + # uefi-ia32.systemd-boot.eltorito has the same requirements as uefi-ia32.systemd-boot.esp + _run_once _make_bootmode_uefi-ia32.systemd-boot.esp - # Additionally set up rEFInd 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..." install -d -m 0755 -- "${isofs_dir}/EFI/BOOT" - # Copy rEFInd EFI binary to the default/fallback boot path - install -m 0644 -- "${pacstrap_dir}/usr/share/refind/refind_x64.efi" \ - "${isofs_dir}/EFI/BOOT/BOOTx64.EFI" + # Copy systemd-boot EFI binary to the default/fallback boot path + install -m 0644 -- "${pacstrap_dir}/usr/lib/systemd/boot/efi/systemd-bootia32.efi" \ + "${isofs_dir}/EFI/BOOT/BOOTIA32.EFI" - # Copy rEFInd configuration files - install -d -m 0755 -- "${isofs_dir}/EFI/BOOT/entries" - install -m 0644 -- "${profile}/efiboot/refind.conf" "${isofs_dir}/EFI/BOOT/" - for _conf in "${profile}/efiboot/entries/"*".conf"; do - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g; - s|%ARCH%|${arch}|g" \ - "${_conf}" > "${isofs_dir}/EFI/BOOT/entries/${_conf##*/}" - done + # Copy systemd-boot configuration files + _run_once _make_common_bootmode_systemd-boot_conf.isofs # edk2-shell based UEFI shell - # shellx64.efi is picked up automatically when on / - 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" + # 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" fi _msg_info "Done!" @@ -819,33 +1066,19 @@ _validate_requirements_bootmode_bios.syslinux.eltorito() { _validate_requirements_bootmode_bios.syslinux.mbr } -_validate_common_requirements_bootmode_uefi-x64() { - # Check if we are building an x64 system - if [[ "${arch}" != @("dual"|"x86_64") ]]; then - (( validation_error=validation_error+1 )) - _msg_error "Validating '${bootmode}': This bootmode is available for 'dual' and 'x86_64' architectures only!" 0 - fi - +_validate_requirements_common_systemd-boot() { # Check if mkfs.fat is available - if ! command -v mkfs.fat &> /dev/null; then + 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 + if ! { command -v mmd &>/dev/null && command -v mcopy &>/dev/null; }; then (( validation_error=validation_error+1 )) _msg_error "Validating '${bootmode}': mmd and/or mcopy are not available on this host. Install 'mtools'!" 0 fi - # Check for optional packages - 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.systemd-boot.esp() { - _validate_common_requirements_bootmode_uefi-x64 # Check if systemd-boot configuration files exist if [[ ! -d "${profile}/efiboot/loader/entries" ]]; then (( validation_error=validation_error+1 )) @@ -865,20 +1098,66 @@ _validate_requirements_bootmode_uefi-x64.systemd-boot.esp() { 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.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_requirements_common_systemd-boot } _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 } +_validate_requirements_bootmode_uefi-ia32.systemd-boot.esp() { + # shellcheck disable=SC2076 + if [[ " ${bootmodes[*]} " =~ ' uefi-ia32.grub.esp ' ]]; then + _msg_error "Validating '${bootmode}': cannot be used with bootmode uefi-ia32.grub.esp!" 0 + fi + + _validate_requirements_common_systemd-boot +} + +_validate_requirements_bootmode_uefi-ia32.systemd-boot.eltorito() { + # shellcheck disable=SC2076 + if [[ " ${bootmodes[*]} " =~ ' uefi-ia32.grub.eltorito ' ]]; then + _msg_error "Validating '${bootmode}': cannot be used with bootmode uefi-ia32.grub.eltorito!" 0 + fi + + # uefi-ia32.systemd-boot.eltorito has the exact same requirements as uefi-ia32.systemd-boot.esp + _validate_requirements_bootmode_uefi-x64.systemd-boot.esp +} + _validate_requirements_bootmode_uefi-ia32.grub.esp() { # Check if GRUB is available - if ! command -v grub-mkstandalone &> /dev/null; then + 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 - _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() { @@ -886,40 +1165,85 @@ _validate_requirements_bootmode_uefi-ia32.grub.eltorito() { _validate_requirements_bootmode_uefi-ia32.grub.esp } -_validate_requirements_bootmode_uefi-x64.refind.esp() { - _validate_common_requirements_bootmode_uefi-x64 - # Check if rEFInd configuration files exist - if [[ ! -d "${profile}/efiboot/entries" ]]; then +_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}': The '${profile}/efiboot/entries' directory is missing!" 0 + _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}/efiboot/refind.conf" ]]; then + if [[ ! -e "${profile}/grub/grub.cfg" ]]; then (( validation_error=validation_error+1 )) - _msg_error "Validating '${bootmode}': File '${profile}/efiboot/refind.conf' not found!" 0 + _msg_error "Validating '${bootmode}': File '${profile}/grub/grub.cfg' not found!" 0 fi local conffile - for conffile in "${profile}/efiboot/entries/"*'.conf'; do + 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}/efiboot/entries/'!" 0 + _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 + # shellcheck disable=SC2076 + if [[ ! " ${pkg_list[*]} " =~ ' memtest86+-efi ' ]]; then + _msg_info "Validating '${bootmode}': 'memtest86+-efi' is not in the package list. Memory testing will not be available from GRUB." + fi } -_validate_requirements_bootmode_uefi-x64.refind.eltorito() { - # uefi-x64.refind.eltorito has the exact same requirements as uefi-x64.refind.esp - _validate_requirements_bootmode_uefi-x64.refind.esp +_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}" _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 } @@ -928,17 +1252,48 @@ _export_netboot_artifacts() { _msg_info "Exporting netboot artifacts..." install -d -m 0755 "${out_dir}" cp -a -- "${isofs_dir}/${install_dir}/" "${out_dir}/" + + # Remove grubenv since it serves no purpose in netboot artifacts + rm -f -- "${out_dir}/${install_dir}/grubenv" + _msg_info "Done!" 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 local _files_to_sign=() _msg_info "Signing netboot artifacts..." _dir="${isofs_dir}/${install_dir}/boot/" - for _file in "${_files_to_sign[@]}" "${_dir}${arch}/vmlinuz-"* "${_dir}${arch}/initramfs-"*.img; do + for _file in "${_files_to_sign[@]}" "${_dir}${arch}/vmlinuz-"!(*.sig) "${_dir}${arch}/initramfs-"*.img; do + rm -f -- "${_file}".ipxe.sig openssl cms \ -sign \ -binary \ @@ -953,14 +1308,14 @@ _sign_netboot_artifacts() { } _validate_requirements_airootfs_image_type_squashfs() { - if ! command -v mksquashfs &> /dev/null; then + if ! command -v mksquashfs &>/dev/null; then (( validation_error=validation_error+1 )) _msg_error "Validating '${airootfs_image_type}': mksquashfs is not available on this host. Install 'squashfs-tools'!" 0 fi } _validate_requirements_airootfs_image_type_ext4+squashfs() { - if ! { command -v mkfs.ext4 &> /dev/null && command -v tune2fs &> /dev/null; }; then + if ! { command -v mkfs.ext4 &>/dev/null && command -v tune2fs &>/dev/null; }; then (( validation_error=validation_error+1 )) _msg_error "Validating '${airootfs_image_type}': mkfs.ext4 and/or tune2fs is not available on this host. Install 'e2fsprogs'!" 0 fi @@ -968,22 +1323,22 @@ _validate_requirements_airootfs_image_type_ext4+squashfs() { } _validate_requirements_airootfs_image_type_erofs() { - if ! command -v mkfs.erofs &> /dev/nul; then + if ! command -v mkfs.erofs &>/dev/nul; then (( validation_error=validation_error+1 )) _msg_error "Validating '${airootfs_image_type}': mkfs.erofs is not available on this host. Install 'erofs-utils'!" 0 fi } _validate_common_requirements_buildmode_all() { - if ! command -v pacman &> /dev/null; then + if ! command -v pacman &>/dev/null; then (( validation_error=validation_error+1 )) _msg_error "Validating build mode '${_buildmode}': pacman is not available on this host. Install 'pacman'!" 0 fi - if ! command -v find &> /dev/null; then + if ! command -v find &>/dev/null; then (( validation_error=validation_error+1 )) _msg_error "Validating build mode '${_buildmode}': find is not available on this host. Install 'findutils'!" 0 fi - if ! command -v gzip &> /dev/null; then + if ! command -v gzip &>/dev/null; then (( validation_error=validation_error+1 )) _msg_error "Validating build mode '${_buildmode}': gzip is not available on this host. Install 'gzip'!" 0 fi @@ -1031,13 +1386,13 @@ _validate_requirements_buildmode_bootstrap() { fi _validate_common_requirements_buildmode_all - if ! command -v bsdtar &> /dev/null; then + if ! command -v bsdtar &>/dev/null; then (( validation_error=validation_error+1 )) _msg_error "Validating build mode '${_buildmode}': bsdtar is not available on this host. Install 'libarchive'!" 0 fi - if [[ "${arch}" == "armv7h" ]] && ! setarch armv7l /bin/true &> /dev/null; then - if ! command -v qemu-arm-static &> /dev/null; then + if [[ "${arch}" == "armv7h" ]] && ! setarch armv7l /bin/true &>/dev/null; then + if ! command -v qemu-arm-static &>/dev/null; then (( validation_error=validation_error+1 )) _msg_error "Validating build mode '${_buildmode}': qemu-arm-static is not available on this host. Install 'qemu-user-static'!" 0 fi @@ -1084,9 +1439,29 @@ _validate_common_requirements_buildmode_iso_netboot() { fi 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 + if typeset -f "_mkairootfs_${airootfs_image_type}" &>/dev/null; then + if typeset -f "_validate_requirements_airootfs_image_type_${airootfs_image_type}" &>/dev/null; then "_validate_requirements_airootfs_image_type_${airootfs_image_type}" else _msg_warning "Function '_validate_requirements_airootfs_image_type_${airootfs_image_type}' does not exist. Validating the requirements of '${airootfs_image_type}' airootfs image type will not be possible." @@ -1106,8 +1481,8 @@ _validate_requirements_buildmode_iso() { _msg_error "No boot modes specified in '${profile}/profiledef.sh'." 0 fi for bootmode in "${bootmodes[@]}"; do - if typeset -f "_make_bootmode_${bootmode}" &> /dev/null; then - if typeset -f "_validate_requirements_bootmode_${bootmode}" &> /dev/null; then + if typeset -f "_make_bootmode_${bootmode}" &>/dev/null; then + if typeset -f "_validate_requirements_bootmode_${bootmode}" &>/dev/null; then "_validate_requirements_bootmode_${bootmode}" else _msg_warning "Function '_validate_requirements_bootmode_${bootmode}' does not exist. Validating the requirements of '${bootmode}' boot mode will not be possible." @@ -1118,47 +1493,24 @@ _validate_requirements_buildmode_iso() { fi done - if ! command -v awk &> /dev/null; then + if ! command -v awk &>/dev/null; then (( validation_error=validation_error+1 )) _msg_error "Validating build mode '${_buildmode}': awk is not available on this host. Install 'awk'!" 0 fi } _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 _add_xorrisofs_options_bios.syslinux.eltorito() { xorrisofs_options+=( # El Torito boot image for x86 BIOS - '-eltorito-boot' 'syslinux/isolinux.bin' + '-eltorito-boot' 'boot/syslinux/isolinux.bin' # El Torito boot catalog file - '-eltorito-catalog' 'syslinux/boot.cat' + '-eltorito-catalog' 'boot/syslinux/boot.cat' # Required options to boot with ISOLINUX '-no-emul-boot' '-boot-load-size' '4' '-boot-info-table' ) @@ -1168,7 +1520,7 @@ _add_xorrisofs_options_bios.syslinux.eltorito() { _add_xorrisofs_options_bios.syslinux.mbr() { xorrisofs_options+=( # SYSLINUX MBR bootstrap code; does not work without "-eltorito-boot syslinux/isolinux.bin" - '-isohybrid-mbr' "${isofs_dir}/syslinux/isohdpfx.bin" + '-isohybrid-mbr' "${isofs_dir}/boot/syslinux/isohdpfx.bin" # When GPT is used, create an additional partition in the MBR (besides 0xEE) for sectors 0–1 (MBR # bootstrap code area) and mark it as bootable # May allow booting on some systems @@ -1183,17 +1535,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 } @@ -1204,14 +1559,14 @@ _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 # 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.systemd-boot.eltorito ' && ! " ${bootmodes[*]} " =~ ' uefi-ia32.grub.eltorito ' ]]; then + if [[ ! " ${bootmodes[*]} " =~ ' uefi-x64.systemd-boot.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. @@ -1251,7 +1606,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/parabolaiso" - cp -a -- "${work_dir}/efiboot.img" "${isofs_dir}/EFI/parabolaiso/efiboot.img" + cp -a -- "${efibootimg}" "${isofs_dir}/EFI/parabolaiso/efiboot.img" # systemd-boot in an embedded efiboot.img via El Torito xorrisofs_options+=( # Start a new El Torito boot entry for UEFI @@ -1267,17 +1622,41 @@ _add_xorrisofs_options_uefi-x64.systemd-boot.eltorito() { [[ " ${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 - _add_xorrisofs_options_uefi-x64.systemd-boot.esp +# 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' "${efibootimg}") + # 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 } -# rEFInd via El Torito -_add_xorrisofs_options_uefi-x64.refind.eltorito() { +# 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.refind.esp ' ]]; then - # rEFInd in an attached EFI system partition via El Torito + 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' @@ -1299,8 +1678,8 @@ _add_xorrisofs_options_uefi-x64.refind.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/parabolaiso" - cp -a -- "${work_dir}/efiboot.img" "${isofs_dir}/EFI/parabolaiso/efiboot.img" - # rEFInd in an embedded efiboot.img via El Torito + cp -a -- "${efibootimg}" "${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' @@ -1329,7 +1708,7 @@ _build_bootstrap_image() { cd -- "${_bootstrap_parent}" _msg_info "Creating ${arch} bootstrap image..." - bsdtar -cf - "root.${arch}" | gzip -cn9 > "${out_dir}/${image_name}" + bsdtar -cf - "root.${arch}" | gzip -cn9 >"${out_dir}/${image_name}" _msg_info "Done!" du -h -- "${out_dir}/${image_name}" cd -- "${OLDPWD}" @@ -1342,33 +1721,38 @@ _build_iso_image() { [[ -d "${out_dir}" ]] || install -d -- "${out_dir}" + # Do not read xorriso startup files to prevent interference and unintended behavior. + # For it to work, -no_rc must be the first argument passed to xorriso. + xorriso_options=('-no_rc') + + if [[ "${quiet}" == "y" ]]; then # The when xorriso is run in mkisofs compatibility mode (xorrisofs), the mkisofs option -quiet is interpreted # too late (e.g. messages about SOURCE_DATE_EPOCH still get shown). # Instead use native xorriso option to silence the output. - xorriso_options=('-report_about' 'SORRY' "${xorriso_options[@]}") + xorriso_options+=('-report_about' 'SORRY') fi # Add required xorrisofs options for each boot mode for bootmode in "${bootmodes[@]}"; do - typeset -f "_add_xorrisofs_options_${bootmode}" &> /dev/null && "_add_xorrisofs_options_${bootmode}" + typeset -f "_add_xorrisofs_options_${bootmode}" &>/dev/null && "_add_xorrisofs_options_${bootmode}" done rm -f -- "${out_dir}/${image_name}" _msg_info "Creating ISO image..." xorriso "${xorriso_options[@]}" -as mkisofs \ - -iso-level 3 \ - -full-iso9660-filenames \ - -joliet \ - -joliet-long \ - -rational-rock \ - -volid "${iso_label}" \ - -appid "${iso_application}" \ - -publisher "${iso_publisher}" \ - -preparer "prepared by ${app_name}" \ - "${xorrisofs_options[@]}" \ - -output "${out_dir}/${image_name}" \ - "${isofs_dir}/" + -iso-level 3 \ + -full-iso9660-filenames \ + -joliet \ + -joliet-long \ + -rational-rock \ + -volid "${iso_label}" \ + -appid "${iso_application}" \ + -publisher "${iso_publisher}" \ + -preparer "prepared by ${app_name}" \ + "${xorrisofs_options[@]}" \ + -output "${out_dir}/${image_name}" \ + "${isofs_dir}/" _msg_info "Done!" du -h -- "${out_dir}/${image_name}" } @@ -1422,7 +1806,7 @@ _read_profile() { # Validate set options _validate_options() { - local validation_error=0 _buildmode + local validation_error=0 _buildmode certfile _msg_info "Validating options..." # Check if pacman configuration file exists @@ -1431,10 +1815,18 @@ _validate_options() { _msg_error "File '${pacman_conf}' does not exist." 0 fi + # Check if the code signing certificate files exist + for certfile in "${cert_list[@]}"; do + if [[ ! -e "$certfile" ]]; then + (( validation_error=validation_error+1 )) + _msg_error "Code signing certificate '${certfile}' does not exist." 0 + fi + done + # Check if the specified buildmodes are supported for _buildmode in "${buildmodes[@]}"; do - if typeset -f "_build_buildmode_${_buildmode}" &> /dev/null; then - if typeset -f "_validate_requirements_buildmode_${_buildmode}" &> /dev/null; then + if typeset -f "_build_buildmode_${_buildmode}" &>/dev/null; then + if typeset -f "_validate_requirements_buildmode_${_buildmode}" &>/dev/null; then "_validate_requirements_buildmode_${_buildmode}" else _msg_warning "Function '_validate_requirements_buildmode_${_buildmode}' does not exist. Validating the requirements of '${_buildmode}' build mode will not be possible." @@ -1500,24 +1892,28 @@ _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 quiet="y" fi + if [[ -v override_rm_work_dir ]]; then + rm_work_dir="$override_rm_work_dir" + fi # Set variables that do not have overrides [[ -n "$airootfs_image_type" ]] || airootfs_image_type="squashfs" [[ -n "$iso_name" ]] || iso_name="${app_name}" + # Precalculate the ISO's modification date in UTC, i.e. its "UUID" + TZ=UTC printf -v iso_uuid '%(%F-%H-%M-%S-00)T' "$SOURCE_DATE_EPOCH" } _export_gpg_publickey() { - rm -f -- "${work_dir}/pubkey.gpg" - gpg --batch --no-armor --output "${work_dir}/pubkey.gpg" --export "${gpg_key}" + gpg_publickey="${work_dir}/pubkey.gpg" + rm -f -- "$gpg_publickey" + gpg --batch --no-armor --output "$gpg_publickey" --export "${gpg_key}" + [[ -s "$gpg_publickey" ]] || return } _make_version() { @@ -1526,16 +1922,23 @@ _make_version() { _msg_info "Creating ${arch} version files..." # Write version file to system installation dir rm -f -- "${pacstrap_dir}/version" - printf '%s\n' "${iso_version}" > "${pacstrap_dir}/version" + printf '%s\n' "${iso_version}" >"${pacstrap_dir}/version" if [[ "${buildmode}" == @("iso"|"netboot") ]]; then install -d -m 0755 -- "${isofs_dir}/${install_dir}" # Write version file to ISO 9660 - printf '%s\n' "${iso_version}" > "${isofs_dir}/${install_dir}/version" + printf '%s\n' "${iso_version}" >"${isofs_dir}/${install_dir}/version" + + fi + if [[ "${buildmode}" == "iso" ]]; then # Write grubenv with version information to ISO 9660 + # TODO: after sufficient time has passed, do not create this file anymore. + # _make_common_bootmode_grub_cfg and _make_common_grubenv_and_loopbackcfg already create a + # ${isofs_dir}/boot/grub/grubenv file + rm -f -- "${isofs_dir}/${install_dir}/grubenv" printf '%.1024s' "$(printf '# GRUB Environment Block\nNAME=%s\nVERSION=%s\n%s' \ "${iso_name}" "${iso_version}" "$(printf '%0.1s' "#"{1..1024})")" \ - > "${isofs_dir}/${install_dir}/grubenv" + >"${isofs_dir}/${install_dir}/grubenv" fi # Append IMAGE_ID & IMAGE_VERSION to os-release @@ -1547,8 +1950,13 @@ _make_version() { _msg_warning "os-release file '${_os_release}' is outside of valid path." else [[ ! -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}" + 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!" } @@ -1556,16 +1964,26 @@ _make_pkglist() { _msg_info "Creating a list of installed packages on ${arch} live-enviroment..." case "${buildmode}" in "bootstrap") - pacman -Q --sysroot "${pacstrap_dir}" > "${pacstrap_dir}/pkglist.${arch}.txt" + pacman -Q --sysroot "${pacstrap_dir}" >"${pacstrap_dir}/pkglist.${arch}.txt" ;; "iso"|"netboot") install -d -m 0755 -- "${isofs_dir}/${install_dir}" - pacman -Q --sysroot "${pacstrap_dir}" > "${isofs_dir}/${install_dir}/pkglist.${arch}.txt" + pacman -Q --sysroot "${pacstrap_dir}" >"${isofs_dir}/${install_dir}/pkglist.${arch}.txt" ;; esac _msg_info "Done!" } +# Create working directory +_make_work_dir() { + if [[ ! -d "${work_dir}" ]]; then + install -d -- "${work_dir}" + elif (( rm_work_dir )); then + rm_work_dir=0 + _msg_warning "Working directory removal requested, but '${work_dir}' already exists. It will not be removed!" 0 + fi +} + # build the base for an ISO and/or a netboot target _build_iso_base() { local run_once_mode="base" @@ -1583,13 +2001,9 @@ _build_iso_base() { isofs_dir="${work_dir}/iso" # Create working directory - [[ -d "${work_dir}" ]] || install -d -- "${work_dir}" - # Write build date to file or if the file exists, read it from there - if [[ -e "${work_dir}/build_date" ]]; then - SOURCE_DATE_EPOCH="$(<"${work_dir}/build_date")" - else - printf '%s\n' "$SOURCE_DATE_EPOCH" > "${work_dir}/build_date" - fi + _run_once _make_work_dir + # Write build date to file if it does not exist already + [[ -e "${work_dir}/build_date" ]] || printf '%s\n' "$SOURCE_DATE_EPOCH" >"${work_dir}/build_date" [[ "${quiet}" == "y" ]] || _show_config _run_dual '_run_once _make_pacman_conf' @@ -1656,6 +2070,13 @@ _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 fi @@ -1666,6 +2087,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 } @@ -1678,23 +2100,29 @@ _build() { for buildmode in "${buildmodes[@]}"; do _run_once "_build_buildmode_${buildmode}" done + if (( rm_work_dir )); then + _msg_info 'Removing the working directory...' + rm -rf -- "${work_dir:?}/" + _msg_info 'Done!' + fi } -while getopts 'c:p:C:L:P:A:D:w:m:o:g:G:vh?' arg; do +while getopts 'c:p:C:L:P:A:D:w:m:o:g:G:vrh?' arg; do case "${arg}" in - p) read -r -a override_pkg_list <<< "${OPTARG}" ;; + p) read -r -a override_pkg_list <<<"${OPTARG}" ;; C) override_pacman_conf="${OPTARG}" ;; L) override_iso_label="${OPTARG}" ;; P) override_iso_publisher="${OPTARG}" ;; A) override_iso_application="${OPTARG}" ;; D) override_install_dir="${OPTARG}" ;; - c) read -r -a override_cert_list <<< "${OPTARG}" ;; + c) read -r -a override_cert_list <<<"${OPTARG}" ;; w) override_work_dir="${OPTARG}" ;; - m) read -r -a override_buildmodes <<< "${OPTARG}" ;; + m) read -r -a override_buildmodes <<<"${OPTARG}" ;; o) override_out_dir="${OPTARG}" ;; g) override_gpg_key="${OPTARG}" ;; G) override_gpg_sender="${OPTARG}" ;; v) override_quiet="n" ;; + r) declare -i override_rm_work_dir=1 ;; h|?) _usage 0 ;; *) _msg_error "Invalid argument '${arg}'" 0 @@ -1717,6 +2145,13 @@ fi # get the absolute path representation of the first non-option argument profile="$(realpath -- "${1}")" +# Read SOURCE_DATE_EPOCH from file early +build_date_file="$(realpath -q -- "${override_work_dir:-./work}/build_date")" || : +if [[ -f "$build_date_file" ]]; then + SOURCE_DATE_EPOCH="$(<"$build_date_file")" +fi +unset build_date_file + _read_profile _set_overrides _validate_options diff --git a/scripts/run_parabolaiso.sh b/scripts/run_parabolaiso.sh index ca8b4c0..4a64e86 100755 --- a/scripts/run_parabolaiso.sh +++ b/scripts/run_parabolaiso.sh @@ -11,7 +11,6 @@ # - qemu # - edk2-ovmf (when UEFI booting) - set -eu print_help() { |