Compare commits
	
		
			5 Commits
		
	
	
		
			a0a05b60d1
			...
			844f574e2d
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 844f574e2d | |||
| b0842ac9ba | |||
| 03ed6e076d | |||
| b5666493f1 | |||
| 81a7fcd64c | 
							
								
								
									
										35
									
								
								setup.sh
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								setup.sh
									
									
									
									
									
								
							@@ -18,7 +18,6 @@ exec 3>&1
 | 
			
		||||
 | 
			
		||||
declare this_script_url
 | 
			
		||||
this_script_url="${SCRIPT_URL:?}"
 | 
			
		||||
postconf_hook="$(dirname "${this_script_url}")"'/zbm_set_new_uefi_boot_entries.sh'
 | 
			
		||||
 | 
			
		||||
declare zpool_name zfs_arch_dataset_name
 | 
			
		||||
zpool_name='zpool'
 | 
			
		||||
@@ -658,25 +657,22 @@ function configure_zfsbootmenu () {
 | 
			
		||||
    paru_install 'zfsbootmenu'
 | 
			
		||||
 | 
			
		||||
    if [[ "${part_schema}" = 'gpt' ]]; then
 | 
			
		||||
        mkdir -p '/etc/zfsbootmenu/posthooks.d'
 | 
			
		||||
        cat > '/etc/zfsbootmenu/config.yaml' <<EOF
 | 
			
		||||
Global:
 | 
			
		||||
  ManageImages: true
 | 
			
		||||
  BootMountPoint: /efi
 | 
			
		||||
  InitCPIO: true
 | 
			
		||||
  PostHooksDir: /etc/zfsbootmenu/posthooks.d
 | 
			
		||||
Components:
 | 
			
		||||
  Enabled: false
 | 
			
		||||
EFI:
 | 
			
		||||
  ImageDir: /efi/EFI/ZBM
 | 
			
		||||
  Versions: false
 | 
			
		||||
  Enabled: true
 | 
			
		||||
  Stub: /etc/zfsbootmenu/stub-loader.d/linuxx64.efi.stub
 | 
			
		||||
  Stub: /usr/share/zfsbootmenu/stubs/linuxx64.efi.stub/linuxx64.efi.stub  # workaround: https://github.com/zbm-dev/zfsbootmenu/discussions/501
 | 
			
		||||
Kernel:
 | 
			
		||||
  CommandLine: ro loglevel=0 zbm.import_policy=hostid
 | 
			
		||||
  Prefix: vmlinuz
 | 
			
		||||
EOF
 | 
			
		||||
        get_known_good_stub_loader
 | 
			
		||||
    else
 | 
			
		||||
        configure_syslinux
 | 
			
		||||
        cat > '/etc/zfsbootmenu/config.yaml' <<EOF
 | 
			
		||||
@@ -701,14 +697,6 @@ EOF
 | 
			
		||||
    zfs set org.zfsbootmenu:commandline='rw nowatchdog rd.vconsole.keymap=de-latin1' "${zpool_name}"'/root/'"${zfs_arch_dataset_name}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_known_good_stub_loader () {
 | 
			
		||||
    local known_good_stub_loader local_stub_loader_abs
 | 
			
		||||
    known_good_stub_loader='https://github.com/zbm-dev/zfsbootmenu/raw/master/testing/stubs/linuxx64.efi.stub'
 | 
			
		||||
    local local_stub_loader_abs='/etc/zfsbootmenu/stub-loader.d/linuxx64.efi.stub'
 | 
			
		||||
    mkdir -p "$(dirname "${local_stub_loader_abs}")"
 | 
			
		||||
    curl --silent --location "${known_good_stub_loader}" --output "${local_stub_loader_abs}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function add_syslinux_pacman_hook () {
 | 
			
		||||
    mkdir -p '/opt/git/quico.space/quico-os-setup/zbm-syslinux-pacman-hook/branches/main'
 | 
			
		||||
    git -C '/opt/git/quico.space/quico-os-setup/zbm-syslinux-pacman-hook/branches/main' clone 'https://quico.space/quico-os-setup/zbm-syslinux-pacman-hook.git' .
 | 
			
		||||
@@ -717,6 +705,12 @@ function add_syslinux_pacman_hook () {
 | 
			
		||||
    ln -s '/opt/git/quico.space/quico-os-setup/zbm-syslinux-pacman-hook/branches/main/pacman-zbm-syslinux-regen.hook' '/usr/share/libalpm/hooks/pacman-zbm-syslinux-regen.hook'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function add_zbm_pacman_hook () {
 | 
			
		||||
    mkdir -p '/opt/git/quico.space/quico-os-setup/zbm-regen-pacman-hook/branches/main'
 | 
			
		||||
    git -C '/opt/git/quico.space/quico-os-setup/zbm-regen-pacman-hook/branches/main' clone 'https://quico.space/quico-os-setup/zbm-regen-pacman-hook.git' .
 | 
			
		||||
    ln -s '/opt/git/quico.space/quico-os-setup/zbm-regen-pacman-hook/branches/main/pacman-zbm-image-regen.hook' '/usr/share/libalpm/hooks/pacman-zbm-image-regen.hook'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_disks_with_one_efipart () {
 | 
			
		||||
    local disks_with_one_efipart
 | 
			
		||||
    # Find disks that have exactly one EFI partition and where that EFI
 | 
			
		||||
@@ -764,9 +758,8 @@ function install_os_in_chroot () {
 | 
			
		||||
    if [[ "${part_schema}" = 'mbr' ]]; then
 | 
			
		||||
        paru_install 'rsync'
 | 
			
		||||
        add_syslinux_pacman_hook
 | 
			
		||||
    else
 | 
			
		||||
        :
 | 
			
		||||
    fi
 | 
			
		||||
    add_zbm_pacman_hook
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function set_root_pw () {
 | 
			
		||||
@@ -864,15 +857,8 @@ function set_new_uefi_boot_entries () {
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function insert_zbm_postconf_hook () {
 | 
			
		||||
    #3.9
 | 
			
		||||
    declare postconf_target_abs='/mnt/etc/zfsbootmenu/posthooks.d/'"$(basename "${postconf_hook}")"
 | 
			
		||||
    curl --silent --location "${postconf_hook}" --output "${postconf_target_abs}"
 | 
			
		||||
    chmod +x "${postconf_target_abs}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function umount_all () {
 | 
			
		||||
    #3.10
 | 
			
		||||
    #3.9
 | 
			
		||||
    if [[ "${part_schema}" = 'mbr' ]]; then
 | 
			
		||||
        umount '/mnt/boot/syslinux'
 | 
			
		||||
    else
 | 
			
		||||
@@ -892,9 +878,8 @@ function finalize_os_setup () {
 | 
			
		||||
    configure_zfs_mount_gen                     #3.7
 | 
			
		||||
    if [[ "${part_schema}" = 'gpt' ]]; then
 | 
			
		||||
        set_new_uefi_boot_entries               #3.8
 | 
			
		||||
        insert_zbm_postconf_hook                #3.9
 | 
			
		||||
    fi
 | 
			
		||||
    umount_all                                  #3.10
 | 
			
		||||
    umount_all                                  #3.9
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function main () {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,177 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
# Whatever comes in on file descriptor (FD) 3 gets redirected to where file
 | 
			
		||||
# descriptor 1 is pointing. File descriptor 1 points to stdout so when we
 | 
			
		||||
# output-redirect something into FD 3 it shows up on stdout. We can use this
 | 
			
		||||
# to produce arbitrary logging output inside a subshell like so:
 | 
			
		||||
#
 | 
			
		||||
# function my_func () {
 | 
			
		||||
#     some_command "${1:?}"
 | 
			
		||||
#     >&3 echo 'A log message'
 | 
			
		||||
# }
 | 
			
		||||
#
 | 
			
		||||
# var="$(my_func arg_1)"
 | 
			
		||||
#
 | 
			
		||||
# Here "${var}" will only capture the output of some_command "${1:?}". It
 | 
			
		||||
# will not capture 'echo' which will instead show up on our stdout/FD 1.
 | 
			
		||||
exec 3>&1
 | 
			
		||||
 | 
			
		||||
# https://unix.stackexchange.com/a/48550
 | 
			
		||||
set -E
 | 
			
		||||
trap '[ "$?" -ne 77 ] || exit 77' ERR
 | 
			
		||||
 | 
			
		||||
function get_partitions () {
 | 
			
		||||
    declare partitions_json
 | 
			
		||||
    partitions_json="$(lsblk --output PATH,PARTTYPE --json --tree)" || return 1
 | 
			
		||||
    printf -- '%s' "${partitions_json}"
 | 
			
		||||
    return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_parts () {
 | 
			
		||||
    local zfs_install_drive
 | 
			
		||||
    declare parttype parts
 | 
			
		||||
    parttype="${1:?}"
 | 
			
		||||
    zfs_install_drive="${2:-}"
 | 
			
		||||
    case "${parttype}" in
 | 
			
		||||
        zfs)
 | 
			
		||||
            parts="$(get_partitions | jq --raw-output '.[][] | select(.children | length > 0) | .children[] | select(.parttype=="6a85cf4d-1dd2-11b2-99a6-080020736631") | .path')" || exit 1
 | 
			
		||||
            ;;
 | 
			
		||||
        efi)
 | 
			
		||||
            parts="$(get_partitions | jq --raw-output '.[][] | select(.children | length > 0) | select(.path=="'"${zfs_install_drive:?}"'") | .children[] | select(.parttype=="c12a7328-f81f-11d2-ba4b-00a0c93ec93b") | .path')" || exit 1
 | 
			
		||||
            ;;
 | 
			
		||||
        *)
 | 
			
		||||
            >&3 printf -- '%s\n' 'Unknown partition type '"'"'"${parttype}"'"'"', exiting ...'
 | 
			
		||||
            exit 77
 | 
			
		||||
            ;;
 | 
			
		||||
    esac
 | 
			
		||||
    printf -- '%s' "${parts}"
 | 
			
		||||
    return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function we_have_exactly_one_part () {
 | 
			
		||||
    local parttype parts_list parts_count
 | 
			
		||||
    parttype="${1:?}"
 | 
			
		||||
    parts_list="${2:?}"
 | 
			
		||||
    parts_count="$(wc -l <<<"${parts_list}")"
 | 
			
		||||
    if [[ "$(wc -c <<<"${parts_list}")" -gt '1' ]]; then
 | 
			
		||||
        case "${parts_count}" in
 | 
			
		||||
            0)
 | 
			
		||||
                >&3 printf -- '%s\n' 'No '"${parttype^^}"' partition found. Exiting ...'
 | 
			
		||||
                exit 77
 | 
			
		||||
                ;;
 | 
			
		||||
            1)
 | 
			
		||||
                return 0
 | 
			
		||||
                ;;
 | 
			
		||||
            *)
 | 
			
		||||
                return 1
 | 
			
		||||
                ;;
 | 
			
		||||
        esac
 | 
			
		||||
        >&3 printf -- '%s\n' 'Partition list does not look valid. Cowardly exiting ...'
 | 
			
		||||
        exit 77
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function select_part () {
 | 
			
		||||
    local parts enriched_parts enriched_parts_count part_number part_type zfs_install_drive
 | 
			
		||||
    declare part
 | 
			
		||||
    part_type="${1:?}" # 'efi' or 'zfs'
 | 
			
		||||
    zfs_install_drive="${2:-}"
 | 
			
		||||
    if [[ "${zfs_install_drive}" ]]; then
 | 
			
		||||
        # This is intended to find correct EFI partition
 | 
			
		||||
        parts="$(get_parts "${part_type}" "${zfs_install_drive}")"
 | 
			
		||||
    else
 | 
			
		||||
        parts="$(get_parts "${part_type}")"
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    if [[ ! "${parts}" ]]; then
 | 
			
		||||
        case "${part_type}" in
 | 
			
		||||
            efi)
 | 
			
		||||
                part_type_human_readable='EFI system partition (ESP) with partition type code EF00'
 | 
			
		||||
                ;;
 | 
			
		||||
            zfs)
 | 
			
		||||
                part_type_human_readable='ZFS zpool partition with partition type code BF00'
 | 
			
		||||
                ;;
 | 
			
		||||
        esac
 | 
			
		||||
        >&3 printf -- '%s\n' \
 | 
			
		||||
            'It looks as if there is no '"${part_type_human_readable}" \
 | 
			
		||||
            'on any of the disks. Is this a chroot? Exiting ...'
 | 
			
		||||
        exit 77
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    if we_have_exactly_one_part "${part_type}" "${parts}"; then
 | 
			
		||||
        part="${parts}"
 | 
			
		||||
    else
 | 
			
		||||
        >&3 printf -- '%s\n' 'More than one '"${part_type^^}"' partition to pick for installation. Cowardly exiting ...'
 | 
			
		||||
        exit 77
 | 
			
		||||
    fi
 | 
			
		||||
    printf -- '%s' "${part}"
 | 
			
		||||
    return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_part_parent () {
 | 
			
		||||
    local child_partition parent_partition
 | 
			
		||||
    child_partition="${1:?}"
 | 
			
		||||
    parent_partition="$(get_partitions | jq --raw-output '.[][] | select(.children | length > 0) | select(.children[].path=="'"${child_partition:?}"'") | .path')"
 | 
			
		||||
    printf -- '%s' "${parent_partition}"
 | 
			
		||||
    return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function get_disks_with_one_efipart () {
 | 
			
		||||
    local disks_with_one_efipart
 | 
			
		||||
    # Find disks that have exactly one EFI partition and where that EFI
 | 
			
		||||
    # partition is partition number 1. We expect exactly one disk to meet
 | 
			
		||||
    # these criteria. Anything else and we bail.
 | 
			
		||||
    disks_with_one_efipart="$(lsblk --output PATH,PARTTYPE --json --tree | jq --raw-output '.[][] | select(.children | length > 0) | select( any (.children[]; (.path | test("^[^[:digit:]]+1")) and (.parttype=="c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) and ([select(.children[].parttype=="c12a7328-f81f-11d2-ba4b-00a0c93ec93b")] | length == 1) ) | .path')"
 | 
			
		||||
    if [[ "$(wc -l <<<"${disks_with_one_efipart}")" -eq '1' ]] && [[ "$(wc -c <<<"${disks_with_one_efipart}")" -gt '1' ]]; then
 | 
			
		||||
        printf -- '%s' "${disks_with_one_efipart}"
 | 
			
		||||
        return 0
 | 
			
		||||
    fi
 | 
			
		||||
    return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function set_new_uefi_boot_entries () {
 | 
			
		||||
    declare -a uefi_images
 | 
			
		||||
    mapfile -t uefi_images < \
 | 
			
		||||
        <(find '/efi/EFI/ZBM' -type f -iname '*.efi' -print0 | \
 | 
			
		||||
        xargs -0 --no-run-if-empty --max-args '1' stat -c '%Y %n' | \
 | 
			
		||||
        sort -V | \
 | 
			
		||||
        awk '{print $2}')
 | 
			
		||||
    zpool_drive="$(select_part 'zfs')"
 | 
			
		||||
    zfs_parent="$(get_part_parent "${zpool_drive:?}")"
 | 
			
		||||
    efi_drive="${zfs_parent}"
 | 
			
		||||
 | 
			
		||||
    if efibootmgr | grep -Piq -- 'ZFSBootMenu'; then
 | 
			
		||||
        local -a old_uefi_entries
 | 
			
		||||
        mapfile -t old_uefi_entries < \
 | 
			
		||||
            <(efibootmgr | \
 | 
			
		||||
            grep -Pio -- '(?<=^Boot)[^\*[:space:]]+(?=\*? ZFSBootMenu)')
 | 
			
		||||
        for old_uefi_entry in "${old_uefi_entries[@]}"; do
 | 
			
		||||
            efibootmgr --bootnum "${old_uefi_entry}" --delete-bootnum &>/dev/null && {
 | 
			
		||||
                >&3 printf -- '%s\n' \
 | 
			
		||||
                    'EFI boot entry '"${old_uefi_entry}"' deleted.'
 | 
			
		||||
            }
 | 
			
		||||
        done
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    if ! efibootmgr | grep -Piq -- 'ZFSBootMenu'; then
 | 
			
		||||
        local efi_disks_list
 | 
			
		||||
        efi_disks_list="$(get_disks_with_one_efipart)"
 | 
			
		||||
        if grep -Piq -- '^'"${efi_drive}"'$' <<<"${efi_disks_list}"; then
 | 
			
		||||
            for uefi_image in "${uefi_images[@]}"; do
 | 
			
		||||
                uefi_image_version="$(basename "${uefi_image%%.EFI}")"
 | 
			
		||||
                uefi_image_inverted="${uefi_image#/efi}"
 | 
			
		||||
                uefi_image_inverted="${uefi_image_inverted//\//\\}"
 | 
			
		||||
                efibootmgr --disk "${efi_drive}" \
 | 
			
		||||
                    --part 1 \
 | 
			
		||||
                    --create \
 | 
			
		||||
                    --label 'ZFSBootMenu '"${uefi_image_version}" \
 | 
			
		||||
                    --loader "${uefi_image_inverted}" &>/dev/null && {
 | 
			
		||||
                        >&3 printf -- '%s\n' \
 | 
			
		||||
                            'EFI boot entry ZFSBootMenu '"${uefi_image_version}"' added.'
 | 
			
		||||
            }
 | 
			
		||||
            done
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
set_new_uefi_boot_entries
 | 
			
		||||
		Reference in New Issue
	
	Block a user