#!/usr/bin/bash # vim:ft=sh:fdm=marker:fmr={,} # shellcheck disable=2034,2154 # archlabs installer library script file # this file is not meant to be run directly # sourcing this file in a non bash shell is not advised # command used to install each bootloader declare -Ag BCMDS=( [UEFI-syslinux]='efibootmgr -c -d $BOOT_DEVICE -p $BOOT_PART_NUM -l /EFI/syslinux/syslinux.efi -L $DIST' [BIOS-syslinux]='syslinux-install_update -iam' [UEFI-grub]='grub-install --recheck --force --bootloader-id=$DIST && grub-mkconfig -o /boot/grub/grub.cfg' [BIOS-grub]='grub-install --recheck --force --bootloader-id=$DIST --target=i386-pc $BOOT_DEVICE && grub-mkconfig -o /boot/grub/grub.cfg' [systemd-boot]='bootctl --path=/boot install' ) # boot partition mount points for each bootloader declare -Ag BMNTS=( [BIOS-grub]="/boot" [UEFI-grub]="/boot/efi" [BIOS-syslinux]="/boot" [UEFI-syslinux]="/boot" [UEFI-systemd-boot]="/boot" ) # bootloader options with respective boot partition mountpoint declare -Ag BOOTLDRS=( [BIOS]="grub ${BMNTS[BIOS-grub]} syslinux ${BMNTS[BIOS-syslinux]}" [UEFI]="systemd-boot ${BMNTS[UEFI-systemd-boot]} grub ${BMNTS[UEFI-grub]} syslinux ${BMNTS[UEFI-syslinux]}" ) pre_grub() { FILES[9]="/etc/default/grub" if [[ $SYS == 'BIOS' && $BOOT_DEVICE == "" ]]; then select_device 'boot' || return 1 elif [[ $SYS == 'UEFI' && $ROOT_PART =~ /dev/mapper && ! $LVM && ! $LUKS_PASS ]]; then luks_pass "$_LuksOpen" "$ROOT_PART" || return 1 fi return 0 } pre_syslinux() { if [[ $SYS == 'BIOS' ]]; then FILES[9]="/boot/syslinux/syslinux.cfg" else FILES[9]="/boot/EFI/syslinux/syslinux.cfg" fi } pre_systemd-boot() { FILES[9]="/boot/loader/entries/$DIST.conf" } prerun_grub() { local cfg="$MNT/etc/default/grub" sed -i "s/GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR=\"${DIST}\"/g; s/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"\"/g" $cfg if [[ $LUKS_DEV ]]; then sed -i "s~#GRUB_ENABLE_CRYPTODISK~GRUB_ENABLE_CRYPTODISK~g; s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\"${LUKS_DEV}\"~g" $cfg fi if [[ $SYS == 'BIOS' && $LVM && $SEPERATE_BOOT == false ]]; then sed -i "s/GRUB_PRELOAD_MODULES=.*/GRUB_PRELOAD_MODULES=\"lvm\"/g" $cfg fi # needed for os-prober module to work properly in the chroot if [[ $SYS == 'UEFI' ]]; then # mkdir -p /run/lvm $MNT/hostrun/lvm # mount --bind /run/lvm $MNT/hostrun/lvm mkdir -p /run/udev $MNT/hostrun/udev mount --bind /run/udev $MNT/hostrun/udev BCMDS[grub]="mkdir -p /run/udev && mount --bind /hostrun/udev /run/udev && ${BCMDS[grub]} && umount /run/udev" fi return 0 } prerun_systemd-boot() { # no LVM then systemd-boot uses PARTUUID [[ $ROOT_PART =~ /dev/mapper ]] || ROOT_PART_ID="PART$ROOT_PART_ID" # create the boot entry configs mkdir -p ${MNT}${BMNTS[$SYS-$BOOTLDR]}/loader/entries cat > ${MNT}${BMNTS[$SYS-$BOOTLDR]}/loader/loader.conf << EOF default $DIST timeout 5 editor no EOF cat > ${MNT}${BMNTS[$SYS-$BOOTLDR]}/loader/entries/${DIST}.conf << EOF title $DIST Linux linux /vmlinuz-${KERNEL}$([[ $UCODE ]] && printf "\ninitrd %s" "/${UCODE}.img") initrd /initramfs-$KERNEL.img options root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw EOF # add pacman hook to update the bootloader when systemd receives an update mkdir -p $MNT/etc/pacman.d/hooks cat > $MNT/etc/pacman.d/hooks/systemd-boot.hook << EOF [Trigger] Type = Package Operation = Upgrade Target = systemd [Action] Description = Updating systemd-boot When = PostTransaction Exec = /usr/bin/bootctl update EOF # systemd-boot requires this before running bootctl systemd-machine-id-setup --root="$MNT" >/dev/null 2>&1 return 0 } prerun_syslinux() { if [[ $SYS == 'UEFI' ]]; then local cfgdir="${MNT}${BMNTS[$SYS-$BOOTLDR]}/EFI/syslinux" local cfgsrcdir="/usr/lib/syslinux/efi32/" [[ $IS_64BIT == true ]] && cfgsrcdir="/usr/lib/syslinux/efi64/" else local cfgdir="$MNT${BMNTS[$SYS-$BOOTLDR]}/syslinux" local cfgsrcdir="/usr/lib/syslinux/bios/" fi mkdir -p $cfgdir cp -r $cfgsrcdir $cfgdir/ cat > $cfgdir/syslinux.cfg << EOF UI menu.c32 PROMPT 0 MENU TITLE $DIST Syslinux Boot Menu TIMEOUT 50 DEFAULT $DIST LABEL $DIST MENU LABEL $DIST Linux LINUX ../vmlinuz-$KERNEL APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw INITRD ../initramfs-$KERNEL.img$([[ $UCODE ]] && printf "\nINITRD %s" "../${UCODE}.img") LABEL ${DIST}fallback MENU LABEL $DIST Linux Fallback LINUX ../vmlinuz-$KERNEL APPEND root=$ROOT_PART_ID $([[ $LUKS_DEV ]] && printf "%s " "$LUKS_DEV")rw INITRD ../initramfs-$KERNEL-fallback.img$([[ $UCODE ]] && printf "\nINITRD %s" "../${UCODE}.img") EOF return 0 } install_bootloader() { if ! [[ $ROOT_PART =~ /dev/mapper ]]; then ROOT_PART_ID="UUID=$(blkid -s PARTUUID -o value $ROOT_PART)" else # for LVM we just use the partition label ROOT_PART_ID="$ROOT_PART" fi # remove old UEFI boot entries if [[ $SYS == 'UEFI' ]]; then find ${MNT}${BMNTS[$SYS-$BOOTLDR]}/EFI/ \ -maxdepth 1 -mindepth 1 -name '[aA][rR][cC][hH][lL]abs' \ -type d -exec rm -rf '{}' \; >/dev/null 2>&1 fi prerun_$BOOTLDR printf "\nInstalling and setting up $BOOTLDR in ${BMNTS[$SYS-$BOOTLDR]}\n\n" chrun "eval ${BCMDS[$SYS-$BOOTLDR]}" if [[ -d $MNT/hostrun/udev ]]; then umount $MNT/hostrun/udev rm -rf $MNT/hostrun fi # copy efi stub to generic catch all [[ $SYS == 'UEFI' && $BOOTLDR =~ (grub|syslinux) ]] && uefi_boot_fallback return 0 } uefi_boot_fallback() { # some UEFI firmware requires a dir in the ESP with a generic bootx64.efi # see: https://wiki.archlinux.org/index.php/GRUB#UEFI # also: https://wiki.archlinux.org/index.php/syslinux#UEFI_Systems local esp="${MNT}${BMNTS[$SYS-$BOOTLDR]}" local default="boot" default="$(find $esp/EFI/ -maxdepth 1 -mindepth 1 \ -name '[Bb][oO][oO][tT]' -type d)" [[ $default ]] && default="$(basename $default)" if [[ -d $esp/EFI/$default ]]; then rm -rf $esp/EFI/$default/* else mkdir -p $esp/EFI/$default fi if [[ $BOOTLDR == 'syslinux' ]]; then cp -rf $esp/EFI/syslinux/* $esp/EFI/$default/ cp -f $esp/EFI/syslinux/syslinux.efi $esp/EFI/$default/bootx64.efi elif [[ $BOOTLDR == 'grub' && $IS_64BIT == true ]]; then cp -f $esp/EFI/$DIST/grubx64.efi $esp/EFI/$default/bootx64.efi elif [[ $BOOTLDR == 'grub' ]]; then cp -f $esp/EFI/$DIST/grubia32.efi $esp/EFI/$default/bootia32.efi fi return 0 } shim_secure_boot() { # still a W.I.P local shim_file="shim.efi" [[ $IS_64BIT == true ]] && shim_file="shim64.efi" efibootmgr -c -w -L $DIST -d $BOOT_DEVICE -p $BOOT_PART_NUM -l ${MNT}${BMNTS[$SYS-$BOOTLDR]}/$shim_file return 0 }