]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-stub: if we are http booted, query source URL and write to EFI variable
authorLennart Poettering <lennart@poettering.net>
Fri, 7 Feb 2025 22:30:13 +0000 (23:30 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 21 Feb 2025 09:03:32 +0000 (10:03 +0100)
This way userspace can read the field, and use it to retrieve more
resources from the same place.

12 files changed:
docs/BOOT_LOADER_INTERFACE.md
man/systemd-boot.xml
man/systemd-stub.xml
src/boot/boot.c
src/boot/export-vars.c
src/boot/meson.build
src/boot/proto/device-path.h
src/boot/stub.c
src/boot/url-discovery.c [new file with mode: 0644]
src/boot/url-discovery.h [new file with mode: 0644]
src/bootctl/bootctl-status.c
src/fundamental/efivars-fundamental.h

index 4bf074df5e52cad3dbe94c4b1cbee2bd3b7c84e2..e264c2cc3c1ac482c6356a6acff209c7dea0a442 100644 (file)
@@ -97,6 +97,9 @@ variables. All EFI variables use the vendor UUID
   generally only written once, by the OS installer, and is usually not touched
   after that.
 
+* The EFI variable `LoaderDeviceURL` contains the URL the boot loader was
+  downloaded from, in UTF-16 format. Only set in case of network boots.
+
 If `LoaderTimeInitUSec` and `LoaderTimeExecUSec` are set, `systemd-analyze`
 will include them in its boot-time analysis.  If `LoaderDevicePartUUID` is set,
 systemd will mount the ESP that was used for the boot to `/boot`, but only if
index 18b0708035d82f294ab036d5399a7636dddabb54..22f3cdb4cae39baa70ca2bd9b0957a83b3375d77 100644 (file)
         <xi:include href="version-info.xml" xpointer="v220"/></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>LoaderDeviceURL</varname></term>
+
+        <listitem><para>If the boot loader has been invoked via network booting this variable contains the
+        originating URL. This may be used to automatically acquire additional resources from the same
+        source.</para>
+
+        <xi:include href="version-info.xml" xpointer="v258"/></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>LoaderEntries</varname></term>
 
index 730d27cf6c392fa23183b03cdf0fa745b48de456..273513c14bd9ef76fe8afd5db118dd7a833836fe 100644 (file)
         <xi:include href="version-info.xml" xpointer="v257"/></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>StubDeviceURL</varname></term>
+
+        <listitem><para>If the kernel image has been invoked via network booting this variable contains the
+        originating URL. This may be used to automatically acquire additional resources from the same
+        source.</para>
+
+        <xi:include href="version-info.xml" xpointer="v258"/></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>StubInfo</varname></term>
 
index 53bd22c42d459549c4ca474935d226e53e9fadd8..7c91e5d3896f751dc543c8aa8e1585550ca88e8d 100644 (file)
@@ -2764,6 +2764,7 @@ static void export_loader_variables(
                 EFI_LOADER_FEATURE_RETAIN_SHIM |
                 EFI_LOADER_FEATURE_MENU_DISABLE |
                 EFI_LOADER_FEATURE_MULTI_PROFILE_UKI |
+                EFI_LOADER_FEATURE_REPORT_URL |
                 0;
 
         assert(loaded_image);
index 12fbd10b054da2f9715a742a9373bf9f91bcd59c..fb281ad394c795ccbe2256eff843dd1c859ebeb8 100644 (file)
@@ -4,17 +4,25 @@
 #include "efivars.h"
 #include "export-vars.h"
 #include "part-discovery.h"
+#include "url-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 (loaded_image->DeviceHandle &&
-            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_str16(MAKE_GUID_PTR(LOADER), u"LoaderDevicePartUUID", uuid, 0);
+        if (loaded_image->DeviceHandle) {
+                if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderDevicePartUUID", /* ret_data= */ NULL, /* ret_size= */ NULL) != EFI_SUCCESS) {
+                        _cleanup_free_ char16_t *uuid = disk_get_part_uuid(loaded_image->DeviceHandle);
+                        if (uuid)
+                                efivar_set_str16(MAKE_GUID_PTR(LOADER), u"LoaderDevicePartUUID", uuid, 0);
+                }
+
+                if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderDeviceURL", /* ret_data= */ NULL, /* ret_size= */ NULL) != EFI_SUCCESS) {
+                        _cleanup_free_ char16_t *url = disk_get_url(loaded_image->DeviceHandle);
+                        if (url)
+                                efivar_set_str16(MAKE_GUID_PTR(LOADER), u"LoaderDeviceURL", url, 0);
+                }
         }
 
         /* If LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from the
index 3af5006d598367413ce95a7100afb6b8660e418e..69c8e40ad3ada070cee7ce65d33269b7e2b6f394 100644 (file)
@@ -300,6 +300,7 @@ libefi_sources = files(
         'shim.c',
         'smbios.c',
         'ticks.c',
+        'url-discovery.c',
         'util.c',
         'vmm.c',
 )
index 0fabae1125cc13ac19dc2a7a4a74b3b1285332a1..a394b0aa6d23a256addfc19fa214fb1f1147d913 100644 (file)
@@ -30,6 +30,8 @@ enum {
         MEDIA_FILEPATH_DP                = 0x04,
         MEDIA_PIWG_FW_FILE_DP            = 0x06,
         MEDIA_PIWG_FW_VOL_DP             = 0x07,
+
+        MSG_URI_DP                       = 24,
 };
 
 struct _packed_ EFI_DEVICE_PATH_PROTOCOL {
@@ -67,6 +69,11 @@ typedef struct {
         char16_t PathName[];
 } _packed_ FILEPATH_DEVICE_PATH;
 
+typedef struct {
+        EFI_DEVICE_PATH Header;
+        char Uri[];
+} _packed_ URI_DEVICE_PATH;
+
 typedef struct {
         char16_t* (EFIAPI *ConvertDeviceNodeToText)(
                         const EFI_DEVICE_PATH *DeviceNode,
index e74b7db95adf0dc07ab4abf7a6ddb9e8a61055a3..3b3a5f6a42822e50ab4260689b84929e91db84ce 100644 (file)
@@ -21,6 +21,7 @@
 #include "splash.h"
 #include "tpm2-pcr.h"
 #include "uki.h"
+#include "url-discovery.h"
 #include "util.h"
 #include "version.h"
 #include "vmm.h"
@@ -151,6 +152,7 @@ static void export_stub_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image, unsig
                 EFI_STUB_FEATURE_DEVICETREE_ADDONS |        /* We pick up .dtb addons */
                 EFI_STUB_FEATURE_MULTI_PROFILE_UKI |        /* We grok the "@1" profile command line argument */
                 EFI_STUB_FEATURE_REPORT_STUB_PARTITION |    /* We set StubDevicePartUUID + StubImageIdentifier */
+                EFI_STUB_FEATURE_REPORT_URL |               /* We set StubDeviceURL + LoaderDeviceURL */
                 0;
 
         assert(loaded_image);
@@ -167,6 +169,10 @@ static void export_stub_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image, unsig
                 _cleanup_free_ char16_t *uuid = disk_get_part_uuid(loaded_image->DeviceHandle);
                 if (uuid)
                         efivar_set_str16(MAKE_GUID_PTR(LOADER), u"StubDevicePartUUID", uuid, 0);
+
+                _cleanup_free_ char16_t *url = disk_get_url(loaded_image->DeviceHandle);
+                if (url)
+                        efivar_set_str16(MAKE_GUID_PTR(LOADER), u"StubDeviceURL", url, 0);
         }
 
         if (loaded_image->FilePath) {
diff --git a/src/boot/url-discovery.c b/src/boot/url-discovery.c
new file mode 100644 (file)
index 0000000..7c7cfb6
--- /dev/null
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "device-path-util.h"
+#include "efi-string.h"
+#include "proto/device-path.h"
+#include "url-discovery.h"
+
+char16_t *disk_get_url(EFI_HANDLE *handle) {
+        EFI_STATUS err;
+        EFI_DEVICE_PATH *dp;
+
+        /* export the device path this image is started from */
+
+        if (!handle)
+                return NULL;
+
+        err = BS->HandleProtocol(handle, MAKE_GUID_PTR(EFI_DEVICE_PATH_PROTOCOL), (void **) &dp);
+        if (err != EFI_SUCCESS)
+                return NULL;
+
+        for (; !device_path_is_end(dp); dp = device_path_next_node(dp)) {
+                if (dp->Type != MESSAGING_DEVICE_PATH || dp->SubType != MSG_URI_DP)
+                        continue;
+
+                URI_DEVICE_PATH *udp = (URI_DEVICE_PATH*) dp;
+                return xstrn8_to_16(udp->Uri, dp->Length);
+        }
+
+        return NULL;
+}
diff --git a/src/boot/url-discovery.h b/src/boot/url-discovery.h
new file mode 100644 (file)
index 0000000..e4e50c3
--- /dev/null
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+char16_t *disk_get_url(EFI_HANDLE *handle);
index e9f3a6f5b516d7bb06534d9bf03d50d96bdd325d..03ebea38dfdea38f54519be6df54bc03937a5f51 100644 (file)
@@ -390,12 +390,15 @@ int verb_status(int argc, char *argv[], void *userdata) {
                         { EFI_LOADER_FEATURE_RETAIN_SHIM,             "Retain SHIM protocols"                 },
                         { EFI_LOADER_FEATURE_MENU_DISABLE,            "Menu can be disabled"                  },
                         { EFI_LOADER_FEATURE_MULTI_PROFILE_UKI,       "Multi-Profile UKIs are supported"      },
+                        { EFI_LOADER_FEATURE_REPORT_URL,              "Loader reports network boot URL"       },
                 };
                 static const struct {
                         uint64_t flag;
                         const char *name;
                 } stub_flags[] = {
-                        { EFI_STUB_FEATURE_REPORT_BOOT_PARTITION,     "Stub sets loader partition information"                      },
+                        { EFI_STUB_FEATURE_REPORT_BOOT_PARTITION,     "Stub reports loader partition information"                   },
+                        { EFI_STUB_FEATURE_REPORT_STUB_PARTITION,     "Stub reports stub partition information"                     },
+                        { EFI_STUB_FEATURE_REPORT_URL,                "Stub reports network boot URL"                               },
                         { EFI_STUB_FEATURE_PICK_UP_CREDENTIALS,       "Picks up credentials from boot partition"                    },
                         { EFI_STUB_FEATURE_PICK_UP_SYSEXTS,           "Picks up system extension images from boot partition"        },
                         { EFI_STUB_FEATURE_PICK_UP_CONFEXTS,          "Picks up configuration extension images from boot partition" },
@@ -405,7 +408,6 @@ int verb_status(int argc, char *argv[], void *userdata) {
                         { EFI_STUB_FEATURE_CMDLINE_SMBIOS,            "Pick up .cmdline from SMBIOS Type 11"                        },
                         { EFI_STUB_FEATURE_DEVICETREE_ADDONS,         "Pick up .dtb from addons"                                    },
                         { EFI_STUB_FEATURE_MULTI_PROFILE_UKI,         "Stub understands profile selector"                           },
-                        { EFI_STUB_FEATURE_REPORT_STUB_PARTITION,     "Stub sets stub partition information"                        },
                 };
                 _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL, *stub_path = NULL,
                         *current_entry = NULL, *oneshot_entry = NULL, *default_entry = NULL;
@@ -480,6 +482,10 @@ int verb_status(int argc, char *argv[], void *userdata) {
                         (void) efi_loader_get_device_part_uuid(&loader_partition_uuid);
                         print_yes_no_line(/* first= */ false, !sd_id128_is_null(loader_partition_uuid), "Boot loader set partition information");
 
+                        _cleanup_free_ char *loader_url = NULL;
+                        (void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE_STR("LoaderDeviceURL"), &loader_url);
+                        print_yes_no_line(/* first= */ false, !!loader_url, "Boot loader set network boot URL information");
+
                         if (!sd_id128_is_null(loader_partition_uuid)) {
                                 if (!sd_id128_is_null(esp_uuid) && !sd_id128_equal(esp_uuid, loader_partition_uuid))
                                         printf("WARNING: The boot loader reports a different partition UUID than the detected ESP ("SD_ID128_UUID_FORMAT_STR" vs. "SD_ID128_UUID_FORMAT_STR")!\n",
@@ -493,6 +499,9 @@ int verb_status(int argc, char *argv[], void *userdata) {
                         if (loader_path)
                                 printf("       Loader: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(loader_path));
 
+                        if (loader_url)
+                                printf(" Net Boot URL: %s\n", loader_url);
+
                         if (current_entry)
                                 printf("Current Entry: %s\n", current_entry);
                         if (default_entry)
@@ -513,6 +522,10 @@ int verb_status(int argc, char *argv[], void *userdata) {
                         (void) efi_stub_get_device_part_uuid(&stub_partition_uuid);
                         print_yes_no_line(/* first= */ false, !sd_id128_is_null(stub_partition_uuid), "Stub loader set partition information");
 
+                        _cleanup_free_ char *stub_url = NULL;
+                        (void) efi_get_variable_string_and_warn(EFI_LOADER_VARIABLE_STR("StubDeviceURL"), &stub_url);
+                        print_yes_no_line(/* first= */ false, !!stub_url, "Stub set network boot URL information");
+
                         if (!sd_id128_is_null(stub_partition_uuid)) {
                                 if (!(!sd_id128_is_null(esp_uuid) && sd_id128_equal(esp_uuid, stub_partition_uuid)) &&
                                     !(!sd_id128_is_null(xbootldr_uuid) && sd_id128_equal(xbootldr_uuid, stub_partition_uuid)))
@@ -526,6 +539,10 @@ int verb_status(int argc, char *argv[], void *userdata) {
 
                         if (stub_path)
                                 printf("         Stub: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(stub_path));
+
+                        if (stub_url)
+                                printf(" Net Boot URL: %s\n", stub_url);
+
                         printf("\n");
                 }
 
index f002e81b532307b31d31824d358987c16a4b2d47..678cdeeff84fbb747d565e4da555e048b578a901 100644 (file)
@@ -24,6 +24,7 @@
 #define EFI_LOADER_FEATURE_RETAIN_SHIM             (UINT64_C(1) << 12)
 #define EFI_LOADER_FEATURE_MENU_DISABLE            (UINT64_C(1) << 13)
 #define EFI_LOADER_FEATURE_MULTI_PROFILE_UKI       (UINT64_C(1) << 14)
+#define EFI_LOADER_FEATURE_REPORT_URL              (UINT64_C(1) << 15)
 
 /* Features of the stub, i.e. systemd-stub */
 #define EFI_STUB_FEATURE_REPORT_BOOT_PARTITION     (UINT64_C(1) << 0)
@@ -37,6 +38,7 @@
 #define EFI_STUB_FEATURE_PICK_UP_CONFEXTS          (UINT64_C(1) << 8)
 #define EFI_STUB_FEATURE_MULTI_PROFILE_UKI         (UINT64_C(1) << 9)
 #define EFI_STUB_FEATURE_REPORT_STUB_PARTITION     (UINT64_C(1) << 10)
+#define EFI_STUB_FEATURE_REPORT_URL                (UINT64_C(1) << 11)
 
 typedef enum SecureBootMode {
         SECURE_BOOT_UNSUPPORTED,