diff options
author | Luca Boccassi <bluca@debian.org> | 2024-11-27 11:55:32 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-27 11:55:32 +0100 |
commit | 0abaa5be10ed35b6998718972f4890a099810a2b (patch) | |
tree | 767447957d3e1a8c1abc2a2d48987d406051f7a3 /src | |
parent | ukify: Switch to JSON HWID description format (#35208) (diff) | |
parent | bootspec: Look at /loader/addons in XBOOTLDR (diff) | |
download | systemd-0abaa5be10ed35b6998718972f4890a099810a2b.tar.xz systemd-0abaa5be10ed35b6998718972f4890a099810a2b.zip |
bootspec fixups (#34959)
Diffstat (limited to 'src')
-rw-r--r-- | src/boot/stub.c | 4 | ||||
-rw-r--r-- | src/bootctl/bootctl-status.c | 1 | ||||
-rw-r--r-- | src/fuzz/fuzz-bootspec.c | 2 | ||||
-rw-r--r-- | src/shared/bootspec.c | 100 | ||||
-rw-r--r-- | src/shared/bootspec.h | 21 |
5 files changed, 89 insertions, 39 deletions
diff --git a/src/boot/stub.c b/src/boot/stub.c index c92df686c8..cf990df2e7 100644 --- a/src/boot/stub.c +++ b/src/boot/stub.c @@ -858,7 +858,7 @@ static void generate_sidecar_initrds( /* access_mode= */ 0444, /* tpm_pcr= */ TPM2_PCR_SYSEXTS, u"System extension initrd", - initrds + INITRD_CONFEXT, + initrds + INITRD_SYSEXT, &m) == EFI_SUCCESS) combine_measured_flag(sysext_measured, m); @@ -871,7 +871,7 @@ static void generate_sidecar_initrds( /* access_mode= */ 0444, /* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG, u"Configuration extension initrd", - initrds + INITRD_SYSEXT, + initrds + INITRD_CONFEXT, &m) == EFI_SUCCESS) combine_measured_flag(confext_measured, m); } diff --git a/src/bootctl/bootctl-status.c b/src/bootctl/bootctl-status.c index 229c1ad535..6bcb348935 100644 --- a/src/bootctl/bootctl-status.c +++ b/src/bootctl/bootctl-status.c @@ -92,7 +92,6 @@ static int status_entries( r = show_boot_entry( boot_config_default_entry(config), - &config->global_addons, /* show_as_default= */ false, /* show_as_selected= */ false, /* show_discovered= */ false); diff --git a/src/fuzz/fuzz-bootspec.c b/src/fuzz/fuzz-bootspec.c index e49acafe31..561deb5977 100644 --- a/src/fuzz/fuzz-bootspec.c +++ b/src/fuzz/fuzz-bootspec.c @@ -55,7 +55,7 @@ static int json_dispatch_entries(const char *name, sd_json_variant *variant, sd_ _cleanup_fclose_ FILE *f = NULL; assert_se(f = data_to_file((const uint8_t*) data, len)); - assert_se(boot_config_load_type1(config, f, "/", "/entries", id) != -ENOMEM); + assert_se(boot_config_load_type1(config, f, "/", BOOT_ENTRY_ESP, "/entries", id) != -ENOMEM); } } diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index 584515a297..9c4877055a 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -44,6 +44,22 @@ static const char* const boot_entry_type_json_table[_BOOT_ENTRY_TYPE_MAX] = { DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type_json, BootEntryType); +static const char* const boot_entry_source_table[_BOOT_ENTRY_SOURCE_MAX] = { + [BOOT_ENTRY_ESP] = "EFI System Partition", + [BOOT_ENTRY_XBOOTLDR] = "Extended Boot Loader Partition", +}; + +DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_source, BootEntrySource); + +static const char* const boot_entry_source_json_table[_BOOT_ENTRY_SOURCE_MAX] = { + [BOOT_ENTRY_ESP] = "esp", + [BOOT_ENTRY_XBOOTLDR] = "xbootldr", +}; + +DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_source_json, BootEntrySource); + +static void boot_entry_addons_done(BootEntryAddons *addons); + static void boot_entry_free(BootEntry *entry) { assert(entry); @@ -59,7 +75,7 @@ static void boot_entry_free(BootEntry *entry) { free(entry->machine_id); free(entry->architecture); strv_free(entry->options); - free(entry->local_addons.items); + boot_entry_addons_done(&entry->local_addons); free(entry->kernel); free(entry->efi); strv_free(entry->initrd); @@ -283,11 +299,12 @@ nothing: static int boot_entry_load_type1( FILE *f, const char *root, + const BootEntrySource source, const char *dir, const char *fname, BootEntry *entry) { - _cleanup_(boot_entry_free) BootEntry tmp = BOOT_ENTRY_INIT(BOOT_ENTRY_CONF); + _cleanup_(boot_entry_free) BootEntry tmp = BOOT_ENTRY_INIT(BOOT_ENTRY_CONF, source); char *c; int r; @@ -393,6 +410,7 @@ int boot_config_load_type1( BootConfig *config, FILE *f, const char *root, + const BootEntrySource source, const char *dir, const char *fname) { int r; @@ -406,10 +424,14 @@ int boot_config_load_type1( if (!GREEDY_REALLOC0(config->entries, config->n_entries + 1)) return log_oom(); - r = boot_entry_load_type1(f, root, dir, fname, config->entries + config->n_entries); + BootEntry *entry = config->entries + config->n_entries; + + r = boot_entry_load_type1(f, root, source, dir, fname, entry); if (r < 0) return r; + entry->global_addons = &config->global_addons[source]; + config->n_entries++; return 0; } @@ -426,7 +448,9 @@ void boot_config_free(BootConfig *config) { FOREACH_ARRAY(i, config->entries, config->n_entries) boot_entry_free(i); free(config->entries); - free(config->global_addons.items); + + FOREACH_ARRAY(i, config->global_addons, _BOOT_ENTRY_SOURCE_MAX) + boot_entry_addons_done(i); set_free(config->inodes_seen); } @@ -592,6 +616,7 @@ static int config_check_inode_relevant_and_unseen(BootConfig *config, int fd, co static int boot_entries_find_type1( BootConfig *config, const char *root, + const BootEntrySource source, const char *dir) { _cleanup_free_ DirectoryEntries *dentries = NULL; @@ -635,7 +660,7 @@ static int boot_entries_find_type1( if (r == 0) /* inode already seen or otherwise not relevant */ continue; - r = boot_config_load_type1(config, f, root, full, de->d_name); + r = boot_config_load_type1(config, f, root, source, full, de->d_name); if (r == -ENOMEM) /* ignore all other errors */ return log_oom(); } @@ -645,6 +670,7 @@ static int boot_entries_find_type1( static int boot_entry_load_unified( const char *root, + const BootEntrySource source, const char *path, unsigned profile, const char *osrelease_text, @@ -717,7 +743,7 @@ static int boot_entry_load_unified( if (r < 0) return log_error_errno(r, "Failed to extract file name from '%s': %m", path); - _cleanup_(boot_entry_free) BootEntry tmp = BOOT_ENTRY_INIT(BOOT_ENTRY_UNIFIED); + _cleanup_(boot_entry_free) BootEntry tmp = BOOT_ENTRY_INIT(BOOT_ENTRY_UNIFIED, source); r = boot_filename_extract_tries(fname, &tmp.id, &tmp.tries_left, &tmp.tries_done); if (r < 0) @@ -1130,18 +1156,21 @@ static int boot_entries_find_unified_addons( static int boot_entries_find_unified_global_addons( BootConfig *config, const char *root, - const char *d_name) { + const char *d_name, + BootEntryAddons *ret_addons) { int r; _cleanup_closedir_ DIR *d = NULL; + assert(ret_addons); + r = chase_and_opendir(root, NULL, CHASE_PROHIBIT_SYMLINKS, NULL, &d); if (r == -ENOENT) return 0; if (r < 0) return log_error_errno(r, "Failed to open '%s/%s': %m", root, d_name); - return boot_entries_find_unified_addons(config, dirfd(d), d_name, root, &config->global_addons); + return boot_entries_find_unified_addons(config, dirfd(d), d_name, root, ret_addons); } static int boot_entries_find_unified_local_addons( @@ -1165,6 +1194,7 @@ static int boot_entries_find_unified_local_addons( static int boot_entries_find_unified( BootConfig *config, const char *root, + BootEntrySource source, const char *dir) { _cleanup_closedir_ DIR *d = NULL; @@ -1212,16 +1242,21 @@ static int boot_entries_find_unified( if (r < 0) continue; - if (!GREEDY_REALLOC0(config->entries, config->n_entries + 2)) + if (!GREEDY_REALLOC0(config->entries, config->n_entries + 1)) return log_oom(); - if (boot_entry_load_unified(root, j, p, osrelease, profile, cmdline, config->entries + config->n_entries) < 0) - continue; + BootEntry *entry = config->entries + config->n_entries; - config->n_entries++; + if (boot_entry_load_unified(root, source, j, p, osrelease, profile, cmdline, config->entries + config->n_entries) < 0) + continue; /* look for .efi.extra.d */ - (void) boot_entries_find_unified_local_addons(config, dirfd(d), de->d_name, full, config->entries + config->n_entries); + (void) boot_entries_find_unified_local_addons(config, dirfd(d), de->d_name, full, entry); + + /* Set up the backpointer, so that we can find the global addons */ + entry->global_addons = &config->global_addons[source]; + + config->n_entries++; } } @@ -1438,32 +1473,37 @@ int boot_config_load( int r; assert(config); - config->global_addons = (BootEntryAddons) {}; if (esp_path) { r = boot_loader_read_conf_path(config, esp_path, "/loader/loader.conf"); if (r < 0) return r; - r = boot_entries_find_type1(config, esp_path, "/loader/entries"); + r = boot_entries_find_type1(config, esp_path, BOOT_ENTRY_ESP, "/loader/entries"); if (r < 0) return r; - r = boot_entries_find_unified(config, esp_path, "/EFI/Linux/"); + r = boot_entries_find_unified(config, esp_path, BOOT_ENTRY_ESP, "/EFI/Linux/"); if (r < 0) return r; - r = boot_entries_find_unified_global_addons(config, esp_path, "/loader/addons/"); + r = boot_entries_find_unified_global_addons(config, esp_path, "/loader/addons/", + &config->global_addons[BOOT_ENTRY_ESP]); if (r < 0) return r; } if (xbootldr_path) { - r = boot_entries_find_type1(config, xbootldr_path, "/loader/entries"); + r = boot_entries_find_type1(config, xbootldr_path, BOOT_ENTRY_XBOOTLDR, "/loader/entries"); + if (r < 0) + return r; + + r = boot_entries_find_unified(config, xbootldr_path, BOOT_ENTRY_XBOOTLDR, "/EFI/Linux/"); if (r < 0) return r; - r = boot_entries_find_unified(config, xbootldr_path, "/EFI/Linux/"); + r = boot_entries_find_unified_global_addons(config, xbootldr_path, "/loader/addons/", + &config->global_addons[BOOT_ENTRY_XBOOTLDR]); if (r < 0) return r; } @@ -1518,6 +1558,7 @@ int boot_config_augment_from_loader( char **found_by_loader, bool only_auto) { + static const BootEntryAddons no_addons = (BootEntryAddons) {}; static const char *const title_table[] = { /* Pretty names for a few well-known automatically discovered entries. */ "auto-osx", "macOS", @@ -1575,6 +1616,7 @@ int boot_config_augment_from_loader( .reported_by_loader = true, .tries_left = UINT_MAX, .tries_done = UINT_MAX, + .global_addons = &no_addons, }; } @@ -1646,9 +1688,7 @@ static int indent_embedded_newlines(char *cmdline, char **ret_cmdline) { return 0; } -static int print_cmdline( - const BootEntry *e, - const BootEntryAddons *global_arr) { +static int print_cmdline(const BootEntry *e) { _cleanup_free_ char *options = NULL, *combined_cmdline = NULL, *t2 = NULL; @@ -1670,7 +1710,7 @@ static int print_cmdline( return log_oom(); } - FOREACH_ARRAY(addon, global_arr->items, global_arr->n_items) { + FOREACH_ARRAY(addon, e->global_addons->items, e->global_addons->n_items) { print_addon(addon, "global-addon"); if (!strextend(&t2, " ", addon->cmdline)) return log_oom(); @@ -1718,7 +1758,6 @@ static int json_addon( static int json_cmdline( const BootEntry *e, - const BootEntryAddons *global_arr, const char *def_cmdline, sd_json_variant **v) { @@ -1734,7 +1773,7 @@ static int json_cmdline( return log_oom(); } - FOREACH_ARRAY(addon, global_arr->items, global_arr->n_items) { + FOREACH_ARRAY(addon, e->global_addons->items, e->global_addons->n_items) { r = json_addon(addon, "globalAddon", &addons_array); if (r < 0) return r; @@ -1761,7 +1800,6 @@ static int json_cmdline( int show_boot_entry( const BootEntry *e, - const BootEntryAddons *global_addons, bool show_as_default, bool show_as_selected, bool show_reported) { @@ -1821,7 +1859,9 @@ int show_boot_entry( if (e->type == BOOT_ENTRY_CONF) (void) terminal_urlify_path(e->path, text, &link); - printf(" source: %s\n", link ?: text ?: e->path); + printf(" source: %s (on the %s)\n", + link ?: text ?: e->path, + boot_entry_source_to_string(e->source)); } if (e->tries_left != UINT_MAX) { printf(" tries: %u left", e->tries_left); @@ -1851,7 +1891,7 @@ int show_boot_entry( *s, &status); - r = print_cmdline(e, global_addons); + r = print_cmdline(e); if (r < 0) return r; @@ -1892,6 +1932,7 @@ int boot_entry_to_json(const BootConfig *c, size_t i, sd_json_variant **ret) { r = sd_json_variant_merge_objectbo( &v, SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(boot_entry_type_json_to_string(e->type))), + SD_JSON_BUILD_PAIR("source", SD_JSON_BUILD_STRING(boot_entry_source_json_to_string(e->source))), SD_JSON_BUILD_PAIR_CONDITION(!!e->id, "id", SD_JSON_BUILD_STRING(e->id)), SD_JSON_BUILD_PAIR_CONDITION(!!e->path, "path", SD_JSON_BUILD_STRING(e->path)), SD_JSON_BUILD_PAIR_CONDITION(!!e->root, "root", SD_JSON_BUILD_STRING(e->root)), @@ -1923,7 +1964,7 @@ int boot_entry_to_json(const BootConfig *c, size_t i, sd_json_variant **ret) { if (r < 0) return log_oom(); - r = json_cmdline(e, &c->global_addons, opts, &v); + r = json_cmdline(e, opts, &v); if (r < 0) return log_oom(); @@ -1956,7 +1997,6 @@ int show_boot_entries(const BootConfig *config, sd_json_format_flags_t json_form for (size_t n = 0; n < config->n_entries; n++) { r = show_boot_entry( config->entries + n, - &config->global_addons, /* show_as_default= */ n == (size_t) config->default_entry, /* show_as_selected= */ n == (size_t) config->selected_entry, /* show_discovered= */ true); diff --git a/src/shared/bootspec.h b/src/shared/bootspec.h index 58c676fbec..6dda8549a1 100644 --- a/src/shared/bootspec.h +++ b/src/shared/bootspec.h @@ -21,6 +21,13 @@ typedef enum BootEntryType { _BOOT_ENTRY_TYPE_INVALID = -EINVAL, } BootEntryType; +typedef enum BootEntrySource { + BOOT_ENTRY_ESP, + BOOT_ENTRY_XBOOTLDR, + _BOOT_ENTRY_SOURCE_MAX, + _BOOT_ENTRY_SOURCE_INVALID = -EINVAL, +} BootEntrySource; + typedef struct BootEntryAddon { char *location; char *cmdline; @@ -31,10 +38,9 @@ typedef struct BootEntryAddons { size_t n_items; } BootEntryAddons; -BootEntryAddon* boot_entry_addon_free(BootEntryAddon *t); - typedef struct BootEntry { BootEntryType type; + BootEntrySource source; bool reported_by_loader; char *id; /* This is the file basename (including extension!) */ char *id_old; /* Old-style ID, for deduplication purposes. */ @@ -49,6 +55,7 @@ typedef struct BootEntry { char *architecture; char **options; BootEntryAddons local_addons; + const BootEntryAddons *global_addons; /* Backpointer into the BootConfig; we don't own this here */ char *kernel; /* linux is #defined to 1, yikes! */ char *efi; char **initrd; @@ -59,9 +66,10 @@ typedef struct BootEntry { unsigned profile; } BootEntry; -#define BOOT_ENTRY_INIT(t) \ +#define BOOT_ENTRY_INIT(t, s) \ { \ .type = (t), \ + .source = (s), \ .tries_left = UINT_MAX, \ .tries_done = UINT_MAX, \ } @@ -76,7 +84,7 @@ typedef struct BootConfig { BootEntry *entries; size_t n_entries; - BootEntryAddons global_addons; + BootEntryAddons global_addons[_BOOT_ENTRY_SOURCE_MAX]; ssize_t default_entry; ssize_t selected_entry; @@ -93,6 +101,9 @@ typedef struct BootConfig { const char* boot_entry_type_to_string(BootEntryType); const char* boot_entry_type_json_to_string(BootEntryType); +const char* boot_entry_source_to_string(BootEntrySource); +const char* boot_entry_source_json_to_string(BootEntrySource); + BootEntry* boot_config_find_entry(BootConfig *config, const char *id); static inline const BootEntry* boot_config_default_entry(const BootConfig *config) { @@ -113,6 +124,7 @@ int boot_config_load_type1( BootConfig *config, FILE *f, const char *root, + const BootEntrySource source, const char *dir, const char *id); @@ -131,7 +143,6 @@ static inline const char* boot_entry_title(const BootEntry *entry) { int show_boot_entry( const BootEntry *e, - const BootEntryAddons *global_addons, bool show_as_default, bool show_as_selected, bool show_reported); |