From: Lennart Poettering Date: Fri, 11 Feb 2022 20:15:22 +0000 (+0100) Subject: bootctl: show more information about boot entry state in list X-Git-Tag: v251-rc1~293^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bb6820576870d0b38dbf9f6e489b126558fc87d9;p=thirdparty%2Fsystemd.git bootctl: show more information about boot entry state in list 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 --- diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index adc66788f85..ab514d28ee0 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -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; diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 72de58631a8..32d619eecf4 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -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) diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index 2d1d2b440b2..15b77f01b21 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -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, }; } diff --git a/src/shared/bootspec.h b/src/shared/bootspec.h index 8649e93bcef..6f1014db4a4 100644 --- a/src/shared/bootspec.h +++ b/src/shared/bootspec.h @@ -11,15 +11,17 @@ #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; }