#!/bin/bash # SPDX-Version: 3.0 # SPDX-CreationInfo: 2025-06-17; WEIDNER, Marc S.; # SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.installer.git # SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency # SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; # SPDX-FileType: SOURCE # SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0 # SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework. # SPDX-PackageName: CISS.debian.installer # SPDX-Security-Contact: security@coresecret.eu guard_sourcing ####################################### # Installation and setup of the GRUB2 (backported) version. # The backported version MUST be installed for LUKS2 '/boot' encryption. # Globals: # ERR_GRUB_BACKGROUND # ERR_GRUB_EFI_FORCE # TARGET # VAR_RECIPE_FIRMWARE # VAR_RECIPE_TABLE # grub_background_enable # grub_background_path # grub_bootdev # grub_force_efi # grub_latest # grub_prober # grub_skip # Arguments: # None # Returns: # ERR_GRUB_BACKGROUND # ERR_GRUB_EFI_FORCE # 0: on success ####################################### setup_grub() { declare -gx var_update_grub_required="false" get_all_boot_devs if [[ "${grub_skip,,}" != "true" ]]; then ### Install GRUB2 package if [[ "${grub_latest,,}" == "true" ]]; then ### Install the GRUB2 backported version from the Bookworm backports repository. if [[ "${VAR_RECIPE_FIRMWARE}" == "uefi" ]]; then case "${VAR_ARCHITECTURE,,}" in amd64) do_in_target "${TARGET}" apt-get install -y -t bookworm-backports grub2 grub2-common grub-efi-amd64 ;; arm64) do_in_target "${TARGET}" apt-get install -y -t bookworm-backports grub2 grub2-common grub-efi-arm64 ;; i386) do_in_target "${TARGET}" apt-get install -y -t bookworm-backports grub2 grub2-common grub-efi-ia32 ;; *) do_log "emergency" "true" "Unsupported UEFI architecture: ${VAR_ARCHITECTURE}"; return "${ERR_GRUB_ARCHITECTURE}" ;; esac else do_in_target "${TARGET}" apt-get install -y -t bookworm-backports grub2 grub2-common grub-pc fi else ### Install the GRUB2 stable version. if [[ "${VAR_RECIPE_FIRMWARE}" == "uefi" ]]; then case "${VAR_ARCHITECTURE,,}" in amd64) do_in_target "${TARGET}" apt-get install -y grub2 grub2-common grub-efi-amd64 ;; arm64) do_in_target "${TARGET}" apt-get install -y grub2 grub2-common grub-efi-arm64 ;; i386) do_in_target "${TARGET}" apt-get install -y grub2 grub2-common grub-efi-ia32 ;; *) do_log "emergency" "true" "Unsupported UEFI architecture: ${VAR_ARCHITECTURE}"; return "${ERR_GRUB_ARCHITECTURE}" ;; esac else do_in_target "${TARGET}" apt-get install -y grub2 grub2-common grub-pc fi fi ### Install grub on the specific device. if [[ "${grub_force_efi,,}" == "false" ]]; then if [[ "${VAR_RECIPE_FIRMWARE,,}" == "uefi" ]]; then install_grub_uefi_all elif [[ "${VAR_RECIPE_FIRMWARE,,}" == "bios" ]]; then install_grub_bios_all fi elif [[ "${grub_force_efi,,}" == "true" ]]; then if [[ "${VAR_RECIPE_TABLE,,}" == "gpt" && "${VAR_RECIPE_FIRMWARE,,}" == "uefi" ]]; then do_in_target "${TARGET}" grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=Debian --modules="btrfs cryptodisk luks2 gcry_rijndael gcry_sha256 gcry_sha512 part_gpt" --force-extra-removable var_update_grub_required="true" else do_log "emergency" "true" "Unsupported combination of partition table: '${VAR_RECIPE_TABLE,,}' and setting: grub_force_efi '${grub_force_efi,,}'." return "${ERR_GRUB_EFI_FORCE}" fi fi ### Enable booting from LUKS encrypted devices by default. cat << EOF >> "${TARGET}/etc/default/grub" # Enable booting from LUKS encrypted devices by default. GRUB_ENABLE_CRYPTODISK=y EOF var_update_grub_required="true" ### Install a boot menu background. if [[ "${grub_background_enable,,}" == "true" ]]; then declare var_background var_background=$(basename "${grub_background_path}") cp --no-preserve=ownership "${grub_background_path}" "${TARGET}/etc/default/grub.d/${var_background}" || return "${ERR_GRUB_BACKGROUND}" chmod 0640 "${TARGET}/etc/default/grub.d/${var_background}" || return "${ERR_GRUB_BACKGROUND}" cat << EOF >> "${TARGET}/etc/default/grub" # Enable boot menu background. GRUB_BACKGROUND="/etc/default/grub.d/${var_background}" # The resolution used on graphical terminal # note that you can use only modes which your graphic card supports via VBE # you can see them in real GRUB with the command 'vbeinfo' GRUB_GFXMODE=1920x1080,1280x1024,1024x768,800x600 GRUB_GFXPAYLOAD_LINUX=keep EOF var_update_grub_required="true" fi ### Change GRUB OS detection configuration accordingly. if [[ "${grub_prober,,}" == "true" ]]; then cat << EOF >> "${TARGET}/etc/default/grub" # If your computer has multiple operating systems installed, then you # probably want to run os-prober. However, if your computer is a host # for guest OSes installed via LVM or raw disk devices, running # os-prober can cause damage to those guest OSes as it mounts # filesystems to look for things. GRUB_DISABLE_OS_PROBER=false EOF var_update_grub_required="true" elif [[ "${grub_prober,,}" == "false" ]]; then cat << EOF >> "${TARGET}/etc/default/grub" # If your computer has multiple operating systems installed, then you # probably want to run os-prober. However, if your computer is a host # for guest OSes installed via LVM or raw disk devices, running # os-prober can cause damage to those guest OSes as it mounts # filesystems to look for things. GRUB_DISABLE_OS_PROBER=true EOF var_update_grub_required="true" fi else do_log "info" "true" "GRUB2 setup skipped." fi [[ "${var_update_grub_required}" == "true" ]] && do_in_target "${TARGET}" update-grub ### Setting the permissions to read and write for root only prevents non-root users from seeing the boot parameters or changing them. chown root:root "${TARGET}/boot/grub/grub.cfg" chmod 0600 "${TARGET}/boot/grub/grub.cfg" chmod -R 0700 "${TARGET}/etc/grub.d" return 0 } ####################################### # Detects and collects all boot devices for GRUB installation. # Supports /dev/sdX, /dev/vdX, /dev/hdX, /dev/nvmeXn1, /dev/mmcblkX. # Globals: # VAR_RECIPE_DEV_COUNTER # ary_bootdev_all # grub_bootdev # Arguments: # None # Returns: # 0: on success ####################################### get_all_boot_devs() { declare -ag ary_bootdev_all=() declare dev="" dev_prefix="" dev_path="" letter="" declare -i ascii ascii_end ascii_start ### Determine prefix from grub_bootdev (e.g., "sd", "vd", "nvme", "mmcblk") dev_prefix=$(basename "${grub_bootdev}" | sed -E 's/^([a-z]+)[a-z0-9]*$/\1/') case "${dev_prefix}" in sd|vd|hd) ascii_start=$(printf '%d' "'a") ascii_end=$(printf '%d' "'${VAR_RECIPE_DEV_COUNTER}") for ((ascii = ascii_start; ascii <= ascii_end; ascii++)); do letter=$(printf "%b" "\\$(printf '%03o' "${ascii}")") dev_path="/dev/${dev_prefix}${letter}" [[ -b "${dev_path}" ]] && ary_bootdev_all+=("${dev_path}") done ;; nvme) # shellcheck disable=SC2312 while read -r dev; do ary_bootdev_all+=("/dev/${dev}") done < <(lsblk -dn -o NAME | grep -E '^nvme[0-9]+n1$') ;; mmcblk) # shellcheck disable=SC2312 while read -r dev; do ary_bootdev_all+=("/dev/${dev}") done < <(lsblk -dn -o NAME | grep -E '^mmcblk[0-9]+$') ;; *) do_log "warning" "true" "Unrecognized boot device prefix: ${dev_prefix}" ;; esac return 0 } ####################################### # Installs GRUB in BIOS mode on all block devices. # Globals: # TARGET # VAR_RECIPE_TABLE # ary_bootdev_all # var_update_grub_required # Arguments: # None # Returns: # 0: on success # ERR_PARTITIONTBL on failure ####################################### install_grub_bios_all() { declare dev="" partmod="" case "${VAR_RECIPE_TABLE,,}" in gpt) partmod="part_gpt" ;; msdos|mbr) partmod="part_msdos" ;; *) do_log "emergency" "true" "Unknown partition table type: '${VAR_RECIPE_TABLE}'."; return "${ERR_PARTITIONTBL}" ;; esac declare var_modules="btrfs cryptodisk luks2 gcry_rijndael gcry_sha256 gcry_sha512 ${partmod}" declare -a args=(--target=i386-pc --boot-directory=/boot "--modules=${var_modules}") args+=(--recheck) for dev in "${ary_bootdev_all[@]}"; do do_in_target "${TARGET}" grub-install "${args[@]}" "${dev}" do_log "info" "true" "Installed: GRUB on Device: '${dev}' (BIOS)." var_update_grub_required="true" done return 0 } ####################################### # Installs GRUB to all ESPs in UEFI mode. # Globals: # TARGET # VAR_RECIPE_TABLE # ary_bootdev_all # var_update_grub_required # Arguments: # None # Returns: # 0: on success # ERR_PARTITIONTBL on failure ####################################### install_grub_uefi_all() { declare dev="" partmod="" case "${VAR_RECIPE_TABLE,,}" in gpt) partmod="part_gpt" ;; msdos|mbr) partmod="part_msdos" ;; *) do_log "emergency" "true" "Unknown partition table type: '${VAR_RECIPE_TABLE}'."; return "${ERR_PARTITIONTBL}" ;; esac declare var_modules="btrfs cryptodisk luks2 gcry_rijndael gcry_sha256 gcry_sha512 ${partmod}" declare -a args=(--target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=Debian "--modules=${var_modules}") for dev in "${ary_bootdev_all[@]}"; do do_in_target "${TARGET}" grub-install "${args[@]}" do_log "info" "true" "Installed: GRUB on Device: '${dev}' (UEFI)." var_update_grub_required="true" done return 0 } # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh