mirror of
https://github.com/systemd/systemd.git
synced 2025-03-14 04:58:28 +03:00
boot: add new 'uki-url' bls type #1 menu items for booting remote UKIs
Companion BLS spec PR: https://github.com/uapi-group/specifications/pull/135
This commit is contained in:
parent
e2a3d56218
commit
1089d0f89e
230
src/boot/boot.c
230
src/boot/boot.c
@ -18,6 +18,7 @@
|
||||
#include "pe.h"
|
||||
#include "proto/block-io.h"
|
||||
#include "proto/device-path.h"
|
||||
#include "proto/load-file.h"
|
||||
#include "proto/simple-text-io.h"
|
||||
#include "random-seed.h"
|
||||
#include "sbat.h"
|
||||
@ -27,6 +28,7 @@
|
||||
#include "ticks.h"
|
||||
#include "tpm2-pcr.h"
|
||||
#include "uki.h"
|
||||
#include "url-discovery.h"
|
||||
#include "util.h"
|
||||
#include "version.h"
|
||||
#include "vmm.h"
|
||||
@ -50,6 +52,7 @@ typedef enum LoaderType {
|
||||
LOADER_EFI, /* Boot loader spec type #1 entries with "efi" line */
|
||||
LOADER_LINUX, /* Boot loader spec type #1 entries with "linux" line */
|
||||
LOADER_UKI, /* Boot loader spec type #1 entries with "uki" line */
|
||||
LOADER_UKI_URL, /* Boot loader spec type #1 entries with "uki-url" line */
|
||||
LOADER_TYPE2_UKI, /* Boot loader spec type #2 entries */
|
||||
LOADER_SECURE_BOOT_KEYS,
|
||||
LOADER_BAD, /* Marker: this boot loader spec type #1 entry is invalid */
|
||||
@ -58,13 +61,13 @@ typedef enum LoaderType {
|
||||
} LoaderType;
|
||||
|
||||
/* Which loader types permit command line editing */
|
||||
#define LOADER_TYPE_ALLOW_EDITOR(t) IN_SET(t, LOADER_EFI, LOADER_LINUX, LOADER_UKI, LOADER_TYPE2_UKI)
|
||||
#define LOADER_TYPE_ALLOW_EDITOR(t) IN_SET(t, LOADER_EFI, LOADER_LINUX, LOADER_UKI, LOADER_UKI_URL, LOADER_TYPE2_UKI)
|
||||
|
||||
/* Which loader types allow command line editing in SecureBoot mode */
|
||||
#define LOADER_TYPE_ALLOW_EDITOR_IN_SB(t) IN_SET(t, LOADER_EFI, LOADER_LINUX)
|
||||
|
||||
/* Which loader types shall be considered for automatic selection */
|
||||
#define LOADER_TYPE_MAY_AUTO_SELECT(t) IN_SET(t, LOADER_EFI, LOADER_LINUX, LOADER_UKI, LOADER_TYPE2_UKI)
|
||||
#define LOADER_TYPE_MAY_AUTO_SELECT(t) IN_SET(t, LOADER_EFI, LOADER_LINUX, LOADER_UKI, LOADER_UKI_URL, LOADER_TYPE2_UKI)
|
||||
|
||||
typedef struct {
|
||||
char16_t *id; /* The unique identifier for this entry (typically the filename of the file defining the entry, possibly suffixed with a profile id) */
|
||||
@ -77,6 +80,7 @@ typedef struct {
|
||||
EFI_HANDLE *device;
|
||||
LoaderType type;
|
||||
char16_t *loader;
|
||||
char16_t *url;
|
||||
char16_t *devicetree;
|
||||
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. */
|
||||
@ -620,6 +624,8 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
|
||||
printf(" device: %ls\n", dp_str);
|
||||
if (entry->loader)
|
||||
printf(" loader: %ls\n", entry->loader);
|
||||
if (entry->url)
|
||||
printf(" url: %ls\n", entry->url);
|
||||
STRV_FOREACH(initrd, entry->initrd)
|
||||
printf(" initrd: %ls\n", *initrd);
|
||||
if (entry->devicetree)
|
||||
@ -1211,6 +1217,7 @@ static BootEntry* boot_entry_free(BootEntry *entry) {
|
||||
free(entry->version);
|
||||
free(entry->machine_id);
|
||||
free(entry->loader);
|
||||
free(entry->url);
|
||||
free(entry->devicetree);
|
||||
free(entry->options);
|
||||
strv_free(entry->initrd);
|
||||
@ -1508,6 +1515,32 @@ static void boot_entry_add_type1(
|
||||
entry->loader = xstr8_to_path(value);
|
||||
entry->key = 'l';
|
||||
|
||||
} else if (streq8(key, "uki-url")) {
|
||||
|
||||
if (!IN_SET(entry->type, LOADER_UNDEFINED, LOADER_UKI_URL)) {
|
||||
entry->type = LOADER_BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
_cleanup_free_ char16_t *p = xstr8_to_16(value);
|
||||
|
||||
const char16_t *e = startswith(p, u":");
|
||||
if (e) {
|
||||
_cleanup_free_ char16_t *origin = disk_get_url(device);
|
||||
|
||||
if (!origin) {
|
||||
/* Automatically hide entries that require an original URL but where none is available. */
|
||||
entry->type = LOADER_IGNORE;
|
||||
break;
|
||||
}
|
||||
|
||||
entry->url = url_replace_last_component(origin, p);
|
||||
} else
|
||||
entry->url = TAKE_PTR(p);
|
||||
|
||||
entry->type = LOADER_UKI_URL;
|
||||
entry->key = 'l';
|
||||
|
||||
} else if (streq8(key, "efi")) {
|
||||
|
||||
if (!IN_SET(entry->type, LOADER_UNDEFINED, LOADER_EFI)) {
|
||||
@ -1560,11 +1593,13 @@ static void boot_entry_add_type1(
|
||||
if (IN_SET(entry->type, LOADER_UNDEFINED, LOADER_BAD, LOADER_IGNORE))
|
||||
return;
|
||||
|
||||
/* check existence */
|
||||
_cleanup_file_close_ EFI_FILE *handle = NULL;
|
||||
err = root_dir->Open(root_dir, &handle, entry->loader, EFI_FILE_MODE_READ, 0ULL);
|
||||
if (err != EFI_SUCCESS)
|
||||
return;
|
||||
/* Check existence of loader file */
|
||||
if (entry->loader) {
|
||||
_cleanup_file_close_ EFI_FILE *handle = NULL;
|
||||
err = root_dir->Open(root_dir, &handle, entry->loader, EFI_FILE_MODE_READ, 0ULL);
|
||||
if (err != EFI_SUCCESS)
|
||||
return;
|
||||
}
|
||||
|
||||
entry->device = device;
|
||||
entry->id = xstrdup16(file);
|
||||
@ -2560,13 +2595,77 @@ static EFI_STATUS initrd_prepare(
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static EFI_STATUS expand_path(
|
||||
EFI_HANDLE parent_image,
|
||||
EFI_DEVICE_PATH *path,
|
||||
EFI_DEVICE_PATH **ret_expanded_path) {
|
||||
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(parent_image);
|
||||
assert(path);
|
||||
assert(ret_expanded_path);
|
||||
|
||||
_cleanup_free_ EFI_HANDLE *handles = NULL;
|
||||
size_t n_handles = 0;
|
||||
err = BS->LocateHandleBuffer(
|
||||
ByProtocol,
|
||||
MAKE_GUID_PTR(EFI_LOAD_FILE_PROTOCOL),
|
||||
/* SearchKey= */ NULL,
|
||||
&n_handles,
|
||||
&handles);
|
||||
if (!IN_SET(err, EFI_SUCCESS, EFI_NOT_FOUND))
|
||||
return log_error_status(err, "Failed to get list of LoadFile protocol handles: %m");
|
||||
|
||||
FOREACH_ARRAY(h, handles, n_handles) {
|
||||
EFI_LOAD_FILE_PROTOCOL *load_file = NULL;
|
||||
err = BS->OpenProtocol(
|
||||
*h,
|
||||
MAKE_GUID_PTR(EFI_LOAD_FILE_PROTOCOL),
|
||||
(void**) &load_file,
|
||||
parent_image,
|
||||
/* ControllerHandler= */ NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
if (IN_SET(err, EFI_NOT_FOUND, EFI_INVALID_PARAMETER))
|
||||
continue; /* Skip over LoadFile() handles that are not suitable for this kind of device path */
|
||||
if (err != EFI_SUCCESS) {
|
||||
log_warning_status(err, "Failed to get LoadFile() protocol, ignoring: %m");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Issue a LoadFile() request without interest in the actual data (i.e. size is zero and
|
||||
* buffer pointer is NULL), but with BootPolicy set to true, this has the effect of
|
||||
* downloading the URL and establishing a handle for it. */
|
||||
size_t size = 0;
|
||||
err = load_file->LoadFile(load_file, path, /* BootPolicy= */ true, &size, /* Buffer= */ NULL);
|
||||
if (IN_SET(err, EFI_NOT_FOUND, EFI_INVALID_PARAMETER))
|
||||
continue; /* Skip over LoadFile() handles that after all don't consider themselves
|
||||
* appropriate for this kind of path */
|
||||
if (err != EFI_BUFFER_TOO_SMALL) {
|
||||
log_warning_status(err, "Failed to get file via LoadFile() protocol, ignoring: %m");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now read the updated file path */
|
||||
EFI_DEVICE_PATH *load_file_path = NULL;
|
||||
err = BS->HandleProtocol(*h, MAKE_GUID_PTR(EFI_DEVICE_PATH_PROTOCOL), (void **) &load_file_path);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Failed to get LoadFile() device path: %m");
|
||||
|
||||
/* And return a copy */
|
||||
*ret_expanded_path = device_path_dup(load_file_path);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
static EFI_STATUS image_start(
|
||||
EFI_HANDLE parent_image,
|
||||
const BootEntry *entry) {
|
||||
|
||||
_cleanup_(devicetree_cleanup) struct devicetree_state dtstate = {};
|
||||
_cleanup_(unload_imagep) EFI_HANDLE image = NULL;
|
||||
_cleanup_free_ EFI_DEVICE_PATH *path = NULL;
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(entry);
|
||||
@ -2576,38 +2675,94 @@ static EFI_STATUS image_start(
|
||||
(void) entry->call();
|
||||
|
||||
_cleanup_file_close_ EFI_FILE *image_root = NULL;
|
||||
err = open_volume(entry->device, &image_root);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error opening root path: %m");
|
||||
|
||||
err = make_file_device_path(entry->device, entry->loader, &path);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error making file device path: %m");
|
||||
|
||||
size_t initrd_size = 0;
|
||||
_cleanup_pages_ Pages initrd_pages = {};
|
||||
_cleanup_free_ char16_t *options_initrd = NULL;
|
||||
err = initrd_prepare(image_root, entry, &options_initrd, &initrd_pages, &initrd_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error preparing initrd: %m");
|
||||
|
||||
err = shim_load_image(parent_image, path, &image);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error loading %ls: %m", entry->loader);
|
||||
|
||||
/* DTBs are loaded by the kernel before ExitBootServices, and they can be used to map and assign
|
||||
* arbitrary memory ranges, so skip them when secure boot is enabled as the DTB here is unverified.
|
||||
*/
|
||||
if (entry->devicetree && !secure_boot_enabled()) {
|
||||
err = devicetree_install(&dtstate, image_root, entry->devicetree);
|
||||
_cleanup_free_ EFI_DEVICE_PATH *path = NULL;
|
||||
bool boot_policy;
|
||||
if (entry->url) {
|
||||
/* Generate a device path that only contains the URL */
|
||||
err = make_url_device_path(entry->url, &path);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error loading %ls: %m", entry->devicetree);
|
||||
return log_error_status(err, "Error making URL device path: %m");
|
||||
|
||||
/* Try to expand this path on all available NICs and IP protocols */
|
||||
_cleanup_free_ EFI_DEVICE_PATH *expanded_path = NULL;
|
||||
for (unsigned n_attempt = 0;; n_attempt++) {
|
||||
err = expand_path(parent_image, path, &expanded_path);
|
||||
if (err == EFI_SUCCESS) {
|
||||
/* If this worked then let's try to boot with the expanded path. */
|
||||
free(path);
|
||||
path = TAKE_PTR(expanded_path);
|
||||
break;
|
||||
}
|
||||
if (err != EFI_NOT_FOUND || n_attempt > 5) {
|
||||
log_warning_status(err, "Failed to expand device path, ignoring: %m");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Maybe the network devices have been configured for this yet (because we are the
|
||||
* first piece of code trying to do networking)? Then let's connect them, and try
|
||||
* again. */
|
||||
reconnect_all_drivers();
|
||||
}
|
||||
|
||||
/* Note: if the path expansion doesn't work, we'll continue with the unexpanded path. Which
|
||||
* will probably fail on many (most?) firmwares, but it's worth a try. */
|
||||
|
||||
boot_policy = true; /* Set BootPolicy parameter to LoadImage() to true, which ultimately
|
||||
* controls whether the LoadFile (and thus HTTP boot) or LoadFile2 (which
|
||||
* does not set up HTTP boot) protocol shall be used. */
|
||||
} else {
|
||||
assert(entry->device);
|
||||
assert(entry->loader);
|
||||
|
||||
err = open_volume(entry->device, &image_root);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error opening root path: %m");
|
||||
|
||||
err = make_file_device_path(entry->device, entry->loader, &path);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error making file device path: %m");
|
||||
|
||||
boot_policy = false;
|
||||
}
|
||||
|
||||
/* Authenticate the image before we continue with initrd or DT stuff */
|
||||
err = shim_load_image(parent_image, path, boot_policy, &image);
|
||||
if (err != EFI_SUCCESS) {
|
||||
if (entry->url) {
|
||||
/* EFI_NOT_FOUND typically indicates that no network stack or NIC was available, let's give the user a hint. */
|
||||
if (err == EFI_NOT_FOUND) {
|
||||
log_info("Unable to boot remote UKI %ls, is networking available?", entry->url);
|
||||
return err;
|
||||
}
|
||||
|
||||
return log_error_status(err, "Error loading loading remote UKI %ls: %m", entry->url);
|
||||
}
|
||||
|
||||
return log_error_status(err, "Error loading EFI binary %ls: %m", entry->loader);
|
||||
}
|
||||
|
||||
_cleanup_(cleanup_initrd) EFI_HANDLE initrd_handle = NULL;
|
||||
err = initrd_register(PHYSICAL_ADDRESS_TO_POINTER(initrd_pages.addr), initrd_size, &initrd_handle);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error registering initrd: %m");
|
||||
_cleanup_free_ char16_t *options_initrd = NULL;
|
||||
_cleanup_pages_ Pages initrd_pages = {};
|
||||
size_t initrd_size = 0;
|
||||
if (image_root) {
|
||||
err = initrd_prepare(image_root, entry, &options_initrd, &initrd_pages, &initrd_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error preparing initrd: %m");
|
||||
|
||||
/* DTBs are loaded by the kernel before ExitBootServices(), and they can be used to map and
|
||||
* assign arbitrary memory ranges, so skip them when secure boot is enabled as the DTB here
|
||||
* is unverified. */
|
||||
if (entry->devicetree && !secure_boot_enabled()) {
|
||||
err = devicetree_install(&dtstate, image_root, entry->devicetree);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error loading %ls: %m", entry->devicetree);
|
||||
}
|
||||
|
||||
err = initrd_register(PHYSICAL_ADDRESS_TO_POINTER(initrd_pages.addr), initrd_size, &initrd_handle);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error registering initrd: %m");
|
||||
}
|
||||
|
||||
EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
|
||||
err = BS->HandleProtocol(image, MAKE_GUID_PTR(EFI_LOADED_IMAGE_PROTOCOL), (void **) &loaded_image);
|
||||
@ -2673,7 +2828,7 @@ static EFI_STATUS image_start(
|
||||
err = EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return log_error_status(err, "Failed to execute %ls (%ls): %m", entry->title_show, entry->loader);
|
||||
return log_error_status(err, "Failed to execute %ls (%ls): %m", entry->title_show, entry->loader ?: entry->url);
|
||||
}
|
||||
|
||||
static void config_free(Config *config) {
|
||||
@ -2803,6 +2958,7 @@ static void export_loader_variables(
|
||||
EFI_LOADER_FEATURE_MULTI_PROFILE_UKI |
|
||||
EFI_LOADER_FEATURE_REPORT_URL |
|
||||
EFI_LOADER_FEATURE_TYPE1_UKI |
|
||||
EFI_LOADER_FEATURE_TYPE1_UKI_URL |
|
||||
0;
|
||||
|
||||
assert(loaded_image);
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "device-path-util.h"
|
||||
#include "efi-string.h"
|
||||
#include "util.h"
|
||||
|
||||
EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DEVICE_PATH **ret_dp) {
|
||||
@ -38,6 +39,38 @@ EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DE
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS make_url_device_path(const char16_t *url, EFI_DEVICE_PATH **ret) {
|
||||
assert(url);
|
||||
assert(ret);
|
||||
|
||||
/* Turns a URL into a simple one-element URL device path. */
|
||||
|
||||
_cleanup_free_ char* u = xstr16_to_ascii(url);
|
||||
if (!u)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
size_t l = strlen8(u);
|
||||
|
||||
size_t t = offsetof(URI_DEVICE_PATH, Uri) + l + sizeof(EFI_DEVICE_PATH);
|
||||
EFI_DEVICE_PATH *dp = xmalloc(t);
|
||||
|
||||
URI_DEVICE_PATH *udp = (URI_DEVICE_PATH*) dp;
|
||||
udp->Header = (EFI_DEVICE_PATH) {
|
||||
.Type = MESSAGING_DEVICE_PATH,
|
||||
.SubType = MSG_URI_DP,
|
||||
.Length = offsetof(URI_DEVICE_PATH, Uri) + l,
|
||||
};
|
||||
memcpy(udp->Uri, u, l);
|
||||
|
||||
EFI_DEVICE_PATH *end = device_path_next_node(dp);
|
||||
*end = DEVICE_PATH_END_NODE;
|
||||
|
||||
assert(((uint8_t*) end + sizeof(EFI_DEVICE_PATH)) == ((uint8_t*) dp + t));
|
||||
|
||||
*ret = TAKE_PTR(dp);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static char16_t *device_path_to_str_internal(const EFI_DEVICE_PATH *dp) {
|
||||
char16_t *str = NULL;
|
||||
|
||||
@ -90,7 +123,7 @@ EFI_STATUS device_path_to_str(const EFI_DEVICE_PATH *dp, char16_t **ret) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
str = dp_to_text->ConvertDevicePathToText(dp, false, false);
|
||||
str = dp_to_text->ConvertDevicePathToText(dp, /* DisplayOnly=*/ false, /* AllowShortcuts= */ false);
|
||||
if (!str)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
||||
@ -136,3 +169,12 @@ EFI_DEVICE_PATH *device_path_replace_node(
|
||||
*end = DEVICE_PATH_END_NODE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t device_path_size(const EFI_DEVICE_PATH *dp) {
|
||||
const EFI_DEVICE_PATH *i = ASSERT_PTR(dp);
|
||||
|
||||
for (; !device_path_is_end(i); i = device_path_next_node(i))
|
||||
;
|
||||
|
||||
return (const uint8_t*) i - (const uint8_t*) dp + sizeof(EFI_DEVICE_PATH);
|
||||
}
|
||||
|
@ -2,8 +2,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "proto/device-path.h"
|
||||
#include "util.h"
|
||||
|
||||
EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DEVICE_PATH **ret_dp);
|
||||
EFI_STATUS make_url_device_path(const char16_t *url, EFI_DEVICE_PATH **ret);
|
||||
EFI_STATUS device_path_to_str(const EFI_DEVICE_PATH *dp, char16_t **ret);
|
||||
bool device_path_startswith(const EFI_DEVICE_PATH *dp, const EFI_DEVICE_PATH *start);
|
||||
EFI_DEVICE_PATH *device_path_replace_node(
|
||||
@ -25,3 +27,9 @@ static inline bool device_path_is_end(const EFI_DEVICE_PATH *dp) {
|
||||
.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE, \
|
||||
.Length = sizeof(EFI_DEVICE_PATH) \
|
||||
}
|
||||
|
||||
size_t device_path_size(const EFI_DEVICE_PATH *dp);
|
||||
|
||||
static inline EFI_DEVICE_PATH *device_path_dup(const EFI_DEVICE_PATH *dp) {
|
||||
return xmemdup(ASSERT_PTR(dp), device_path_size(dp));
|
||||
}
|
||||
|
@ -81,7 +81,12 @@ static bool shim_validate(
|
||||
return shim_lock->shim_verify(file_buffer, file_size) == EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path, EFI_HANDLE *ret_image) {
|
||||
EFI_STATUS shim_load_image(
|
||||
EFI_HANDLE parent,
|
||||
const EFI_DEVICE_PATH *device_path,
|
||||
bool boot_policy,
|
||||
EFI_HANDLE *ret_image) {
|
||||
|
||||
assert(device_path);
|
||||
assert(ret_image);
|
||||
|
||||
@ -91,8 +96,12 @@ EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path
|
||||
install_security_override(shim_validate, NULL);
|
||||
|
||||
EFI_STATUS ret = BS->LoadImage(
|
||||
/*BootPolicy=*/false, parent, (EFI_DEVICE_PATH *) device_path, NULL, 0, ret_image);
|
||||
|
||||
/* BootPolicy= */ boot_policy,
|
||||
parent,
|
||||
(EFI_DEVICE_PATH *) device_path,
|
||||
/* SourceBuffer= */ NULL,
|
||||
/* SourceSize= */ 0,
|
||||
ret_image);
|
||||
if (have_shim)
|
||||
uninstall_security_override();
|
||||
|
||||
|
@ -12,5 +12,5 @@
|
||||
#include "efi.h"
|
||||
|
||||
bool shim_loaded(void);
|
||||
EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path, EFI_HANDLE *ret_image);
|
||||
EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path, bool boot_policy, EFI_HANDLE *ret_image);
|
||||
void shim_retain_protocol(void);
|
||||
|
@ -598,7 +598,7 @@ static EFI_STATUS load_addons(
|
||||
|
||||
/* By using shim_load_image, we cover both the case where the PE files are signed with MoK
|
||||
* and with DB, and running with or without shim. */
|
||||
err = shim_load_image(stub_image, addon_path, &addon);
|
||||
err = shim_load_image(stub_image, addon_path, /* boot_policy= */ false, &addon);
|
||||
if (err != EFI_SUCCESS) {
|
||||
log_error_status(err,
|
||||
"Failed to read '%ls' from '%ls', ignoring: %m",
|
||||
|
@ -1,13 +1,14 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "device-path-util.h"
|
||||
#include "efi-string.h"
|
||||
#include "efivars.h"
|
||||
#include "memory-util-fundamental.h"
|
||||
#include "proto/device-path.h"
|
||||
#include "proto/simple-text-io.h"
|
||||
#include "ticks.h"
|
||||
#include "util.h"
|
||||
#include "version.h"
|
||||
#include "efivars.h"
|
||||
|
||||
/* Never try to read more than 16G into memory (and on 32bit 1G) */
|
||||
#define FILE_READ_MAX MIN(SIZE_MAX/4, UINT64_C(16)*1024U*1024U*1024U)
|
||||
@ -511,3 +512,40 @@ bool free_and_xstrdup16(char16_t **p, const char16_t *s) {
|
||||
*p = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
char16_t *url_replace_last_component(const char16_t *url, const char16_t *filename) {
|
||||
assert(url);
|
||||
assert(filename);
|
||||
|
||||
/* Find colon separating protocol and hostname */
|
||||
const char16_t *d = strchr16(url, ':');
|
||||
if (!d || url == d)
|
||||
return NULL;
|
||||
d++;
|
||||
|
||||
/* Skip slashes after colon */
|
||||
d += strspn(d, u"/");
|
||||
|
||||
/* Skip everything till next slash or end (i.e. the hostname) */
|
||||
size_t n = strcspn(d, u"/?#");
|
||||
if (n == 0)
|
||||
return NULL;
|
||||
|
||||
d += n;
|
||||
|
||||
const char16_t *e = d + strcspn(d, u"?#"); /* Cut off "Query" and "Fragment" */
|
||||
|
||||
while (e > d && e[-1] == '/') /* Eat trailing slashes */
|
||||
e--;
|
||||
|
||||
const char16_t *p = e;
|
||||
while (p > d && p[-1] != '/') /* Find component before that */
|
||||
p--;
|
||||
|
||||
if (e <= p)
|
||||
return NULL;
|
||||
|
||||
_cleanup_free_ char16_t *chopped = xstrndup16(url, p - url);
|
||||
|
||||
return xasprintf("%ls/%ls", chopped, filename);
|
||||
}
|
||||
|
@ -251,3 +251,5 @@ char16_t *get_extra_dir(const EFI_DEVICE_PATH *file_path);
|
||||
#define xnew0(type, n) ASSERT_PTR(new0(type, n))
|
||||
|
||||
#endif
|
||||
|
||||
char16_t *url_replace_last_component(const char16_t *url, const char16_t *filename);
|
||||
|
@ -392,6 +392,7 @@ int verb_status(int argc, char *argv[], void *userdata) {
|
||||
{ EFI_LOADER_FEATURE_MULTI_PROFILE_UKI, "Multi-Profile UKIs are supported" },
|
||||
{ EFI_LOADER_FEATURE_REPORT_URL, "Loader reports network boot URL" },
|
||||
{ EFI_LOADER_FEATURE_TYPE1_UKI, "Support Type #1 uki field" },
|
||||
{ EFI_LOADER_FEATURE_TYPE1_UKI_URL, "Support Type #1 uki-url field" },
|
||||
};
|
||||
static const struct {
|
||||
uint64_t flag;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define EFI_LOADER_FEATURE_MULTI_PROFILE_UKI (UINT64_C(1) << 14)
|
||||
#define EFI_LOADER_FEATURE_REPORT_URL (UINT64_C(1) << 15)
|
||||
#define EFI_LOADER_FEATURE_TYPE1_UKI (UINT64_C(1) << 16)
|
||||
#define EFI_LOADER_FEATURE_TYPE1_UKI_URL (UINT64_C(1) << 17)
|
||||
|
||||
/* Features of the stub, i.e. systemd-stub */
|
||||
#define EFI_STUB_FEATURE_REPORT_BOOT_PARTITION (UINT64_C(1) << 0)
|
||||
|
@ -8,7 +8,9 @@ struct iovec {
|
||||
size_t iov_len;
|
||||
};
|
||||
|
||||
DISABLE_WARNING_REDUNDANT_DECLS;
|
||||
static inline void free(void *p);
|
||||
REENABLE_WARNING;
|
||||
#endif
|
||||
|
||||
/* This accepts both const and non-const pointers */
|
||||
|
@ -52,6 +52,10 @@
|
||||
_Pragma("GCC diagnostic push"); \
|
||||
_Pragma("GCC diagnostic ignored \"-Wstringop-truncation\"")
|
||||
|
||||
#define DISABLE_WARNING_REDUNDANT_DECLS \
|
||||
_Pragma("GCC diagnostic push"); \
|
||||
_Pragma("GCC diagnostic ignored \"-Wredundant-decls\"")
|
||||
|
||||
#if HAVE_WARNING_ZERO_LENGTH_BOUNDS
|
||||
# define DISABLE_WARNING_ZERO_LENGTH_BOUNDS \
|
||||
_Pragma("GCC diagnostic push"); \
|
||||
|
Loading…
x
Reference in New Issue
Block a user