File 2001-systemd-boot-load-addons-from-type-1-and-expose-them.patch of Package systemd
From d6007941d29bd68d9f6794172f55d280c9fc7281 Mon Sep 17 00:00:00 2001
From: Raito Bezarius <masterancpp@gmail.com>
Date: Fri, 16 Jun 2023 14:03:35 +0200
Subject: [PATCH 2001/2007] systemd-boot: load addons from type 1 and expose
them via EFI protocol
This make it possible to attach addons to any Type #1 entry
and get them back in the next bootable stage via an EFI protocol.
---
src/boot/addon-util.c | 48 +++++++++++++++++++++++++++++++++++++++++++
src/boot/addon-util.h | 12 +++++++++++
src/boot/boot.c | 30 ++++++++++++++++++++++++---
src/boot/meson.build | 1 +
4 files changed, 88 insertions(+), 3 deletions(-)
create mode 100644 src/boot/addon-util.c
create mode 100644 src/boot/addon-util.h
diff --git a/src/boot/addon-util.c b/src/boot/addon-util.c
new file mode 100644
index 0000000000..3b99855c93
--- /dev/null
+++ b/src/boot/addon-util.c
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "addon-util.h"
+#include "proto/device-path.h"
+#include "util.h"
+#include "log.h"
+
+EFI_STATUS addons_install_proto(EFI_LOADED_IMAGE_PROTOCOL *stub_image, char16_t * const *addons) {
+ EFI_STATUS err;
+ EFI_DEVICE_PATH **dps;
+
+ assert(stub_image);
+
+ err = make_multiple_file_device_path(stub_image->DeviceHandle, addons, &dps);
+ if (err != EFI_SUCCESS || dps == NULL)
+ return err;
+
+ return BS->InstallMultipleProtocolInterfaces(&stub_image->DeviceHandle,
+ MAKE_GUID_PTR(SYSTEMD_ADDON_MEDIA),
+ dps, NULL);
+}
+
+EFI_STATUS addons_unload_proto(EFI_HANDLE *addons)
+{
+ EFI_STATUS err;
+ EFI_DEVICE_PATH *dps;
+
+ assert(addons);
+
+ if (!*addons)
+ return EFI_SUCCESS;
+
+ /* get the EFI_DEVICE_PATH* interface that we allocated earlier */
+ err = BS->HandleProtocol(*addons, MAKE_GUID_PTR(SYSTEMD_ADDON_MEDIA),
+ (void **) &dps);
+ if (err != EFI_SUCCESS)
+ return err;
+
+ err = BS->UninstallMultipleProtocolInterfaces(*addons,
+ MAKE_GUID_PTR(SYSTEMD_ADDON_MEDIA),
+ &dps, NULL);
+
+ if (err != EFI_SUCCESS)
+ return err;
+
+ *addons = NULL;
+ return EFI_SUCCESS;
+}
diff --git a/src/boot/addon-util.h b/src/boot/addon-util.h
new file mode 100644
index 0000000000..f1883fdcdb
--- /dev/null
+++ b/src/boot/addon-util.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "proto/loaded-image.h"
+#include "device-path-util.h"
+#include "util.h"
+
+#define SYSTEMD_ADDON_MEDIA_GUID \
+ GUID_DEF(0x97ac68bf, 0xc741, 0x4bbb, 0xb7, 0xbf, 0x7f, 0x6c, 0xcc, 0x00, 0x8a, 0x7e)
+
+EFI_STATUS addons_install_proto(EFI_LOADED_IMAGE_PROTOCOL *loaded_image, char16_t * const *addons);
+EFI_STATUS addons_unload_proto(EFI_HANDLE *addons);
diff --git a/src/boot/boot.c b/src/boot/boot.c
index e0a30d0184..ea6b8b150e 100644
--- a/src/boot/boot.c
+++ b/src/boot/boot.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include "addon-util.h"
#include "bcd.h"
#include "bootspec-fundamental.h"
#include "console.h"
@@ -69,6 +70,7 @@ typedef struct {
char16_t *options;
bool options_implied; /* If true, these options are implied if we invoke the PE binary without any parameters (as in: UKI). If false we must specify these options explicitly. */
char16_t **initrd;
+ char16_t **addons; /* systemd-addons for this entry */
char16_t key;
EFI_STATUS (*call)(void);
int tries_done;
@@ -610,6 +612,8 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
printf(" loader: %ls\n", entry->loader);
STRV_FOREACH(initrd, entry->initrd)
printf(" initrd: %ls\n", *initrd);
+ STRV_FOREACH(addon, entry->addons)
+ printf(" addon: %ls\n", *addon);
if (entry->devicetree)
printf(" devicetree: %ls\n", entry->devicetree);
if (entry->options)
@@ -1203,6 +1207,7 @@ static BootEntry* boot_entry_free(BootEntry *entry) {
free(entry->devicetree);
free(entry->options);
strv_free(entry->initrd);
+ strv_free(entry->addons);
free(entry->path);
free(entry->current_name);
free(entry->next_name);
@@ -1439,7 +1444,7 @@ static void boot_entry_add_type1(
_cleanup_(boot_entry_freep) BootEntry *entry = NULL;
char *line;
- size_t pos = 0, n_initrd = 0;
+ size_t pos = 0, n_initrd = 0, n_addons = 0;
char *key, *value;
EFI_STATUS err;
@@ -1508,7 +1513,13 @@ static void boot_entry_add_type1(
(n_initrd + 2) * sizeof(uint16_t *));
entry->initrd[n_initrd++] = xstr8_to_path(value);
entry->initrd[n_initrd] = NULL;
-
+ } else if (streq8(key, "add-on")) {
+ entry->addons = xrealloc(
+ entry->addons,
+ n_addons == 0 ? 0 : (n_addons + 1) * sizeof(uint16_t *),
+ (n_addons + 2) * sizeof(uint16_t *));
+ entry->addons[n_addons++] = xstr8_to_path(value);
+ entry->addons[n_addons] = NULL;
} else if (streq8(key, "options")) {
_cleanup_free_ char16_t *new = NULL;
@@ -2524,6 +2535,13 @@ static EFI_STATUS initrd_prepare(
return EFI_SUCCESS;
}
+static void cleanup_loaded_image(EFI_LOADED_IMAGE_PROTOCOL **loaded_image) {
+ assert(loaded_image);
+
+ (void) addons_unload_proto((EFI_HANDLE *)*loaded_image);
+ *loaded_image = NULL;
+}
+
static EFI_STATUS image_start(
EFI_HANDLE parent_image,
const BootEntry *entry) {
@@ -2573,7 +2591,7 @@ static EFI_STATUS image_start(
if (err != EFI_SUCCESS)
return log_error_status(err, "Error registering initrd: %m");
- EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
+ _cleanup_(cleanup_loaded_image) EFI_LOADED_IMAGE_PROTOCOL *loaded_image = NULL;
err = BS->HandleProtocol(image, MAKE_GUID_PTR(EFI_LOADED_IMAGE_PROTOCOL), (void **) &loaded_image);
if (err != EFI_SUCCESS)
return log_error_status(err, "Error getting LoadedImageProtocol handle: %m");
@@ -2611,6 +2629,12 @@ static EFI_STATUS image_start(
(void) tpm_log_load_options(options, NULL);
}
+ if (entry->addons) {
+ err = addons_install_proto(loaded_image, entry->addons);
+ if (err != EFI_SUCCESS)
+ return log_error_status(err, "Error installing addons protocol: %m");
+ }
+
efivar_set_time_usec(MAKE_GUID_PTR(LOADER), u"LoaderTimeExecUSec", 0);
err = BS->StartImage(image, NULL, NULL);
graphics_mode(false);
diff --git a/src/boot/meson.build b/src/boot/meson.build
index 9370274d96..da0790a25e 100644
--- a/src/boot/meson.build
+++ b/src/boot/meson.build
@@ -254,6 +254,7 @@ endif
############################################################
libefi_sources = files(
+ 'addon-util.c',
'chid.c',
'console.c',
'device-path-util.c',
--
2.49.0