<div>Package: grub-common<br></div><div>Version: 2.02~beta2-22+deb8u1<br></div><div><br></div><div>Scenario: <br></div><div>* Say the Debian-derived Linux OS from which "update-grub" is run is "A". <br></div><div>* Say another Linux OS on the same hard drive is "B". <br></div><div>* Say "B" has multiple kernel versions (when each version was installed, the<br></div><div>   previous one wasn't deleted). <br></div><div><br></div><div>In this case, GRUB2 makes a submenu for the available kernels in B, plus a main-<br></div><div>menu entry for one of those kernels.  That is expected. <br></div><div><br></div><div>The problem is that, in my testing, the submenu looked like: <br></div><div><br></div><div>Ubuntu XX.YY (XX.YY)<br></div><div>Ubuntu XX.YY (XX.YY)<br></div><div>Ubuntu XX.YY (XX.YY)<br></div><div>Ubuntu XX.YY (XX.YY)<br></div><div><br></div><div>... where XX was the same in every menu entry (*including the main-menu<br></div><div>entry*), and YY was also the same.  There was no way to tell which menu entry<br></div><div>would start which kernel version.  In fact, I believe the kernel versions were<br></div><div>sorted backward, so that the main-menu entry started the *oldest* available<br></div><div>kernel version of B, whereas a user would expect the main-menu entry to start<br></div><div>the newest available kernel of B. <br></div><div><br></div><div>The following patch fixed this in my testing.  Please consider adding this<br></div><div>patch (or a modified version of it, if bugs are found in this patch) to GRUB2. <br></div><div><br></div><div>For my testing, I renamed the os-prober script from 30_os-prober to<br></div><div>15_os-prober, because I wanted the OS boot options to be before memtest86+.  In<br></div><div>the diff, the name difference indicates the original vs. modified files: <br></div><div><br></div><div>30_os-prober = existing file in Debian package<br></div><div>15_os-prober = my modified file<br></div><div><br></div><div>--- 30_os-prober       2015-12-14 12:37:32.000000000 -0500<br></div><div>+++ 15_os-prober    2017-02-23 17:28:47.692140837 -0500<br></div><div>@@ -27,6 +27,9 @@<br></div><div><br></div><div>. "${datarootdir}/grub/grub-mkconfig_lib"<br></div><div><br></div><div>+safe_echo () { printf %s\\n "$*" ; }<br></div><div>+# from <a href="http://www.etalabs.net/sh_tricks.html">http://www.etalabs.net/sh_tricks.html</a><br></div><div>+<br></div><div>found_other_os=<br></div><div><br></div><div>adjust_timeout () {<br></div><div>@@ -232,6 +235,11 @@<br></div><div>       title_correction_code=<br></div><div>       OS="${LONGNAME}"<br></div><div><br></div><div>+      LINUXPROBED=$(safe_echo "${LINUXPROBED}" | tr " " "\n" | \<br></div><div>+        sort -t ":" -k 4 -rV | tr "\n" " ")<br></div><div>+      # Try to sort the kernels with the newest first, so the newest one will<br></div><div>+      # be the default. <br></div><div>+<br></div><div>       for LINUX in ${LINUXPROBED} ; do<br></div><div>         LROOT="`echo ${LINUX} | cut -d ':' -f 1`"<br></div><div>         LBOOT="`echo ${LINUX} | cut -d ':' -f 2`"<br></div><div>@@ -254,6 +262,68 @@<br></div><div>  [ "${prepare_boot_cache}" ] || continue<br></div><div>fi<br></div><div><br></div><div>+LSB_QUERY_MOUNT_POINT=$(findmnt -flno TARGET ${DEVICE})<br></div><div>+<br></div><div>+if [ -z "${LSB_QUERY_MOUNT_POINT}" ] ; then<br></div><div>+  LSB_QUERY_MOUNT_POINT=$(mktemp -d)<br></div><div>+  mount ${DEVICE} ${LSB_QUERY_MOUNT_POINT}<br></div><div>+  TEMP_MOUNT="true"<br></div><div>+  # It appears that this code doesn't run:  Although syslog indicates that<br></div><div>+  # /usr/lib/os-probes/mounted/40lsb indeed scans unmounted partitions, it<br></div><div>+  # seems that /usr/bin/os-prober (which is indirectly the parent process of<br></div><div>+  # "40lsb") still doesn't report any OS that exists on such a partition.  The<br></div><div>+  # partition tested was formatted as btrfs. <br></div><div>+else<br></div><div>+  TEMP_MOUNT="false"<br></div><div>+fi<br></div><div>+<br></div><div>+LSB_DATABASE=${LSB_QUERY_MOUNT_POINT}/etc/lsb-release<br></div><div>+<br></div><div>+LCODENAME=$(grep ^DISTRIB_CODENAME ${LSB_DATABASE} | cut -d "=" -f 2)<br></div><div>+LDESC=$(grep ^DISTRIB_DESCRIPTION ${LSB_DATABASE} | cut -d "=" -f 2)<br></div><div>+<br></div><div>+if [ ${TEMP_MOUNT} = true ] ; then<br></div><div>+  # not "x${TEMP_MOUNT}=xtrue", because ${TEMP_MOUNT} is known to have a value<br></div><div>+  umount ${LSB_QUERY_MOUNT_POINT}<br></div><div>+fi<br></div><div>+<br></div><div>+if safe_echo "${LDESC}" | egrep "^(['\"]).*\1$" >/dev/null; then<br></div><div>+  LDESC=$(safe_echo "${LDESC}" | cut -c 2- | rev | cut -c 2- | rev)<br></div><div>+fi  # If ${LDESC} is quoted, then remove the quote marks. <br></div><div>+<br></div><div>+LKERNEL_DISPLAY=$(safe_echo "${LKERNEL}" | cut -d "-" -f 2-)<br></div><div>+# Try to extract the version number of the kernel image file. <br></div><div>+<br></div><div>+name_to_compare () { echo "${1}" | tr -c "[:alpha:]" " " | tr -s " " | \<br></div><div>+                     tr "[:upper:]" "[:lower:]" | \<br></div><div>+                     sed "s/[ ]\+$//" ; }<br></div><div>+# Convert all non-letters in ${1} to spaces. <br></div><div>+# Convert multiple consecutive spaces to single spaces. <br></div><div>+# Convert all uppercase letters to lowercase. <br></div><div>+# Then remove trailing spaces if present<br></div><div>+#   (sed "s/ $//" doesn't seem to work for this). <br></div><div>+# We do these things so an LCODENAME of "betsy" will be detected at the end of<br></div><div>+#   an LDESC of "LMDE 2 (Betsy)", but not in an LDESC of "LMDE blah b_e.t-s.y"<br></div><div>+<br></div><div>+LDESC_CMP=$(name_to_compare "${LDESC}")<br></div><div>+LCODENAME_CMP=$(name_to_compare "${LCODENAME}")<br></div><div>+<br></div><div>+if safe_echo "${LDESC_CMP}" | egrep "${LCODENAME_CMP}$" >/dev/null; then<br></div><div>+  # ${LDESC} ends in ${LCODENAME}. <br></div><div>+  OS_SUBMENU="${LDESC}"<br></div><div>+else<br></div><div>+  # ${LDESC} doesn't end in ${LCODENAME}. <br></div><div>+  OS_SUBMENU="${LDESC} \"${LCODENAME}\""<br></div><div>+fi<br></div><div>+<br></div><div>+OS="${OS_SUBMENU}, with Linux kernel ${LKERNEL_DISPLAY}"<br></div><div>+# Examples: <br></div><div>+# LMDE 2 Betsy, with Linux kernel 3.16.0-4-amd64<br></div><div>+#   (if codename is "betsy" & description ends in "Betsy")<br></div><div>+# Ubuntu 13.04 "raring", with Linux kernel 3.8.0-35-generic<br></div><div>+<br></div><div>+printf "Adding '%s' to menu\n" "${OS}" >&2<br></div><div>+<br></div><div>found_other_os=1<br></div><div>onstr="$(gettext_printf "(on %s)" "${DEVICE}")"<br></div><div>recovery_params="$(echo "${LPARAMS}" | grep 'single\|recovery')" || true<br></div><div>@@ -283,10 +353,11 @@<br></div><div>         cat << EOF<br></div><div>}<br></div><div>EOF<br></div><div>-        echo "submenu '$(gettext_printf "Advanced options for %s" "${OS} $onstr" | grub_quote)' \$menuentry_id_option 'osprober-gnulinux-advanced-$boot_device_id' {"<br></div><div>+            echo "submenu '$(gettext_printf "Advanced options for %s" "${OS_SUBMENU} $onstr" | grub_quote)' \$menuentry_id_option 'osprober-gnulinux-advanced-$boot_device_id' {"<br></div><div>+<br></div><div>    is_top_level=false<br></div><div>fi<br></div><div>-     title="${LLABEL} $onstr"<br></div><div>+    title="${OS} $onstr"<br></div><div>         cat << EOF<br></div><div>menuentry '$(echo "$title" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-$LKERNEL-${recovery_params}-$boot_device_id' {<br></div><div>EOF<br></div><div><br></div><div>Thanks for considering this.  <br></div><div class="protonmail_signature_block "><div class="protonmail_signature_block-user "><div>-dg1727<br></div></div><div><br></div></div><div><br></div>