diff options
24 files changed, 788 insertions, 1576 deletions
diff --git a/.editorconfig b/.editorconfig index 74ed4eb..7bc540f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,4 @@ -# EditorConfig for archiso +# EditorConfig for parabolaiso # https://editorconfig.org/ # # SPDX-License-Identifier: GPL-3.0-or-later @@ -23,6 +23,7 @@ lint: scripts/run_parabolaiso.sh \ $(INSTALL_FILES) \ $(wildcard configs/*/build.sh) \ + $(wildcard configs/*/profiledef.sh) \ configs/releng/airootfs/root/.automated_script.sh \ configs/releng/airootfs/usr/local/bin/choose-mirror \ configs/releng-openrc/airootfs/root/.automated_script.sh \ @@ -32,8 +32,7 @@ Profiles parabolaiso comes with the following profiles: **baseline**, **releng**, **releng-openrc**, **lxde-openrc** and **talkingparabola**. They can be found below `configs/baseline/ <configs/baseline/>`_, `configs/releng/ <configs/releng/>`_, `configs/releng-openrc/ <configs/releng-openrc/>`_, `configs/lxde-openrc/ <configs/lxde-openrc/>`_, `configs/talkingparabola/ <configs/talkingparabola/>`_ -(respectively). Profiles are defined by files to be placed into overlays (e.g. *airootfs* -> *the image's /*) and -dynamic actions (i.e. *build.sh* scripts). +(respectively). Profiles are defined by files to be placed into overlays (e.g. *airootfs* -> *the image's /*). Create images ============= @@ -50,28 +49,27 @@ be lost on update). The examples below will assume an unmodified profile in a system location (unless noted otherwise). -It is advised to check the help information of the **build.sh** scripts in the profiles: +It is advised to check the help information of the **mkparabolaiso**: .. code:: bash - /usr/share/parabolaiso/configs/releng/build.sh --help + mkparabolaiso -h Create images with packaged parabolaiso --------------------------------------- .. code:: bash - /usr/share/parabolaiso/configs/releng/build.sh -w path/to/work_dir -o path/to/out_dir + mkparabolaiso -B path/to/profile -w path/to/work_dir -o path/to/out_dir build_profile Create images with local clone ------------------------------ -Clone this repository and make sure to run with the local `mkparabolaiso <parabolaiso/mkparabolaiso>`_ script in *PATH* (if it has -been modified): +Clone this repository and run: .. code:: bash - PATH="parabolaiso:$PATH" ./configs/releng/build.sh -w path/to/work_dir -o path/to/out_dir + ./parabolaiso/mkparabolaiso -B path/to/profile -w path/to/work_dir -o path/to/out_dir build_profile Testing ======= diff --git a/configs/baseline/build.sh b/configs/baseline/build.sh index fce82fb..9a9f654 100755 --- a/configs/baseline/build.sh +++ b/configs/baseline/build.sh @@ -2,113 +2,6 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -set -e -u - -iso_name=parabola -iso_label="PARA_$(date +%Y%m)" -iso_version=$(date +%Y.%m.%d) -install_dir=parabola -arch=$(uname -m) -work_dir=work -out_dir=out - -script_path="$( cd -P "$( dirname "$(readlink -f "$0")" )" && pwd )" - -umask 0022 - -# Helper function to run make_*() only one time per architecture. -run_once() { - if [[ ! -e "${work_dir}/build.${1}_${arch}" ]]; then - "$1" - touch "${work_dir}/build.${1}_${arch}" - fi -} - -# Setup custom pacman.conf with current cache directories. -make_pacman_conf() { - local _cache_dirs - _cache_dirs=("$(pacman -v 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g')") - sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n "${_cache_dirs[@]}")|g" \ - "${script_path}/pacman.conf" > "${work_dir}/pacman.conf" -} - -# Prepare working directory and copy custom airootfs files (airootfs) -make_custom_airootfs() { - local _airootfs="${work_dir}/airootfs" - mkdir -p -- "${_airootfs}" - - if [[ -d "${script_path}/airootfs" ]]; then - cp -af --no-preserve=ownership -- "${script_path}/airootfs/." "${_airootfs}" - [[ -e "${_airootfs}/etc/shadow" ]] && chmod -f 0400 -- "${_airootfs}/etc/shadow" - [[ -e "${_airootfs}/etc/gshadow" ]] && chmod -f 0400 -- "${_airootfs}/etc/gshadow" - - # Set up user home directories and permissions - if [[ -e "${_airootfs}/etc/passwd" ]]; then - while IFS=':' read -a passwd -r; do - [[ "${passwd[5]}" == '/' ]] && continue - - if [[ -d "${_airootfs}${passwd[5]}" ]]; then - chown -hR -- "${passwd[2]}:${passwd[3]}" "${_airootfs}${passwd[5]}" - chmod -f 0750 -- "${_airootfs}${passwd[5]}" - else - install -d -m 0750 -o "${passwd[2]}" -g "${passwd[3]}" -- "${_airootfs}${passwd[5]}" - fi - done < "${_airootfs}/etc/passwd" - fi - fi -} - -# Packages (airootfs) -make_packages() { - mkparabolaiso -v -w "${work_dir}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -p "$(grep -h -v '^#' "${script_path}/packages.both"| sed ':a;N;$!ba;s/\n/ /g')" install -} - -# Prepare ${install_dir}/boot/ -make_boot() { - mkdir -p "${work_dir}/iso/${install_dir}/boot/${arch}" - cp "${work_dir}/airootfs/boot/parabolaiso.img" "${work_dir}/iso/${install_dir}/boot/${arch}/parabolaiso.img" - cp "${work_dir}/airootfs/boot/vmlinuz-linux-libre" "${work_dir}/iso/${install_dir}/boot/${arch}/" -} - -# Prepare /${install_dir}/boot/syslinux -make_syslinux() { - mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux" - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g; - s|%ARCH%|${arch}|g" "${script_path}/syslinux/syslinux.cfg" > \ - "${work_dir}/iso/${install_dir}/boot/syslinux/syslinux.cfg" - cp "${work_dir}/airootfs/usr/lib/syslinux/bios/ldlinux.c32" "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/airootfs/usr/lib/syslinux/bios/menu.c32" "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/airootfs/usr/lib/syslinux/bios/libutil.c32" "${work_dir}/iso/${install_dir}/boot/syslinux/" -} - -# Prepare /isolinux -make_isolinux() { - mkdir -p "${work_dir}/iso/isolinux" - sed "s|%INSTALL_DIR%|${install_dir}|g" "${script_path}/isolinux/isolinux.cfg" > \ - "${work_dir}/iso/isolinux/isolinux.cfg" - cp "${work_dir}/airootfs/usr/lib/syslinux/bios/isolinux.bin" "${work_dir}/iso/isolinux/" - cp "${work_dir}/airootfs/usr/lib/syslinux/bios/isohdpfx.bin" "${work_dir}/iso/isolinux/" - cp "${work_dir}/airootfs/usr/lib/syslinux/bios/ldlinux.c32" "${work_dir}/iso/isolinux/" -} - -# Build airootfs filesystem image -make_prepare() { - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" prepare -} - -# Build ISO -make_iso() { - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" -L "${iso_label}" -o "${out_dir}" iso \ - "${iso_name}-${iso_version}-${arch}.iso" -} - -run_once make_custom_airootfs -run_once make_pacman_conf -run_once make_packages -run_once make_boot -run_once make_syslinux -run_once make_isolinux -run_once make_prepare -run_once make_iso +printf '\n[%s] WARNING: %s\n\n' "mkparabolaiso" "build.sh scripts are deprecated! Please use mkparabolaiso directly." >&2 +_buildsh_path="$(realpath -- "$0")" +exec mkparabolaiso "$@" -B "${_buildsh_path%/*}" build_profile diff --git a/configs/baseline/packages.both b/configs/baseline/packages.x86_64 index 62a9103..62a9103 100644 --- a/configs/baseline/packages.both +++ b/configs/baseline/packages.x86_64 diff --git a/configs/baseline/profiledef.sh b/configs/baseline/profiledef.sh new file mode 100644 index 0000000..4a05474 --- /dev/null +++ b/configs/baseline/profiledef.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2034 + +iso_name="parabola-baseline" +iso_label="PARA_$(date +%Y%m)" +iso_publisher="Parabola GNU/Linux-libre <https://www.parabola.nu>" +iso_application="Parabola GNU/Linux-libre baseline" +iso_version="$(date +%Y.%m.%d)" +install_dir="parabola" +bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito') +arch="x86_64" +pacman_conf="pacman.conf" diff --git a/configs/lxde-openrc/airootfs/root/customize_airootfs.sh b/configs/lxde-openrc/airootfs/root/customize_airootfs.sh index ee8fb9b..05001d9 100755 --- a/configs/lxde-openrc/airootfs/root/customize_airootfs.sh +++ b/configs/lxde-openrc/airootfs/root/customize_airootfs.sh @@ -4,7 +4,7 @@ set -e -u -echo 'Warning: customize_airootfs.sh is deprecated! Support for it will be removed in a future parabolaiso version.' +# Warning: customize_airootfs.sh is deprecated! Support for it will be removed in a future parabolaiso version. sed -i 's/#\(en_US\.UTF-8\)/\1/' /etc/locale.gen sed -i 's/#\(es_ES\.UTF-8\)/\1/' /etc/locale.gen diff --git a/configs/lxde-openrc/build.sh b/configs/lxde-openrc/build.sh index 58f8a84..9a9f654 100755 --- a/configs/lxde-openrc/build.sh +++ b/configs/lxde-openrc/build.sh @@ -1,304 +1,7 @@ -#!/bin/bash +#!/usr/bin/env bash +# +# SPDX-License-Identifier: GPL-3.0-or-later -set -e -u - -iso_name=parabola-openrc-lxde -iso_label="PARA_$(date +%Y%m)" -iso_publisher="Parabola GNU/Linux-libre <http://www.parabola.nu>" -iso_application="Parabola GNU/Linux-libre Live/Rescue CD" -iso_version=$(date +%Y.%m.%d) -install_dir=parabola -work_dir=work -out_dir=out -gpg_key="" - -arch=$(uname -m) -verbose="" -script_path="$( cd -P "$( dirname "$(readlink -f "$0")" )" && pwd )" - -export arch -umask 0022 - -_usage () -{ - echo "usage ${0} [options]" - echo - echo " General options:" - echo " -N <iso_name> Set an iso filename (prefix)" - echo " Default: ${iso_name}" - echo " -V <iso_version> Set an iso version (in filename)" - echo " Default: ${iso_version}" - echo " -L <iso_label> Set an iso label (disk label)" - echo " Default: ${iso_label}" - echo " -P <publisher> Set a publisher for the disk" - echo " Default: '${iso_publisher}'" - echo " -A <application> Set an application name for the disk" - echo " Default: '${iso_application}'" - echo " -D <install_dir> Set an install_dir (directory inside iso)" - echo " Default: ${install_dir}" - echo " -w <work_dir> Set the working directory" - echo " Default: ${work_dir}" - echo " -o <out_dir> Set the output directory" - echo " Default: ${out_dir}" - echo " -v Enable verbose output" - echo " -h This help message" - exit "${1}" -} - -# Helper function to run make_*() only one time per architecture. -run_once() { - if [[ ! -e "${work_dir}/build.${1}_${arch}" ]]; then - "$1" - touch "${work_dir}/build.${1}_${arch}" - fi -} - -# Setup custom pacman.conf with current cache directories and custom mirrorlist. -make_pacman_conf() { - local _cache_dirs - _cache_dirs=("$(pacman -v 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g')") - sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n "${_cache_dirs[@]}")|g" \ - "${script_path}/pacman.conf" > "${work_dir}/pacman.conf" -} - -# Prepare working directory and copy custom airootfs files (airootfs) -make_custom_airootfs() { - local _airootfs="${work_dir}/${arch}/airootfs" - mkdir -p -- "${_airootfs}" - - if [[ -d "${script_path}/airootfs" ]]; then - cp -af --no-preserve=ownership -- "${script_path}/airootfs/." "${_airootfs}" - - [[ -e "${_airootfs}/etc/shadow" ]] && chmod -f 0400 -- "${_airootfs}/etc/shadow" - [[ -e "${_airootfs}/etc/gshadow" ]] && chmod -f 0400 -- "${_airootfs}/etc/gshadow" - - # Set up user home directories and permissions - if [[ -e "${_airootfs}/etc/passwd" ]]; then - while IFS=':' read -a passwd -r; do - [[ "${passwd[5]}" == '/' ]] && continue - - if [[ -d "${_airootfs}${passwd[5]}" ]]; then - chown -hR -- "${passwd[2]}:${passwd[3]}" "${_airootfs}${passwd[5]}" - chmod -f 0750 -- "${_airootfs}${passwd[5]}" - else - install -d -m 0750 -o "${passwd[2]}" -g "${passwd[3]}" -- "${_airootfs}${passwd[5]}" - fi - done < "${_airootfs}/etc/passwd" - fi - fi -} - -# Packages (airootfs) -make_packages() { - if [[ "${gpg_key}" ]]; then - gpg --export "${gpg_key}" >"${work_dir}/gpgkey" - exec 17<>"${work_dir}/gpgkey" - fi - if [ -n "${verbose}" ]; then - PARABOLAISO_GNUPG_FD="${gpg_key:+17}" mkparabolaiso -v -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -p "$(grep -h -v '^#' "${script_path}"/packages.{both,"${arch}"}| sed ':a;N;$!ba;s/\n/ /g')" install - else - PARABOLAISO_GNUPG_FD="${gpg_key:+17}" mkparabolaiso -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -p "$(grep -h -v '^#' "${script_path}"/packages.{both,"${arch}"}| sed ':a;N;$!ba;s/\n/ /g')" install - fi - if [[ "${gpg_key}" ]]; then - exec 17<&- - fi -} - -# Customize installation (airootfs) -make_customize_airootfs() { - if [[ -e "${script_path}/airootfs/etc/passwd" ]]; then - while IFS=':' read -a passwd -r; do - [[ "${passwd[5]}" == '/' ]] && continue - cp -RdT --preserve=mode,timestamps,links -- "${work_dir}/${arch}/airootfs/etc/skel" "${work_dir}/${arch}/airootfs${passwd[5]}" - chown -hR -- "${passwd[2]}:${passwd[3]}" "${work_dir}/${arch}/airootfs${passwd[5]}" - - done < "${script_path}/airootfs/etc/passwd" - fi - - if [[ -e "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh" ]]; then - if [ -n "${verbose}" ]; then - mkparabolaiso -v -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -r '/root/customize_airootfs.sh' run - else - mkparabolaiso -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -r '/root/customize_airootfs.sh' run - fi - rm "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh" - fi -} - -# Prepare kernel/initramfs ${install_dir}/boot/ -make_boot() { - mkdir -p "${work_dir}/iso/${install_dir}/boot/${arch}" - cp "${work_dir}/${arch}/airootfs/boot/parabolaiso.img" "${work_dir}/iso/${install_dir}/boot/${arch}/" - cp "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-libre" "${work_dir}/iso/${install_dir}/boot/${arch}/" -} - -# Add other aditional/extra files to ${install_dir}/boot/ -make_boot_extra() { - if [[ -e "${work_dir}/${arch}/airootfs/boot/memtest86+/memtest.bin" ]]; then - # rename for PXE: https://wiki.parabola.nu/Syslinux#Using_memtest - cp "${work_dir}/${arch}/airootfs/boot/memtest86+/memtest.bin" "${work_dir}/iso/${install_dir}/boot/memtest" - mkdir -p "${work_dir}/iso/${install_dir}/boot/licenses/memtest86+/" - cp "${work_dir}/${arch}/airootfs/usr/share/licenses/common/GPL2/license.txt" \ - "${work_dir}/iso/${install_dir}/boot/licenses/memtest86+/" - fi -} - -# Prepare /${install_dir}/boot/syslinux -make_syslinux() { - _uname_r=$(file -b "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-libre"| awk 'f{print;f=0} /version/{f=1}' RS=' ') - mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux" - for _cfg in "${script_path}/syslinux/"*.cfg; do - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g" "${_cfg}" > "${work_dir}/iso/${install_dir}/boot/syslinux/${_cfg##*/}" - done - cp "${script_path}/syslinux/splash.png" "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/"*.c32 "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/lpxelinux.0" "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/memdisk" "${work_dir}/iso/${install_dir}/boot/syslinux/" - mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux/hdt" - gzip -c -9 "${work_dir}/${arch}/airootfs/usr/lib/modules/${_uname_r}/modules.alias" > \ - "${work_dir}/iso/${install_dir}/boot/syslinux/hdt/modalias.gz" -} - -# Prepare /isolinux -make_isolinux() { - mkdir -p "${work_dir}/iso/isolinux" - sed "s|%INSTALL_DIR%|${install_dir}|g" \ - "${script_path}/isolinux/isolinux.cfg" > "${work_dir}/iso/isolinux/isolinux.cfg" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isolinux.bin" "${work_dir}/iso/isolinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isohdpfx.bin" "${work_dir}/iso/isolinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/ldlinux.c32" "${work_dir}/iso/isolinux/" -} - -# Prepare /EFI -make_efi() { - mkdir -p "${work_dir}/iso/EFI/boot/entries" - cp "${work_dir}/x86_64/airootfs/usr/share/refind/refind_x64.efi" \ - "${work_dir}/iso/EFI/boot/bootx64.efi" - - cp "${script_path}/efiboot/EFI/boot/refind.conf" "${work_dir}/iso/EFI/boot/" - - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g" \ - "${script_path}/efiboot/EFI/boot/entries/parabolaiso-x86_64-usb.conf" > \ - "${work_dir}/iso/EFI/boot/entries/parabolaiso-x86_64.conf" - - # edk2-shell based UEFI shell - # shellx64.efi is picked up automatically when on / - cp "${work_dir}/x86_64/airootfs/usr/share/edk2-shell/x64/Shell_Full.efi" "${work_dir}/iso/shellx64.efi" -} - -# Prepare efiboot.img::/EFI for "El Torito" EFI boot mode -make_efiboot() { - mkdir -p "${work_dir}/iso/EFI/parabolaiso" - truncate -s 64M "${work_dir}/iso/EFI/parabolaiso/efiboot.img" - mkfs.fat -n PARABOLAISO_EFI "${work_dir}/iso/EFI/parabolaiso/efiboot.img" - - mkdir -p "${work_dir}/efiboot" - mount "${work_dir}/iso/EFI/parabolaiso/efiboot.img" "${work_dir}/efiboot" - - mkdir -p "${work_dir}/efiboot/EFI/parabolaiso" - cp "${work_dir}/iso/${install_dir}/boot/x86_64/vmlinuz-linux-libre" "${work_dir}/efiboot/EFI/parabolaiso/" - cp "${work_dir}/iso/${install_dir}/boot/x86_64/parabolaiso.img" "${work_dir}/efiboot/EFI/parabolaiso/" - - mkdir -p "${work_dir}/efiboot/EFI/boot/entries" - cp "${work_dir}/x86_64/airootfs/usr/share/refind/refind_x64.efi" \ - "${work_dir}/efiboot/EFI/boot/bootx64.efi" - - cp "${script_path}/efiboot/EFI/boot/refind.conf" "${work_dir}/efiboot/EFI/boot/" - - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g" \ - "${script_path}/efiboot/EFI/boot/entries/parabolaiso-x86_64-cd.conf" > \ - "${work_dir}/efiboot/EFI/boot/entries/parabolaiso-x86_64.conf" - - # shellx64.efi is picked up automatically when on / - cp "${work_dir}/iso/shellx64.efi" "${work_dir}/efiboot/" - - umount -d "${work_dir}/efiboot" -} - -# Build airootfs filesystem image -make_prepare() { - cp -a -l -f "${work_dir}/${arch}/airootfs" "${work_dir}" - if [ -n "${verbose}" ]; then - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" pkglist - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" ${gpg_key:+-g ${gpg_key}} prepare - else - mkparabolaiso -w "${work_dir}" -D "${install_dir}" pkglist - mkparabolaiso -w "${work_dir}" -D "${install_dir}" ${gpg_key:+-g ${gpg_key}} prepare - fi - rm -rf "${work_dir}/airootfs" - # rm -rf "${work_dir}/${arch}/airootfs" (if low space, this helps) -} - -# Build ISO -make_iso() { - if [ -n "${verbose}" ]; then - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" -L "${iso_label}" -P "${iso_publisher}" \ - -A "${iso_application}" -o "${out_dir}" iso "${iso_name}-${iso_version}-dual.iso" - else - mkparabolaiso -w "${work_dir}" -D "${install_dir}" -L "${iso_label}" -P "${iso_publisher}" \ - -A "${iso_application}" -o "${out_dir}" iso "${iso_name}-${iso_version}-dual.iso" - fi -} - -if [[ ${EUID} -ne 0 ]]; then - echo "This script must be run as root." - _usage 1 -fi - -while getopts 'N:V:L:P:A:D:w:o:g:vh' arg; do - case "${arg}" in - N) iso_name="${OPTARG}" ;; - V) iso_version="${OPTARG}" ;; - L) iso_label="${OPTARG}" ;; - P) iso_publisher="${OPTARG}" ;; - A) iso_application="${OPTARG}" ;; - D) install_dir="${OPTARG}" ;; - w) work_dir="${OPTARG}" ;; - o) out_dir="${OPTARG}" ;; - g) gpg_key="${OPTARG}" ;; - v) verbose="-v" ;; - h) _usage 0 ;; - *) - echo "Invalid argument '${arg}'" - _usage 1 - ;; - esac -done - -mkdir -p "${work_dir}" - -run_once make_pacman_conf - -# Do all stuff for each airootfs -for arch in i686 x86_64; do - run_once make_custom_airootfs - run_once make_packages -done - -for arch in i686 x86_64; do - run_once make_customize_airootfs -done - -for arch in i686 x86_64; do - run_once make_boot -done - -# Do all stuff for "iso" -run_once make_boot_extra -run_once make_syslinux -run_once make_isolinux -run_once make_efi -run_once make_efiboot - -for arch in i686 x86_64; do - run_once make_prepare -done - -run_once make_iso +printf '\n[%s] WARNING: %s\n\n' "mkparabolaiso" "build.sh scripts are deprecated! Please use mkparabolaiso directly." >&2 +_buildsh_path="$(realpath -- "$0")" +exec mkparabolaiso "$@" -B "${_buildsh_path%/*}" build_profile diff --git a/configs/lxde-openrc/profiledef.sh b/configs/lxde-openrc/profiledef.sh new file mode 100644 index 0000000..c86b846 --- /dev/null +++ b/configs/lxde-openrc/profiledef.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2034 + +iso_name="parabola-openrc-lxde" +iso_label="PARA_$(date +%Y%m)" +iso_publisher="Parabola GNU/Linux-libre <https://www.parabola.nu>" +iso_application="Parabola GNU/Linux-libre Live/Rescue CD" +iso_version="$(date +%Y.%m.%d)" +install_dir="parabola" +bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito' 'uefi-x64.refind.esp' 'uefi-x64.refind.eltorito') +arch="dual" +pacman_conf="pacman.conf" diff --git a/configs/lxde-openrc/syslinux/parabolaiso_sys32.cfg b/configs/lxde-openrc/syslinux/parabolaiso_sys32.cfg index f1996bb..da6f10a 100644 --- a/configs/lxde-openrc/syslinux/parabolaiso_sys32.cfg +++ b/configs/lxde-openrc/syslinux/parabolaiso_sys32.cfg @@ -1,6 +1,8 @@ # # SPDX-License-Identifier: GPL-3.0-or-later +TIMEOUT 30 + LABEL parabola32 TEXT HELP Boot the Parabola GNU/Linux-libre (i686) live medium. diff --git a/configs/releng-openrc/airootfs/root/customize_airootfs.sh b/configs/releng-openrc/airootfs/root/customize_airootfs.sh index c72644a..92e57de 100755 --- a/configs/releng-openrc/airootfs/root/customize_airootfs.sh +++ b/configs/releng-openrc/airootfs/root/customize_airootfs.sh @@ -4,7 +4,7 @@ set -e -u -echo 'Warning: customize_airootfs.sh is deprecated! Support for it will be removed in a future parabolaiso version.' +# Warning: customize_airootfs.sh is deprecated! Support for it will be removed in a future parabolaiso version. sed -i 's/#\(en_US\.UTF-8\)/\1/' /etc/locale.gen locale-gen diff --git a/configs/releng-openrc/build.sh b/configs/releng-openrc/build.sh index 7bbabd2..9a9f654 100755 --- a/configs/releng-openrc/build.sh +++ b/configs/releng-openrc/build.sh @@ -1,304 +1,7 @@ -#!/bin/bash +#!/usr/bin/env bash +# +# SPDX-License-Identifier: GPL-3.0-or-later -set -e -u - -iso_name=parabola-openrc -iso_label="PARA_$(date +%Y%m)" -iso_publisher="Parabola GNU/Linux-libre <http://www.parabola.nu>" -iso_application="Parabola GNU/Linux-libre Live/Rescue CD" -iso_version=$(date +%Y.%m.%d) -install_dir=parabola -work_dir=work -out_dir=out -gpg_key="" - -arch=$(uname -m) -verbose="" -script_path="$( cd -P "$( dirname "$(readlink -f "$0")" )" && pwd )" - -export arch -umask 0022 - -_usage () -{ - echo "usage ${0} [options]" - echo - echo " General options:" - echo " -N <iso_name> Set an iso filename (prefix)" - echo " Default: ${iso_name}" - echo " -V <iso_version> Set an iso version (in filename)" - echo " Default: ${iso_version}" - echo " -L <iso_label> Set an iso label (disk label)" - echo " Default: ${iso_label}" - echo " -P <publisher> Set a publisher for the disk" - echo " Default: '${iso_publisher}'" - echo " -A <application> Set an application name for the disk" - echo " Default: '${iso_application}'" - echo " -D <install_dir> Set an install_dir (directory inside iso)" - echo " Default: ${install_dir}" - echo " -w <work_dir> Set the working directory" - echo " Default: ${work_dir}" - echo " -o <out_dir> Set the output directory" - echo " Default: ${out_dir}" - echo " -v Enable verbose output" - echo " -h This help message" - exit "${1}" -} - -# Helper function to run make_*() only one time per architecture. -run_once() { - if [[ ! -e "${work_dir}/build.${1}_${arch}" ]]; then - "$1" - touch "${work_dir}/build.${1}_${arch}" - fi -} - -# Setup custom pacman.conf with current cache directories and custom mirrorlist. -make_pacman_conf() { - local _cache_dirs - _cache_dirs=("$(pacman -v 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g')") - sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n "${_cache_dirs[@]}")|g" \ - "${script_path}/pacman.conf" > "${work_dir}/pacman.conf" -} - -# Prepare working directory and copy custom airootfs files (airootfs) -make_custom_airootfs() { - local _airootfs="${work_dir}/${arch}/airootfs" - mkdir -p -- "${_airootfs}" - - if [[ -d "${script_path}/airootfs" ]]; then - cp -af --no-preserve=ownership -- "${script_path}/airootfs/." "${_airootfs}" - - [[ -e "${_airootfs}/etc/shadow" ]] && chmod -f 0400 -- "${_airootfs}/etc/shadow" - [[ -e "${_airootfs}/etc/gshadow" ]] && chmod -f 0400 -- "${_airootfs}/etc/gshadow" - - # Set up user home directories and permissions - if [[ -e "${_airootfs}/etc/passwd" ]]; then - while IFS=':' read -a passwd -r; do - [[ "${passwd[5]}" == '/' ]] && continue - - if [[ -d "${_airootfs}${passwd[5]}" ]]; then - chown -hR -- "${passwd[2]}:${passwd[3]}" "${_airootfs}${passwd[5]}" - chmod -f 0750 -- "${_airootfs}${passwd[5]}" - else - install -d -m 0750 -o "${passwd[2]}" -g "${passwd[3]}" -- "${_airootfs}${passwd[5]}" - fi - done < "${_airootfs}/etc/passwd" - fi - fi -} - -# Packages (airootfs) -make_packages() { - if [[ "${gpg_key}" ]]; then - gpg --export "${gpg_key}" >"${work_dir}/gpgkey" - exec 17<>"${work_dir}/gpgkey" - fi - if [ -n "${verbose}" ]; then - PARABOLAISO_GNUPG_FD="${gpg_key:+17}" mkparabolaiso -v -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -p "$(grep -h -v '^#' "${script_path}"/packages.{both,"${arch}"}| sed ':a;N;$!ba;s/\n/ /g')" install - else - PARABOLAISO_GNUPG_FD="${gpg_key:+17}" mkparabolaiso -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -p "$(grep -h -v '^#' "${script_path}"/packages.{both,"${arch}"}| sed ':a;N;$!ba;s/\n/ /g')" install - fi - if [[ "${gpg_key}" ]]; then - exec 17<&- - fi -} - -# Customize installation (airootfs) -make_customize_airootfs() { - if [[ -e "${script_path}/airootfs/etc/passwd" ]]; then - while IFS=':' read -a passwd -r; do - [[ "${passwd[5]}" == '/' ]] && continue - cp -RdT --preserve=mode,timestamps,links -- "${work_dir}/${arch}/airootfs/etc/skel" "${work_dir}/${arch}/airootfs${passwd[5]}" - chown -hR -- "${passwd[2]}:${passwd[3]}" "${work_dir}/${arch}/airootfs${passwd[5]}" - - done < "${script_path}/airootfs/etc/passwd" - fi - - if [[ -e "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh" ]]; then - if [ -n "${verbose}" ]; then - mkparabolaiso -v -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -r '/root/customize_airootfs.sh' run - else - mkparabolaiso -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -r '/root/customize_airootfs.sh' run - fi - rm "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh" - fi -} - -# Prepare kernel/initramfs ${install_dir}/boot/ -make_boot() { - mkdir -p "${work_dir}/iso/${install_dir}/boot/${arch}" - cp "${work_dir}/${arch}/airootfs/boot/parabolaiso.img" "${work_dir}/iso/${install_dir}/boot/${arch}/" - cp "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-libre" "${work_dir}/iso/${install_dir}/boot/${arch}/" -} - -# Add other aditional/extra files to ${install_dir}/boot/ -make_boot_extra() { - if [[ -e "${work_dir}/${arch}/airootfs/boot/memtest86+/memtest.bin" ]]; then - # rename for PXE: https://wiki.parabola.nu/Syslinux#Using_memtest - cp "${work_dir}/${arch}/airootfs/boot/memtest86+/memtest.bin" "${work_dir}/iso/${install_dir}/boot/memtest" - mkdir -p "${work_dir}/iso/${install_dir}/boot/licenses/memtest86+/" - cp "${work_dir}/${arch}/airootfs/usr/share/licenses/common/GPL2/license.txt" \ - "${work_dir}/iso/${install_dir}/boot/licenses/memtest86+/" - fi -} - -# Prepare /${install_dir}/boot/syslinux -make_syslinux() { - _uname_r=$(file -b "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-libre"| awk 'f{print;f=0} /version/{f=1}' RS=' ') - mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux" - for _cfg in "${script_path}/syslinux/"*.cfg; do - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g" "${_cfg}" > "${work_dir}/iso/${install_dir}/boot/syslinux/${_cfg##*/}" - done - cp "${script_path}/syslinux/splash.png" "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/"*.c32 "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/lpxelinux.0" "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/memdisk" "${work_dir}/iso/${install_dir}/boot/syslinux/" - mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux/hdt" - gzip -c -9 "${work_dir}/${arch}/airootfs/usr/lib/modules/${_uname_r}/modules.alias" > \ - "${work_dir}/iso/${install_dir}/boot/syslinux/hdt/modalias.gz" -} - -# Prepare /isolinux -make_isolinux() { - mkdir -p "${work_dir}/iso/isolinux" - sed "s|%INSTALL_DIR%|${install_dir}|g" \ - "${script_path}/isolinux/isolinux.cfg" > "${work_dir}/iso/isolinux/isolinux.cfg" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isolinux.bin" "${work_dir}/iso/isolinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isohdpfx.bin" "${work_dir}/iso/isolinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/ldlinux.c32" "${work_dir}/iso/isolinux/" -} - -# Prepare /EFI -make_efi() { - mkdir -p "${work_dir}/iso/EFI/boot/entries" - cp "${work_dir}/x86_64/airootfs/usr/share/refind/refind_x64.efi" \ - "${work_dir}/iso/EFI/boot/bootx64.efi" - - cp "${script_path}/efiboot/EFI/boot/refind.conf" "${work_dir}/iso/EFI/boot/" - - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g" \ - "${script_path}/efiboot/EFI/boot/entries/parabolaiso-x86_64-usb.conf" > \ - "${work_dir}/iso/EFI/boot/entries/parabolaiso-x86_64.conf" - - # edk2-shell based UEFI shell - # shellx64.efi is picked up automatically when on / - cp "${work_dir}/x86_64/airootfs/usr/share/edk2-shell/x64/Shell_Full.efi" "${work_dir}/iso/shellx64.efi" -} - -# Prepare efiboot.img::/EFI for "El Torito" EFI boot mode -make_efiboot() { - mkdir -p "${work_dir}/iso/EFI/parabolaiso" - truncate -s 64M "${work_dir}/iso/EFI/parabolaiso/efiboot.img" - mkfs.fat -n PARABOLAISO_EFI "${work_dir}/iso/EFI/parabolaiso/efiboot.img" - - mkdir -p "${work_dir}/efiboot" - mount "${work_dir}/iso/EFI/parabolaiso/efiboot.img" "${work_dir}/efiboot" - - mkdir -p "${work_dir}/efiboot/EFI/parabolaiso" - cp "${work_dir}/iso/${install_dir}/boot/x86_64/vmlinuz-linux-libre" "${work_dir}/efiboot/EFI/parabolaiso/" - cp "${work_dir}/iso/${install_dir}/boot/x86_64/parabolaiso.img" "${work_dir}/efiboot/EFI/parabolaiso/" - - mkdir -p "${work_dir}/efiboot/EFI/boot/entries" - cp "${work_dir}/x86_64/airootfs/usr/share/refind/refind_x64.efi" \ - "${work_dir}/efiboot/EFI/boot/bootx64.efi" - - cp "${script_path}/efiboot/EFI/boot/refind.conf" "${work_dir}/efiboot/EFI/boot/" - - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g" \ - "${script_path}/efiboot/EFI/boot/entries/parabolaiso-x86_64-cd.conf" > \ - "${work_dir}/efiboot/EFI/boot/entries/parabolaiso-x86_64.conf" - - # shellx64.efi is picked up automatically when on / - cp "${work_dir}/iso/shellx64.efi" "${work_dir}/efiboot/" - - umount -d "${work_dir}/efiboot" -} - -# Build airootfs filesystem image -make_prepare() { - cp -a -l -f "${work_dir}/${arch}/airootfs" "${work_dir}" - if [ -n "${verbose}" ]; then - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" pkglist - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" ${gpg_key:+-g ${gpg_key}} prepare - else - mkparabolaiso -w "${work_dir}" -D "${install_dir}" pkglist - mkparabolaiso -w "${work_dir}" -D "${install_dir}" ${gpg_key:+-g ${gpg_key}} prepare - fi - rm -rf "${work_dir}/airootfs" - # rm -rf "${work_dir}/${arch}/airootfs" (if low space, this helps) -} - -# Build ISO -make_iso() { - if [ -n "${verbose}" ]; then - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" -L "${iso_label}" -P "${iso_publisher}" \ - -A "${iso_application}" -o "${out_dir}" iso "${iso_name}-${iso_version}-dual.iso" - else - mkparabolaiso -w "${work_dir}" -D "${install_dir}" -L "${iso_label}" -P "${iso_publisher}" \ - -A "${iso_application}" -o "${out_dir}" iso "${iso_name}-${iso_version}-dual.iso" - fi -} - -if [[ ${EUID} -ne 0 ]]; then - echo "This script must be run as root." - _usage 1 -fi - -while getopts 'N:V:L:P:A:D:w:o:g:vh' arg; do - case "${arg}" in - N) iso_name="${OPTARG}" ;; - V) iso_version="${OPTARG}" ;; - L) iso_label="${OPTARG}" ;; - P) iso_publisher="${OPTARG}" ;; - A) iso_application="${OPTARG}" ;; - D) install_dir="${OPTARG}" ;; - w) work_dir="${OPTARG}" ;; - o) out_dir="${OPTARG}" ;; - g) gpg_key="${OPTARG}" ;; - v) verbose="-v" ;; - h) _usage 0 ;; - *) - echo "Invalid argument '${arg}'" - _usage 1 - ;; - esac -done - -mkdir -p "${work_dir}" - -run_once make_pacman_conf - -# Do all stuff for each airootfs -for arch in i686 x86_64; do - run_once make_custom_airootfs - run_once make_packages -done - -for arch in i686 x86_64; do - run_once make_customize_airootfs -done - -for arch in i686 x86_64; do - run_once make_boot -done - -# Do all stuff for "iso" -run_once make_boot_extra -run_once make_syslinux -run_once make_isolinux -run_once make_efi -run_once make_efiboot - -for arch in i686 x86_64; do - run_once make_prepare -done - -run_once make_iso +printf '\n[%s] WARNING: %s\n\n' "mkparabolaiso" "build.sh scripts are deprecated! Please use mkparabolaiso directly." >&2 +_buildsh_path="$(realpath -- "$0")" +exec mkparabolaiso "$@" -B "${_buildsh_path%/*}" build_profile diff --git a/configs/releng-openrc/profiledef.sh b/configs/releng-openrc/profiledef.sh new file mode 100644 index 0000000..11a74c8 --- /dev/null +++ b/configs/releng-openrc/profiledef.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2034 + +iso_name="parabola-openrc" +iso_label="PARA_$(date +%Y%m)" +iso_publisher="Parabola GNU/Linux-libre <https://www.parabola.nu>" +iso_application="Parabola GNU/Linux-libre Live/Rescue CD" +iso_version="$(date +%Y.%m.%d)" +install_dir="parabola" +bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito' 'uefi-x64.refind.esp' 'uefi-x64.refind.eltorito') +arch="dual" +pacman_conf="pacman.conf" diff --git a/configs/releng-openrc/syslinux/parabolaiso_sys32.cfg b/configs/releng-openrc/syslinux/parabolaiso_sys32.cfg index f1996bb..da6f10a 100644 --- a/configs/releng-openrc/syslinux/parabolaiso_sys32.cfg +++ b/configs/releng-openrc/syslinux/parabolaiso_sys32.cfg @@ -1,6 +1,8 @@ # # SPDX-License-Identifier: GPL-3.0-or-later +TIMEOUT 30 + LABEL parabola32 TEXT HELP Boot the Parabola GNU/Linux-libre (i686) live medium. diff --git a/configs/releng/airootfs/root/customize_airootfs.sh b/configs/releng/airootfs/root/customize_airootfs.sh index c72644a..92e57de 100755 --- a/configs/releng/airootfs/root/customize_airootfs.sh +++ b/configs/releng/airootfs/root/customize_airootfs.sh @@ -4,7 +4,7 @@ set -e -u -echo 'Warning: customize_airootfs.sh is deprecated! Support for it will be removed in a future parabolaiso version.' +# Warning: customize_airootfs.sh is deprecated! Support for it will be removed in a future parabolaiso version. sed -i 's/#\(en_US\.UTF-8\)/\1/' /etc/locale.gen locale-gen diff --git a/configs/releng/build.sh b/configs/releng/build.sh index 10ca01f..9a9f654 100755 --- a/configs/releng/build.sh +++ b/configs/releng/build.sh @@ -2,307 +2,6 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -set -e -u - -iso_name=parabola -iso_label="PARA_$(date +%Y%m)" -iso_publisher="Parabola GNU/Linux-libre <http://www.parabola.nu>" -iso_application="Parabola GNU/Linux-libre Live/Rescue CD" -iso_version=$(date +%Y.%m.%d) -install_dir=parabola -work_dir=work -out_dir=out -gpg_key="" - -arch=$(uname -m) -verbose="" -script_path="$( cd -P "$( dirname "$(readlink -f "$0")" )" && pwd )" - -export arch -umask 0022 - -_usage () -{ - echo "usage ${0} [options]" - echo - echo " General options:" - echo " -N <iso_name> Set an iso filename (prefix)" - echo " Default: ${iso_name}" - echo " -V <iso_version> Set an iso version (in filename)" - echo " Default: ${iso_version}" - echo " -L <iso_label> Set an iso label (disk label)" - echo " Default: ${iso_label}" - echo " -P <publisher> Set a publisher for the disk" - echo " Default: '${iso_publisher}'" - echo " -A <application> Set an application name for the disk" - echo " Default: '${iso_application}'" - echo " -D <install_dir> Set an install_dir (directory inside iso)" - echo " Default: ${install_dir}" - echo " -w <work_dir> Set the working directory" - echo " Default: ${work_dir}" - echo " -o <out_dir> Set the output directory" - echo " Default: ${out_dir}" - echo " -v Enable verbose output" - echo " -h This help message" - exit "${1}" -} - -# Helper function to run make_*() only one time per architecture. -run_once() { - if [[ ! -e "${work_dir}/build.${1}_${arch}" ]]; then - "$1" - touch "${work_dir}/build.${1}_${arch}" - fi -} - -# Setup custom pacman.conf with current cache directories and custom mirrorlist. -make_pacman_conf() { - local _cache_dirs - _cache_dirs=("$(pacman -v 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g')") - sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n "${_cache_dirs[@]}")|g" \ - "${script_path}/pacman.conf" > "${work_dir}/pacman.conf" -} - -# Prepare working directory and copy custom airootfs files (airootfs) -make_custom_airootfs() { - local _airootfs="${work_dir}/${arch}/airootfs" - mkdir -p -- "${_airootfs}" - - if [[ -d "${script_path}/airootfs" ]]; then - cp -af --no-preserve=ownership -- "${script_path}/airootfs/." "${_airootfs}" - - [[ -e "${_airootfs}/etc/shadow" ]] && chmod -f 0400 -- "${_airootfs}/etc/shadow" - [[ -e "${_airootfs}/etc/gshadow" ]] && chmod -f 0400 -- "${_airootfs}/etc/gshadow" - - # Set up user home directories and permissions - if [[ -e "${_airootfs}/etc/passwd" ]]; then - while IFS=':' read -a passwd -r; do - [[ "${passwd[5]}" == '/' ]] && continue - - if [[ -d "${_airootfs}${passwd[5]}" ]]; then - chown -hR -- "${passwd[2]}:${passwd[3]}" "${_airootfs}${passwd[5]}" - chmod -f 0750 -- "${_airootfs}${passwd[5]}" - else - install -d -m 0750 -o "${passwd[2]}" -g "${passwd[3]}" -- "${_airootfs}${passwd[5]}" - fi - done < "${_airootfs}/etc/passwd" - fi - fi -} - -# Packages (airootfs) -make_packages() { - if [[ "${gpg_key}" ]]; then - gpg --export "${gpg_key}" >"${work_dir}/gpgkey" - exec 17<>"${work_dir}/gpgkey" - fi - if [ -n "${verbose}" ]; then - PARABOLAISO_GNUPG_FD="${gpg_key:+17}" mkparabolaiso -v -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -p "$(grep -h -v '^#' "${script_path}"/packages.{both,"${arch}"}| sed ':a;N;$!ba;s/\n/ /g')" install - else - PARABOLAISO_GNUPG_FD="${gpg_key:+17}" mkparabolaiso -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -p "$(grep -h -v '^#' "${script_path}"/packages.{both,"${arch}"}| sed ':a;N;$!ba;s/\n/ /g')" install - fi - if [[ "${gpg_key}" ]]; then - exec 17<&- - fi -} - -# Customize installation (airootfs) -make_customize_airootfs() { - if [[ -e "${script_path}/airootfs/etc/passwd" ]]; then - while IFS=':' read -a passwd -r; do - [[ "${passwd[5]}" == '/' ]] && continue - cp -RdT --preserve=mode,timestamps,links -- "${work_dir}/${arch}/airootfs/etc/skel" "${work_dir}/${arch}/airootfs${passwd[5]}" - chown -hR -- "${passwd[2]}:${passwd[3]}" "${work_dir}/${arch}/airootfs${passwd[5]}" - - done < "${script_path}/airootfs/etc/passwd" - fi - - if [[ -e "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh" ]]; then - if [ -n "${verbose}" ]; then - mkparabolaiso -v -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -r '/root/customize_airootfs.sh' run - else - mkparabolaiso -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -r '/root/customize_airootfs.sh' run - fi - rm "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh" - fi -} - -# Prepare kernel/initramfs ${install_dir}/boot/ -make_boot() { - mkdir -p "${work_dir}/iso/${install_dir}/boot/${arch}" - cp "${work_dir}/${arch}/airootfs/boot/parabolaiso.img" "${work_dir}/iso/${install_dir}/boot/${arch}/" - cp "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-libre" "${work_dir}/iso/${install_dir}/boot/${arch}/" -} - -# Add other aditional/extra files to ${install_dir}/boot/ -make_boot_extra() { - if [[ -e "${work_dir}/${arch}/airootfs/boot/memtest86+/memtest.bin" ]]; then - # rename for PXE: https://wiki.parabola.nu/Syslinux#Using_memtest - cp "${work_dir}/${arch}/airootfs/boot/memtest86+/memtest.bin" "${work_dir}/iso/${install_dir}/boot/memtest" - mkdir -p "${work_dir}/iso/${install_dir}/boot/licenses/memtest86+/" - cp "${work_dir}/${arch}/airootfs/usr/share/licenses/common/GPL2/license.txt" \ - "${work_dir}/iso/${install_dir}/boot/licenses/memtest86+/" - fi -} - -# Prepare /${install_dir}/boot/syslinux -make_syslinux() { - _uname_r=$(file -b "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-libre"| awk 'f{print;f=0} /version/{f=1}' RS=' ') - mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux" - for _cfg in "${script_path}/syslinux/"*.cfg; do - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g" "${_cfg}" > "${work_dir}/iso/${install_dir}/boot/syslinux/${_cfg##*/}" - done - cp "${script_path}/syslinux/splash.png" "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/"*.c32 "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/lpxelinux.0" "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/memdisk" "${work_dir}/iso/${install_dir}/boot/syslinux/" - mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux/hdt" - gzip -c -9 "${work_dir}/${arch}/airootfs/usr/lib/modules/${_uname_r}/modules.alias" > \ - "${work_dir}/iso/${install_dir}/boot/syslinux/hdt/modalias.gz" -} - -# Prepare /isolinux -make_isolinux() { - mkdir -p "${work_dir}/iso/isolinux" - sed "s|%INSTALL_DIR%|${install_dir}|g" \ - "${script_path}/isolinux/isolinux.cfg" > "${work_dir}/iso/isolinux/isolinux.cfg" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isolinux.bin" "${work_dir}/iso/isolinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isohdpfx.bin" "${work_dir}/iso/isolinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/ldlinux.c32" "${work_dir}/iso/isolinux/" -} - -# Prepare /EFI -make_efi() { - mkdir -p "${work_dir}/iso/EFI/boot" - cp "${work_dir}/x86_64/airootfs/usr/lib/systemd/boot/efi/systemd-bootx64.efi" \ - "${work_dir}/iso/EFI/boot/bootx64.efi" - - mkdir -p "${work_dir}/iso/loader/entries" - cp "${script_path}/efiboot/loader/loader.conf" "${work_dir}/iso/loader/" - - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g" \ - "${script_path}/efiboot/loader/entries/parabolaiso-x86_64-usb.conf" > \ - "${work_dir}/iso/loader/entries/parabolaiso-x86_64.conf" - - # edk2-shell based UEFI shell - # shellx64.efi is picked up automatically when on / - cp "${work_dir}/x86_64/airootfs/usr/share/edk2-shell/x64/Shell_Full.efi" "${work_dir}/iso/shellx64.efi" -} - -# Prepare efiboot.img::/EFI for "El Torito" EFI boot mode -make_efiboot() { - mkdir -p "${work_dir}/iso/EFI/parabolaiso" - truncate -s 64M "${work_dir}/iso/EFI/parabolaiso/efiboot.img" - mkfs.fat -n PARABOLAISO_EFI "${work_dir}/iso/EFI/parabolaiso/efiboot.img" - - mkdir -p "${work_dir}/efiboot" - mount "${work_dir}/iso/EFI/parabolaiso/efiboot.img" "${work_dir}/efiboot" - - mkdir -p "${work_dir}/efiboot/EFI/parabolaiso" - cp "${work_dir}/iso/${install_dir}/boot/x86_64/vmlinuz-linux-libre" "${work_dir}/efiboot/EFI/parabolaiso/" - cp "${work_dir}/iso/${install_dir}/boot/x86_64/parabolaiso.img" "${work_dir}/efiboot/EFI/parabolaiso/" - - mkdir -p "${work_dir}/efiboot/EFI/boot" - cp "${work_dir}/x86_64/airootfs/usr/lib/systemd/boot/efi/systemd-bootx64.efi" \ - "${work_dir}/efiboot/EFI/boot/bootx64.efi" - - mkdir -p "${work_dir}/efiboot/loader/entries" - cp "${script_path}/efiboot/loader/loader.conf" "${work_dir}/efiboot/loader/" - - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g" \ - "${script_path}/efiboot/loader/entries/parabolaiso-x86_64-cd.conf" > \ - "${work_dir}/efiboot/loader/entries/parabolaiso-x86_64.conf" - - # shellx64.efi is picked up automatically when on / - cp "${work_dir}/iso/shellx64.efi" "${work_dir}/efiboot/" - - umount -d "${work_dir}/efiboot" -} - -# Build airootfs filesystem image -make_prepare() { - cp -a -l -f "${work_dir}/${arch}/airootfs" "${work_dir}" - if [ -n "${verbose}" ]; then - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" pkglist - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" ${gpg_key:+-g ${gpg_key}} prepare - else - mkparabolaiso -w "${work_dir}" -D "${install_dir}" pkglist - mkparabolaiso -w "${work_dir}" -D "${install_dir}" ${gpg_key:+-g ${gpg_key}} prepare - fi - rm -rf "${work_dir}/airootfs" - # rm -rf "${work_dir}/${arch}/airootfs" (if low space, this helps) -} - -# Build ISO -make_iso() { - if [ -n "${verbose}" ]; then - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" -L "${iso_label}" -P "${iso_publisher}" \ - -A "${iso_application}" -o "${out_dir}" iso "${iso_name}-${iso_version}-dual.iso" - else - mkparabolaiso -w "${work_dir}" -D "${install_dir}" -L "${iso_label}" -P "${iso_publisher}" \ - -A "${iso_application}" -o "${out_dir}" iso "${iso_name}-${iso_version}-dual.iso" - fi -} - -if [[ ${EUID} -ne 0 ]]; then - echo "This script must be run as root." - _usage 1 -fi - -while getopts 'N:V:L:P:A:D:w:o:g:vh' arg; do - case "${arg}" in - N) iso_name="${OPTARG}" ;; - V) iso_version="${OPTARG}" ;; - L) iso_label="${OPTARG}" ;; - P) iso_publisher="${OPTARG}" ;; - A) iso_application="${OPTARG}" ;; - D) install_dir="${OPTARG}" ;; - w) work_dir="${OPTARG}" ;; - o) out_dir="${OPTARG}" ;; - g) gpg_key="${OPTARG}" ;; - v) verbose="-v" ;; - h) _usage 0 ;; - *) - echo "Invalid argument '${arg}'" - _usage 1 - ;; - esac -done - -mkdir -p "${work_dir}" - -run_once make_pacman_conf - -# Do all stuff for each airootfs -for arch in i686 x86_64; do - run_once make_custom_airootfs - run_once make_packages -done - -for arch in i686 x86_64; do - run_once make_customize_airootfs -done - -for arch in i686 x86_64; do - run_once make_boot -done - -# Do all stuff for "iso" -run_once make_boot_extra -run_once make_syslinux -run_once make_isolinux -run_once make_efi -run_once make_efiboot - -for arch in i686 x86_64; do - run_once make_prepare -done - -run_once make_iso +printf '\n[%s] WARNING: %s\n\n' "mkparabolaiso" "build.sh scripts are deprecated! Please use mkparabolaiso directly." >&2 +_buildsh_path="$(realpath -- "$0")" +exec mkparabolaiso "$@" -B "${_buildsh_path%/*}" build_profile diff --git a/configs/releng/profiledef.sh b/configs/releng/profiledef.sh new file mode 100644 index 0000000..70927d6 --- /dev/null +++ b/configs/releng/profiledef.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2034 + +iso_name="parabola" +iso_label="PARA_$(date +%Y%m)" +iso_publisher="Parabola GNU/Linux-libre <https://www.parabola.nu>" +iso_application="Parabola GNU/Linux-libre Live/Rescue CD" +iso_version="$(date +%Y.%m.%d)" +install_dir="parabola" +bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito' 'uefi-x64.systemd-boot.esp' 'uefi-x64.systemd-boot.eltorito') +arch="dual" +pacman_conf="pacman.conf" diff --git a/configs/releng/syslinux/parabolaiso_sys32.cfg b/configs/releng/syslinux/parabolaiso_sys32.cfg index f1996bb..da6f10a 100644 --- a/configs/releng/syslinux/parabolaiso_sys32.cfg +++ b/configs/releng/syslinux/parabolaiso_sys32.cfg @@ -1,6 +1,8 @@ # # SPDX-License-Identifier: GPL-3.0-or-later +TIMEOUT 30 + LABEL parabola32 TEXT HELP Boot the Parabola GNU/Linux-libre (i686) live medium. diff --git a/configs/talkingparabola/airootfs/root/customize_airootfs.sh b/configs/talkingparabola/airootfs/root/customize_airootfs.sh index c72644a..92e57de 100755 --- a/configs/talkingparabola/airootfs/root/customize_airootfs.sh +++ b/configs/talkingparabola/airootfs/root/customize_airootfs.sh @@ -4,7 +4,7 @@ set -e -u -echo 'Warning: customize_airootfs.sh is deprecated! Support for it will be removed in a future parabolaiso version.' +# Warning: customize_airootfs.sh is deprecated! Support for it will be removed in a future parabolaiso version. sed -i 's/#\(en_US\.UTF-8\)/\1/' /etc/locale.gen locale-gen diff --git a/configs/talkingparabola/build.sh b/configs/talkingparabola/build.sh index d0901ed..9a9f654 100755 --- a/configs/talkingparabola/build.sh +++ b/configs/talkingparabola/build.sh @@ -2,307 +2,6 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -set -e -u - -iso_name=talkingparabola -iso_label="PARA_$(date +%Y%m)" -iso_publisher="Parabola GNU/Linux-libre <http://www.parabola.nu>" -iso_application="Parabola GNU/Linux-libre Live/Rescue CD" -iso_version=$(date +%Y.%m.%d) -install_dir=parabola -work_dir=work -out_dir=out -gpg_key="" - -arch=$(uname -m) -verbose="" -script_path="$( cd -P "$( dirname "$(readlink -f "$0")" )" && pwd )" - -export arch -umask 0022 - -_usage () -{ - echo "usage ${0} [options]" - echo - echo " General options:" - echo " -N <iso_name> Set an iso filename (prefix)" - echo " Default: ${iso_name}" - echo " -V <iso_version> Set an iso version (in filename)" - echo " Default: ${iso_version}" - echo " -L <iso_label> Set an iso label (disk label)" - echo " Default: ${iso_label}" - echo " -P <publisher> Set a publisher for the disk" - echo " Default: '${iso_publisher}'" - echo " -A <application> Set an application name for the disk" - echo " Default: '${iso_application}'" - echo " -D <install_dir> Set an install_dir (directory inside iso)" - echo " Default: ${install_dir}" - echo " -w <work_dir> Set the working directory" - echo " Default: ${work_dir}" - echo " -o <out_dir> Set the output directory" - echo " Default: ${out_dir}" - echo " -v Enable verbose output" - echo " -h This help message" - exit "${1}" -} - -# Helper function to run make_*() only one time per architecture. -run_once() { - if [[ ! -e "${work_dir}/build.${1}_${arch}" ]]; then - "$1" - touch "${work_dir}/build.${1}_${arch}" - fi -} - -# Setup custom pacman.conf with current cache directories and custom mirrorlist. -make_pacman_conf() { - local _cache_dirs - _cache_dirs=("$(pacman -v 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g')") - sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n "${_cache_dirs[@]}")|g" \ - "${script_path}/pacman.conf" > "${work_dir}/pacman.conf" -} - -# Prepare working directory and copy custom airootfs files (airootfs) -make_custom_airootfs() { - local _airootfs="${work_dir}/${arch}/airootfs" - mkdir -p -- "${_airootfs}" - - if [[ -d "${script_path}/airootfs" ]]; then - cp -af --no-preserve=ownership -- "${script_path}/airootfs/." "${_airootfs}" - - [[ -e "${_airootfs}/etc/shadow" ]] && chmod -f 0400 -- "${_airootfs}/etc/shadow" - [[ -e "${_airootfs}/etc/gshadow" ]] && chmod -f 0400 -- "${_airootfs}/etc/gshadow" - - # Set up user home directories and permissions - if [[ -e "${_airootfs}/etc/passwd" ]]; then - while IFS=':' read -a passwd -r; do - [[ "${passwd[5]}" == '/' ]] && continue - - if [[ -d "${_airootfs}${passwd[5]}" ]]; then - chown -hR -- "${passwd[2]}:${passwd[3]}" "${_airootfs}${passwd[5]}" - chmod -f 0750 -- "${_airootfs}${passwd[5]}" - else - install -d -m 0750 -o "${passwd[2]}" -g "${passwd[3]}" -- "${_airootfs}${passwd[5]}" - fi - done < "${_airootfs}/etc/passwd" - fi - fi -} - -# Packages (airootfs) -make_packages() { - if [[ "${gpg_key}" ]]; then - gpg --export "${gpg_key}" >"${work_dir}/gpgkey" - exec 17<>"${work_dir}/gpgkey" - fi - if [ -n "${verbose}" ]; then - PARABOLAISO_GNUPG_FD="${gpg_key:+17}" mkparabolaiso -v -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -p "$(grep -h -v '^#' "${script_path}"/packages.{both,"${arch}"}| sed ':a;N;$!ba;s/\n/ /g')" install - else - PARABOLAISO_GNUPG_FD="${gpg_key:+17}" mkparabolaiso -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -p "$(grep -h -v '^#' "${script_path}"/packages.{both,"${arch}"}| sed ':a;N;$!ba;s/\n/ /g')" install - fi - if [[ "${gpg_key}" ]]; then - exec 17<&- - fi -} - -# Customize installation (airootfs) -make_customize_airootfs() { - if [[ -e "${script_path}/airootfs/etc/passwd" ]]; then - while IFS=':' read -a passwd -r; do - [[ "${passwd[5]}" == '/' ]] && continue - cp -RdT --preserve=mode,timestamps,links -- "${work_dir}/${arch}/airootfs/etc/skel" "${work_dir}/${arch}/airootfs${passwd[5]}" - chown -hR -- "${passwd[2]}:${passwd[3]}" "${work_dir}/${arch}/airootfs${passwd[5]}" - - done < "${script_path}/airootfs/etc/passwd" - fi - - if [[ -e "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh" ]]; then - if [ -n "${verbose}" ]; then - mkparabolaiso -v -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -r '/root/customize_airootfs.sh' run - else - mkparabolaiso -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" \ - -r '/root/customize_airootfs.sh' run - fi - rm "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh" - fi -} - -# Prepare kernel/initramfs ${install_dir}/boot/ -make_boot() { - mkdir -p "${work_dir}/iso/${install_dir}/boot/${arch}" - cp "${work_dir}/${arch}/airootfs/boot/parabolaiso.img" "${work_dir}/iso/${install_dir}/boot/${arch}/" - cp "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-libre" "${work_dir}/iso/${install_dir}/boot/${arch}/" -} - -# Add other aditional/extra files to ${install_dir}/boot/ -make_boot_extra() { - if [[ -e "${work_dir}/${arch}/airootfs/boot/memtest86+/memtest.bin" ]]; then - # rename for PXE: https://wiki.parabola.nu/Syslinux#Using_memtest - cp "${work_dir}/${arch}/airootfs/boot/memtest86+/memtest.bin" "${work_dir}/iso/${install_dir}/boot/memtest" - mkdir -p "${work_dir}/iso/${install_dir}/boot/licenses/memtest86+/" - cp "${work_dir}/${arch}/airootfs/usr/share/licenses/common/GPL2/license.txt" \ - "${work_dir}/iso/${install_dir}/boot/licenses/memtest86+/" - fi -} - -# Prepare /${install_dir}/boot/syslinux -make_syslinux() { - _uname_r=$(file -b "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-libre"| awk 'f{print;f=0} /version/{f=1}' RS=' ') - mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux" - for _cfg in "${script_path}/syslinux/"*.cfg; do - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g" "${_cfg}" > "${work_dir}/iso/${install_dir}/boot/syslinux/${_cfg##*/}" - done - cp "${script_path}/syslinux/splash.png" "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/"*.c32 "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/lpxelinux.0" "${work_dir}/iso/${install_dir}/boot/syslinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/memdisk" "${work_dir}/iso/${install_dir}/boot/syslinux/" - mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux/hdt" - gzip -c -9 "${work_dir}/${arch}/airootfs/usr/lib/modules/${_uname_r}/modules.alias" > \ - "${work_dir}/iso/${install_dir}/boot/syslinux/hdt/modalias.gz" -} - -# Prepare /isolinux -make_isolinux() { - mkdir -p "${work_dir}/iso/isolinux" - sed "s|%INSTALL_DIR%|${install_dir}|g" \ - "${script_path}/isolinux/isolinux.cfg" > "${work_dir}/iso/isolinux/isolinux.cfg" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isolinux.bin" "${work_dir}/iso/isolinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isohdpfx.bin" "${work_dir}/iso/isolinux/" - cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/ldlinux.c32" "${work_dir}/iso/isolinux/" -} - -# Prepare /EFI -make_efi() { - mkdir -p "${work_dir}/iso/EFI/boot" - cp "${work_dir}/x86_64/airootfs/usr/lib/systemd/boot/efi/systemd-bootx64.efi" \ - "${work_dir}/iso/EFI/boot/bootx64.efi" - - mkdir -p "${work_dir}/iso/loader/entries" - cp "${script_path}/efiboot/loader/loader.conf" "${work_dir}/iso/loader/" - - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g" \ - "${script_path}/efiboot/loader/entries/parabolaiso-x86_64-usb.conf" > \ - "${work_dir}/iso/loader/entries/parabolaiso-x86_64.conf" - - # edk2-shell based UEFI shell - # shellx64.efi is picked up automatically when on / - cp "${work_dir}/x86_64/airootfs/usr/share/edk2-shell/x64/Shell_Full.efi" "${work_dir}/iso/shellx64.efi" -} - -# Prepare efiboot.img::/EFI for "El Torito" EFI boot mode -make_efiboot() { - mkdir -p "${work_dir}/iso/EFI/parabolaiso" - truncate -s 64M "${work_dir}/iso/EFI/parabolaiso/efiboot.img" - mkfs.fat -n PARABOLAISO_EFI "${work_dir}/iso/EFI/parabolaiso/efiboot.img" - - mkdir -p "${work_dir}/efiboot" - mount "${work_dir}/iso/EFI/parabolaiso/efiboot.img" "${work_dir}/efiboot" - - mkdir -p "${work_dir}/efiboot/EFI/parabolaiso" - cp "${work_dir}/iso/${install_dir}/boot/x86_64/vmlinuz-linux-libre" "${work_dir}/efiboot/EFI/parabolaiso/" - cp "${work_dir}/iso/${install_dir}/boot/x86_64/parabolaiso.img" "${work_dir}/efiboot/EFI/parabolaiso/" - - mkdir -p "${work_dir}/efiboot/EFI/boot" - cp "${work_dir}/x86_64/airootfs/usr/lib/systemd/boot/efi/systemd-bootx64.efi" \ - "${work_dir}/efiboot/EFI/boot/bootx64.efi" - - mkdir -p "${work_dir}/efiboot/loader/entries" - cp "${script_path}/efiboot/loader/loader.conf" "${work_dir}/efiboot/loader/" - - sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; - s|%INSTALL_DIR%|${install_dir}|g" \ - "${script_path}/efiboot/loader/entries/parabolaiso-x86_64-cd.conf" > \ - "${work_dir}/efiboot/loader/entries/parabolaiso-x86_64.conf" - - # shellx64.efi is picked up automatically when on / - cp "${work_dir}/iso/shellx64.efi" "${work_dir}/efiboot/" - - umount -d "${work_dir}/efiboot" -} - -# Build airootfs filesystem image -make_prepare() { - cp -a -l -f "${work_dir}/${arch}/airootfs" "${work_dir}" - if [ -n "${verbose}" ]; then - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" pkglist - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" ${gpg_key:+-g ${gpg_key}} prepare - else - mkparabolaiso -w "${work_dir}" -D "${install_dir}" pkglist - mkparabolaiso -w "${work_dir}" -D "${install_dir}" ${gpg_key:+-g ${gpg_key}} prepare - fi - rm -rf "${work_dir}/airootfs" - # rm -rf "${work_dir}/${arch}/airootfs" (if low space, this helps) -} - -# Build ISO -make_iso() { - if [ -n "${verbose}" ]; then - mkparabolaiso -v -w "${work_dir}" -D "${install_dir}" -L "${iso_label}" -P "${iso_publisher}" \ - -A "${iso_application}" -o "${out_dir}" iso "${iso_name}-${iso_version}-dual.iso" - else - mkparabolaiso -w "${work_dir}" -D "${install_dir}" -L "${iso_label}" -P "${iso_publisher}" \ - -A "${iso_application}" -o "${out_dir}" iso "${iso_name}-${iso_version}-dual.iso" - fi -} - -if [[ ${EUID} -ne 0 ]]; then - echo "This script must be run as root." - _usage 1 -fi - -while getopts 'N:V:L:P:A:D:w:o:g:vh' arg; do - case "${arg}" in - N) iso_name="${OPTARG}" ;; - V) iso_version="${OPTARG}" ;; - L) iso_label="${OPTARG}" ;; - P) iso_publisher="${OPTARG}" ;; - A) iso_application="${OPTARG}" ;; - D) install_dir="${OPTARG}" ;; - w) work_dir="${OPTARG}" ;; - o) out_dir="${OPTARG}" ;; - g) gpg_key="${OPTARG}" ;; - v) verbose="-v" ;; - h) _usage 0 ;; - *) - echo "Invalid argument '${arg}'" - _usage 1 - ;; - esac -done - -mkdir -p "${work_dir}" - -run_once make_pacman_conf - -# Do all stuff for each airootfs -for arch in i686 x86_64; do - run_once make_custom_airootfs - run_once make_packages -done - -for arch in i686 x86_64; do - run_once make_customize_airootfs -done - -for arch in i686 x86_64; do - run_once make_boot -done - -# Do all stuff for "iso" -run_once make_boot_extra -run_once make_syslinux -run_once make_isolinux -run_once make_efi -run_once make_efiboot - -for arch in i686 x86_64; do - run_once make_prepare -done - -run_once make_iso +printf '\n[%s] WARNING: %s\n\n' "mkparabolaiso" "build.sh scripts are deprecated! Please use mkparabolaiso directly." >&2 +_buildsh_path="$(realpath -- "$0")" +exec mkparabolaiso "$@" -B "${_buildsh_path%/*}" build_profile diff --git a/configs/talkingparabola/profiledef.sh b/configs/talkingparabola/profiledef.sh new file mode 100644 index 0000000..e62388f --- /dev/null +++ b/configs/talkingparabola/profiledef.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2034 + +iso_name="talkingparabola" +iso_label="PARA_$(date +%Y%m)" +iso_publisher="Parabola GNU/Linux-libre <https://www.parabola.nu>" +iso_application="Parabola GNU/Linux-libre Live/Rescue CD" +iso_version="$(date +%Y.%m.%d)" +install_dir="parabola" +bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito' 'uefi-x64.systemd-boot.esp' 'uefi-x64.systemd-boot.eltorito') +arch="dual" +pacman_conf="pacman.conf" diff --git a/configs/talkingparabola/syslinux/parabolaiso_sys32.cfg b/configs/talkingparabola/syslinux/parabolaiso_sys32.cfg index ec49748..e791d82 100644 --- a/configs/talkingparabola/syslinux/parabolaiso_sys32.cfg +++ b/configs/talkingparabola/syslinux/parabolaiso_sys32.cfg @@ -1,6 +1,8 @@ # # SPDX-License-Identifier: GPL-3.0-or-later +TIMEOUT 30 + LABEL parabola32speech TEXT HELP Boot the Parabola GNU/Linux-libre (i686) live medium with speakup enabled. diff --git a/parabolaiso/mkparabolaiso b/parabolaiso/mkparabolaiso index f7fae78..51251f5 100755 --- a/parabolaiso/mkparabolaiso +++ b/parabolaiso/mkparabolaiso @@ -4,29 +4,49 @@ set -e -u -export LANG=C +# Control the environment +umask 0022 +export LANG="C" +export SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-"$(date +%s)"}" -app_name=${0##*/} -arch=${arch:-$(uname -m)} +# mkparabolaiso defaults +app_name="${0##*/}" pkg_list=() run_cmd="" quiet="y" -pacman_conf="/etc/pacman.conf" -iso_label="PARA_$(date +%Y%m)" -iso_publisher="Parabola GNU/Linux-libre <https://www.parabola.nu>" -iso_application="Parabola GNU/Linux-libre Live/Rescue CD" -install_dir="parabola" work_dir="work" out_dir="out" +img_name="${app_name}.iso" sfs_mode="sfs" sfs_comp="xz" -gpg_key= +gpg_key="" + +# profile defaults +profile="" +iso_name="${app_name}" +iso_label="${app_name^^}" +iso_publisher="${app_name}" +iso_application="${app_name} iso" +iso_version="" +install_dir="${app_name}" +arch="${arch:-$(uname -m)}" +pacman_conf="/etc/pacman.conf" +bootmodes=() + # Show an INFO message # $1: message string _msg_info() { local _msg="${1}" - echo "[mkparabolaiso] INFO: ${_msg}" + [[ "${quiet}" == "y" ]] || printf '[%s] INFO: %s\n' "${app_name}" "${_msg}" + +} + +# Show a WARNING message +# $1: message string +_msg_warning() { + local _msg="${1}" + printf '\n[%s] WARNING: %s\n\n' "${app_name}" "${_msg}" >&2 } # Show an ERROR message then exit with status @@ -35,83 +55,73 @@ _msg_info() { _msg_error() { local _msg="${1}" local _error=${2} - echo - echo "[mkparabolaiso] ERROR: ${_msg}" - echo - if [[ ${_error} -gt 0 ]]; then - "exit ${_error}" + printf '\n[%s] ERROR: %s\n\n' "${app_name}" "${_msg}" >&2 + if (( _error > 0 )); then + exit "${_error}" fi } _chroot_init() { - mkdir -p ${work_dir}/airootfs + mkdir -p -- "${airootfs_dir}" _pacman base syslinux } _chroot_run() { - eval arch-chroot ${work_dir}/airootfs "${run_cmd}" + eval -- arch-chroot "${airootfs_dir}" "${run_cmd}" } _mount_airootfs() { trap "_umount_airootfs" EXIT HUP INT TERM - mkdir -p "${work_dir}/mnt/airootfs" - _msg_info "Mounting '${work_dir}/airootfs.img' on '${work_dir}/mnt/airootfs'" - mount "${work_dir}/airootfs.img" "${work_dir}/mnt/airootfs" + mkdir -p -- "${work_dir}/mnt/airootfs" + _msg_info "Mounting '${airootfs_dir}.img' on '${work_dir}/mnt/airootfs'" + mount -- "${airootfs_dir}.img" "${work_dir}/mnt/airootfs" _msg_info "Done!" } _umount_airootfs() { _msg_info "Unmounting '${work_dir}/mnt/airootfs'" - umount -d "${work_dir}/mnt/airootfs" + umount -d -- "${work_dir}/mnt/airootfs" _msg_info "Done!" - rmdir "${work_dir}/mnt/airootfs" + rmdir -- "${work_dir}/mnt/airootfs" trap - EXIT HUP INT TERM } # Show help usage, with an exit status. # $1: exit status number. -_usage () -{ - echo "usage ${app_name} [options] command <command options>" - echo " general options:" - echo " -p PACKAGE(S) Package(s) to install, can be used multiple times" - echo " -r <command> Run <command> inside airootfs" - echo " -C <file> Config file for pacman." - echo " Default: '${pacman_conf}'" - echo " -L <label> Set a label for the disk" - echo " Default: '${iso_label}'" - echo " -P <publisher> Set a publisher for the disk" - echo " Default: '${iso_publisher}'" - echo " -A <application> Set an application name for the disk" - echo " Default: '${iso_application}'" - echo " -D <install_dir> Set an install_dir. All files will by located here." - echo " Default: '${install_dir}'" - echo " NOTE: Max 8 characters, use only [a-z0-9]" - echo " -w <work_dir> Set the working directory" - echo " Default: '${work_dir}'" - echo " -o <out_dir> Set the output directory" - echo " Default: '${out_dir}'" - echo " -s <sfs_mode> Set SquashFS image mode (img or sfs)" - echo " img: prepare airootfs.sfs for dm-snapshot usage" - echo " sfs: prepare airootfs.sfs for overlayfs usage" - echo " Default: ${sfs_mode}" - echo " -c <comp_type> Set SquashFS compression type (gzip, lzma, lzo, xz, zstd)" - echo " Default: '${sfs_comp}'" - echo " -v Enable verbose output" - echo " -h This message" - echo " commands:" - echo " init" - echo " Make base layout and install base group" - echo " install" - echo " Install all specified packages (-p)" - echo " run" - echo " run command specified by -r" - echo " prepare" - echo " build all images" - echo " pkglist" - echo " make a pkglist.txt of packages installed on airootfs" - echo " iso <image name>" - echo " build an iso image from the working dir" +_usage () { + IFS='' read -r -d '' usagetext <<ENDUSAGETEXT || true +usage ${app_name} [options] command <command options> + general options: + -B <profile_dir> Directory of the parabolaiso profile to build + -p PACKAGE(S) Package(s) to install, can be used multiple times + -C <file> Config file for pacman. + Default: '${pacman_conf}' + -L <label> Set a label for the disk + Default: '${iso_label}' + -P <publisher> Set a publisher for the disk + Default: '${iso_publisher}' + -A <application> Set an application name for the disk + Default: '${iso_application}' + -D <install_dir> Set an install_dir. All files will by located here. + Default: '${install_dir}' + NOTE: Max 8 characters, use only [a-z0-9] + -w <work_dir> Set the working directory + Default: '${work_dir}' + -o <out_dir> Set the output directory + Default: '${out_dir}' + -s <sfs_mode> Set SquashFS image mode (img or sfs) + img: prepare airootfs.sfs for dm-snapshot usage + sfs: prepare airootfs.sfs for overlayfs usage + Default: '${sfs_mode}' + -c <comp_type> Set SquashFS compression type (gzip, lzma, lzo, xz, zstd) + Default: '${sfs_comp}' + -v Enable verbose output + -h This message + commands: + build_profile + build an iso image from a profile +ENDUSAGETEXT + printf '%s\n' "${usagetext}" exit "${1}" } @@ -119,7 +129,7 @@ _usage () # $1: init | install | run | prepare | iso _show_config () { local _mode="$1" - echo + printf '\n' _msg_info "Configuration settings" _msg_info " Command: ${command_name}" _msg_info " Architecture: ${arch}" @@ -147,18 +157,17 @@ _show_config () { _msg_info " Disk application: ${iso_application}" ;; esac - echo + printf '\n' } # Install desired packages to airootfs -_pacman () -{ - _msg_info "Installing packages to '${work_dir}/airootfs/'..." +_pacman () { + _msg_info "Installing packages to '${airootfs_dir}/'..." if [[ "${quiet}" = "y" ]]; then - pacstrap -C "${pacman_conf}" -c -G -M "${work_dir}/airootfs" "$@" &> /dev/null + pacstrap -C "${pacman_conf}" -c -G -M -- "${airootfs_dir}" --arch "${arch}" "$@" &> /dev/null else - pacstrap -C "${pacman_conf}" -c -G -M "${work_dir}/airootfs" "$@" + pacstrap -C "${pacman_conf}" -c -G -M -- "${airootfs_dir}" --arch "${arch}" "$@" fi _msg_info "Packages installed successfully!" @@ -168,86 +177,84 @@ _pacman () _cleanup () { _msg_info "Cleaning up what we can on airootfs..." - # Delete initcpio image(s) - if [[ -d "${work_dir}/airootfs/boot" ]]; then - find "${work_dir}/airootfs/boot" -type f -name '*.img' -delete - fi - # Delete kernel(s) - if [[ -d "${work_dir}/airootfs/boot" ]]; then - find "${work_dir}/airootfs/boot" -type f -name 'vmlinuz*' -delete + # Delete all files in /boot + if [[ -d "${airootfs_dir}/boot" ]]; then + find "${airootfs_dir}/boot" -mindepth 1 -delete fi # Delete pacman database sync cache files (*.tar.gz) - if [[ -d "${work_dir}/airootfs/var/lib/pacman" ]]; then - find "${work_dir}/airootfs/var/lib/pacman" -maxdepth 1 -type f -delete + if [[ -d "${airootfs_dir}/var/lib/pacman" ]]; then + find "${airootfs_dir}/var/lib/pacman" -maxdepth 1 -type f -delete fi # Delete pacman database sync cache - if [[ -d "${work_dir}/airootfs/var/lib/pacman/sync" ]]; then - find "${work_dir}/airootfs/var/lib/pacman/sync" -delete + if [[ -d "${airootfs_dir}/var/lib/pacman/sync" ]]; then + find "${airootfs_dir}/var/lib/pacman/sync" -delete fi # Delete pacman package cache - if [[ -d "${work_dir}/airootfs/var/cache/pacman/pkg" ]]; then - find "${work_dir}/airootfs/var/cache/pacman/pkg" -type f -delete + if [[ -d "${airootfs_dir}/var/cache/pacman/pkg" ]]; then + find "${airootfs_dir}/var/cache/pacman/pkg" -type f -delete fi # Delete all log files, keeps empty dirs. - if [[ -d "${work_dir}/airootfs/var/log" ]]; then - find "${work_dir}/airootfs/var/log" -type f -delete + if [[ -d "${airootfs_dir}/var/log" ]]; then + find "${airootfs_dir}/var/log" -type f -delete fi # Delete all temporary files and dirs - if [[ -d "${work_dir}/airootfs/var/tmp" ]]; then - find "${work_dir}/airootfs/var/tmp" -mindepth 1 -delete + if [[ -d "${airootfs_dir}/var/tmp" ]]; then + find "${airootfs_dir}/var/tmp" -mindepth 1 -delete fi # Delete package pacman related files. - find "${work_dir}" \( -name "*.pacnew" -o -name "*.pacsave" -o -name "*.pacorig" \) -delete + find "${work_dir}" \( -name '*.pacnew' -o -name '*.pacsave' -o -name '*.pacorig' \) -delete _msg_info "Done!" + # Create an empty /etc/machine-id + printf '' > "${airootfs_dir}/etc/machine-id" } # Makes a ext4 filesystem inside a SquashFS from a source directory. _mkairootfs_img () { - if [[ ! -e "${work_dir}/airootfs" ]]; then - _msg_error "The path '${work_dir}/airootfs' does not exist" 1 + if [[ ! -e "${airootfs_dir}" ]]; then + _msg_error "The path '${airootfs_dir}' does not exist" 1 fi _msg_info "Creating ext4 image of 32GiB..." - truncate -s 32G "${work_dir}/airootfs.img" - local _qflag="" + truncate -s 32G -- "${airootfs_dir}.img" if [[ "${quiet}" == "y" ]]; then - _qflag="-q" + mkfs.ext4 -q -O '^has_journal,^resize_inode' -E 'lazy_itable_init=0' -m 0 -F -- "${airootfs_dir}.img" + else + mkfs.ext4 -O '^has_journal,^resize_inode' -E 'lazy_itable_init=0' -m 0 -F -- "${airootfs_dir}.img" fi - mkfs.ext4 ${_qflag} -O ^has_journal,^resize_inode -E lazy_itable_init=0 -m 0 -F "${work_dir}/airootfs.img" - tune2fs -c 0 -i 0 "${work_dir}/airootfs.img" &> /dev/null + tune2fs -c 0 -i 0 -- "${airootfs_dir}.img" &> /dev/null _msg_info "Done!" _mount_airootfs - _msg_info "Copying '${work_dir}/airootfs/' to '${work_dir}/mnt/airootfs/'..." - cp -aT "${work_dir}/airootfs/" "${work_dir}/mnt/airootfs/" - chown root:root "${work_dir}/mnt/airootfs/" + _msg_info "Copying '${airootfs_dir}/' to '${work_dir}/mnt/airootfs/'..." + cp -aT -- "${airootfs_dir}/" "${work_dir}/mnt/airootfs/" + chown root:root -- "${work_dir}/mnt/airootfs/" _msg_info "Done!" _umount_airootfs - mkdir -p "${work_dir}/iso/${install_dir}/${arch}" + mkdir -p -- "${isofs_dir}/${install_dir}/${arch}" _msg_info "Creating SquashFS image, this may take some time..." if [[ "${quiet}" = "y" ]]; then - mksquashfs "${work_dir}/airootfs.img" "${work_dir}/iso/${install_dir}/${arch}/airootfs.sfs" -noappend \ + mksquashfs "${airootfs_dir}.img" "${isofs_dir}/${install_dir}/${arch}/airootfs.sfs" -noappend \ -comp "${sfs_comp}" -no-progress &> /dev/null else - mksquashfs "${work_dir}/airootfs.img" "${work_dir}/iso/${install_dir}/${arch}/airootfs.sfs" -noappend \ + mksquashfs "${airootfs_dir}.img" "${isofs_dir}/${install_dir}/${arch}/airootfs.sfs" -noappend \ -comp "${sfs_comp}" fi _msg_info "Done!" - rm "${work_dir}/airootfs.img" + rm -- "${airootfs_dir}.img" } # Makes a SquashFS filesystem from a source directory. _mkairootfs_sfs () { - if [[ ! -e "${work_dir}/airootfs" ]]; then - _msg_error "The path '${work_dir}/airootfs' does not exist" 1 + if [[ ! -e "${airootfs_dir}" ]]; then + _msg_error "The path '${airootfs_dir}' does not exist" 1 fi - mkdir -p "${work_dir}/iso/${install_dir}/${arch}" + mkdir -p -- "${isofs_dir}/${install_dir}/${arch}" _msg_info "Creating SquashFS image, this may take some time..." if [[ "${quiet}" = "y" ]]; then - mksquashfs "${work_dir}/airootfs" "${work_dir}/iso/${install_dir}/${arch}/airootfs.sfs" -noappend \ + mksquashfs "${airootfs_dir}" "${isofs_dir}/${install_dir}/${arch}/airootfs.sfs" -noappend \ -comp "${sfs_comp}" -no-progress &> /dev/null else - mksquashfs "${work_dir}/airootfs" "${work_dir}/iso/${install_dir}/${arch}/airootfs.sfs" -noappend \ + mksquashfs "${airootfs_dir}" "${isofs_dir}/${install_dir}/${arch}/airootfs.sfs" -noappend \ -comp "${sfs_comp}" fi _msg_info "Done!" @@ -255,44 +262,340 @@ _mkairootfs_sfs () { _mkchecksum () { _msg_info "Creating checksum file for self-test..." - cd "${work_dir}/iso/${install_dir}/${arch}" + cd -- "${isofs_dir}/${install_dir}/${arch}" sha512sum airootfs.sfs > airootfs.sha512 - cd "${OLDPWD}" + cd -- "${OLDPWD}" _msg_info "Done!" } _mksignature () { _msg_info "Creating signature file..." - cd "${work_dir}/iso/${install_dir}/${arch}" + cd -- "${isofs_dir}/${install_dir}/${arch}" gpg --detach-sign --default-key "${gpg_key}" airootfs.sfs - cd "${OLDPWD}" + cd -- "${OLDPWD}" _msg_info "Done!" } -command_pkglist () { - _show_config pkglist +# Helper function to run functions only one time. +_run_once() { + if [[ ! -e "${work_dir}/build.${1}_${arch}" ]]; then + "$1" + touch "${work_dir}/build.${1}_${arch}" + fi +} - _msg_info "Creating a list of installed packages on live-enviroment..." - pacman -Q --sysroot "${work_dir}/airootfs" > \ - "${work_dir}/iso/${install_dir}/pkglist.${arch}.txt" - _msg_info "Done!" +# Set up custom pacman.conf with current cache directories. +_make_pacman_conf() { + local _cache_dirs + _cache_dirs="$(pacman-conf CacheDir)" + sed -r "s|^#?\\s*CacheDir.+|CacheDir = ${_cache_dirs[*]//$'\n'/ }|g" \ + "${pacman_conf}" > "${work_dir}/pacman.conf" +} + +# Prepare working directory and copy custom airootfs files (airootfs) +_make_custom_airootfs() { + mkdir -m 755 -- "${airootfs_dir}" + + local passwd=() + if [[ -d "${profile}/airootfs" ]]; then + cp -af --no-preserve=ownership -- "${profile}/airootfs/." "${airootfs_dir}" + + [[ -e "${airootfs_dir}/etc/shadow" ]] && chmod -f 0400 -- "${airootfs_dir}/etc/shadow" + [[ -e "${airootfs_dir}/etc/gshadow" ]] && chmod -f 0400 -- "${airootfs_dir}/etc/gshadow" + + # Set up user home directories and permissions + if [[ -e "${airootfs_dir}/etc/passwd" ]]; then + while IFS=':' read -a passwd -r; do + [[ "${passwd[5]}" == '/' ]] && continue + [[ -z "${passwd[5]}" ]] && continue + + if [[ -d "${airootfs_dir}${passwd[5]}" ]]; then + chown -hR -- "${passwd[2]}:${passwd[3]}" "${airootfs_dir}${passwd[5]}" + chmod -f 0750 -- "${airootfs_dir}${passwd[5]}" + else + install -d -m 0750 -o "${passwd[2]}" -g "${passwd[3]}" -- "${airootfs_dir}${passwd[5]}" + fi + done < "${airootfs_dir}/etc/passwd" + fi + fi +} +# Packages (airootfs) +_make_packages() { + if [[ -n "${gpg_key}" ]]; then + exec {parabolaiso_GNUPG_FD}<>"${work_dir}/pubkey.gpg" + export parabolaiso_GNUPG_FD + fi + local pkg_list_arch + eval "pkg_list_arch=(\${pkg_list_${arch}[@]})" + _pacman "${pkg_list[@]}" "${pkg_list_arch[@]}" + if [[ -n "${gpg_key}" ]]; then + exec {parabolaiso_GNUPG_FD}<&- + unset parabolaiso_GNUPG_FD + fi } -# Create an ISO9660 filesystem from "iso" directory. -command_iso () { - local _iso_efi_boot_args=() +# Customize installation (airootfs) +_make_customize_airootfs() { + local passwd=() + if [[ -e "${profile}/airootfs/etc/passwd" ]]; then + while IFS=':' read -a passwd -r; do + if [[ "${passwd[5]}" == '/' ]]; then + continue + fi + cp -RdT --preserve=mode,timestamps,links -- "${airootfs_dir}/etc/skel" "${airootfs_dir}${passwd[5]}" + chown -hR -- "${passwd[2]}:${passwd[3]}" "${airootfs_dir}${passwd[5]}" + + done < "${profile}/airootfs/etc/passwd" + fi + + if [[ -e "${airootfs_dir}/root/customize_airootfs.sh" ]]; then + _msg_warning "customize_airootfs.sh is deprecated! Support for it will be removed in a future parabolaiso version." + local run_cmd="/root/customize_airootfs.sh" + local work_dir="${work_dir}/${arch}" + command_run + rm -- "${airootfs_dir}/root/customize_airootfs.sh" + fi +} + +# Set up boot loaders +_make_bootmodes() { + local bootmode + for bootmode in "${bootmodes[@]}"; do + if typeset -f "_make_boot_${bootmode}" &> /dev/null; then + _run_once "_make_boot_${bootmode}" + else + _msg_error "${bootmode} is not a valid boot mode" 1 + fi + done +} + +# Prepare kernel/initramfs ${install_dir}/boot/ +_make_boot_on_iso() { + mkdir -p -- "${isofs_dir}/${install_dir}/boot/${arch}" + install -m 0644 -- "${airootfs_dir}/boot/parabolaiso.img" "${isofs_dir}/${install_dir}/boot/${arch}/" + install -m 0644 -- "${airootfs_dir}/boot/vmlinuz-linux-libre" "${isofs_dir}/${install_dir}/boot/${arch}/" +} - if [[ ! -f "${work_dir}/iso/isolinux/isolinux.bin" ]]; then - _msg_error "The file '${work_dir}/iso/isolinux/isolinux.bin' does not exist." 1 +# Prepare /${install_dir}/boot/syslinux +_make_boot_bios.syslinux.mbr() { + mkdir -p "${isofs_dir}/${install_dir}/boot/syslinux" + for _cfg in "${profile}/syslinux/"*.cfg; do + sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; + s|%INSTALL_DIR%|${install_dir}|g; + s|%ARCH%|${arch}|g" \ + "${_cfg}" > "${isofs_dir}/${install_dir}/boot/syslinux/${_cfg##*/}" + done + if [[ -e "${profile}/syslinux/splash.png" ]]; then + install -m 0644 -- "${profile}/syslinux/splash.png" "${isofs_dir}/${install_dir}/boot/syslinux/" + fi + install -m 0644 -- "${airootfs_dir}/usr/lib/syslinux/bios/"*.c32 "${isofs_dir}/${install_dir}/boot/syslinux/" + install -m 0644 -- "${airootfs_dir}/usr/lib/syslinux/bios/lpxelinux.0" "${isofs_dir}/${install_dir}/boot/syslinux/" + install -m 0644 -- "${airootfs_dir}/usr/lib/syslinux/bios/memdisk" "${isofs_dir}/${install_dir}/boot/syslinux/" + + if [[ "${arch}" == "dual" ]]; then + for arch in i686 x86_64; do + local airootfs_dir="${work_dir}/${arch}/airootfs" + _make_boot_on_iso + done + else + _make_boot_on_iso fi - if [[ ! -f "${work_dir}/iso/isolinux/isohdpfx.bin" ]]; then - _msg_error "The file '${work_dir}/iso/isolinux/isohdpfx.bin' does not exist." 1 + _uname_r=$(file -b "${isofs_dir}/${install_dir}/boot/${arch}/vmlinuz-linux-libre" | awk 'f{print;f=0} /version/{f=1}' RS=' ') + + mkdir -p "${isofs_dir}/${install_dir}/boot/syslinux/hdt" + gzip -c -9 "${airootfs_dir}/usr/share/hwdata/pci.ids" > \ + "${isofs_dir}/${install_dir}/boot/syslinux/hdt/pciids.gz" + gzip -c -9 "${airootfs_dir}/usr/lib/modules/${_uname_r}/modules.alias" > \ + "${isofs_dir}/${install_dir}/boot/syslinux/hdt/modalias.gz" + + # Add other aditional/extra files to ${install_dir}/boot/ + if [[ -e "${airootfs_dir}/boot/memtest86+/memtest.bin" ]]; then + # rename for PXE: https://wiki.parabola.nu/index.php/Syslinux#Using_memtest + install -m 0644 -- "${airootfs_dir}/boot/memtest86+/memtest.bin" "${isofs_dir}/${install_dir}/boot/memtest" + mkdir -p "${isofs_dir}/${install_dir}/boot/licenses/memtest86+/" + install -m 0644 -- "${airootfs_dir}/usr/share/licenses/common/GPL2/license.txt" \ + "${isofs_dir}/${install_dir}/boot/licenses/memtest86+/" fi +} - # If exists, add an EFI "El Torito" boot image (FAT filesystem) to ISO-9660 image. - if [[ -f "${work_dir}/iso/EFI/parabolaiso/efiboot.img" ]]; then - _iso_efi_boot_args+=( +# Prepare /isolinux +_make_boot_bios.syslinux.eltorito() { + mkdir -p "${isofs_dir}/isolinux" + sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; + s|%INSTALL_DIR%|${install_dir}|g; + s|%ARCH%|${arch}|g" \ + "${profile}/isolinux/isolinux.cfg" > "${isofs_dir}/isolinux/isolinux.cfg" + install -m 0644 -- "${airootfs_dir}/usr/lib/syslinux/bios/isolinux.bin" "${isofs_dir}/isolinux/" + install -m 0644 -- "${airootfs_dir}/usr/lib/syslinux/bios/isohdpfx.bin" "${isofs_dir}/isolinux/" + install -m 0644 -- "${airootfs_dir}/usr/lib/syslinux/bios/ldlinux.c32" "${isofs_dir}/isolinux/" + + # isolinux.cfg loads syslinux.cfg + _run_once _make_boot_bios.syslinux.mbr +} + +# Prepare /EFI on ISO-9660 +_make_efi() { + mkdir -p "${isofs_dir}/EFI/BOOT" + install -m 0644 -- "${airootfs_dir}/usr/lib/systemd/boot/efi/systemd-bootx64.efi" \ + "${isofs_dir}/EFI/BOOT/BOOTx64.EFI" + + mkdir -p "${isofs_dir}/loader/entries" + install -m 0644 -- "${profile}/efiboot/loader/loader.conf" "${isofs_dir}/loader/" + + sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; + s|%INSTALL_DIR%|${install_dir}|g; + s|%ARCH%|${arch}|g" \ + "${profile}/efiboot/loader/entries/parabolaiso-x86_64-usb.conf" > \ + "${isofs_dir}/loader/entries/parabolaiso-x86_64.conf" + + # edk2-shell based UEFI shell + # shellx64.efi is picked up automatically when on / + if [[ -e "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then + install -m 0644 -- "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" "${isofs_dir}/shellx64.efi" + fi +} + +_make_refind_efi() { + mkdir -p "${isofs_dir}/EFI/boot/entries" + install -m 0644 -- "${airootfs_dir}/usr/share/refind/refind_x64.efi" \ + "${isofs_dir}/EFI/boot/bootx64.efi" + + install -m 0644 -- "${profile}/efiboot/EFI/boot/refind.conf" "${isofs_dir}/EFI/boot/" + + sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; + s|%INSTALL_DIR%|${install_dir}|g; + s|%ARCH%|${arch}|g" \ + "${profile}/efiboot/EFI/boot/entries/parabolaiso-x86_64-usb.conf" > \ + "${isofs_dir}/EFI/boot/entries/parabolaiso-x86_64.conf" + + # edk2-shell based UEFI shell + # shellx64.efi is picked up automatically when on / + if [[ -e "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then + install -m 0644 -- "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" "${isofs_dir}/shellx64.efi" + fi +} + +# Prepare kernel/initramfs on efiboot.img +_make_boot_on_fat() { + mkdir -p "${work_dir}/efiboot/EFI/parabolaiso" + install -m 0644 -- "${airootfs_dir}/boot/vmlinuz-linux-libre" "${work_dir}/efiboot/EFI/parabolaiso/" + install -m 0644 -- "${isofs_dir}/${install_dir}/boot/${arch}/parabolaiso.img" "${work_dir}/efiboot/EFI/parabolaiso/" +} + +# Prepare efiboot.img::/EFI for EFI boot mode +_make_boot_uefi-x64.systemd-boot.esp() { + mkdir -p "${isofs_dir}/EFI/parabolaiso" + mkfs.fat -C -n parabolaiso_EFI "${isofs_dir}/EFI/parabolaiso/efiboot.img" 65536 + + mkdir -p "${work_dir}/efiboot" + mount "${isofs_dir}/EFI/parabolaiso/efiboot.img" "${work_dir}/efiboot" + + mkdir -p "${work_dir}/efiboot/EFI/BOOT" + install -m 0644 -- "${airootfs_dir}/usr/lib/systemd/boot/efi/systemd-bootx64.efi" \ + "${work_dir}/efiboot/EFI/BOOT/BOOTx64.EFI" + + mkdir -p "${work_dir}/efiboot/loader/entries" + install -m 0644 -- "${profile}/efiboot/loader/loader.conf" "${work_dir}/efiboot/loader/" + + sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; + s|%INSTALL_DIR%|${install_dir}|g; + s|%ARCH%|${arch}|g" \ + "${profile}/efiboot/loader/entries/parabolaiso-x86_64-cd.conf" > \ + "${work_dir}/efiboot/loader/entries/parabolaiso-x86_64.conf" + + # shellx64.efi is picked up automatically when on / + if [[ -e "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then + install -m 0644 -- "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" "${work_dir}/efiboot/shellx64.efi" + fi + + # Copy kernel and initramfs + _make_boot_on_fat + + umount -d "${work_dir}/efiboot" +} + +_make_boot_uefi-x64.refind.esp() { + mkdir -p "${isofs_dir}/EFI/parabolaiso" + mkfs.fat -C -n parabolaiso_EFI "${isofs_dir}/EFI/parabolaiso/efiboot.img" 65536 + + mkdir -p "${work_dir}/efiboot" + mount "${isofs_dir}/EFI/parabolaiso/efiboot.img" "${work_dir}/efiboot" + + mkdir -p "${work_dir}/efiboot/EFI/boot/entries" + install -m 0644 -- "${airootfs_dir}/usr/share/refind/refind_x64.efi" \ + "${work_dir}/efiboot/EFI/boot/bootx64.efi" + + install -m 0644 -- "${profile}/efiboot/EFI/boot/refind.conf" "${work_dir}/efiboot/EFI/boot/" + + sed "s|%PARABOLAISO_LABEL%|${iso_label}|g; + s|%INSTALL_DIR%|${install_dir}|g; + s|%ARCH%|${arch}|g" \ + "${profile}/efiboot/EFI/boot/entries/parabolaiso-x86_64-cd.conf" > \ + "${work_dir}/efiboot/EFI/boot/entries/parabolaiso-x86_64.conf" + + # shellx64.efi is picked up automatically when on / + if [[ -e "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then + install -m 0644 -- "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" "${work_dir}/efiboot/shellx64.efi" + fi + + # Copy kernel and initramfs + _make_boot_on_fat + + umount -d "${work_dir}/efiboot" +} + +# Prepare efiboot.img::/EFI for "El Torito" EFI boot mode +_make_boot_uefi-x64.systemd-boot.eltorito() { + _run_once _make_boot_uefi-x64.systemd-boot.esp + # Set up /EFI on ISO-9660 + _run_once _make_efi +} + +_make_boot_uefi-x64.refind.eltorito() { + _run_once _make_boot_uefi-x64.refind.esp + # Set up /EFI on ISO-9660 + _run_once _make_refind_efi +} + +# Build airootfs filesystem image +_make_prepare() { + if [[ "${sfs_mode}" == "sfs" ]]; then + _mkairootfs_sfs + else + _mkairootfs_img + fi + _mkchecksum + if [[ "${gpg_key}" ]]; then + _mksignature + fi +} + +# Build ISO +_make_iso() { + local xorrisofs_options=() + + if [[ "${quiet}" == "y" ]]; then + xorrisofs_options+=('-quiet') + fi + # shellcheck disable=SC2076 + if [[ " ${bootmodes[*]} " =~ ' bios.syslinux.' ]]; then + if [[ ! -f "${isofs_dir}/isolinux/isolinux.bin" ]]; then + _msg_error "The file '${isofs_dir}/isolinux/isolinux.bin' does not exist." 1 + fi + if [[ ! -f "${isofs_dir}/isolinux/isohdpfx.bin" ]]; then + _msg_error "The file '${isofs_dir}/isolinux/isohdpfx.bin' does not exist." 1 + fi + xorrisofs_options+=( + '-eltorito-boot' 'isolinux/isolinux.bin' + '-eltorito-catalog' 'isolinux/boot.cat' + '-no-emul-boot' '-boot-load-size' '4' '-boot-info-table' + '-isohybrid-mbr' "${isofs_dir}/isolinux/isohdpfx.bin" + ) + fi + # shellcheck disable=SC2076 + if [[ " ${bootmodes[*]} " =~ ( uefi-x64.refind.| uefi-x64.systemd-boot.) ]]; then + xorrisofs_options+=( '-eltorito-alt-boot' '-e' 'EFI/parabolaiso/efiboot.img' '-no-emul-boot' @@ -300,45 +603,137 @@ command_iso () { ) fi - _show_config iso - - mkdir -p "${out_dir}" _msg_info "Creating ISO image..." - local _qflag="" - if [[ "${quiet}" == "y" ]]; then - xorriso -as mkisofs -quiet \ + xorriso -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 mkparabolaiso" \ - -eltorito-boot isolinux/isolinux.bin \ - -eltorito-catalog isolinux/boot.cat \ - -no-emul-boot -boot-load-size 4 -boot-info-table \ - -isohybrid-mbr "${work_dir}/iso/isolinux/isohdpfx.bin" \ - "${_iso_efi_boot_args[@]}" \ + -preparer "prepared by ${app_name}" \ + "${xorrisofs_options[@]}" \ -output "${out_dir}/${img_name}" \ - "${work_dir}/iso/" + "${isofs_dir}/" + _msg_info "Done! | $(du -h -- "${out_dir}/${img_name}")" +} + +# Read profile's values from profiledef.sh +_read_profile () { + if [[ -z "${profile}" ]]; then + _msg_error "No profile specified!" 1 + fi + if [[ ! -d "${profile}" ]]; then + _msg_error "Profile '${profile}' does not exist!" 1 + elif [[ ! -e "${profile}/profiledef.sh" ]]; then + _msg_error "Profile '${profile}' is missing 'profiledef.sh'!" 1 else - xorriso -as mkisofs \ - -iso-level 3 \ - -full-iso9660-filenames \ - -rational-rock \ - -volid "${iso_label}" \ - -appid "${iso_application}" \ - -publisher "${iso_publisher}" \ - -preparer "prepared by mkparabolaiso" \ - -eltorito-boot isolinux/isolinux.bin \ - -eltorito-catalog isolinux/boot.cat \ - -no-emul-boot -boot-load-size 4 -boot-info-table \ - -isohybrid-mbr "${work_dir}/iso/isolinux/isohdpfx.bin" \ - "${_iso_efi_boot_args[@]}" \ - -output "${out_dir}/${img_name}" \ - "${work_dir}/iso/" + # Source profile's variables + # shellcheck source=configs/releng/profiledef.sh + . "${profile}/profiledef.sh" + cd -- "${profile}" + + if [[ "${arch}" == "dual" ]]; then + # Resolve paths + packages="$(realpath -- "${profile}"/packages.{both,i686,x86_64})" + pacman_conf="$(realpath -- "${pacman_conf}")" + + # Enumerate packages + local pkgs + for pkgs in ${packages}; do + if [[ "${pkgs##*/}" = "packages.both" ]]; then + [[ -e "${pkgs}" ]] || _msg_error "File '${pkgs}' does not exist!" 1 + mapfile -t pkg_list < <(sed '/^[[:blank:]]*#.*/d;s/#.*//;/^[[:blank:]]*$/d' "${pkgs}") + if (( ${#pkg_list[@]} == 0 )); then + _msg_error "'${pkgs}' does not list any packages!" 1 + fi + elif [[ -e "${pkgs}" ]]; then + mapfile -t "pkg_list_${pkgs##*.}" < <(sed '/^[[:blank:]]*#.*/d;s/#.*//;/^[[:blank:]]*$/d' "${pkgs}") + fi + done + else + # Resolve paths + packages="$(realpath -- "${profile}/packages.${arch}")" + pacman_conf="$(realpath -- "${pacman_conf}")" + + # Enumerate packages + [[ -e "${packages}" ]] || _msg_error "File '${packages}' does not exist!" 1 + mapfile -t pkg_list < <(sed '/^[[:blank:]]*#.*/d;s/#.*//;/^[[:blank:]]*$/d' "${packages}") + if (( ${#pkg_list[@]} == 0 )); then + _msg_error "'${packages}' does not list any packages!" 1 + fi + fi + + cd -- "${OLDPWD}" + fi +} + +_set_up_directories() { + local directory + for directory in "${work_dir}" "${out_dir}" "${work_dir}/${arch}" "${isofs_dir}" "${isofs_dir}/${install_dir}"; do + [[ -d "${directory}" ]] || mkdir -m 0755 -- "${directory}" + done +} + +_print_settings() { + _msg_info "${app_name} configuration settings" + _msg_info " Command: ${command_name}" + _msg_info " Working directory: ${work_dir}" + _msg_info " Output directory: ${out_dir}" + _msg_info " GPG key: ${gpg_key:-None}" + _msg_info "Profile configuration settings" + _msg_info " Profile: ${profile}" + _msg_info " Architecture: ${arch}" + _msg_info " Image name: ${img_name}" + _msg_info " Disk label: ${iso_label}" + _msg_info " Disk publisher: ${iso_publisher}" + _msg_info " Disk application: ${iso_application}" + _msg_info " Installation directory: ${install_dir}" + _msg_info " Pacman config file: ${pacman_conf}" + _msg_info " Packages: ${pkg_list[*]}" + if [[ "${arch}" == "dual" ]]; then + _msg_info " Packages (x86_64): ${pkg_list_x86_64[*]:-None}" + _msg_info " Packages (i686): ${pkg_list_i686[*]:-None}" + fi + _msg_info " Boot modes: ${bootmodes[*]}" +} + +_export_gpg_publickey() { + if [[ -n "${gpg_key}" ]]; then + gpg --batch --output "${work_dir}/pubkey.gpg" --export "${gpg_key}" fi - _msg_info "Done! | $(ls -sh "${out_dir}/${img_name}")" +} + + +_make_pkglist() { + _msg_info "Creating a list of installed packages on live-enviroment..." + pacman -Q --sysroot "${airootfs_dir}" > "${isofs_dir}/${install_dir}/pkglist.${arch}.txt" + _msg_info "Done!" +} + +command_pkglist () { + _show_config pkglist + _make_pkglist +} + +# Create an ISO9660 filesystem from "iso" directory. +command_iso () { + bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito') + + # If exists, add an EFI "El Torito" boot image (FAT filesystem) to ISO-9660 image. + if [[ -f "${isofs_dir}/EFI/parabolaiso/efiboot.img" ]]; then + if [[ -e "${airootfs_dir}/usr/share/refind/refind_x64.efi" ]]; then + bootmodes+=('uefi-x64.refind.esp' 'uefi-x64.refind.eltorito') + else + bootmodes+=('uefi-x64.systemd-boot.esp' 'uefi-x64.systemd-boot.eltorito') + fi + fi + + _show_config iso + mkdir -p -- "${out_dir}" + _make_iso } # create airootfs.sfs filesystem, and push it in "iso" directory. @@ -346,15 +741,7 @@ command_prepare () { _show_config prepare _cleanup - if [[ "${sfs_mode}" == "sfs" ]]; then - _mkairootfs_sfs - else - _mkairootfs_img - fi - _mkchecksum - if [[ "${gpg_key}" ]]; then - _mksignature - fi + _make_prepare } # Install packages on airootfs. @@ -364,14 +751,14 @@ command_install () { _msg_error "Pacman config file '${pacman_conf}' does not exist" 1 fi - if [[ "${#pkg_list[@]}" -eq 0 ]]; then + if (( ${#pkg_list[@]} == 0 )); then _msg_error "Packages must be specified" 0 _usage 1 fi _show_config install - _pacman "${pkg_list[@]}" + _make_packages } command_init() { @@ -384,26 +771,74 @@ command_run() { _chroot_run } -if [[ "${EUID}" -ne 0 ]]; then - _msg_error "This script must be run as root." 1 -fi - -umask 0022 +command_build_profile() { + # Set up essential directory paths + airootfs_dir="${work_dir}/${arch}/airootfs" + isofs_dir="${work_dir}/iso" + # Set ISO file name + img_name="${iso_name}-${iso_version}-${arch}.iso" + + if [[ "${arch}" == "dual" ]]; then + _print_settings + for arch in i686 x86_64; do + _run_once _set_up_directories + done + _run_once _make_pacman_conf + _run_once _export_gpg_publickey + for arch in i686 x86_64; do + airootfs_dir="${work_dir}/${arch}/airootfs" + _run_once _make_custom_airootfs + _run_once _make_packages + done + for arch in i686 x86_64; do + airootfs_dir="${work_dir}/${arch}/airootfs" + _run_once _make_customize_airootfs + done + for arch in i686 x86_64; do + _run_once _make_pkglist + done + arch="dual" + _make_bootmodes + _run_once _cleanup + for arch in i686 x86_64; do + airootfs_dir="${work_dir}/${arch}/airootfs" + _run_once _make_prepare + done + _run_once _make_iso + else + _print_settings + _run_once _set_up_directories + _run_once _make_pacman_conf + _run_once _export_gpg_publickey + _run_once _make_custom_airootfs + _run_once _make_packages + _run_once _make_customize_airootfs + _run_once _make_pkglist + _make_bootmodes + _run_once _cleanup + _run_once _make_prepare + _run_once _make_iso + fi +} -while getopts 'p:r:C:L:P:A:D:w:o:s:c:g:i:vh' arg; do +while getopts 'B:p:r:C:L:P:A:D:w:o:s:c:g:dvh' arg; do case "${arg}" in + B) + profile="$(realpath -- "${OPTARG}")" + _read_profile + ;; p) read -r -a opt_pkg_list <<< "${OPTARG}" pkg_list+=("${opt_pkg_list[@]}") ;; r) run_cmd="${OPTARG}" ;; - C) pacman_conf="${OPTARG}" ;; + C) pacman_conf="$(realpath -- "${OPTARG}")" ;; L) iso_label="${OPTARG}" ;; P) iso_publisher="${OPTARG}" ;; A) iso_application="${OPTARG}" ;; D) install_dir="${OPTARG}" ;; - w) work_dir="${OPTARG}" ;; - o) out_dir="${OPTARG}" ;; + w) work_dir="$(realpath -- "${OPTARG}")" ;; + o) out_dir="$(realpath -- "${OPTARG}")" ;; s) sfs_mode="${OPTARG}" ;; c) sfs_comp="${OPTARG}" ;; g) gpg_key="${OPTARG}" ;; @@ -416,38 +851,55 @@ while getopts 'p:r:C:L:P:A:D:w:o:s:c:g:i:vh' arg; do esac done +if (( EUID != 0 )); then + _msg_error "${app_name} must be run as root." 1 +fi + shift $((OPTIND - 1)) -if [[ $# -lt 1 ]]; then +if (( $# < 1 )); then _msg_error "No command specified" 0 _usage 1 fi command_name="${1}" +# Set directory path defaults +airootfs_dir="${work_dir}/airootfs" +isofs_dir="${work_dir}/iso" + case "${command_name}" in init) + _msg_warning "The '${command_name}' command is deprecated!" command_init ;; install) + _msg_warning "The '${command_name}' command is deprecated!" command_install ;; run) + _msg_warning "The '${command_name}' command is deprecated!" command_run ;; prepare) + _msg_warning "The '${command_name}' command is deprecated!" command_prepare ;; pkglist) + _msg_warning "The '${command_name}' command is deprecated!" command_pkglist ;; iso) - if [[ $# -lt 2 ]]; then + _msg_warning "The '${command_name}' command is deprecated!" + if (( $# < 2 )); then _msg_error "No image specified" 0 _usage 1 fi img_name="${2}" command_iso ;; + build_profile) + command_build_profile + ;; *) _msg_error "Invalid command name '${command_name}'" 0 _usage 1 diff --git a/scripts/run_parabolaiso.sh b/scripts/run_parabolaiso.sh index 01f0a7d..cc75d24 100755 --- a/scripts/run_parabolaiso.sh +++ b/scripts/run_parabolaiso.sh @@ -15,117 +15,113 @@ set -eu print_help() { - cat << EOF + local usagetext + IFS='' read -r -d '' usagetext <<EOF || true Usage: run_parabolaiso [options] Options: - -b set boot type to 'bios' (default) + -b set boot type to 'BIOS' (default) + -d set image type to hard disk instead of optical disc -h print help -i [image] image to boot into - -s use secure boot (only relevant when using UEFI) - -u set boot type to 'uefi' + -s use Secure Boot (only relevant when using UEFI) + -u set boot type to 'UEFI' Example: Run an image using UEFI: $ run_parabolaiso -u -i parabolaiso-2020.05.23-x86_64.iso EOF + printf '%s' "${usagetext}" } cleanup_working_dir() { - if [ -d "${working_dir}" ]; then - rm -rf "${working_dir}" + if [[ -d "${working_dir}" ]]; then + rm -rf -- "${working_dir}" fi } copy_ovmf_vars() { - if [ ! -f /usr/share/edk2-ovmf/x64/OVMF_VARS.fd ]; then - echo "ERROR: OVMF_VARS.fd not found. Install edk2-ovmf." + if [[ ! -f '/usr/share/edk2-ovmf/x64/OVMF_VARS.fd' ]]; then + printf 'ERROR: %s\n' "OVMF_VARS.fd not found. Install edk2-ovmf." exit 1 fi - cp -av /usr/share/edk2-ovmf/x64/OVMF_VARS.fd "${working_dir}" + cp -av -- '/usr/share/edk2-ovmf/x64/OVMF_VARS.fd' "${working_dir}/" } check_image() { - if [ -z "$image" ]; then - echo "ERROR: Image name can not be empty." + if [[ -z "$image" ]]; then + printf 'ERROR: %s\n' "Image name can not be empty." exit 1 fi - if [ ! -f "$image" ]; then - echo "ERROR: Image file ($image) does not exist." + if [[ ! -f "$image" ]]; then + printf 'ERROR: %s\n' "Image file (${image}) does not exist." exit 1 fi } run_image() { - [ "$boot_type" == "bios" ] && run_image_using_bios - [ "$boot_type" == "uefi" ] && run_image_using_uefi -} + if [[ "$boot_type" == 'uefi' ]]; then + copy_ovmf_vars + if [[ "${secure_boot}" == 'on' ]]; then + printf '%s\n' 'Using Secure Boot' + local ovmf_code='/usr/share/edk2-ovmf/x64/OVMF_CODE.secboot.fd' + else + local ovmf_code='/usr/share/edk2-ovmf/x64/OVMF_CODE.fd' + fi + qemu_options+=( + '-drive' "if=pflash,format=raw,unit=0,file=${ovmf_code},readonly" + '-drive' "if=pflash,format=raw,unit=1,file=${working_dir}/OVMF_VARS.fd" + '-global' "driver=cfi.pflash01,property=secure,value=${secure_boot}" + ) + fi -run_image_using_bios() { qemu-system-x86_64 \ -boot order=d,menu=on,reboot-timeout=5000 \ - -m size=3072,slots=0,maxmem=$((3072*1024*1024)) \ + -m "size=3072,slots=0,maxmem=$((3072*1024*1024))" \ -k en \ -name parabolaiso,process=parabolaiso_0 \ - -drive file="${image}",media=cdrom,readonly=on,if=virtio \ + -device virtio-scsi-pci,id=scsi0 \ + -device "scsi-${mediatype%rom},bus=scsi0.0,drive=${mediatype}0" \ + -drive "id=${mediatype}0,if=none,format=raw,media=${mediatype/hd/disk},readonly=on,file=${image}" \ -display sdl \ -vga virtio \ - -device virtio-net-pci,netdev=net0 -netdev user,id=net0 \ - -enable-kvm \ - -no-reboot -} - -run_image_using_uefi() { - local ovmf_code=/usr/share/edk2-ovmf/x64/OVMF_CODE.fd - local secure_boot_state=off - copy_ovmf_vars - if [ "${secure_boot}" == "yes" ]; then - echo "Using Secure Boot" - ovmf_code=/usr/share/edk2-ovmf/x64/OVMF_CODE.secboot.fd - secure_boot_state=on - fi - qemu-system-x86_64 \ - -boot order=d,menu=on,reboot-timeout=5000 \ - -m size=3072,slots=0,maxmem=$((3072*1024*1024)) \ - -k en \ - -name parabolaiso,process=parabolaiso_0 \ - -drive file="${image}",media=cdrom,readonly=on,if=virtio \ - -drive if=pflash,format=raw,unit=0,file="${ovmf_code}",readonly \ - -drive if=pflash,format=raw,unit=1,file="${working_dir}/OVMF_VARS.fd" \ + -device virtio-net-pci,romfile=,netdev=net0 -netdev user,id=net0 \ -machine type=q35,smm=on,accel=kvm \ - -global driver=cfi.pflash01,property=secure,value="${secure_boot_state}" \ -global ICH9-LPC.disable_s3=1 \ - -display sdl \ - -vga virtio \ - -device virtio-net-pci,netdev=net0 -netdev user,id=net0 \ -enable-kvm \ + "${qemu_options[@]}" \ -no-reboot } set_image() { - if [ -z "$image" ]; then - echo "ERROR: Image name can not be empty." + if [[ -z "$image" ]]; then + printf 'ERROR: %s\n' "Image name can not be empty." exit 1 fi - if [ ! -f "$image" ]; then - echo "ERROR: Image ($image) does not exist." + if [[ ! -f "$image" ]]; then + printf 'ERROR: %s\n' "Image (${image}) does not exist." exit 1 fi image="$1" } -image="" -boot_type="bios" -secure_boot="no" -working_dir="$(mktemp -d)" +image='' +boot_type='bios' +mediatype='cdrom' +secure_boot='off' +qemu_options=() +working_dir="$(mktemp -dt run_parabolaiso.XXXXXXXXXX)" trap cleanup_working_dir EXIT -if [ ${#@} -gt 0 ]; then - while getopts 'bhi:su' flag; do - case "${flag}" in +if (( ${#@} > 0 )); then + while getopts 'bdhi:su' flag; do + case "$flag" in b) - boot_type=bios + boot_type='bios' + ;; + d) + mediatype='hd' ;; h) print_help @@ -135,13 +131,13 @@ if [ ${#@} -gt 0 ]; then image="$OPTARG" ;; u) - boot_type=uefi + boot_type='uefi' ;; s) - secure_boot=yes + secure_boot='on' ;; *) - echo "Error: Wrong option. Try 'run_parabolaiso -h'." + printf '%s\n' "Error: Wrong option. Try 'run_parabolaiso -h'." exit 1 ;; esac |