From a2f8664e9a544d7547f4fcdbfe2fa6396b8f7654 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 28 Jan 2019 18:56:53 +0100 Subject: [PATCH] bootspec: load entries from both the ESP and XBOOTLDR partitions Let's simply search in both. --- src/boot/bootctl.c | 4 +-- src/shared/bootspec.c | 74 ++++++++++++++++++++++++--------------- src/shared/bootspec.h | 4 +-- src/systemctl/systemctl.c | 2 +- 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index 2424aa011f7..ddbcac92007 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -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; diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index c662e890684..6f28c74a5d1 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -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; } diff --git a/src/shared/bootspec.h b/src/shared/bootspec.h index 0fac051398a..f1849025586 100644 --- a/src/shared/bootspec.h +++ b/src/shared/bootspec.h @@ -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); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index d30b607c43e..57e3111b8d6 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -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) -- 2.39.5