]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
bootctl: show more information about boot entry state in list
authorLennart Poettering <lennart@poettering.net>
Fri, 11 Feb 2022 20:15:22 +0000 (21:15 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 14 Feb 2022 14:44:07 +0000 (15:44 +0100)
Let's improve display of boot entries and show what type they have (i.e.
boot loader spec type 1, or type 2, or auto-discovered or reported by
boot loader), and in particular mark entries the boot loader discovered
but we can't find (i.e. that likely vanished, or possibly couldn't be
found due to a misconfiguration) and that the boot loader didn't find
but we see (which are new, or possibly also the result of
misconfiguraiton).

This is supposed to be a replacement for #22161, but instead of hiding
vanished entries, highlights them, which I think is more appropriate for
a low-level tool such bootctl.

Replaces: #22161 #22398

src/boot/bootctl.c
src/login/logind-dbus.c
src/shared/bootspec.c
src/shared/bootspec.h

index adc66788f857d1f3b79ed3a52bb0f50fb1b23277..ab514d28ee07da46260997a1df1cca9c6bd82e91 100644 (file)
@@ -36,6 +36,7 @@
 #include "rm-rf.h"
 #include "stat-util.h"
 #include "stdio-util.h"
+#include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
 #include "sync-util.h"
@@ -411,10 +412,20 @@ static void boot_entry_file_list(const char *field, const char *root, const char
                 *ret_status = status;
 }
 
+static const char* const boot_entry_type_table[_BOOT_ENTRY_TYPE_MAX] = {
+        [BOOT_ENTRY_CONF]        = "Boot Loader Specification Type #1 (.conf)",
+        [BOOT_ENTRY_UNIFIED]     = "Boot Loader Specification Type #2 (.efi)",
+        [BOOT_ENTRY_LOADER]      = "Reported by Boot Loader",
+        [BOOT_ENTRY_LOADER_AUTO] = "Automatic",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type, BootEntryType);
+
 static int boot_entry_show(
                 const BootEntry *e,
                 bool show_as_default,
-                bool show_as_selected) {
+                bool show_as_selected,
+                bool show_reported) {
 
         int status = 0;
 
@@ -423,10 +434,30 @@ static int boot_entry_show(
 
         assert(e);
 
-        printf("        title: %s%s%s" "%s%s%s" "%s%s%s\n",
-               ansi_highlight(), boot_entry_title(e), ansi_normal(),
-               ansi_highlight_green(), show_as_default ? " (default)" : "", ansi_normal(),
-               ansi_highlight_magenta(), show_as_selected ? " (selected)" : "", ansi_normal());
+        printf("         type: %s\n",
+               boot_entry_type_to_string(e->type));
+
+        printf("        title: %s%s%s",
+               ansi_highlight(), boot_entry_title(e), ansi_normal());
+
+        if (show_as_default)
+                printf(" %s(default)%s",
+                       ansi_highlight_green(), ansi_normal());
+
+        if (show_as_selected)
+                printf(" %s(selected)%s",
+                       ansi_highlight_magenta(), ansi_normal());
+
+        if (show_reported) {
+                if (e->type == BOOT_ENTRY_LOADER)
+                        printf(" %s(reported/absent)%s",
+                               ansi_highlight_red(), ansi_normal());
+                else if (!e->reported_by_loader && e->type != BOOT_ENTRY_LOADER_AUTO)
+                        printf(" %s(not reported/new)%s",
+                               ansi_highlight_green(), ansi_normal());
+        }
+
+        putchar('\n');
 
         if (e->id)
                 printf("           id: %s\n", e->id);
@@ -524,7 +555,11 @@ static int status_entries(
         else {
                 printf("Default Boot Loader Entry:\n");
 
-                r = boot_entry_show(config.entries + config.default_entry, /* show_as_default= */ false, /* show_as_selected= */ false);
+                r = boot_entry_show(
+                                config.entries + config.default_entry,
+                                /* show_as_default= */ false,
+                                /* show_as_selected= */ false,
+                                /* show_discovered= */ false);
                 if (r > 0)
                         /* < 0 is already logged by the function itself, let's just emit an extra warning if
                            the default entry is broken */
@@ -1619,7 +1654,7 @@ static int verb_list(int argc, char *argv[], void *userdata) {
         else if (r < 0)
                 log_warning_errno(r, "Failed to determine entries reported by boot loader, ignoring: %m");
         else
-                (void) boot_entries_augment_from_loader(&config, efi_entries, false);
+                (void) boot_entries_augment_from_loader(&config, efi_entries, /* only_auto= */ false);
 
         if (config.n_entries == 0)
                 log_info("No boot loader entries found.");
@@ -1631,8 +1666,9 @@ static int verb_list(int argc, char *argv[], void *userdata) {
                 for (size_t n = 0; n < config.n_entries; n++) {
                         r = boot_entry_show(
                                         config.entries + n,
-                                        n == (size_t) config.default_entry,
-                                        n == (size_t) config.selected_entry);
+                                        /* show_as_default= */  n == (size_t) config.default_entry,
+                                        /* show_as_selected= */ n == (size_t) config.selected_entry,
+                                        /* show_discovered= */  true);
                         if (r < 0)
                                 return r;
 
index 72de58631a887881507542cc79ebcd5310a74212..32d619eecf4e75edf929b4c981d693231d9dcc50 100644 (file)
@@ -2923,9 +2923,9 @@ static int boot_loader_entry_exists(Manager *m, const char *id) {
 
         r = manager_read_efi_boot_loader_entries(m);
         if (r >= 0)
-                (void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries, true);
+                (void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries, /* auto_only= */ true);
 
-        return boot_config_has_entry(&config, id);
+        return !!boot_config_find_entry(&config, id);
 }
 
 static int method_set_reboot_to_boot_loader_entry(
@@ -3081,7 +3081,7 @@ static int property_get_boot_loader_entries(
 
         r = manager_read_efi_boot_loader_entries(m);
         if (r >= 0)
-                (void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries, true);
+                (void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries, /* auto_only= */ true);
 
         r = sd_bus_message_open_container(reply, 'a', "s");
         if (r < 0)
index 2d1d2b440b26dc1c5c8d571cd58142dc8e81fb3c..15b77f01b2187d39077690c414d14f6c96c3dbd2 100644 (file)
@@ -561,7 +561,7 @@ static int boot_entries_find_unified(
         return 0;
 }
 
-static bool find_nonunique(BootEntry *entries, size_t n_entries, bool *arr) {
+static bool find_nonunique(const BootEntry *entries, size_t n_entries, bool arr[]) {
         size_t i, j;
         bool non_unique = false;
 
@@ -833,11 +833,15 @@ int boot_entries_augment_from_loader(
          * already included there. */
 
         STRV_FOREACH(i, found_by_loader) {
+                BootEntry *existing;
                 _cleanup_free_ char *c = NULL, *t = NULL, *p = NULL;
                 char **a, **b;
 
-                if (boot_config_has_entry(config, *i))
+                existing = boot_config_find_entry(config, *i);
+                if (existing) {
+                        existing->reported_by_loader = true;
                         continue;
+                }
 
                 if (only_auto && !startswith(*i, "auto-"))
                         continue;
@@ -862,10 +866,11 @@ int boot_entries_augment_from_loader(
                         return log_oom();
 
                 config->entries[config->n_entries++] = (BootEntry) {
-                        .type = BOOT_ENTRY_LOADER,
+                        .type = startswith(*i, "auto-") ? BOOT_ENTRY_LOADER_AUTO : BOOT_ENTRY_LOADER,
                         .id = TAKE_PTR(c),
                         .title = TAKE_PTR(t),
                         .path = TAKE_PTR(p),
+                        .reported_by_loader = true,
                 };
         }
 
index 8649e93bcef84c9132e44cdadc18edf7d8428c16..6f1014db4a48138d0db02a54840650b392a0d08a 100644 (file)
 #include "string-util.h"
 
 typedef enum BootEntryType {
-        BOOT_ENTRY_CONF,     /* Type #1 entries: *.conf files */
-        BOOT_ENTRY_UNIFIED,  /* Type #2 entries: *.efi files */
-        BOOT_ENTRY_LOADER,   /* Additional entries augmented from LoaderEntries EFI var */
-        _BOOT_ENTRY_MAX,
-        _BOOT_ENTRY_INVALID = -EINVAL,
+        BOOT_ENTRY_CONF,        /* Boot Loader Specification Type #1 entries: *.conf files */
+        BOOT_ENTRY_UNIFIED,     /* Boot Loader Specification Type #2 entries: *.efi files */
+        BOOT_ENTRY_LOADER,      /* Additional entries augmented from LoaderEntries EFI variable (regular entries) */
+        BOOT_ENTRY_LOADER_AUTO, /* Additional entries augmented from LoaderEntries EFI variable (special "automatic" entries) */
+        _BOOT_ENTRY_TYPE_MAX,
+        _BOOT_ENTRY_TYPE_INVALID = -EINVAL,
 } BootEntryType;
 
 typedef struct BootEntry {
         BootEntryType type;
+        bool reported_by_loader;
         char *id;       /* This is the file basename (including extension!) */
         char *id_old;   /* Old-style ID, for deduplication purposes. */
         char *path;     /* This is the full path to the drop-in file */
@@ -57,20 +59,21 @@ typedef struct BootConfig {
         ssize_t selected_entry;
 } BootConfig;
 
-static inline bool boot_config_has_entry(BootConfig *config, const char *id) {
-        size_t j;
+static inline BootEntry* boot_config_find_entry(BootConfig *config, const char *id) {
+        assert(config);
+        assert(id);
 
-        for (j = 0; j < config->n_entries; j++) {
-                const char* entry_id_old = config->entries[j].id_old;
-                if (streq(config->entries[j].id, id) ||
-                    (entry_id_old && streq(entry_id_old, id)))
-                        return true;
-        }
+        for (size_t j = 0; j < config->n_entries; j++)
+                if (streq_ptr(config->entries[j].id, id) ||
+                    streq_ptr(config->entries[j].id_old, id))
+                        return config->entries + j;
 
-        return false;
+        return NULL;
 }
 
 static inline BootEntry* boot_config_default_entry(BootConfig *config) {
+        assert(config);
+
         if (config->default_entry < 0)
                 return NULL;
 
@@ -83,6 +86,8 @@ int boot_entries_load_config_auto(const char *override_esp_path, const char *ove
 int boot_entries_augment_from_loader(BootConfig *config, char **list, bool only_auto);
 
 static inline const char* boot_entry_title(const BootEntry *entry) {
+        assert(entry);
+
         return entry->show_title ?: entry->title ?: entry->id;
 }