bootspec: load entries from both the ESP and XBOOTLDR partitions
authorLennart Poettering <lennart@poettering.net>
Mon, 28 Jan 2019 17:56:53 +0000 (18:56 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 1 Mar 2019 11:41:32 +0000 (12:41 +0100)
Let's simply search in both.

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

index 2424aa0..ddbcac9 100644 (file)
@@ -323,7 +323,7 @@ static int status_entries(const char *esp_path, sd_id128_t partition) {
         _cleanup_(boot_config_free) BootConfig config = {};
         int r;
 
-        r = boot_entries_load_config(esp_path, &config);
+        r = boot_entries_load_config(esp_path, NULL, &config);
         if (r < 0)
                 return r;
 
@@ -1075,7 +1075,7 @@ static int verb_list(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        r = boot_entries_load_config(arg_path, &config);
+        r = boot_entries_load_config(arg_path, NULL, &config);
         if (r < 0)
                 return r;
 
index c662e89..6f28c74 100644 (file)
@@ -228,39 +228,38 @@ static int boot_entry_compare(const BootEntry *a, const BootEntry *b) {
 static int boot_entries_find(
                 const char *root,
                 const char *dir,
-                BootEntry **ret_entries,
-                size_t *ret_n_entries) {
+                BootEntry **entries,
+                size_t *n_entries) {
 
         _cleanup_strv_free_ char **files = NULL;
+        size_t n_allocated = *n_entries;
+        bool added = false;
         char **f;
         int r;
-        BootEntry *array = NULL;
-        size_t n_allocated = 0, n = 0;
 
         assert(root);
         assert(dir);
-        assert(ret_entries);
-        assert(ret_n_entries);
+        assert(entries);
+        assert(n_entries);
 
         r = conf_files_list(&files, ".conf", NULL, 0, dir, NULL);
         if (r < 0)
                 return log_error_errno(r, "Failed to list files in \"%s\": %m", dir);
 
         STRV_FOREACH(f, files) {
-                if (!GREEDY_REALLOC0(array, n_allocated, n + 1))
+                if (!GREEDY_REALLOC0(*entries, n_allocated, *n_entries + 1))
                         return log_oom();
 
-                r = boot_entry_load(root, *f, array + n);
+                r = boot_entry_load(root, *f, *entries + *n_entries);
                 if (r < 0)
                         continue;
 
-                n++;
+                (*n_entries) ++;
+                added = true;
         }
 
-        typesafe_qsort(array, n, boot_entry_compare);
-
-        *ret_entries = array;
-        *ret_n_entries = n;
+        if (added)
+                typesafe_qsort(*entries, *n_entries, boot_entry_compare);
 
         return 0;
 }
@@ -372,22 +371,34 @@ static int boot_entries_select_default(const BootConfig *config) {
         return config->n_entries - 1; /* -1 means "no default" */
 }
 
-int boot_entries_load_config(const char *esp_path, BootConfig *config) {
+int boot_entries_load_config(
+                const char *esp_path,
+                const char *xbootldr_path,
+                BootConfig *config) {
+
         const char *p;
         int r;
 
-        assert(esp_path);
         assert(config);
 
-        p = strjoina(esp_path, "/loader/loader.conf");
-        r = boot_loader_read_conf(p, config);
-        if (r < 0)
-                return r;
+        if (esp_path) {
+                p = strjoina(esp_path, "/loader/loader.conf");
+                r = boot_loader_read_conf(p, config);
+                if (r < 0)
+                        return r;
 
-        p = strjoina(esp_path, "/loader/entries");
-        r = boot_entries_find(esp_path, p, &config->entries, &config->n_entries);
-        if (r < 0)
-                return r;
+                p = strjoina(esp_path, "/loader/entries");
+                r = boot_entries_find(esp_path, p, &config->entries, &config->n_entries);
+                if (r < 0)
+                        return r;
+        }
+
+        if (xbootldr_path) {
+                p = strjoina(xbootldr_path, "/loader/entries");
+                r = boot_entries_find(xbootldr_path, p, &config->entries, &config->n_entries);
+                if (r < 0)
+                        return r;
+        }
 
         r = boot_entries_uniquify(config->entries, config->n_entries);
         if (r < 0)
@@ -815,29 +826,34 @@ found:
 
 int find_default_boot_entry(
                 const char *esp_path,
+                const char *xbootldr_path,
                 BootConfig *config,
                 const BootEntry **e) {
 
-        _cleanup_free_ char *where = NULL;
+        _cleanup_free_ char *esp_where = NULL, *xbootldr_where = NULL;
         int r;
 
         assert(config);
         assert(e);
 
-        r = find_esp_and_warn(esp_path, false, &where, NULL, NULL, NULL, NULL);
+        r = find_esp_and_warn(esp_path, false, &esp_where, NULL, NULL, NULL, NULL);
         if (r < 0)
                 return r;
 
-        r = boot_entries_load_config(where, config);
+        r = find_xbootldr_and_warn(xbootldr_path, false, &xbootldr_where, NULL);
+        if (r < 0 && r != -ENOKEY)
+                return r;
+
+        r = boot_entries_load_config(esp_where, xbootldr_where, config);
         if (r < 0)
-                return log_error_errno(r, "Failed to load bootspec config from \"%s/loader\": %m", where);
+                return log_error_errno(r, "Failed to load boot loader entries: %m");
 
         if (config->default_entry < 0)
                 return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
-                                       "No entry suitable as default, refusing to guess.");
+                                       "No boot loader entry suitable as default, refusing to guess.");
 
         *e = &config->entries[config->default_entry];
-        log_debug("Found default boot entry in file \"%s\"", (*e)->path);
+        log_debug("Found default boot loader entry in file \"%s\"", (*e)->path);
 
         return 0;
 }
index 0fac051..f184902 100644 (file)
@@ -41,7 +41,7 @@ typedef struct BootConfig {
 } BootConfig;
 
 void boot_config_free(BootConfig *config);
-int boot_entries_load_config(const char *esp_path, BootConfig *config);
+int boot_entries_load_config(const char *esp_path, const char *xbootldr_path, BootConfig *config);
 
 static inline const char* boot_entry_title(const BootEntry *entry) {
         return entry->show_title ?: entry->title ?: entry->id;
@@ -50,4 +50,4 @@ static inline const char* boot_entry_title(const BootEntry *entry) {
 int find_esp_and_warn(const char *path, bool unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid);
 int find_xbootldr_and_warn(const char *path, bool unprivileged_mode, char **ret_path,sd_id128_t *ret_uuid);
 
-int find_default_boot_entry(const char *esp_path, BootConfig *config, const BootEntry **e);
+int find_default_boot_entry(const char *esp_path, const char *xbootldr_path, BootConfig *config, const BootEntry **e);
index d30b607..57e3111 100644 (file)
@@ -3531,7 +3531,7 @@ static int load_kexec_kernel(void) {
         if (access(KEXEC, X_OK) < 0)
                 return log_error_errno(errno, KEXEC" is not available: %m");
 
-        r = find_default_boot_entry(NULL, &config, &e);
+        r = find_default_boot_entry(NULL, NULL, &config, &e);
         if (r == -ENOKEY) /* find_default_boot_entry() doesn't warn about this case */
                 return log_error_errno(r, "Cannot find the ESP partition mount point.");
         if (r < 0)