From: Lennart Poettering Date: Tue, 11 Feb 2025 08:34:20 +0000 (+0100) Subject: boot: add new 'uki-url' bls type #1 menu items for booting remote UKIs X-Git-Tag: v258-rc1~1280^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1089d0f89e3c7c8a2b17ebeba32d567061fb3ba1;p=thirdparty%2Fsystemd.git 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 --- diff --git a/src/boot/boot.c b/src/boot/boot.c index e57c5986541..980fcff7c32 100644 --- a/src/boot/boot.c +++ b/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"); + _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 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; + } - 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"); + /* 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(); + } - 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"); + /* 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. */ - err = shim_load_image(parent_image, path, &image); - if (err != EFI_SUCCESS) - return log_error_status(err, "Error loading %ls: %m", entry->loader); + 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); - /* 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); + 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 loading %ls: %m", entry->devicetree); + 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); diff --git a/src/boot/device-path-util.c b/src/boot/device-path-util.c index 2a85e8bbfc0..0e991f941f5 100644 --- a/src/boot/device-path-util.c +++ b/src/boot/device-path-util.c @@ -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); +} diff --git a/src/boot/device-path-util.h b/src/boot/device-path-util.h index 08f1a9c2167..c33669a866b 100644 --- a/src/boot/device-path-util.h +++ b/src/boot/device-path-util.h @@ -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)); +} diff --git a/src/boot/shim.c b/src/boot/shim.c index 514a1d0eda3..87d7dff1915 100644 --- a/src/boot/shim.c +++ b/src/boot/shim.c @@ -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(); diff --git a/src/boot/shim.h b/src/boot/shim.h index e0cb39f7950..ef9dc7ba276 100644 --- a/src/boot/shim.h +++ b/src/boot/shim.h @@ -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); diff --git a/src/boot/stub.c b/src/boot/stub.c index 3b3a5f6a428..ac6c1124590 100644 --- a/src/boot/stub.c +++ b/src/boot/stub.c @@ -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", diff --git a/src/boot/util.c b/src/boot/util.c index 395c1f2abc8..5dd111e7c5a 100644 --- a/src/boot/util.c +++ b/src/boot/util.c @@ -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); +} diff --git a/src/boot/util.h b/src/boot/util.h index 49ba1196137..2b5cc7213e9 100644 --- a/src/boot/util.h +++ b/src/boot/util.h @@ -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); diff --git a/src/bootctl/bootctl-status.c b/src/bootctl/bootctl-status.c index 541f7f25cce..798c86dba29 100644 --- a/src/bootctl/bootctl-status.c +++ b/src/bootctl/bootctl-status.c @@ -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; diff --git a/src/fundamental/efivars-fundamental.h b/src/fundamental/efivars-fundamental.h index b7197a874ed..d556e7718f8 100644 --- a/src/fundamental/efivars-fundamental.h +++ b/src/fundamental/efivars-fundamental.h @@ -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) diff --git a/src/fundamental/iovec-util-fundamental.h b/src/fundamental/iovec-util-fundamental.h index 68d5bf4ee0c..edd95fa4e9a 100644 --- a/src/fundamental/iovec-util-fundamental.h +++ b/src/fundamental/iovec-util-fundamental.h @@ -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 */ diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h index 78a87d150b5..d56dcb6eb6d 100644 --- a/src/fundamental/macro-fundamental.h +++ b/src/fundamental/macro-fundamental.h @@ -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"); \