sd-boot: fix menu ordering with boot counting
authorDaniel Fullmer <danielrf12@gmail.com>
Thu, 23 Apr 2020 18:47:56 +0000 (14:47 -0400)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 20 Sep 2020 09:04:18 +0000 (11:04 +0200)
systemd-boot selects the last valid entry by default, not the first.

Fixes: #15256
(cherry picked from commit e6190e2882e1d6772a9e586fcc65c91d406e52fb)

docs/AUTOMATIC_BOOT_ASSESSMENT.md
man/systemd-boot.xml
src/boot/efi/boot.c

index aff203b5906e215c25b858509a2376c8d60835a4..83ddf28fdd8770a87abc9b1445b46af12547b8bd 100644 (file)
@@ -101,9 +101,9 @@ Here's an example walkthrough of how this all fits together.
 
 6. If this boot also fails, on the next boot the boot loader will see the
    tag `+0-3`, i.e. the counter reached zero. At this point the entry will be
-   considered "bad", and ordered to the end of the list of entries. The next
-   newest boot entry is now tried, i.e. the system automatically reverted back
-   to an earlier version.
+   considered "bad", and ordered to the beginning of the list of entries. The
+   next newest boot entry is now tried, i.e. the system automatically reverted
+   back to an earlier version.
 
 The above describes the walkthrough when the selected boot entry continuously
 fails. Let's have a look at an alternative ending to this walkthrough. In this
index ee513ed40983f47c9b00c11ebf29e70c8dc9806e..1284fbe0a04413ccb80d65a586423627929c7d5f 100644 (file)
     considered 'good' from then on.</para>
 
     <para>The boot menu takes the 'tries left' counter into account when sorting the menu entries: entries in 'bad'
-    state are ordered at the end of the list, and entries in 'good' or 'indeterminate' at the beginning. The user can
+    state are ordered at the beginning of the list, and entries in 'good' or 'indeterminate' at the end. The user can
     freely choose to boot any entry of the menu, including those already marked 'bad'. If the menu entry to boot is
-    automatically determined, this means that 'good' or 'indeterminate' entries are generally preferred (as the top item of
-    the menu is the one booted by default), and 'bad' entries will only be considered if there are no 'good' or
+    automatically determined, this means that 'good' or 'indeterminate' entries are generally preferred (as the bottom
+    item of the menu is the one booted by default), and 'bad' entries will only be considered if there are no 'good' or
     'indeterminate' entries left.</para>
 
     <para>The <citerefentry><refentrytitle>kernel-install</refentrytitle><manvolnum>8</manvolnum></citerefentry> kernel
index 99938c547a25cd7d846aa4c9707c57fdcb07f378..cd3d3dd4e3778ff839d4255e0b2d490f38825916 100644 (file)
@@ -1518,11 +1518,11 @@ static VOID config_load_entries(
 static INTN config_entry_compare(ConfigEntry *a, ConfigEntry *b) {
         INTN r;
 
-        /* Order entries that have no tries left to the end of the list */
+        /* Order entries that have no tries left to the beginning of the list */
         if (a->tries_left != 0 && b->tries_left == 0)
-                return -1;
-        if (a->tries_left == 0 && b->tries_left != 0)
                 return 1;
+        if (a->tries_left == 0 && b->tries_left != 0)
+                return -1;
 
         r = str_verscmp(a->id, b->id);
         if (r != 0)
@@ -1532,17 +1532,17 @@ static INTN config_entry_compare(ConfigEntry *a, ConfigEntry *b) {
             b->tries_left == (UINTN) -1)
                 return 0;
 
-        /* If both items have boot counting, and otherwise are identical, put the entry with more tries left first */
+        /* If both items have boot counting, and otherwise are identical, put the entry with more tries left last */
         if (a->tries_left > b->tries_left)
-                return -1;
-        if (a->tries_left < b->tries_left)
                 return 1;
+        if (a->tries_left < b->tries_left)
+                return -1;
 
         /* If they have the same number of tries left, then let the one win which was tried fewer times so far */
         if (a->tries_done < b->tries_done)
-                return -1;
-        if (a->tries_done > b->tries_done)
                 return 1;
+        if (a->tries_done > b->tries_done)
+                return -1;
 
         return 0;
 }