@@ -629,8 +629,9 @@ set_default_kernel() {
629629 set_rw_pool " ${pool} " || return 1
630630 CLEAR_SCREEN=1 load_key " ${fs} "
631631
632- # Strip /boot/ to list only the file
633- kernel=" ${2#/ boot/ } "
632+ # Strip leading /boot/ or / to list only the file
633+ kernel=" ${2#/ } "
634+ kernel=" ${kernel# boot/ } "
634635
635636 # Restore nonspecific default when no kernel specified
636637 if [ -z " $kernel " ]; then
@@ -682,8 +683,7 @@ set_default_env() {
682683
683684find_be_kernels () {
684685 local fs mnt
685- local kernel kernel_base labels version kernel_records
686- local defaults def_kernel def_kernel_file
686+ local kpath kdir kernel kernel_base labels version kernel_records
687687
688688 fs=" ${1} "
689689 if [ -z " ${fs} " ]; then
@@ -698,76 +698,71 @@ find_be_kernels() {
698698 return 1
699699 fi
700700
701- # Check if /boot even exists in the environment
702- if [ ! -d " ${mnt} /boot" ]; then
703- zdebug " ${mnt} /boot not present"
704- umount " ${mnt} "
705- return 1
706- fi
707-
708701 # Make sure the kernel list starts fresh
709- kernel_records=" ${mnt/ mnt / kernels} "
702+ kernel_records=" ${mnt%/* } /kernels"
710703 : > " ${kernel_records} "
711704
712- # shellcheck disable=SC2012,2086
713- for kernel in $( ls \
714- ${mnt} /boot/{{vm,}linu{x,z},kernel}{,-* } 2> /dev/null | sort -V ) ; do
715- # Pull basename and validate
716- kernel=" ${kernel##*/ } "
717- [ -e " ${mnt} /boot/${kernel} " ] || continue
718- zdebug " found ${mnt} /boot/${kernel} "
705+ # Look for kernels in / and /boot, sorted in version order
706+ while read -r kpath; do
707+ # Strip mount point from path
708+ kpath=" ${kpath# " ${mnt} " } "
709+ # Ensure kpath has leading slash
710+ kpath=" /${kpath#/ } "
711+ zdebug " found kernel: ${mnt}${kpath} "
712+
713+ # Extract base name and kernel directory
714+ kernel=" ${kpath##*/ } "
715+ kdir=" ${kpath% " ${kernel} " } "
716+ # Trim trailing slash (note: kdir will be empty if kernel is at root)
717+ kdir=" ${kdir%/ } "
718+ zdebug " kernel directory: '${kdir} ', file: '${kernel} '"
719719
720720 # Kernel "base" extends to first hyphen
721721 kernel_base=" ${kernel%% -* } "
722+
722723 # Kernel "version" is everything after base and may be empty
723724 version=" ${kernel# " ${kernel_base} " } "
724725 version=" ${version# -} "
725- zdebug " kernel version: ${version} "
726+ zdebug " kernel base: ' ${kernel_base} ', version: ' ${version} ' "
726727
727728 # initramfs images can take many forms, look for a sensible one
728729 labels=( " $kernel " )
729730 if [ -n " $version " ]; then
730731 labels+=( " $version " )
731732 fi
732733
733- local ext pfx lbl i
734734 # Use a mess of loops instead better brace expansions to control priorities
735+ local ext pfx lbl i ipath
735736 for ext in {.img," " }{" " ,.{gz,bz2,xz,lzma,lz4,lzo,zstd}}; do
736737 for pfx in initramfs initrd; do
737738 for lbl in " ${labels[@]} " ; do
738739 for i in " ${pfx} -${lbl}${ext} " " ${pfx}${ext} -${lbl} " ; do
739- if [ -e " ${mnt} /boot/ ${i} " ] ; then
740- zdebug " matching ${i} to ${kernel} "
741- echo " ${fs} /boot/ ${kernel} /boot/ ${i} " >> " ${kernel_records} "
742- break 4
743- fi
740+ ipath= " ${kdir} / ${i} "
741+ [ -e " ${mnt}${ipath} " ] || continue
742+ zdebug " matching ' ${i} ' to ' ${kernel} ' "
743+ echo " ${fs} ${kpath} ${ipath} " >> " ${kernel_records} "
744+ break 4
744745 done
745746 done
746747 done
747748 done
748- done
749+
750+ done <<< " $(
751+ for k in " ${mnt} /boot" /{{vm,}linu{x,z},kernel}{,-*}; do
752+ [ -e " ${k} " ] && echo " ${k} "
753+ done | sort -V
754+ )"
749755
750756 # No further need for the mount
751757 umount " ${mnt} "
752758
753- defaults=" $( select_kernel " ${fs} " ) "
754-
755- # shellcheck disable=SC2034
756- IFS=' ' read -r def_fs def_kernel def_initramfs <<< " ${defaults}"
759+ # Search was successful if at least one kernel can be selected
760+ [ -s " ${kernel_records} " ] && select_kernel " ${fs} " > /dev/null && return 0
757761
758- def_kernel_file=" ${mnt/ mnt/ default_kernel} "
759-
760- # If no default kernel is found, there are no kernels; leave the BE
761- # directory in the same state it would be in had no /boot existed
762- if [ -z " ${def_kernel} " ]; then
763- zdebug " no default kernel found for ${fs} "
764- rm -f " ${kernel_records} " " ${def_kernel_file} "
765- return 1
766- fi
767-
768- zdebug " default kernel set to ${def_kernel} "
769- echo " ${def_kernel##*/ } " > " ${def_kernel_file} "
770- return 0
762+ # Remove an invalid kernel record if the search failed
763+ zerror " failed to find kernels on ${fs} "
764+ rm -f " ${kernel_records} "
765+ return 1
771766}
772767
773768# arg1: ZFS filesystem
@@ -786,8 +781,8 @@ select_kernel() {
786781
787782 kernel_list=" $( be_location " ${zfsbe} " ) /kernels"
788783
789- if [ ! -f " ${kernel_list} " ]; then
790- zerror " kernel list '${kernel_list} ' missing"
784+ if [ ! -s " ${kernel_list} " ]; then
785+ zerror " kernel list '${kernel_list} ' missing or empty "
791786 return 1
792787 fi
793788
@@ -804,9 +799,13 @@ select_kernel() {
804799 if [[ " ${kernel} " =~ ${specific_kernel} ]]; then
805800 zdebug " matched ${kernel} to ${specific_kernel} "
806801 kexec_args=" ${spec_kexec_args} "
807- break
808802 fi
809- done <<< " $( tac " ${kernel_list} " )"
803+ done < " ${kernel_list} "
804+ fi
805+
806+ if [ -z " ${kexec_args} " ]; then
807+ zerror " failed to identify kexec arguments for ${fs} "
808+ return 1
810809 fi
811810
812811 zdebug " using kexec args: ${kexec_args} "
0 commit comments