diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index 5715c94d68..c662e89068 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -27,6 +27,7 @@ static void boot_entry_free(BootEntry *entry) { free(entry->id); free(entry->path); + free(entry->root); free(entry->title); free(entry->show_title); free(entry->version); @@ -39,13 +40,18 @@ static void boot_entry_free(BootEntry *entry) { free(entry->device_tree); } -static int boot_entry_load(const char *path, BootEntry *entry) { +static int boot_entry_load( + const char *root, + const char *path, + BootEntry *entry) { + _cleanup_(boot_entry_free) BootEntry tmp = {}; _cleanup_fclose_ FILE *f = NULL; unsigned line = 1; char *b, *c; int r; + assert(root); assert(path); assert(entry); @@ -62,6 +68,10 @@ static int boot_entry_load(const char *path, BootEntry *entry) { if (!tmp.path) return log_oom(); + tmp.root = strdup(root); + if (!tmp.root) + return log_oom(); + f = fopen(path, "re"); if (!f) return log_error_errno(errno, "Failed to open \"%s\": %m", path); @@ -215,13 +225,19 @@ static int boot_entry_compare(const BootEntry *a, const BootEntry *b) { return str_verscmp(a->id, b->id); } -static int boot_entries_find(const char *dir, BootEntry **ret_entries, size_t *ret_n_entries) { +static int boot_entries_find( + const char *root, + const char *dir, + BootEntry **ret_entries, + size_t *ret_n_entries) { + _cleanup_strv_free_ char **files = NULL; 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); @@ -234,7 +250,7 @@ static int boot_entries_find(const char *dir, BootEntry **ret_entries, size_t *r if (!GREEDY_REALLOC0(array, n_allocated, n + 1)) return log_oom(); - r = boot_entry_load(*f, array + n); + r = boot_entry_load(root, *f, array + n); if (r < 0) continue; @@ -369,7 +385,7 @@ int boot_entries_load_config(const char *esp_path, BootConfig *config) { return r; p = strjoina(esp_path, "/loader/entries"); - r = boot_entries_find(p, &config->entries, &config->n_entries); + r = boot_entries_find(esp_path, p, &config->entries, &config->n_entries); if (r < 0) return r; @@ -799,7 +815,6 @@ found: int find_default_boot_entry( const char *esp_path, - char **esp_where, BootConfig *config, const BootEntry **e) { @@ -824,8 +839,5 @@ int find_default_boot_entry( *e = &config->entries[config->default_entry]; log_debug("Found default boot entry in file \"%s\"", (*e)->path); - if (esp_where) - *esp_where = TAKE_PTR(where); - return 0; } diff --git a/src/shared/bootspec.h b/src/shared/bootspec.h index 8a22fd5cdd..0fac051398 100644 --- a/src/shared/bootspec.h +++ b/src/shared/bootspec.h @@ -10,7 +10,8 @@ typedef struct BootEntry { char *id; /* This is the file basename without extension */ - char *path; /* This is the full path to the file */ + 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 */ char *title; char *show_title; char *version; @@ -49,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, char **esp_where, BootConfig *config, const BootEntry **e); +int find_default_boot_entry(const char *esp_path, BootConfig *config, const BootEntry **e); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 63dae2c872..6900f61e9e 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3519,7 +3519,7 @@ static int prepare_firmware_setup(void) { static int load_kexec_kernel(void) { _cleanup_(boot_config_free) BootConfig config = {}; - _cleanup_free_ char *where = NULL, *kernel = NULL, *initrd = NULL, *options = NULL; + _cleanup_free_ char *kernel = NULL, *initrd = NULL, *options = NULL; const BootEntry *e; pid_t pid; int r; @@ -3532,7 +3532,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(arg_esp_path, &where, &config, &e); + r = find_default_boot_entry(arg_esp_path, &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) @@ -3544,9 +3544,9 @@ static int load_kexec_kernel(void) { return -EINVAL; } - kernel = path_join(where, e->kernel); + kernel = path_join(e->root, e->kernel); if (!strv_isempty(e->initrd)) - initrd = path_join(where, *e->initrd); + initrd = path_join(e->root, *e->initrd); options = strv_join(e->options, " "); if (!options) return log_oom();