diff options
Diffstat (limited to 'os/etc/kernel/efi.sh')
| -rwxr-xr-x | os/etc/kernel/efi.sh | 186 |
1 files changed, 88 insertions, 98 deletions
diff --git a/os/etc/kernel/efi.sh b/os/etc/kernel/efi.sh index b1d5e05..d23e317 100755 --- a/os/etc/kernel/efi.sh +++ b/os/etc/kernel/efi.sh @@ -27,9 +27,6 @@ path_from_efi() { path_to_efi() { sed -e "s,${EFI_PARTITION},," -e 's,/,\\,g' } -path_to_boot() { - sed -e "s,${EFI_PARTITION}${EFI_DIR},/boot," -} hashsum() { sha1sum | cut -d' ' -f1 } @@ -78,7 +75,7 @@ create_efi() ( bootorder=$(jq -r '.bootorder' <<<"$ln") label=$(jq -r '.label' <<<"$ln") args=$(jq -r '.args' <<<"$ln") - disk=$(findmnt -no SOURCE --target "$(path_from_efi <<<"$loader")") + disk=$(findmnt -no SOURCE --target "$(path_from_efi <<<"$loader")" || echo none) part=$(sed -e 's,^.*p\([0-9]\)$,\1,' <<<"$disk") disk=${disk//p${part}/} @@ -105,17 +102,23 @@ deactivate_efi() ( parse_kernels() ( local kernel_dir=${1:-/boot} - # test -n "$kernel_dir" || eerror "need kernel directory argument" + test -d "$kernel_dir" || eerror "kernel_dir should be a directory" local current_kernel current_hash - current_kernel=$(parse_efi | jq -rc '.[]|select(.current == false)|.loader' | path_from_efi) + current_kernel=$(parse_efi | jq -rc '.[] | select(.current==true) | .loader' | path_from_efi) current_hash=$(hashsum <"$current_kernel") find "$kernel_dir" -maxdepth 1 -type f -name 'vmlinuz*' -print | while read -r ln; do - local file mtime ver ext hash + local file mtime ver ext hash aux="[]" file=$ln + aux=$(jq -nc \ + --arg img "$(kernel_to_initramfs "$file")" \ + --arg sys "$(kernel_to_aux "$file" System.map)" \ + --arg con "$(kernel_to_aux "$file" config)" \ + '[$img,$sys]') + hash=$(hashsum <"$file") mtime=$(stat -c '%Y' "$file") ln=$(sed -e "s,^${kernel_dir}/\([^-]*\)-\([0-9]*\.[0-9]*\.[0-9]*[^\.]*\)\(.*\)\$,\1\t\2\t\3," <<<"$ln") @@ -128,20 +131,31 @@ parse_kernels() ( --arg version "$ver" \ --argjson mtime "$mtime" \ --arg hash "$hash" \ - '{file:$file,old:$old,version:$version,mtime:$mtime,hash:$hash,current:$current}' + --argjson aux "$aux" \ + '{file:$file,old:$old,version:$version,mtime:$mtime,hash:$hash,current:$current,aux:$aux}' done | jq -s 'sort_by(.mtime)|reverse' ) -kernel_to_initramfs() { - local file - - file=$(dirname "$1")/$(basename "$1" | sed -e 's,^vmlinuz,initramfs,') - if grep -Eq '\.efi$' <<<"$file"; then - sed -e 's,\.efi$,.img,' <<<"$file" - else - sed -e 's,$,.img,' <<<"$file" +kernel_to_aux() { + local kernel=$1 aux_name=$2 aux_ext=$3 + + aux=$(dirname "$kernel")/$(basename "$kernel" | sed -e "s,^vmlinuz,${aux_name},") + if [ -n "$aux_ext" ]; then + if grep -Eq '\.efi$' <<<"$aux"; then + aux=$(sed -e "s,\.efi$,.${aux_ext}," <<<"$aux") + elif grep -Eq '\.old$' <<<"$aux"; then + aux=$(sed -e "s,\.old$,.${aux_ext}.old," <<<"$aux") + else + aux=$(sed -e "s,$,.${aux_ext}," <<<"$aux") + fi fi + # echo "+" "$kernel" "->" "$aux" >&2 + echo "$aux" +} + +kernel_to_initramfs() { + kernel_to_aux "$1" initramfs img } install_kernel() { @@ -155,23 +169,25 @@ install_kernel() { } remove_kernel() { - local file=$1 initramfs - initramfs=$(kernel_to_initramfs "$file") - - _ rm -vf "$file" >&2 - _ rm -vf "$initramfs" >&2 - - # _ rm -vf "$(path_to_boot <<<"$file")" >&2 - # _ rm -vf "$(path_to_boot <<<"$file").old" >&2 - # - # _ rm -vf "$(path_to_boot <<<"$initramfs")" >&2 - # _ rm -vf "$(path_to_boot <<<"$initramfs").old" >&2 - # - # _ rm -vf "$(path_to_boot <<<"$file" | sed -e 's,vmlinuz,System.map,')" >&2 - # _ rm -vf "$(path_to_boot <<<"$file" | sed -e 's,vmlinuz,System.map,').old" >&2 - # - # _ rm -vf "$(path_to_boot <<<"$file" | sed -e 's,vmlinuz,config,')" >&2 - # _ rm -vf "$(path_to_boot <<<"$file" | sed -e 's,vmlinuz,config,').old" >&2 + local kernel_version=$1 file + + kernel_entries=$(parse_kernels | jq -cr --arg version "$kernel_version" '.[] | select(.version==$version)') + for kernel in "$kernel_entries"; do + file="$(jq -r '.file' <<<"$kernel")" + test -f "$file" && _ rm -vf "$file" >&2 + + efi_kernel=${EFI_PARTITION}${EFI_DIR}/$(basename "$file").efi + test -f "$efi_kernel" && _ rm -vf "$efi_kernel" >&2 + + for file in $(jq -cr '.aux[]' <<<"$kernel"); do + test -f "$file" && _ rm -vf "$file" >&2 + + if [[ "$file" = *initramfs* ]]; then + efi_initramfs=${EFI_PARTITION}${EFI_DIR}/$(basename "$file") + test -f "$efi_initramfs" && _ rm -vf "$efi_initramfs" >&2 + fi + done + done } # $1 : new kernel version, e.g. 6.1.27-gentoo-dist @@ -188,60 +204,18 @@ new_kernel() { efi_kernel=${EFI_PARTITION}${EFI_DIR}/$(basename "$kernel").efi efi_entries=$(parse_efi | jq -rc) - efi_entries_dup=$(jq -rc --arg version "$version" '.[]|select(.version==$version)|{entry:.entry,loader:.loader}' <<<"$efi_entries") - ebegin "Remove duplicate kernel and boot entry with version $version" - for efi in $efi_entries_dup; do - delete_efi "$(jq -rc '.entry' <<<"$efi")" - remove_kernel "$(jq -rc '.loader' <<<"$efi" | path_from_efi)" + ebegin "Remove old and duplicate boot entries" + # efi entries that are NOT the current version + efi_entries_old=$(jq -rc '. as $in | .[] | select(.current) | .version as $current | $in | map(select(.version!=$current))[] | {entry,version}' <<<"$efi_entries") + for efi_entry in $efi_entries_old; do + delete_efi "$(jq -rc '.entry' <<<"$efi_entry")" + remove_kernel "$(jq -rc '.version' <<<"$efi_entry")" done - eend - - # ebegin "Create fallback boot entry" - # local bootcurrent_entry bootcurrent - # bootcurrent_entry=$(efibootmgr -u | grep '^BootCurrent' | sed -e 's,BootCurrent: ,,') - # bootcurrent=$(jq -rc --arg current "$bootcurrent_entry" '.[]|select(.entry == $current)' <<<"$efi_entries") - # if [ -f "$(jq -r '.loader' <<<"$bootcurrent" | path_from_efi)" ]; then - # if [ "$efi_kernel" = "$(jq -r '.loader' <<<"$bootcurrent" | path_from_efi)" ]; then - # efibootmgr -u --bootnum "$bootcurrent_entry" --delete-bootnum - # - # local bootcurrent_kernel bootcurrent_initramfs - # bootcurrent_kernel=$(jq -rc '.loader' <<<"$bootcurrent" | path_from_efi) - # bootcurrent_initramfs=$(dirname "$bootcurrent_kernel")/$(basename "$bootcurrent_kernel" | sed -e 's,^vmlinuz,initramfs,' -e 's,efi$,img,') - # mv -v "$bootcurrent_kernel" "$bootcurrent_kernel.old" >&2 - # mv -v "$bootcurrent_initramfs" "$bootcurrent_initramfs.old" >&2 - # - # jq -cnS \ - # --arg loader "$(path_to_efi <<<"$bootcurrent_kernel")" \ - # --argjson bootorder 1 \ - # --arg label "Gentoo Linux (old)" \ - # --arg args "initrd=$(path_to_efi <<<"$bootcurrent_initramfs")" \ - # '[{label:$label,loader:$loader,args:$args,bootorder:$bootorder}]' | - # create_efi - # else - # eerror "can't demote boot entry" - # exit 2 - # #efibootmgr -u --bootnum "$bootcurrent_entry" --index 2 - # fi - # else - # local oldkernel - # oldkernel=$(parse_kernels "/boot" | jq -rc '[.[]|select(.current != true)]|first|.file') - # efi_oldkernel=$(install_kernel "$oldkernel") - # jq -cnS \ - # --arg loader "$(path_to_efi <<<"$efi_oldkernel")" \ - # --argjson bootorder 1 \ - # --arg label "Gentoo Linux (old)" \ - # --arg args "initrd=$(kernel_to_initramfs "$efi_oldkernel" | path_to_efi)" \ - # '[{label:$label,loader:$loader,args:$args,bootorder:$bootorder}]' | - # create_efi - # fi - # eend + eend $? ebegin "Install new kernel" efi_kernel=$(install_kernel "$kernel") - if [ ! -e "$efi_kernel" ]; then - eerror "Installing kernel to $efi_kernel failed!" - fi - eend + eend $? ebegin "Create new boot entry (debug)" jq -cnS \ @@ -250,7 +224,7 @@ new_kernel() { --arg args "initrd=$(kernel_to_initramfs "$efi_kernel" | path_to_efi) rd.cmdline=ask" \ '[{label:$label,loader:$loader,args:$args}]' | create_efi - eend + eend $? ebegin "Create new boot entry (default)" jq -cnS \ @@ -259,7 +233,18 @@ new_kernel() { --arg args "initrd=$(kernel_to_initramfs "$efi_kernel" | path_to_efi)" \ '[{label:$label,loader:$loader,args:$args}]' | create_efi - eend + eend $? + + # refresh efi+kernel entries + efi_entries=$(parse_efi | jq -rc) + kernel_entries=$(parse_kernels | jq -rc) + + ebegin "Remove unreferenced kernels" + kernel_entries_unref=$(jq -rc --argjson efi "$efi_entries" '. as $kernels | $efi | map(.version) as $refs | $kernels | map(select(. as $this | ($refs|contains([($this|.version)])|not) )) | .[].version' <<<"$kernel_entries") + for kernel_version in $kernel_entries_unref; do + remove_kernel "$kernel_version" + done + eend $? } # check for cli usage @@ -291,14 +276,21 @@ fi # always mount efivarfs first mount_efi -# run list -if [ -n "$list" ]; then - [ -n "$efi" ] && parse_efi | - jq '[.[] | {boot:([(if .current then "*" else " " end), .entry]|join("")),label:.label}]' | +list_efi() { + parse_efi | + jq 'map({A:(if .current then "*" else " " end),boot:.bootorder,entry,label})' | /home/robert/bin/jq-table - [ -n "$kernel" ] && parse_kernels | - jq '[.[] | {hash:([(if .current then "*" else " " end), .hash[:6]]|join("")),version:.version}]' | +} +list_kernels() { + parse_kernels | + jq 'map({A:(if .current then "*" else " " end),hash:(.hash[:6]),version,O:(if .old then "*" else " " end)})|sort_by(.version)' | /home/robert/bin/jq-table +} + +# run list +if [ -n "$list" ]; then + [ -n "$efi" ] && list_efi + [ -n "$kernel" ] && list_kernels exit $? fi @@ -312,19 +304,15 @@ fi if [ -n "$interactive" ]; then export BEMENU_BACKEND=curses - entry=$(parse_efi | - jq '[.[] | {boot:([(if .current then "*" else " " end), .entry]|join("")),label:.label}]' | - /home/robert/bin/jq-table | - tail -n+2 | + entry=$(list_efi | tail -n+2 | bemenu -p ' efi: select boot entry ' | - cut -c2-) + cut -c5- | + sed -e 's,^\s*,,') [ -z "$entry" ] && exit bootnum=$(cut -d' ' -f1 <<<"$entry") [ -z "$bootnum" ] && exit - echo ">>> $(cut -d' ' -f2 <<<"$entry")" - action=$(cat <<-EOF | bemenu -p " efi: $(cut -d' ' -f2 <<<"$entry") " delete activate @@ -334,6 +322,8 @@ EOF ) [ -z "$action" ] && exit + echo ">>>" "$action" + case "$action" in delete) delete_efi "$bootnum" ;; activate) activate_efi "$bootnum" ;; |