mirror of
https://github.com/systemd/systemd.git
synced 2024-10-27 10:25:37 +03:00
Merge pull request #26542 from medhefgo/boot-device-path
boot: Misc device path improvements
This commit is contained in:
commit
2457a36d30
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
128
src/boot/efi/device-path-util.c
Normal file
128
src/boot/efi/device-path-util.c
Normal file
@ -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;
|
||||
}
|
27
src/boot/efi/device-path-util.h
Normal file
27
src/boot/efi/device-path-util.h
Normal file
@ -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) \
|
||||
}
|
@ -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;
|
||||
}
|
@ -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]);
|
@ -1,5 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "device-path-util.h"
|
||||
#include "drivers.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,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
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
@ -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
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user