]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
efi: share setting of generic efivars between sd-stub/sd-boot 33493/head
authorLennart Poettering <lennart@poettering.net>
Wed, 26 Jun 2024 13:18:57 +0000 (15:18 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 26 Jun 2024 15:09:45 +0000 (17:09 +0200)
We have very similar code for setting generic efi vars in sd-stub and
sd-boot. Let's share it.

This changes behaviour in a minor way: if you chainload multiple
versions of an sd-boot you'll see the efi vars of the first one now in
the OS, not of the last one.

But this should not matter, invocation like that should generally not
happen.

src/boot/efi/boot.c
src/boot/efi/export-vars.c [new file with mode: 0644]
src/boot/efi/export-vars.h [new file with mode: 0644]
src/boot/efi/meson.build
src/boot/efi/stub.c

index 99061a1339076bb3f2d1741ef87f56d971305930..9dbf96f169f232a7ed625ac0411d497e40610503 100644 (file)
@@ -7,6 +7,7 @@
 #include "devicetree.h"
 #include "drivers.h"
 #include "efivars-fundamental.h"
+#include "export-vars.h"
 #include "graphics.h"
 #include "initrd.h"
 #include "linux.h"
@@ -2538,9 +2539,8 @@ static EFI_STATUS secure_boot_discover_keys(Config *config, EFI_FILE *root_dir)
         return EFI_SUCCESS;
 }
 
-static void export_variables(
+static void export_loader_variables(
                 EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
-                const char16_t *loaded_image_path,
                 uint64_t init_usec) {
 
         static const uint64_t loader_features =
@@ -2560,28 +2560,11 @@ static void export_variables(
                 EFI_LOADER_FEATURE_MENU_DISABLE |
                 0;
 
-        _cleanup_free_ char16_t *infostr = NULL, *typestr = NULL;
-
         assert(loaded_image);
 
-        efivar_set_time_usec(MAKE_GUID_PTR(LOADER), u"LoaderTimeInitUSec", init_usec);
-        efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderInfo", u"systemd-boot " GIT_VERSION, 0);
-
-        infostr = xasprintf("%ls %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
-        efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareInfo", infostr, 0);
-
-        typestr = xasprintf("UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
-        efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareType", typestr, 0);
-
+        (void) efivar_set_time_usec(MAKE_GUID_PTR(LOADER), u"LoaderTimeInitUSec", init_usec);
+        (void) efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderInfo", u"systemd-boot " GIT_VERSION, 0);
         (void) efivar_set_uint64_le(MAKE_GUID_PTR(LOADER), u"LoaderFeatures", loader_features, 0);
-
-        /* the filesystem path to this image, to prevent adding ourselves to the menu */
-        efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderImageIdentifier", loaded_image_path, 0);
-
-        /* export the device path this image is started from */
-        _cleanup_free_ char16_t *uuid = disk_get_part_uuid(loaded_image->DeviceHandle);
-        if (uuid)
-                efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderDevicePartUUID", uuid, 0);
 }
 
 static void config_load_all_entries(
@@ -2681,7 +2664,6 @@ static EFI_STATUS run(EFI_HANDLE image) {
         EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
         _cleanup_(file_closep) EFI_FILE *root_dir = NULL;
         _cleanup_(config_free) Config config = {};
-        _cleanup_free_ char16_t *loaded_image_path = NULL;
         EFI_STATUS err;
         uint64_t init_usec;
         bool menu = false;
@@ -2696,9 +2678,8 @@ static EFI_STATUS run(EFI_HANDLE image) {
         if (err != EFI_SUCCESS)
                 return log_error_status(err, "Error getting a LoadedImageProtocol handle: %m");
 
-        (void) device_path_to_str(loaded_image->FilePath, &loaded_image_path);
-
-        export_variables(loaded_image, loaded_image_path, init_usec);
+        export_common_variables(loaded_image);
+        export_loader_variables(loaded_image, init_usec);
 
         err = discover_root_dir(loaded_image, &root_dir);
         if (err != EFI_SUCCESS)
@@ -2706,6 +2687,8 @@ static EFI_STATUS run(EFI_HANDLE image) {
 
         (void) load_drivers(image, loaded_image, root_dir);
 
+        _cleanup_free_ char16_t *loaded_image_path = NULL;
+        (void) device_path_to_str(loaded_image->FilePath, &loaded_image_path);
         config_load_all_entries(&config, loaded_image, loaded_image_path, root_dir);
 
         if (config.n_entries == 0)
diff --git a/src/boot/efi/export-vars.c b/src/boot/efi/export-vars.c
new file mode 100644 (file)
index 0000000..3926747
--- /dev/null
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "device-path-util.h"
+#include "export-vars.h"
+#include "part-discovery.h"
+#include "util.h"
+
+void export_common_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) {
+        assert(loaded_image);
+
+        /* Export the device path this image is started from, if it's not set yet */
+        if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderDevicePartUUID", NULL, NULL) != EFI_SUCCESS) {
+                _cleanup_free_ char16_t *uuid = disk_get_part_uuid(loaded_image->DeviceHandle);
+                if (uuid)
+                        efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderDevicePartUUID", uuid, 0);
+        }
+
+        /* If LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from the
+         * UEFI firmware without any boot loader, and hence set the LoaderImageIdentifier ourselves. Note
+         * that some boot chain loaders neither set LoaderImageIdentifier nor make FilePath available to us,
+         * in which case there's simple nothing to set for us. (The UEFI spec doesn't really say who's wrong
+         * here, i.e. whether FilePath may be NULL or not, hence handle this gracefully and check if FilePath
+         * is non-NULL explicitly.) */
+        if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderImageIdentifier", NULL, NULL) != EFI_SUCCESS &&
+            loaded_image->FilePath) {
+                _cleanup_free_ char16_t *s = NULL;
+                if (device_path_to_str(loaded_image->FilePath, &s) == EFI_SUCCESS)
+                        efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderImageIdentifier", s, 0);
+        }
+
+        /* if LoaderFirmwareInfo is not set, let's set it */
+        if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) {
+                _cleanup_free_ char16_t *s = NULL;
+                s = xasprintf("%ls %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
+                efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareInfo", s, 0);
+        }
+
+        /* ditto for LoaderFirmwareType */
+        if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) {
+                _cleanup_free_ char16_t *s = NULL;
+                s = xasprintf("UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
+                efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareType", s, 0);
+        }
+}
diff --git a/src/boot/efi/export-vars.h b/src/boot/efi/export-vars.h
new file mode 100644 (file)
index 0000000..a925d09
--- /dev/null
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "proto/loaded-image.h"
+
+void export_common_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image);
index 7a60b0ec7ed1be70cfff6fa12cadf8e8f43f3dcb..42a7914bf685df7159598271d78a969ce80755ae 100644 (file)
@@ -258,6 +258,7 @@ libefi_sources = files(
         'devicetree.c',
         'drivers.c',
         'efi-string.c',
+        'export-vars.c',
         'graphics.c',
         'initrd.c',
         'log.c',
index 3e95eb17859fcf0f7c3160cc86791adbee6365ba..db4f4734102effe5446abbc45d29ddc52f57abfe 100644 (file)
@@ -3,6 +3,7 @@
 #include "cpio.h"
 #include "device-path-util.h"
 #include "devicetree.h"
+#include "export-vars.h"
 #include "graphics.h"
 #include "iovec-util-fundamental.h"
 #include "linux.h"
@@ -138,7 +139,7 @@ static EFI_STATUS combine_initrds(
         return EFI_SUCCESS;
 }
 
-static void export_general_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) {
+static void export_stub_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) {
         static const uint64_t stub_features =
                 EFI_STUB_FEATURE_REPORT_BOOT_PARTITION |    /* We set LoaderDevicePartUUID */
                 EFI_STUB_FEATURE_PICK_UP_CREDENTIALS |      /* We pick up credentials from the boot partition */
@@ -153,40 +154,6 @@ static void export_general_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) {
 
         assert(loaded_image);
 
-        /* Export the device path this image is started from, if it's not set yet */
-        if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderDevicePartUUID", NULL, NULL) != EFI_SUCCESS) {
-                _cleanup_free_ char16_t *uuid = disk_get_part_uuid(loaded_image->DeviceHandle);
-                if (uuid)
-                        efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderDevicePartUUID", uuid, 0);
-        }
-
-        /* If LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from the
-         * UEFI firmware without any boot loader, and hence set the LoaderImageIdentifier ourselves. Note
-         * that some boot chain loaders neither set LoaderImageIdentifier nor make FilePath available to us,
-         * in which case there's simple nothing to set for us. (The UEFI spec doesn't really say who's wrong
-         * here, i.e. whether FilePath may be NULL or not, hence handle this gracefully and check if FilePath
-         * is non-NULL explicitly.) */
-        if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderImageIdentifier", NULL, NULL) != EFI_SUCCESS &&
-            loaded_image->FilePath) {
-                _cleanup_free_ char16_t *s = NULL;
-                if (device_path_to_str(loaded_image->FilePath, &s) == EFI_SUCCESS)
-                        efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderImageIdentifier", s, 0);
-        }
-
-        /* if LoaderFirmwareInfo is not set, let's set it */
-        if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) {
-                _cleanup_free_ char16_t *s = NULL;
-                s = xasprintf("%ls %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
-                efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareInfo", s, 0);
-        }
-
-        /* ditto for LoaderFirmwareType */
-        if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) {
-                _cleanup_free_ char16_t *s = NULL;
-                s = xasprintf("UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
-                efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareType", s, 0);
-        }
-
         /* add StubInfo (this is one is owned by the stub, hence we unconditionally override this with our
          * own data) */
         (void) efivar_set(MAKE_GUID_PTR(LOADER), u"StubInfo", u"systemd-stub " GIT_VERSION, 0);
@@ -939,7 +906,8 @@ static EFI_STATUS run(EFI_HANDLE image) {
         cmdline_append_and_measure_addons(cmdline_addons, &cmdline, &parameters_measured);
         cmdline_append_and_measure_smbios(&cmdline, &parameters_measured);
 
-        export_general_variables(loaded_image);
+        export_common_variables(loaded_image);
+        export_stub_variables(loaded_image);
 
         /* First load the base device tree, then fix it up using addons - global first, then per-UKI. */
         install_embedded_devicetree(loaded_image, sections, &dt_state);