]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
bootctl: discover and pring global UKI PE addons 28761/head
authorEmanuele Giuseppe Esposito <eesposit@redhat.com>
Thu, 21 Sep 2023 11:59:24 +0000 (07:59 -0400)
committerEmanuele Giuseppe Esposito <eesposit@redhat.com>
Wed, 14 Feb 2024 09:58:28 +0000 (04:58 -0500)
An UKI final command line is not just made of the content of .cmdline,
but also from the addons that are inserted in
/boot/efi/EFI/Linux/<UKI_NAME>.efi.extra.d (local addons) and /boot/efi/loader/addons
(global addons).

Therefore bootclt "status" and "list" should also include these addons
when printing the UKI command line.

Support for /boot/efi/EFI/Linux/<UKI_NAME>.efi.extra.d is already present,
so now cover addons present in /boot/efi/loader/addons (global addons).

Example (assume UKI_NAME=devel):
$ bootctl
ukiCmdline: console=tty0 console=ttyS0
  globalAddon: loader/addons/global.addon.efi
      cmdline: └─quiet
   localAddon: devel.efi.extra.d/rpm_addon.addon.efi
      cmdline: └─this is a normal addon
 finalCmdline: console=tty0 console=ttyS0 quiet this is a normal addon

src/boot/bootctl-status.c
src/shared/bootspec.c
src/shared/bootspec.h

index b8813ec40a6fc8e4af928eb67b72e100d9e9d161..f8b57c1f9d474fbf5ae27f8e21b5d336501891f8 100644 (file)
@@ -92,6 +92,7 @@ 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);
index 16986c791229f0186efee1a950ec2ad8709ed95d..b0bf94c7daefcd4e8cc15956d6c514ea9b899cd9 100644 (file)
@@ -445,6 +445,7 @@ void boot_config_free(BootConfig *config) {
         for (size_t i = 0; i < config->n_entries; i++)
                 boot_entry_free(config->entries + i);
         free(config->entries);
+        free(config->global_addons.items);
 
         set_free(config->inodes_seen);
 }
@@ -958,6 +959,23 @@ static int boot_entries_find_unified_addons(
         return 0;
 }
 
+static int boot_entries_find_unified_global_addons(
+                BootConfig *config,
+                const char *root,
+                const char *d_name) {
+
+        int r;
+        _cleanup_closedir_ DIR *d = NULL;
+
+        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);
+}
+
 static int boot_entries_find_unified_local_addons(
                 BootConfig *config,
                 int d_fd,
@@ -1251,6 +1269,7 @@ 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");
@@ -1264,6 +1283,10 @@ int boot_config_load(
                 r = boot_entries_find_unified(config, esp_path, "/EFI/Linux/");
                 if (r < 0)
                         return r;
+
+                r = boot_entries_find_unified_global_addons(config, esp_path, "/loader/addons/");
+                if (r < 0)
+                        return r;
         }
 
         if (xbootldr_path) {
@@ -1435,7 +1458,10 @@ static void print_addon(
         printf("      cmdline: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), addon->cmdline);
 }
 
-static int print_cmdline(const BootEntry *e) {
+static int print_cmdline(
+                const BootEntry *e,
+                const BootEntryAddons *global_arr) {
+
         _cleanup_free_ char *final_cmdline = NULL;
 
         assert(e);
@@ -1460,6 +1486,12 @@ static int print_cmdline(const BootEntry *e) {
                 final_cmdline = TAKE_PTR(t2);
         }
 
+        FOREACH_ARRAY(addon, global_arr->items, global_arr->count) {
+                print_addon(addon, "globalAddon");
+                if (!strextend(&final_cmdline, " ", addon->cmdline))
+                        return log_oom();
+        }
+
         FOREACH_ARRAY(addon, e->local_addons.items, e->local_addons.count) {
                 /* Add space at the beginning of addon_str to align it correctly */
                 print_addon(addon, " localAddon");
@@ -1490,7 +1522,11 @@ static int json_addon(
         return 0;
 }
 
-static int json_cmdline(const BootEntry *e, JsonVariant **v) {
+static int json_cmdline(
+                const BootEntry *e,
+                const BootEntryAddons *global_arr,
+                JsonVariant **v) {
+
         _cleanup_free_ char *final_cmdline = NULL, *def_cmdline = NULL;
         _cleanup_(json_variant_unrefp) JsonVariant *addons_array = NULL;
         int r;
@@ -1504,6 +1540,14 @@ static int json_cmdline(const BootEntry *e, JsonVariant **v) {
                 final_cmdline = TAKE_PTR(def_cmdline);
         }
 
+        FOREACH_ARRAY(addon, global_arr->items, global_arr->count) {
+                r = json_addon(addon, "globalAddon", &addons_array);
+                if (r < 0)
+                        return r;
+                if (!strextend(&final_cmdline, " ", addon->cmdline))
+                        return log_oom();
+        }
+
         FOREACH_ARRAY(addon, e->local_addons.items, e->local_addons.count) {
                 r = json_addon(addon, "localAddon", &addons_array);
                 if (r < 0)
@@ -1524,6 +1568,7 @@ static int json_cmdline(const BootEntry *e, JsonVariant **v) {
 
 int show_boot_entry(
                 const BootEntry *e,
+                const BootEntryAddons *global_addons,
                 bool show_as_default,
                 bool show_as_selected,
                 bool show_reported) {
@@ -1607,7 +1652,7 @@ int show_boot_entry(
                                      *s,
                                      &status);
 
-        r = print_cmdline(e);
+        r = print_cmdline(e, global_addons);
         if (r < 0)
                 return r;
 
@@ -1655,7 +1700,7 @@ int show_boot_entries(const BootConfig *config, JsonFormatFlags json_format) {
                         if (r < 0)
                                 return log_oom();
 
-                        r = json_cmdline(e, &v);
+                        r = json_cmdline(e, &config->global_addons, &v);
                         if (r < 0)
                                 return log_oom();
 
@@ -1684,6 +1729,7 @@ int show_boot_entries(const BootConfig *config, JsonFormatFlags json_format) {
                 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);
index 141388143c966254825bd49d450102787992dd1c..8289325b9e313dd1cab7152206a0c525c577539e 100644 (file)
@@ -79,6 +79,8 @@ typedef struct BootConfig {
         BootEntry *entries;
         size_t n_entries;
 
+        BootEntryAddons global_addons;
+
         ssize_t default_entry;
         ssize_t selected_entry;
 
@@ -132,6 +134,7 @@ 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);