summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLuca Boccassi <bluca@debian.org>2024-11-27 11:55:32 +0100
committerGitHub <noreply@github.com>2024-11-27 11:55:32 +0100
commit0abaa5be10ed35b6998718972f4890a099810a2b (patch)
tree767447957d3e1a8c1abc2a2d48987d406051f7a3 /src
parentukify: Switch to JSON HWID description format (#35208) (diff)
parentbootspec: Look at /loader/addons in XBOOTLDR (diff)
downloadsystemd-0abaa5be10ed35b6998718972f4890a099810a2b.tar.xz
systemd-0abaa5be10ed35b6998718972f4890a099810a2b.zip
bootspec fixups (#34959)
Diffstat (limited to 'src')
-rw-r--r--src/boot/stub.c4
-rw-r--r--src/bootctl/bootctl-status.c1
-rw-r--r--src/fuzz/fuzz-bootspec.c2
-rw-r--r--src/shared/bootspec.c100
-rw-r--r--src/shared/bootspec.h21
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);