boot: Split out device path functions
No code changes aside from renaming path_replace_hd() and making its parameter take any device path node type.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include "bcd.h"
|
||||
#include "bootspec-fundamental.h"
|
||||
#include "console.h"
|
||||
#include "device-path-util.h"
|
||||
#include "devicetree.h"
|
||||
#include "drivers.h"
|
||||
#include "efivars-fundamental.h"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "device-path-util.h"
|
||||
#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 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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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, new_node_len = 0;
|
||||
if (new_node)
|
||||
new_node_len = DevicePathNodeLength(new_node);
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "efi.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);
|
||||
@@ -1,5 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "device-path-util.h"
|
||||
#include "drivers.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
@@ -332,6 +332,7 @@ efi_headers = files(
|
||||
'bcd.h',
|
||||
'console.h',
|
||||
'cpio.h',
|
||||
'device-path-util.h',
|
||||
'devicetree.h',
|
||||
'drivers.h',
|
||||
'efi-string.h',
|
||||
@@ -366,6 +367,7 @@ efi_headers = files(
|
||||
|
||||
common_sources = files(
|
||||
'console.c',
|
||||
'device-path-util.c',
|
||||
'devicetree.c',
|
||||
'drivers.c',
|
||||
'efi-string.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;
|
||||
@@ -204,7 +180,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 +234,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* https://github.com/mjg59/efitools
|
||||
*/
|
||||
|
||||
#include "device-path-util.h"
|
||||
#include "secure-boot.h"
|
||||
#include "shim.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "cpio.h"
|
||||
#include "device-path-util.h"
|
||||
#include "devicetree.h"
|
||||
#include "graphics.h"
|
||||
#include "linux.h"
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -184,8 +184,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;
|
||||
|
||||
+1
-21
@@ -4,6 +4,7 @@
|
||||
# include <cpuid.h>
|
||||
#endif
|
||||
|
||||
#include "device-path-util.h"
|
||||
#include "drivers.h"
|
||||
#include "efi-string.h"
|
||||
#include "proto/device-path.h"
|
||||
@@ -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
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user