diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index ea19dd82d2..ee507e379a 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -3,8 +3,8 @@ #include "bcd.h" #include "bootspec-fundamental.h" #include "console.h" +#include "device-path-util.h" #include "devicetree.h" -#include "disk.h" #include "drivers.h" #include "efivars-fundamental.h" #include "graphics.h" @@ -2542,7 +2542,6 @@ static void export_variables( 0; _cleanup_free_ char16_t *infostr = NULL, *typestr = NULL; - char16_t uuid[37]; assert(loaded_image); @@ -2561,7 +2560,8 @@ static void export_variables( efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderImageIdentifier", loaded_image_path, 0); /* export the device path this image is started from */ - if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == 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); } diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c index 2e971a9167..f82a31b475 100644 --- a/src/boot/efi/cpio.c +++ b/src/boot/efi/cpio.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "cpio.h" +#include "device-path-util.h" #include "measure.h" #include "proto/device-path.h" #include "util.h" @@ -310,8 +311,9 @@ static char16_t *get_dropin_dir(const EFI_DEVICE_PATH *file_path) { * not create a legal EFI file path that the file protocol can use. */ /* Make sure we really only got file paths. */ - for (const EFI_DEVICE_PATH *node = file_path; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) - if (DevicePathType(node) != MEDIA_DEVICE_PATH || DevicePathSubType(node) != MEDIA_FILEPATH_DP) + for (const EFI_DEVICE_PATH *node = file_path; !device_path_is_end(node); + node = device_path_next_node(node)) + if (node->Type != MEDIA_DEVICE_PATH || node->SubType != MEDIA_FILEPATH_DP) return NULL; _cleanup_free_ char16_t *file_path_str = NULL; diff --git a/src/boot/efi/device-path-util.c b/src/boot/efi/device-path-util.c new file mode 100644 index 0000000000..fe5e3a83ce --- /dev/null +++ b/src/boot/efi/device-path-util.c @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "device-path-util.h" +#include "util.h" + +EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DEVICE_PATH **ret_dp) { + EFI_STATUS err; + EFI_DEVICE_PATH *dp; + + assert(file); + assert(ret_dp); + + err = BS->HandleProtocol(device, MAKE_GUID_PTR(EFI_DEVICE_PATH_PROTOCOL), (void **) &dp); + if (err != EFI_SUCCESS) + return err; + + EFI_DEVICE_PATH *end_node = dp; + while (!device_path_is_end(end_node)) + end_node = device_path_next_node(end_node); + + size_t file_size = strsize16(file); + size_t dp_size = (uint8_t *) end_node - (uint8_t *) dp; + + /* Make a copy that can also hold a file media device path. */ + *ret_dp = xmalloc(dp_size + file_size + sizeof(FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH)); + dp = mempcpy(*ret_dp, dp, dp_size); + + FILEPATH_DEVICE_PATH *file_dp = (FILEPATH_DEVICE_PATH *) dp; + file_dp->Header = (EFI_DEVICE_PATH) { + .Type = MEDIA_DEVICE_PATH, + .SubType = MEDIA_FILEPATH_DP, + .Length = sizeof(FILEPATH_DEVICE_PATH) + file_size, + }; + memcpy(file_dp->PathName, file, file_size); + + dp = device_path_next_node(dp); + *dp = DEVICE_PATH_END_NODE; + return EFI_SUCCESS; +} + +EFI_STATUS device_path_to_str(const EFI_DEVICE_PATH *dp, char16_t **ret) { + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *dp_to_text; + EFI_STATUS err; + _cleanup_free_ char16_t *str = NULL; + + assert(dp); + assert(ret); + + err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_DEVICE_PATH_TO_TEXT_PROTOCOL), NULL, (void **) &dp_to_text); + if (err != EFI_SUCCESS) { + /* If the device path to text protocol is not available we can still do a best-effort attempt + * to convert it ourselves if we are given filepath-only device path. */ + + size_t size = 0; + for (const EFI_DEVICE_PATH *node = dp; !device_path_is_end(node); + node = device_path_next_node(node)) { + + if (node->Type != MEDIA_DEVICE_PATH || node->SubType != MEDIA_FILEPATH_DP) + return err; + + size_t path_size = node->Length; + if (path_size <= offsetof(FILEPATH_DEVICE_PATH, PathName) || path_size % sizeof(char16_t)) + return EFI_INVALID_PARAMETER; + path_size -= offsetof(FILEPATH_DEVICE_PATH, PathName); + + _cleanup_free_ char16_t *old = str; + str = xmalloc(size + path_size); + if (old) { + memcpy(str, old, size); + str[size / sizeof(char16_t) - 1] = '\\'; + } + + memcpy(str + (size / sizeof(char16_t)), + ((uint8_t *) node) + offsetof(FILEPATH_DEVICE_PATH, PathName), + path_size); + size += path_size; + } + + *ret = TAKE_PTR(str); + return EFI_SUCCESS; + } + + str = dp_to_text->ConvertDevicePathToText(dp, false, false); + if (!str) + return EFI_OUT_OF_RESOURCES; + + *ret = TAKE_PTR(str); + return EFI_SUCCESS; +} + +bool device_path_startswith(const EFI_DEVICE_PATH *dp, const EFI_DEVICE_PATH *start) { + if (!start) + return true; + if (!dp) + return false; + for (;;) { + if (device_path_is_end(start)) + return true; + if (device_path_is_end(dp)) + return false; + if (start->Length != dp->Length) + return false; + if (memcmp(dp, start, start->Length) != 0) + return false; + start = device_path_next_node(start); + dp = device_path_next_node(dp); + } +} + +EFI_DEVICE_PATH *device_path_replace_node( + const EFI_DEVICE_PATH *path, const EFI_DEVICE_PATH *node, const EFI_DEVICE_PATH *new_node) { + + /* Create a new device path as a copy of path, while chopping off the remainder starting at the given + * node. If new_node is provided, it is appended at the end of the new path. */ + + assert(path); + assert(node); + + size_t len = (uint8_t *) node - (uint8_t *) path; + EFI_DEVICE_PATH *ret = xmalloc(len + (new_node ? new_node->Length : 0) + sizeof(EFI_DEVICE_PATH)); + EFI_DEVICE_PATH *end = mempcpy(ret, path, len); + + if (new_node) + end = mempcpy(end, new_node, new_node->Length); + + *end = DEVICE_PATH_END_NODE; + return ret; +} diff --git a/src/boot/efi/device-path-util.h b/src/boot/efi/device-path-util.h new file mode 100644 index 0000000000..08f1a9c216 --- /dev/null +++ b/src/boot/efi/device-path-util.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "proto/device-path.h" + +EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DEVICE_PATH **ret_dp); +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( + const EFI_DEVICE_PATH *path, const EFI_DEVICE_PATH *node, const EFI_DEVICE_PATH *new_node); + +static inline EFI_DEVICE_PATH *device_path_next_node(const EFI_DEVICE_PATH *dp) { + assert(dp); + return (EFI_DEVICE_PATH *) ((uint8_t *) dp + dp->Length); +} + +static inline bool device_path_is_end(const EFI_DEVICE_PATH *dp) { + assert(dp); + return dp->Type == END_DEVICE_PATH_TYPE && dp->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE; +} + +#define DEVICE_PATH_END_NODE \ + (EFI_DEVICE_PATH) { \ + .Type = END_DEVICE_PATH_TYPE, \ + .SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE, \ + .Length = sizeof(EFI_DEVICE_PATH) \ + } diff --git a/src/boot/efi/disk.c b/src/boot/efi/disk.c deleted file mode 100644 index 44be3232ee..0000000000 --- a/src/boot/efi/disk.c +++ /dev/null @@ -1,58 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "disk.h" -#include "proto/device-path.h" -#include "util.h" - -EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, char16_t uuid[static 37]) { - EFI_STATUS err; - EFI_DEVICE_PATH *dp; - - /* export the device path this image is started from */ - - if (!handle) - return EFI_NOT_FOUND; - - err = BS->HandleProtocol(handle, MAKE_GUID_PTR(EFI_DEVICE_PATH_PROTOCOL), (void **) &dp); - if (err != EFI_SUCCESS) - return err; - - for (; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) { - if (DevicePathType(dp) != MEDIA_DEVICE_PATH) - continue; - if (DevicePathSubType(dp) != MEDIA_HARDDRIVE_DP) - continue; - - /* The HD device path may be misaligned. */ - HARDDRIVE_DEVICE_PATH hd; - memcpy(&hd, dp, MIN(sizeof(hd), (size_t) DevicePathNodeLength(dp))); - - if (hd.SignatureType != SIGNATURE_TYPE_GUID) - continue; - - _cleanup_free_ char16_t *tmp = xasprintf( - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - hd.Signature[3], - hd.Signature[2], - hd.Signature[1], - hd.Signature[0], - - hd.Signature[5], - hd.Signature[4], - hd.Signature[7], - hd.Signature[6], - - hd.Signature[8], - hd.Signature[9], - hd.Signature[10], - hd.Signature[11], - hd.Signature[12], - hd.Signature[13], - hd.Signature[14], - hd.Signature[15]); - strcpy16(uuid, tmp); - return EFI_SUCCESS; - } - - return EFI_NOT_FOUND; -} diff --git a/src/boot/efi/disk.h b/src/boot/efi/disk.h deleted file mode 100644 index 2da5bca133..0000000000 --- a/src/boot/efi/disk.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include "efi.h" - -EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, char16_t uuid[static 37]); diff --git a/src/boot/efi/drivers.c b/src/boot/efi/drivers.c index 25bf694723..067455771f 100644 --- a/src/boot/efi/drivers.c +++ b/src/boot/efi/drivers.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "device-path-util.h" #include "drivers.h" #include "util.h" diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build index 8d85dac844..bf595c3390 100644 --- a/src/boot/efi/meson.build +++ b/src/boot/efi/meson.build @@ -332,8 +332,8 @@ efi_headers = files( 'bcd.h', 'console.h', 'cpio.h', + 'device-path-util.h', 'devicetree.h', - 'disk.h', 'drivers.h', 'efi-string.h', 'efi.h', @@ -367,9 +367,9 @@ efi_headers = files( common_sources = files( 'console.c', + 'device-path-util.c', 'devicetree.c', 'drivers.c', - 'disk.c', 'efi-string.c', 'graphics.c', 'initrd.c', diff --git a/src/boot/efi/part-discovery.c b/src/boot/efi/part-discovery.c index e25905ff48..f5b1573055 100644 --- a/src/boot/efi/part-discovery.c +++ b/src/boot/efi/part-discovery.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "device-path-util.h" #include "part-discovery.h" #include "proto/block-io.h" #include "proto/device-path.h" @@ -29,31 +30,6 @@ typedef struct { } _packed_ GptHeader; assert_cc(sizeof(GptHeader) == 512); -static EFI_DEVICE_PATH *path_replace_hd( - const EFI_DEVICE_PATH *path, - const EFI_DEVICE_PATH *node, - const HARDDRIVE_DEVICE_PATH *new_node) { - - /* Create a new device path as a copy of path, while chopping off the remainder starting at the given - * node. If new_node is provided, it is appended at the end of the new path. */ - - assert(path); - assert(node); - - size_t len = (uint8_t *) node - (uint8_t *) path, new_node_len = 0; - if (new_node) - new_node_len = DevicePathNodeLength(&new_node->Header); - - EFI_DEVICE_PATH *ret = xmalloc(len + new_node_len + sizeof(EFI_DEVICE_PATH)); - EFI_DEVICE_PATH *end = mempcpy(ret, path, len); - - if (new_node) - end = mempcpy(end, new_node, new_node_len); - - SetDevicePathEndNode(end); - return ret; -} - static bool verify_gpt(/*const*/ GptHeader *h, EFI_LBA lba_expected) { uint32_t crc32, crc32_saved; EFI_STATUS err; @@ -189,11 +165,9 @@ static EFI_STATUS find_device(const EFI_GUID *type, EFI_HANDLE *device, EFI_DEVI /* Find the (last) partition node itself. */ EFI_DEVICE_PATH *part_node = NULL; - for (EFI_DEVICE_PATH *node = partition_path; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) { - if (DevicePathType(node) != MEDIA_DEVICE_PATH) - continue; - - if (DevicePathSubType(node) != MEDIA_HARDDRIVE_DP) + for (EFI_DEVICE_PATH *node = partition_path; !device_path_is_end(node); + node = device_path_next_node(node)) { + if (node->Type != MEDIA_DEVICE_PATH || node->SubType != MEDIA_HARDDRIVE_DP) continue; part_node = node; @@ -204,7 +178,7 @@ static EFI_STATUS find_device(const EFI_GUID *type, EFI_HANDLE *device, EFI_DEVI /* Chop off the partition part, leaving us with the full path to the disk itself. */ _cleanup_free_ EFI_DEVICE_PATH *disk_path = NULL; - EFI_DEVICE_PATH *p = disk_path = path_replace_hd(partition_path, part_node, NULL); + EFI_DEVICE_PATH *p = disk_path = device_path_replace_node(partition_path, part_node, NULL); EFI_HANDLE disk_handle; EFI_BLOCK_IO_PROTOCOL *block_io; @@ -258,7 +232,7 @@ static EFI_STATUS find_device(const EFI_GUID *type, EFI_HANDLE *device, EFI_DEVI } /* Patch in the data we found */ - *ret_device_path = path_replace_hd(partition_path, part_node, &hd); + *ret_device_path = device_path_replace_node(partition_path, part_node, (EFI_DEVICE_PATH *) &hd); return EFI_SUCCESS; } @@ -295,3 +269,30 @@ EFI_STATUS partition_open(const EFI_GUID *type, EFI_HANDLE *device, EFI_HANDLE * *ret_root_dir = root_dir; return EFI_SUCCESS; } + +char16_t *disk_get_part_uuid(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 != MEDIA_DEVICE_PATH || dp->SubType != MEDIA_HARDDRIVE_DP) + continue; + + HARDDRIVE_DEVICE_PATH *hd = (HARDDRIVE_DEVICE_PATH *) dp; + if (hd->SignatureType != SIGNATURE_TYPE_GUID) + continue; + + return xasprintf(GUID_FORMAT_STR, GUID_FORMAT_VAL(hd->SignatureGuid)); + } + + return NULL; +} diff --git a/src/boot/efi/part-discovery.h b/src/boot/efi/part-discovery.h index 597ded3b3e..bbc87ffe36 100644 --- a/src/boot/efi/part-discovery.h +++ b/src/boot/efi/part-discovery.h @@ -9,3 +9,4 @@ { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } } EFI_STATUS partition_open(const EFI_GUID *type, EFI_HANDLE *device, EFI_HANDLE *ret_device, EFI_FILE **ret_root_dir); +char16_t *disk_get_part_uuid(EFI_HANDLE *handle); diff --git a/src/boot/efi/proto/device-path.h b/src/boot/efi/proto/device-path.h index 8d8bd0c3f7..0fabae1125 100644 --- a/src/boot/efi/proto/device-path.h +++ b/src/boot/efi/proto/device-path.h @@ -54,7 +54,10 @@ typedef struct { uint32_t PartitionNumber; uint64_t PartitionStart; uint64_t PartitionSize; - uint8_t Signature[16]; + union { + uint8_t Signature[16]; + EFI_GUID SignatureGuid; + }; uint8_t MBRType; uint8_t SignatureType; } _packed_ HARDDRIVE_DEVICE_PATH; @@ -81,24 +84,3 @@ typedef struct { EFI_DEVICE_PATH* (EFIAPI *ConvertTextToDevicPath)( const char16_t *ConvertTextToDevicPath); } EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL; - -#define DevicePathType(dp) ((dp)->Type) -#define DevicePathSubType(dp) ((dp)->SubType) -#define DevicePathNodeLength(dp) ((dp)->Length) - -static inline EFI_DEVICE_PATH *NextDevicePathNode(const EFI_DEVICE_PATH *dp) { - assert(dp); - return (EFI_DEVICE_PATH *) ((uint8_t *) dp + dp->Length); -} - -static inline bool IsDevicePathEnd(const EFI_DEVICE_PATH *dp) { - assert(dp); - return dp->Type == END_DEVICE_PATH_TYPE && dp->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE; -} - -static inline void SetDevicePathEndNode(EFI_DEVICE_PATH *dp) { - assert(dp); - dp->Type = END_DEVICE_PATH_TYPE; - dp->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; - dp->Length = sizeof(EFI_DEVICE_PATH); -} diff --git a/src/boot/efi/shim.c b/src/boot/efi/shim.c index e0bb470cf2..dda727ee8e 100644 --- a/src/boot/efi/shim.c +++ b/src/boot/efi/shim.c @@ -8,6 +8,7 @@ * https://github.com/mjg59/efitools */ +#include "device-path-util.h" #include "secure-boot.h" #include "shim.h" #include "util.h" diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index d85424ceae..2635445b04 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "cpio.h" +#include "device-path-util.h" #include "devicetree.h" -#include "disk.h" #include "graphics.h" #include "linux.h" #include "measure.h" @@ -87,14 +87,14 @@ static void export_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) { EFI_STUB_FEATURE_RANDOM_SEED | /* We pass a random seed to the kernel */ 0; - char16_t uuid[37]; - 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) - if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) + 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 diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c index 96c62e6bfa..19c4788b8f 100644 --- a/src/boot/efi/util.c +++ b/src/boot/efi/util.c @@ -622,91 +622,6 @@ EFI_STATUS open_volume(EFI_HANDLE device, EFI_FILE **ret_file) { return EFI_SUCCESS; } -EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DEVICE_PATH **ret_dp) { - EFI_STATUS err; - EFI_DEVICE_PATH *dp; - - assert(file); - assert(ret_dp); - - err = BS->HandleProtocol(device, MAKE_GUID_PTR(EFI_DEVICE_PATH_PROTOCOL), (void **) &dp); - if (err != EFI_SUCCESS) - return err; - - EFI_DEVICE_PATH *end_node = dp; - while (!IsDevicePathEnd(end_node)) - end_node = NextDevicePathNode(end_node); - - size_t file_size = strsize16(file); - size_t dp_size = (uint8_t *) end_node - (uint8_t *) dp; - - /* Make a copy that can also hold a file media device path. */ - *ret_dp = xmalloc(dp_size + file_size + sizeof(FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH)); - dp = mempcpy(*ret_dp, dp, dp_size); - - /* Replace end node with file media device path. Use memcpy() in case dp is unaligned (if accessed as - * FILEPATH_DEVICE_PATH). */ - dp->Type = MEDIA_DEVICE_PATH; - dp->SubType = MEDIA_FILEPATH_DP; - dp->Length = sizeof(FILEPATH_DEVICE_PATH) + file_size; - memcpy((uint8_t *) dp + sizeof(FILEPATH_DEVICE_PATH), file, file_size); - - dp = NextDevicePathNode(dp); - SetDevicePathEndNode(dp); - return EFI_SUCCESS; -} - -EFI_STATUS device_path_to_str(const EFI_DEVICE_PATH *dp, char16_t **ret) { - EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *dp_to_text; - EFI_STATUS err; - _cleanup_free_ char16_t *str = NULL; - - assert(dp); - assert(ret); - - err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_DEVICE_PATH_TO_TEXT_PROTOCOL), NULL, (void **) &dp_to_text); - if (err != EFI_SUCCESS) { - /* If the device path to text protocol is not available we can still do a best-effort attempt - * to convert it ourselves if we are given filepath-only device path. */ - - size_t size = 0; - for (const EFI_DEVICE_PATH *node = dp; !IsDevicePathEnd(node); - node = NextDevicePathNode(node)) { - - if (DevicePathType(node) != MEDIA_DEVICE_PATH || - DevicePathSubType(node) != MEDIA_FILEPATH_DP) - return err; - - size_t path_size = DevicePathNodeLength(node); - if (path_size <= offsetof(FILEPATH_DEVICE_PATH, PathName) || path_size % sizeof(char16_t)) - return EFI_INVALID_PARAMETER; - path_size -= offsetof(FILEPATH_DEVICE_PATH, PathName); - - _cleanup_free_ char16_t *old = str; - str = xmalloc(size + path_size); - if (old) { - memcpy(str, old, size); - str[size / sizeof(char16_t) - 1] = '\\'; - } - - memcpy(str + (size / sizeof(char16_t)), - ((uint8_t *) node) + offsetof(FILEPATH_DEVICE_PATH, PathName), - path_size); - size += path_size; - } - - *ret = TAKE_PTR(str); - return EFI_SUCCESS; - } - - str = dp_to_text->ConvertDevicePathToText(dp, false, false); - if (!str) - return EFI_OUT_OF_RESOURCES; - - *ret = TAKE_PTR(str); - return EFI_SUCCESS; -} - void *find_configuration_table(const EFI_GUID *guid) { for (size_t i = 0; i < ST->NumberOfTableEntries; i++) if (efi_guid_equal(&ST->ConfigurationTable[i].VendorGuid, guid)) diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h index 614d83fb71..a28228c4cc 100644 --- a/src/boot/efi/util.h +++ b/src/boot/efi/util.h @@ -119,6 +119,11 @@ static inline void unload_imagep(EFI_HANDLE *image) { #define LOADER_GUID \ { 0x4a67b082, 0x0a4c, 0x41cf, { 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } } +/* Note that GUID is evaluated multiple times! */ +#define GUID_FORMAT_STR "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X" +#define GUID_FORMAT_VAL(g) (g).Data1, (g).Data2, (g).Data3, (g).Data4[0], (g).Data4[1], \ + (g).Data4[2], (g).Data4[3], (g).Data4[4], (g).Data4[5], (g).Data4[6], (g).Data4[7] + void print_at(size_t x, size_t y, size_t attr, const char16_t *str); void clear_screen(size_t attr); @@ -184,8 +189,6 @@ static inline void beep(unsigned beep_count) {} #endif EFI_STATUS open_volume(EFI_HANDLE device, EFI_FILE **ret_file); -EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DEVICE_PATH **ret_dp); -EFI_STATUS device_path_to_str(const EFI_DEVICE_PATH *dp, char16_t **ret); static inline bool efi_guid_equal(const EFI_GUID *a, const EFI_GUID *b) { return memcmp(a, b, sizeof(EFI_GUID)) == 0; diff --git a/src/boot/efi/vmm.c b/src/boot/efi/vmm.c index c3816e1b2d..f5c17a9eca 100644 --- a/src/boot/efi/vmm.c +++ b/src/boot/efi/vmm.c @@ -4,6 +4,7 @@ # include #endif +#include "device-path-util.h" #include "drivers.h" #include "efi-string.h" #include "proto/device-path.h" @@ -19,7 +20,7 @@ /* detect direct boot */ bool is_direct_boot(EFI_HANDLE device) { EFI_STATUS err; - VENDOR_DEVICE_PATH *dp; /* NB: Alignment of this structure might be quirky! */ + VENDOR_DEVICE_PATH *dp; err = BS->HandleProtocol(device, MAKE_GUID_PTR(EFI_DEVICE_PATH_PROTOCOL), (void **) &dp); if (err != EFI_SUCCESS) @@ -28,7 +29,7 @@ bool is_direct_boot(EFI_HANDLE device) { /* 'qemu -kernel systemd-bootx64.efi' */ if (dp->Header.Type == MEDIA_DEVICE_PATH && dp->Header.SubType == MEDIA_VENDOR_DP && - memcmp(&dp->Guid, MAKE_GUID_PTR(QEMU_KERNEL_LOADER_FS_MEDIA), sizeof(EFI_GUID)) == 0) /* Don't change to efi_guid_equal() because EFI device path objects are not necessarily aligned! */ + memcmp(&dp->Guid, MAKE_GUID_PTR(QEMU_KERNEL_LOADER_FS_MEDIA), sizeof(EFI_GUID)) == 0) return true; /* loaded from firmware volume (sd-boot added to ovmf) */ @@ -39,27 +40,6 @@ bool is_direct_boot(EFI_HANDLE device) { return false; } -static bool device_path_startswith(const EFI_DEVICE_PATH *dp, const EFI_DEVICE_PATH *start) { - if (!start) - return true; - if (!dp) - return false; - for (;;) { - if (IsDevicePathEnd(start)) - return true; - if (IsDevicePathEnd(dp)) - return false; - size_t l1 = DevicePathNodeLength(start); - size_t l2 = DevicePathNodeLength(dp); - if (l1 != l2) - return false; - if (memcmp(dp, start, l1) != 0) - return false; - start = NextDevicePathNode(start); - dp = NextDevicePathNode(dp); - } -} - /* * Try find ESP when not loaded from ESP *