TommyTran732 / Arch-Setup-Script

Setting up Arch Linux with BTRFS, snapshots and full disk encryption including /boot (UEFI only)
Apache License 2.0
43 stars 35 forks source link

`GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol}"` ? #31

Closed averyfreeman closed 2 months ago

averyfreeman commented 2 months ago

Hi, love the script. Big fan of OpenSUSE's snapper layout, have never tried adapting it to Arch before - have only ever used sd-boot on Arch.

Wondering what you think of the difference between the way you've handled deleting these lines in /etc/grub.d/{10_linux,20_linux_zen}:

# $ grep rootflags /etc/grub.d/10_linux
        GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"

And the way MicroOS's version of 10_linux (this is a diff):

    rootsubvol="`make_system_path_relative_to_its_root /`"
    rootsubvol="${rootsubvol#/}"
-   if [ "x${rootsubvol}" != x ]; then
+   if [ "x${rootsubvol}" != x ] && [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" != "xtrue" ]; then
        GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
+       rel_dirname="\${btrfs_subvol}$dirname"

Just to be clear, the removal you suggest should result in this, correct?:

case x"$GRUB_FS" in
    xbtrfs)
    rootsubvol="`make_system_path_relative_to_its_root /`"
    rootsubvol="${rootsubvol#/}"
    if [ "x${rootsubvol}" != x ]; then
        GRUB_CMDLINE_LINUX="${GRUB_CMDLINE_LINUX}"
    fi;;
    xzfs)
    rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true`
    bootfs="`make_system_path_relative_to_its_root / | sed -e "s,@$,,"`"
    LINUX_ROOT_DEVICE="ZFS=${rpool}${bootfs%/}"
    ;;
esac

That full switch statement on MicroOS is this:

case x"$GRUB_FS" in
    xbtrfs)
    if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ]; then
    GRUB_CMDLINE_LINUX="${GRUB_CMDLINE_LINUX} \${extra_cmdline}"
    else
    rootsubvol="`make_system_path_relative_to_its_root /`"
    rootsubvol="${rootsubvol#/}"
    if [ "x${rootsubvol}" != x ] && [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" != "xtrue" ]; then
        GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
    fi
    fi;;
    xzfs)
    rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true`
    bootfs="`make_system_path_relative_to_its_root / | sed -e "s,@$,,"`"
    LINUX_ROOT_DEVICE="ZFS=${rpool}${bootfs%/}"
    ;;
esac

Here's a full diff between the two:

--- 10_linux_arch_default   2024-06-27 10:30:50.309648690 -0700
+++ 10_linux_opensuse_microos   2024-06-27 10:28:56.372645865 -0700
@@ -23,15 +23,15 @@

 . "$pkgdatadir/grub-mkconfig_lib"

-export TEXTDOMAIN=grub
+export TEXTDOMAIN=grub2
 export TEXTDOMAINDIR="${datarootdir}/locale"

 CLASS="--class gnu-linux --class gnu --class os"

 if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
-  OS=Linux
+  OS=GNU/Linux
 else
-  OS="${GRUB_DISTRIBUTOR} Linux"
+  OS="${GRUB_DISTRIBUTOR}"
   CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}"
 fi

@@ -54,23 +54,33 @@
 if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] && [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] ) \
     || ( [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
    && [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ] ) \
-    || ( ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
-   && ! test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ) \
     || ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then
   LINUX_ROOT_DEVICE=${GRUB_DEVICE}
 elif [ "x${GRUB_DEVICE_UUID}" = "x" ] \
     || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ]; then
+  test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ||
+    echo "WARN: Use PARTUUID=${GRUB_DEVICE_PARTUUID} despite missing by-partuuid symlink" >&2
   LINUX_ROOT_DEVICE=PARTUUID=${GRUB_DEVICE_PARTUUID}
 else
+  test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ||
+    echo "WARN: Use UUID=${GRUB_DEVICE_UUID} despite missing by-uuid symlink" >&2
   LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
 fi

+if [ "x$GRUB_CONMODE" != "x" ]; then
+  GRUB_CMDLINE_LINUX="conmode=${GRUB_CONMODE} ${GRUB_CMDLINE_LINUX}"
+fi
+
 case x"$GRUB_FS" in
     xbtrfs)
+   if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ]; then
+   GRUB_CMDLINE_LINUX="${GRUB_CMDLINE_LINUX} \${extra_cmdline}"
+   else
    rootsubvol="`make_system_path_relative_to_its_root /`"
    rootsubvol="${rootsubvol#/}"
-   if [ "x${rootsubvol}" != x ]; then
+   if [ "x${rootsubvol}" != x ] && [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" != "xtrue" ]; then
        GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
+   fi
    fi;;
     xzfs)
    rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true`
@@ -79,8 +89,237 @@
    ;;
 esac

+if [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" = "xtrue" ]; then
+  LINUX_ROOT_DEVICE=""
+fi
+
+populate_header_warn()
+{
+  bls_parser="blscfg command"
+cat <<EOF
+
+# This section was generated by a script. Do not modify the generated file - all changes
+# will be lost the next time file is regenerated. Instead edit the BootLoaderSpec files.
+#
+# The $bls_parser parses the BootLoaderSpec files stored in /boot/loader/entries and
+# populates the boot menu. Please refer to the Boot Loader Specification documentation
+# for the files format: https://systemd.io/BOOT_LOADER_SPECIFICATION/.
+
+EOF
+}
+
+read_config()
+{
+    config_file=${1}
+    title=""
+    initrd=""
+    options=""
+    linux=""
+    grub_arg=""
+
+    while read -r line
+    do
+        record=$(echo ${line} | cut -f 1 -d ' ')
+        value=$(echo ${line} | cut -s -f2- -d ' ')
+        case "${record}" in
+            "title")
+                title=${value}
+                ;;
+            "initrd")
+                initrd=${value}
+                ;;
+            "linux")
+                linux=${value}
+                ;;
+            "options")
+                options=${value}
+                ;;
+            "grub_arg")
+                grub_arg=${value}
+                ;;
+        esac
+    done < ${config_file}
+}
+
+blsdir="/boot/loader/entries"
+
+get_sorted_bls()
+{
+    if ! [ -d "${blsdir}" ] || [ -f /run/ostree-booted ] || [ -d /ostree/repo ]; then
+        return
+    fi
+
+    local IFS=$'\n'
+
+    files=($(for bls in ${blsdir}/*.conf; do
+        if ! [[ -e "${bls}" ]] ; then
+            continue
+        fi
+        bls="${bls%.conf}"
+        bls="${bls##*/}"
+        echo "${bls}"
+    done | ${kernel_sort} 2>/dev/null | tac)) || :
+
+    echo "${files[@]}"
+}
+
+update_bls_cmdline()
+{
+    local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+    local -a files=($(get_sorted_bls))
+
+    for bls in "${files[@]}"; do
+        local options="${cmdline}"
+        if [ -z "${bls##*debug*}" ]; then
+            options="${options} ${GRUB_CMDLINE_LINUX_DEBUG}"
+        fi
+        options="$(echo "${options}" | sed -e 's/\//\\\//g')"
+        sed -i -e "s/^options.*/options ${options}/" "${blsdir}/${bls}.conf"
+    done
+}
+
+populate_menu()
+{
+    local -a files=($(get_sorted_bls))
+
+    gettext_printf "Generating boot entries from BLS files...\n" >&2
+
+    for bls in "${files[@]}"; do
+        read_config "${blsdir}/${bls}.conf"
+
+        menu="${menu}menuentry '${title}' ${grub_arg} --id=${bls} {\n"
+        menu="${menu}\t linux ${linux} ${options}\n"
+        if [ -n "${initrd}" ] ; then
+            menu="${menu}\t initrd ${boot_prefix}${initrd}\n"
+        fi
+        menu="${menu}}\n\n"
+    done
+    # The printf command seems to be more reliable across shells for special character (\n, \t) evaluation
+    printf "$menu"
+}
+
+
+if [ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]; then
+  if [ x$dirname = x/ ]; then
+    if [ -z "${prepare_root_cache}" ]; then
+      prepare_grub_to_access_device ${GRUB_DEVICE}
+    fi
+  else
+    if [ -z "${prepare_boot_cache}" ]; then
+      prepare_grub_to_access_device ${GRUB_DEVICE_BOOT}
+    fi
+  fi
+
+  if [ -d /sys/firmware/efi ]; then
+      bootefi_device="`${grub_probe} --target=device /boot/efi/`"
+      prepare_grub_to_access_device_with_variable boot ${bootefi_device}
+  else
+      boot_device="`${grub_probe} --target=device /boot/`"
+      prepare_grub_to_access_device_with_variable boot ${boot_device}
+  fi
+
+  arch="$(uname -m)"
+  if [ "x${arch}" = "xppc64le" ] && [ -d /sys/firmware/opal ]; then
+
+      BLS_POPULATE_MENU="true"
+      petitboot_path="/sys/firmware/devicetree/base/ibm,firmware-versions/petitboot"
+
+      if test -e ${petitboot_path}; then
+          read -r -d '' petitboot_version < ${petitboot_path}
+          petitboot_version="$(echo ${petitboot_version//v})"
+
+     if test -n ${petitboot_version}; then
+              major_version="$(echo ${petitboot_version} | cut -d . -f1)"
+              minor_version="$(echo ${petitboot_version} | cut -d . -f2)"
+
+              re='^[0-9]+$'
+              if [[ $major_version =~ $re ]] && [[ $minor_version =~ $re ]] &&
+                 ([[ ${major_version} -gt 1 ]] ||
+                  [[ ${major_version} -eq 1 &&
+                     ${minor_version} -ge 8  ]]); then
+                  BLS_POPULATE_MENU="false"
+              fi
+          fi
+      fi
+  fi
+
+  populate_header_warn
+
+      cat << EOF
+
+insmod blscfg
+blscfg
+EOF
+
+  if [ "x${GRUB_GRUBENV_UPDATE}" = "xyes" ]; then
+      blsdir="/boot/loader/entries"
+      [ -d "${blsdir}" ] && GRUB_BLS_FS="$(${grub_probe} --target=fs ${blsdir})"
+      if [ "x${GRUB_BLS_FS}" = "xbtrfs" ] || [ "x${GRUB_BLS_FS}" = "xzfs" ]; then
+          blsdir=$(make_system_path_relative_to_its_root "${blsdir}")
+          if [ "x${blsdir}" != "x/loader/entries" ] && [ "x${blsdir}" != "x/boot/loader/entries" ]; then
+              ${grub_editenv} - set blsdir="${blsdir}"
+          fi
+      fi
+
+      if [ -n "${GRUB_EARLY_INITRD_LINUX_CUSTOM}" ]; then
+          ${grub_editenv} - set early_initrd="${GRUB_EARLY_INITRD_LINUX_CUSTOM}"
+      fi
+
+      if [ -n "${GRUB_DEFAULT_DTB}" ]; then
+          ${grub_editenv} - set devicetree="${GRUB_DEFAULT_DTB}"
+      fi
+
+      if [ -n "${GRUB_SAVEDEFAULT}" ]; then
+           ${grub_editenv} - set save_default="${GRUB_SAVEDEFAULT}"
+      fi
+  fi
+
+  exit 0
+fi
+
+mktitle ()
+{
+  local title_type
+  local version
+  local OS_NAME
+  local OS_VERS
+
+  title_type=$1 && shift
+  version=$1 && shift
+
+  OS_NAME="$(eval $(grep ^NAME= /etc/os-release) ; echo ${NAME})"
+  OS_VERS="$(eval $(grep ^VERSION= /etc/os-release) ; echo ${VERSION})"
+
+  case $title_type in
+    recovery)
+      title=$(printf '%s (%s) %s (recovery mode)' \
+                     "${OS_NAME}" "${version}" "${OS_VERS}")
+      ;;
+    *)
+      title=$(printf '%s (%s) %s' \
+                     "${OS_NAME}" "${version}" "${OS_VERS}")
+      ;;
+  esac
+  echo -n ${title}
+}
+
 title_correction_code=

+hotkey=1
+incr_hotkey()
+{
+  [ -z "$hotkey" ] && return
+  expr $hotkey + 1
+}
+print_hotkey()
+{
+  keys="123456789abdfgijklmnoprtuvwyz"
+  if [ -z "$hotkey" ]||[ $hotkey -eq 0 ]||[ $hotkey -gt 30 ]; then
+    return
+  fi
+  echo "--hotkey=$(expr substr $keys $hotkey 1)"
+}
+
 linux_entry ()
 {
   os="$1"
@@ -88,15 +327,18 @@
   type="$3"
   args="$4"

+  if [ -n "${linux_root_device_thisversion}" ]; then
+    root_device="root=${linux_root_device_thisversion}"
+  else
+    root_device=""
+  fi
+
   if [ -z "$boot_device_id" ]; then
       boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
   fi
+
   if [ x$type != xsimple ] ; then
       case $type in
-     booster)
-         title="$(gettext_printf "%s, with Linux %s (booster initramfs)" "${os}" "${version}")" ;;
-     fallback)
-         title="$(gettext_printf "%s, with Linux %s (fallback initramfs)" "${os}" "${version}")" ;;
      recovery)
          title="$(gettext_printf "%s, with Linux %s (recovery mode)" "${os}" "${version}")" ;;
      *)
@@ -108,9 +350,11 @@
      title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
      grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")"
       fi
-      echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+      echo "menuentry '$(echo "$title" | grub_quote)' $(print_hotkey) ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+      hotkey=$(incr_hotkey)
   else
-      echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+      echo "menuentry '$(echo "$os" | grub_quote)' $(print_hotkey) ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+      hotkey=$(incr_hotkey)
   fi      
   if [ x$type != xrecovery ] ; then
       save_default_entry | grub_add_tab
@@ -120,7 +364,7 @@
   # FIXME: We need an interface to select vesafb in case efifb can't be used.
   if [ "x$GRUB_GFXPAYLOAD_LINUX" = x ]; then
       echo "   load_video" | sed "s/^/$submenu_indentation/"
-      if grep -qx "CONFIG_FB_EFI=y" "${config}" 2> /dev/null \
+      if grep -qx "CONFIG_\(FB_EFI\|SYSFB_SIMPLEFB\)=y" "${config}" 2> /dev/null \
      && grep -qx "CONFIG_VT_HW_CONSOLE_BINDING=y" "${config}" 2> /dev/null; then
      echo "    set gfxpayload=keep" | sed "s/^/$submenu_indentation/"
       fi
@@ -133,6 +377,7 @@

   echo "   insmod gzio" | sed "s/^/$submenu_indentation/"

+ if [ $PLATFORM != emu ]; then # 'search' does not work for now
   if [ x$dirname = x/ ]; then
     if [ -z "${prepare_root_cache}" ]; then
       prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | grub_add_tab)"
@@ -144,10 +389,11 @@
     fi
     printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
   fi
+ fi
   message="$(gettext_printf "Loading Linux %s ..." ${version})"
   sed "s/^/$submenu_indentation/" << EOF
    echo    '$(echo "$message" | grub_quote)'
-   linux   ${rel_dirname}/${basename} root=${linux_root_device_thisversion} rw ${args}
+   linux   ${rel_dirname}/${basename} ${root_device} ${args}
 EOF
   if test -n "${initrd}" ; then
     # TRANSLATORS: ramdisk isn't identifier. Should be translated.
@@ -168,17 +414,18 @@

 machine=`uname -m`
 case "x$machine" in
-    xi?86 | xx86_64)
-   list=
-   for i in /boot/vmlinuz-* /vmlinuz-* /boot/kernel-* ; do
-       if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
-   done ;;
-    *) 
-   list=
-   for i in /boot/vmlinuz-* /boot/vmlinux-* /vmlinuz-* /vmlinux-* /boot/kernel-* ; do
-                  if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
-   done ;;
+    xi?86 | xx86_64) klist="/boot/vmlinuz-* /vmlinuz-* /boot/kernel-*" ;;
+    xaarch64) klist="/boot/Image-* /Image-* /boot/kernel-*" ;;
+    xarm*) klist="/boot/zImage-* /zImage-* /boot/kernel-*" ;;
+    xriscv64) klist="/boot/Image-* /Image-* /boot/kernel-*" ;;
+    xs390 | xs390x)  klist="/boot/image-* /boot/kernel-*" ;;
+    *) klist="/boot/vmlinuz-* /boot/vmlinux-* /vmlinuz-* /vmlinux-* \
+       /boot/kernel-*" ;;
 esac
+list=
+for i in $klist ; do
+    if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
+done

 case "$machine" in
     i?86) GENKERNEL_ARCH="x86" ;;
@@ -188,6 +435,15 @@
     *) GENKERNEL_ARCH="$machine" ;;
 esac

+PLATFORM="native"
+if [ -d /sys/firmware/efi ]&&[ "x${GRUB_USE_LINUXEFI}" = "xtrue" ]; then
+    PLATFORM="efi"
+else
+    case "$machine" in
+        s390*) PLATFORM="emu" ;;
+    esac
+fi
+
 prepare_boot_cache=
 prepare_root_cache=
 boot_device_id=
@@ -197,12 +453,56 @@
 # yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
 submenu_indentation=""

+listvrf=""
+pre_sort () {
+    local l=""
+
+    for f in $list; do
+        vr="`echo $f | sed -e 's/[^-]*-//' -e 's/-\([^0-9]*\)$/\.\1/' -e 's/-/~/g' -e 's/~\([^~]*\)$/-\1/'`"
+        l="$l $vr"
+        listvrf="$listvrf $vr:$f"
+    done
+
+    list=$l
+}
+
+post_sort () {
+    local l=""
+    local vr=""
+    local f=""
+    local found=""
+
+    for i in $reverse_sorted_list; do
+        found=""
+        for vrf in $listvrf; do
+            vr=${vrf%%:*}
+            f=${vrf#*:}
+       if test x"$vr" = x"$i"; then
+           l="$l $f"
+           found=$vrf
+           break
+       fi
+        done
+        if test -n "$found"; then
+            listvrf="`echo $listvrf | (sed -e 's!'$found'!!' 2>/dev/null || echo $listvrf)`"
+        fi
+    done
+
+    for vrf in $listvrf; do
+        f=${vrf#*:}
+        l="$l $f"
+    done
+
+    reverse_sorted_list=$l
+}
+pre_sort
 # Perform a reverse version sort on the entire list.
 # Temporarily replace the '.old' suffix by ' 1' and append ' 2' for all
 # other files to order the '.old' files after their non-old counterpart
 # in reverse-sorted order.

 reverse_sorted_list=$(echo $list | tr ' ' '\n' | sed -e 's/\.old$/ 1/; / 1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/ 2$//')
+post_sort

 if [ "x$GRUB_TOP_LEVEL" != x ]; then
   reverse_sorted_list=$(grub_move_to_front "$GRUB_TOP_LEVEL" ${reverse_sorted_list})
@@ -211,10 +511,21 @@
 is_top_level=true
 for linux in ${reverse_sorted_list}; do
   gettext_printf "Found linux image: %s\n" "$linux" >&2
+
   basename=`basename $linux`
   dirname=`dirname $linux`
   rel_dirname=`make_system_path_relative_to_its_root $dirname`
-  version=`echo $basename | sed -e "s,vmlinuz-,,g"`
+  if [ $PLATFORM != "emu" ]; then
+    hotkey=0
+  else
+    if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ] &&
+       [ "x${GRUB_FS}" = "xbtrfs" ] ; then
+       rel_dirname="\${btrfs_subvol}$dirname"
+    else
+       rel_dirname="$dirname"
+    fi
+  fi
+  version=`echo $basename | sed -e "s,^[^0-9]*-,,g"`
   alt_version=`echo $version | sed -e "s,\.old$,,g"`
   linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"

@@ -251,17 +562,53 @@
     for i in ${initrd}; do
       initrd_display="${initrd_display} ${dirname}/${i}"
     done
-    gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
+    if [ "x${GRUB_ENABLE_BLSCFG}" != "xtrue" ]; then
+      gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
+    fi
   fi

   config=
-  for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
+  for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" "/usr/lib/modules/${version}/config" ; do
     if test -e "${i}" ; then
       config="${i}"
       break
     fi
   done

+  # try to get the kernel config if $linux is a symlink
+  if test -z "${config}" ; then
+    lnk_version=`basename \`readlink -f $linux\` | sed -e "s,^[^0-9]*-,,g"`
+    if (test -n ${lnk_version} && test -e "${dirname}/config-${lnk_version}") ; then
+      config="${dirname}/config-${lnk_version}"
+    fi
+  fi
+
+  # check if we are in xen domU
+  if [ ! -e /proc/xen/xsd_port -a -e /proc/xen ]; then
+    # we're running on xen domU guest
+    dmi=/sys/class/dmi/id
+    if [ -r "${dmi}/product_name" -a -r "${dmi}/sys_vendor" ]; then
+      product_name=`cat ${dmi}/product_name`
+      sys_vendor=`cat ${dmi}/sys_vendor`
+      if test "${sys_vendor}" = "Xen" -a "${product_name}" = "HVM domU"; then
+        # xen HVM guest
+        xen_pv_domU=false
+      fi
+    fi
+  else
+    # we're running on baremetal or xen dom0
+    xen_pv_domU=false
+  fi
+
+  if test "$xen_pv_domU" = "false" ; then
+    # prevent xen kernel without pv_opt support from booting
+    if (grep -qx "CONFIG_XEN=y" "${config}" 2> /dev/null && ! grep -qx "CONFIG_PARAVIRT=y" "${config}" 2> /dev/null); then
+      echo "Skip xenlinux kernel $linux" >&2
+      list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '`
+      continue
+    fi
+  fi
+
   initramfs=
   if test -n "${config}" ; then
       initramfs=`grep CONFIG_INITRAMFS_SOURCE= "${config}" | cut -f2 -d= | tr -d \"`
@@ -297,35 +644,13 @@
    boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
     fi
     # TRANSLATORS: %s is replaced with an OS name
-    echo "submenu '$(gettext_printf "Advanced options for %s" "${OS}" | grub_quote)' \$menuentry_id_option 'gnulinux-advanced-$boot_device_id' {"
+    echo "submenu '$(gettext_printf "Advanced options for %s" "${OS}" | grub_quote)' $(print_hotkey) \$menuentry_id_option 'gnulinux-advanced-$boot_device_id' {"
+    hotkey=$(incr_hotkey)
     is_top_level=false
   fi

   linux_entry "${OS}" "${version}" advanced \
               "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
-
-  if test -e "${dirname}/initramfs-${version}-fallback.img" ; then
-    initrd="${initrd_early} initramfs-${version}-fallback.img"
-
-    if test -n "${initrd}" ; then
-      gettext_printf "Found fallback initrd image(s) in %s:%s\n" "${dirname}" "${initrd_extra} ${initrd}" >&2
-    fi
-
-    linux_entry "${OS}" "${version}" fallback \
-                "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
-  fi
-
-  if test -e "${dirname}/booster-${version}.img" ; then
-    initrd="${initrd_early} booster-${version}.img"
-
-    if test -n "${initrd}" ; then
-      gettext_printf "Found booster initrd image(s) in %s:%s\n" "${dirname}" "${initrd_extra} ${initrd}" >&2
-    fi
-
-    linux_entry "${OS}" "${version}" booster \
-                "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
-  fi
-
   if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
     linux_entry "${OS}" "${version}" recovery \
                 "${GRUB_CMDLINE_LINUX_RECOVERY} ${GRUB_CMDLINE_LINUX}"
TommyTran732 commented 2 months ago

Okay, so here is the current situation:

I hope this clears it up. Feel free to reopen if you have any further questions :)

TommyTran732 commented 2 months ago

@averyfreeman I had a quick look at your fork, so I think I will mention this here:

snap-pac handles making pre and post snapshots with snapper. grub-btrfs generates grub menu entries for the snapshots it detects (pre, post, AND timeline).

snap-pac-grub is unnecessary, if you intend to use this setup. grub-btrfs already does that job for you.

averyfreeman commented 2 months ago

Thanks for getting back to me, I appreciate it - yes, I think I was still confused about what was happening when I threw snap-pac-grub in the mix a few weeks ago (my bad)

In fstab, it looks like snapshot to be mounted as root is identified by x-initrd.mount - is that right?

just a rootflag ... so funny, I've seen that so many times but it just now clicked what it is doing

Could you clear one other big-picture thing up for me, please? (sorry to be so needy)

Why do we have a separate /root during setup? am I correct in thinking this is what becomes snapshot 1?

Do you keep date at 1999 in info.xml purposefully, or was that an issue with string substitution? It's very minor, but I have this working if you want a PR.

TommyTran732 commented 1 month ago

In fstab, it looks like snapshot to be mounted as root is identified by x-initrd.mount - is that right?

No. We just set the default subvolume with btrfs subvolume set-default. Snapper automatically sets the new default subvolumes whenever you do a snapper rollback and what not.

Why do we have a separate /root during setup? am I correct in thinking this is what becomes snapshot 1?

It's the same logic as splitting out /home. We don't want to roll /home back with the rest of the system, do we? Then we don't wanna roll root's home back either.

Do you keep date at 1999 in info.xml purposefully, or was that an issue with string substitution? It's very minor, but I have this working if you want a PR.

Ah I was just being lazy and hardcoded it. I fixed it in https://github.com/TommyTran732/Arch-Setup-Script/commit/a5e2f37b751af7d35ce972bd7eb9a7eb8315ce8b. Thank you though :)

averyfreeman commented 1 month ago

Awesome. Thanks again for getting back to me.