]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
bootspec: move augmentation of loader-discovered entries into bootspec.c
authorLennart Poettering <lennart@poettering.net>
Fri, 1 Mar 2019 17:35:26 +0000 (18:35 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 5 Mar 2019 15:50:58 +0000 (16:50 +0100)
Previously, bootctl would show boot loader entries discovered by the
boot loader which couldn't found locally separately in the output.

Let's move this code into bootspec.c, and beef it up a bit. This way we
can use it later on for logind, and correctly show automatically
discovered windows/macos entries too.

src/boot/bootctl.c
src/shared/bootspec.c
src/shared/bootspec.h

index 6c0885198add65ca8d90834d344188c047359ada..b5f4b8e5a3d3c49dd58da99784bc435d687faec2 100644 (file)
@@ -311,13 +311,15 @@ static int status_variables(void) {
 static int boot_entry_show(const BootEntry *e, bool show_as_default) {
         assert(e);
 
-        printf("        title: %s%s%s%s%s%s\n",
+        printf("        title: %s%s%s%s%s%s\n"
+               "         type: %s\n",
                ansi_highlight(),
                boot_entry_title(e),
                ansi_normal(),
                ansi_highlight_green(),
                show_as_default ? " (default)" : "",
-               ansi_normal());
+               ansi_normal(),
+               boot_entry_type_to_string(e->type));
 
         if (e->id)
                 printf("           id: %s\n", e->id);
@@ -1173,7 +1175,6 @@ static int verb_status(int argc, char *argv[], void *userdata) {
 
 static int verb_list(int argc, char *argv[], void *userdata) {
         _cleanup_(boot_config_free) BootConfig config = {};
-        _cleanup_free_ char **found_by_loader = NULL;
         int r;
 
         /* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
@@ -1196,9 +1197,7 @@ static int verb_list(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        r = efi_loader_get_entries(&found_by_loader);
-        if (r < 0 && !IN_SET(r, -ENOENT, -EOPNOTSUPP))
-                log_debug_errno(r, "Failed to acquire boot loader discovered entries: %m");
+        (void) boot_entries_augment_from_loader(&config, false);
 
         if (config.n_entries == 0)
                 log_info("No boot loader entries found.");
@@ -1216,20 +1215,9 @@ static int verb_list(int argc, char *argv[], void *userdata) {
 
                         if (n+1 < config.n_entries)
                                 putchar('\n');
-
-                        strv_remove(found_by_loader, config.entries[n].id);
                 }
         }
 
-        if (!strv_isempty(found_by_loader)) {
-                char **i;
-
-                printf("\nAutomatic/Other Entries Found by Boot Loader:\n\n");
-
-                STRV_FOREACH(i, found_by_loader)
-                        puts(*i);
-        }
-
         return 0;
 }
 
index d5bd0ff75e17b766f6261288ebc7c93b80bcdf78..d0841e8ee5f4b09a5b14163d601d3f876e36dcf2 100644 (file)
@@ -22,6 +22,7 @@
 #include "path-util.h"
 #include "pe-header.h"
 #include "stat-util.h"
+#include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
 #include "unaligned.h"
@@ -50,7 +51,10 @@ static int boot_entry_load(
                 const char *path,
                 BootEntry *entry) {
 
-        _cleanup_(boot_entry_free) BootEntry tmp = {};
+        _cleanup_(boot_entry_free) BootEntry tmp = {
+                .type = BOOT_ENTRY_CONF,
+        };
+
         _cleanup_fclose_ FILE *f = NULL;
         unsigned line = 1;
         char *b, *c;
@@ -272,7 +276,9 @@ static int boot_entry_load_unified(
                 BootEntry *ret) {
 
         _cleanup_free_ char *os_pretty_name = NULL, *os_id = NULL, *version_id = NULL, *build_id = NULL;
-        _cleanup_(boot_entry_free) BootEntry tmp = {};
+        _cleanup_(boot_entry_free) BootEntry tmp = {
+                .type = BOOT_ENTRY_UNIFIED,
+        };
         _cleanup_fclose_ FILE *f = NULL;
         const char *k;
         int r;
@@ -664,6 +670,70 @@ int boot_entries_load_config(
         return 0;
 }
 
+int boot_entries_augment_from_loader(BootConfig *config, bool only_auto) {
+
+        static const char * const title_table[] = {
+                /* Pretty names for a few well-known automatically discovered entries. */
+                "auto-osx",                      "macOS",
+                "auto-windows",                  "Windows Boot Manager",
+                "auto-efi-shell",                "EFI Shell",
+                "auto-efi-default",              "EFI Default Loader",
+                "auto-reboot-to-firmware-setup", "Reboot Into Firmware Interface",
+        };
+
+        _cleanup_free_ char **found_by_loader = NULL;
+        size_t n_allocated;
+        char **i;
+        int r;
+
+        assert(config);
+
+        /* Let's add the entries discovered by the boot loader to the end of our list, unless they are
+         * already included there. */
+
+        r = efi_loader_get_entries(&found_by_loader);
+        if (IN_SET(r, -ENOENT, -EOPNOTSUPP))
+                return log_debug_errno(r, "Boot loader reported no entries.");
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine entries reported by boot loader: %m");
+
+        n_allocated = config->n_entries;
+
+        STRV_FOREACH(i, found_by_loader) {
+                _cleanup_free_ char *c = NULL, *t = NULL;
+                char **a, **b;
+
+                if (boot_config_has_entry(config, *i))
+                        continue;
+
+                if (only_auto && !startswith(*i, "auto-"))
+                        continue;
+
+                c = strdup(*i);
+                if (!c)
+                        return log_oom();
+
+                STRV_FOREACH_PAIR(a, b, (char**) title_table)
+                        if (streq(*a, *i)) {
+                                t = strdup(*b);
+                                if (!t)
+                                        return log_oom();
+                                break;
+                        }
+
+                if (!GREEDY_REALLOC0(config->entries, n_allocated, config->n_entries + 1))
+                        return log_oom();
+
+                config->entries[config->n_entries++] = (BootEntry) {
+                        .type = BOOT_ENTRY_LOADER,
+                        .id = TAKE_PTR(c),
+                        .title = TAKE_PTR(t),
+                };
+        }
+
+        return 0;
+}
+
 /********************************************************************************/
 
 static int verify_esp_blkid(
@@ -1327,3 +1397,11 @@ int find_default_boot_entry(
 
         return 0;
 }
+
+static const char* const boot_entry_type_table[_BOOT_ENTRY_MAX] = {
+        [BOOT_ENTRY_CONF] = "conf",
+        [BOOT_ENTRY_UNIFIED] = "unified",
+        [BOOT_ENTRY_LOADER] = "loader",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(boot_entry_type, BootEntryType);
index 695e86d8f7baea1f4493594ba3714882da34d310..658905a4cbbe03e7ab4f50dee7611e3ca9c86aee 100644 (file)
@@ -8,7 +8,18 @@
 
 #include "sd-id128.h"
 
+#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 = -1,
+} BootEntryType;
+
 typedef struct BootEntry {
+        BootEntryType type;
         char *id;       /* This is the file basename without extension */
         char *path;     /* This is the full path to the drop-in file */
         char *root;     /* The root path in which the drop-in was found, i.e. to which 'kernel', 'efi' and 'initrd' are relative */
@@ -40,8 +51,19 @@ typedef struct BootConfig {
         ssize_t default_entry;
 } BootConfig;
 
+static inline bool boot_config_has_entry(BootConfig *config, const char *id) {
+        size_t j;
+
+        for (j = 0; j < config->n_entries; j++)
+                if (streq(config->entries[j].id, id))
+                        return true;
+
+        return false;
+}
+
 void boot_config_free(BootConfig *config);
 int boot_entries_load_config(const char *esp_path, const char *xbootldr_path, BootConfig *config);
+int boot_entries_augment_from_loader(BootConfig *config, bool only_auto);
 
 static inline const char* boot_entry_title(const BootEntry *entry) {
         return entry->show_title ?: entry->title ?: entry->id;
@@ -51,3 +73,6 @@ int find_esp_and_warn(const char *path, bool unprivileged_mode, char **ret_path,
 int find_xbootldr_and_warn(const char *path, bool unprivileged_mode, char **ret_path,sd_id128_t *ret_uuid);
 
 int find_default_boot_entry(BootConfig *config, const BootEntry **e);
+
+const char* boot_entry_type_to_string(BootEntryType t) _const_;
+BootEntryType boot_entry_type_from_string(const char *s) _pure_;