+4
-11
@@ -472,7 +472,6 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
|
||||
_cleanup_free_ char16_t *device_part_uuid = NULL;
|
||||
|
||||
assert(config);
|
||||
assert(loaded_image_path);
|
||||
|
||||
clear_screen(COLOR_NORMAL);
|
||||
console_query_mode(&x_max, &y_max);
|
||||
@@ -620,7 +619,6 @@ static bool menu_run(
|
||||
|
||||
assert(config);
|
||||
assert(chosen_entry);
|
||||
assert(loaded_image_path);
|
||||
|
||||
EFI_STATUS err;
|
||||
UINTN visible_max = 0;
|
||||
@@ -1479,7 +1477,7 @@ static void config_entry_add_type1(
|
||||
entry->loader = xstra_to_path(value);
|
||||
|
||||
/* do not add an entry for ourselves */
|
||||
if (loaded_image_path && strcaseeq16(entry->loader, loaded_image_path)) {
|
||||
if (strcaseeq16(entry->loader, loaded_image_path)) {
|
||||
entry->type = LOADER_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
@@ -1909,12 +1907,11 @@ static ConfigEntry *config_entry_add_loader_auto(
|
||||
assert(root_dir);
|
||||
assert(id);
|
||||
assert(title);
|
||||
assert(loader || loaded_image_path);
|
||||
|
||||
if (!config->auto_entries)
|
||||
return NULL;
|
||||
|
||||
if (loaded_image_path) {
|
||||
if (!loader) {
|
||||
loader = L"\\EFI\\BOOT\\BOOT" EFI_MACHINE_TYPE_NAME ".efi";
|
||||
|
||||
/* We are trying to add the default EFI loader here,
|
||||
@@ -2563,7 +2560,6 @@ static void export_variables(
|
||||
char16_t uuid[37];
|
||||
|
||||
assert(loaded_image);
|
||||
assert(loaded_image_path);
|
||||
|
||||
efivar_set_time_usec(LOADER_GUID, L"LoaderTimeInitUSec", init_usec);
|
||||
efivar_set(LOADER_GUID, L"LoaderInfo", L"systemd-boot " GIT_VERSION, 0);
|
||||
@@ -2592,7 +2588,6 @@ static void config_load_all_entries(
|
||||
|
||||
assert(config);
|
||||
assert(loaded_image);
|
||||
assert(loaded_image_path);
|
||||
assert(root_dir);
|
||||
|
||||
config_load_defaults(config, root_dir);
|
||||
@@ -2658,7 +2653,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
|
||||
_cleanup_(file_closep) EFI_FILE *root_dir = NULL;
|
||||
_cleanup_(config_free) Config config = {};
|
||||
char16_t *loaded_image_path;
|
||||
_cleanup_free_ char16_t *loaded_image_path = NULL;
|
||||
EFI_STATUS err;
|
||||
uint64_t init_usec;
|
||||
bool menu = false;
|
||||
@@ -2684,9 +2679,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err);
|
||||
|
||||
err = device_path_to_str(loaded_image->FilePath, &loaded_image_path);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status_stall(err, L"Error getting loaded image path: %r", err);
|
||||
(void) device_path_to_str(loaded_image->FilePath, &loaded_image_path);
|
||||
|
||||
export_variables(loaded_image, loaded_image_path, init_usec);
|
||||
|
||||
|
||||
+23
-38
@@ -20,35 +20,26 @@
|
||||
#define STUB_PAYLOAD_GUID \
|
||||
{ 0x55c5d1f8, 0x04cd, 0x46b5, { 0x8a, 0x20, 0xe5, 0x6c, 0xbb, 0x30, 0x52, 0xd0 } }
|
||||
|
||||
static EFIAPI EFI_STATUS security_hook(
|
||||
const SecurityOverride *this, uint32_t authentication_status, const EFI_DEVICE_PATH *file) {
|
||||
typedef struct {
|
||||
const void *addr;
|
||||
size_t len;
|
||||
const EFI_DEVICE_PATH *device_path;
|
||||
} ValidationContext;
|
||||
|
||||
assert(this);
|
||||
assert(this->hook == security_hook);
|
||||
static bool validate_payload(
|
||||
const void *ctx, const EFI_DEVICE_PATH *device_path, const void *file_buffer, size_t file_size) {
|
||||
|
||||
if (file == this->payload_device_path)
|
||||
return EFI_SUCCESS;
|
||||
const ValidationContext *payload = ASSERT_PTR(ctx);
|
||||
|
||||
return this->original_security->FileAuthenticationState(
|
||||
this->original_security, authentication_status, file);
|
||||
}
|
||||
if (device_path != payload->device_path)
|
||||
return false;
|
||||
|
||||
static EFIAPI EFI_STATUS security2_hook(
|
||||
const SecurityOverride *this,
|
||||
const EFI_DEVICE_PATH *device_path,
|
||||
void *file_buffer,
|
||||
size_t file_size,
|
||||
BOOLEAN boot_policy) {
|
||||
/* Security arch (1) protocol does not provide a file buffer. Instead we are supposed to fetch the payload
|
||||
* ourselves, which is not needed as we already have everything in memory and the device paths match. */
|
||||
if (file_buffer && (file_buffer != payload->addr || file_size != payload->len))
|
||||
return false;
|
||||
|
||||
assert(this);
|
||||
assert(this->hook == security2_hook);
|
||||
|
||||
if (file_buffer == this->payload && file_size == this->payload_len &&
|
||||
device_path == this->payload_device_path)
|
||||
return EFI_SUCCESS;
|
||||
|
||||
return this->original_security2->FileAuthentication(
|
||||
this->original_security2, device_path, file_buffer, file_size, boot_policy);
|
||||
return true;
|
||||
}
|
||||
|
||||
static EFI_STATUS load_image(EFI_HANDLE parent, const void *source, size_t len, EFI_HANDLE *ret_image) {
|
||||
@@ -79,19 +70,13 @@ static EFI_STATUS load_image(EFI_HANDLE parent, const void *source, size_t len,
|
||||
|
||||
/* We want to support unsigned kernel images as payload, which is safe to do under secure boot
|
||||
* because it is embedded in this stub loader (and since it is already running it must be trusted). */
|
||||
SecurityOverride security_override = {
|
||||
.hook = security_hook,
|
||||
.payload = source,
|
||||
.payload_len = len,
|
||||
.payload_device_path = &payload_device_path.payload.Header,
|
||||
}, security2_override = {
|
||||
.hook = security2_hook,
|
||||
.payload = source,
|
||||
.payload_len = len,
|
||||
.payload_device_path = &payload_device_path.payload.Header,
|
||||
};
|
||||
|
||||
install_security_override(&security_override, &security2_override);
|
||||
install_security_override(
|
||||
validate_payload,
|
||||
&(ValidationContext) {
|
||||
.addr = source,
|
||||
.len = len,
|
||||
.device_path = &payload_device_path.payload.Header,
|
||||
});
|
||||
|
||||
EFI_STATUS ret = BS->LoadImage(
|
||||
/*BootPolicy=*/false,
|
||||
@@ -101,7 +86,7 @@ static EFI_STATUS load_image(EFI_HANDLE parent, const void *source, size_t len,
|
||||
len,
|
||||
ret_image);
|
||||
|
||||
uninstall_security_override(&security_override, &security2_override);
|
||||
uninstall_security_override();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+74
-52
@@ -127,69 +127,91 @@ out_deallocate:
|
||||
return err;
|
||||
}
|
||||
|
||||
static EFI_STATUS install_security_override_one(EFI_GUID guid, SecurityOverride *override) {
|
||||
EFI_STATUS err;
|
||||
static struct SecurityOverride {
|
||||
EFI_SECURITY_ARCH_PROTOCOL *security;
|
||||
EFI_SECURITY2_ARCH_PROTOCOL *security2;
|
||||
EFI_SECURITY_FILE_AUTHENTICATION_STATE original_hook;
|
||||
EFI_SECURITY2_FILE_AUTHENTICATION original_hook2;
|
||||
|
||||
assert(override);
|
||||
security_validator_t validator;
|
||||
const void *validator_ctx;
|
||||
} security_override;
|
||||
|
||||
_cleanup_free_ EFI_HANDLE *handles = NULL;
|
||||
size_t n_handles = 0;
|
||||
static EFIAPI EFI_STATUS security_hook(
|
||||
const EFI_SECURITY_ARCH_PROTOCOL *this,
|
||||
uint32_t authentication_status,
|
||||
const EFI_DEVICE_PATH *file) {
|
||||
|
||||
err = BS->LocateHandleBuffer(ByProtocol, &guid, NULL, &n_handles, &handles);
|
||||
if (err != EFI_SUCCESS)
|
||||
/* No security arch protocol around? */
|
||||
return err;
|
||||
assert(security_override.validator);
|
||||
assert(security_override.security);
|
||||
assert(security_override.original_hook);
|
||||
|
||||
/* There should only ever be one security arch protocol instance, but let's be paranoid here. */
|
||||
assert(n_handles == 1);
|
||||
if (security_override.validator(security_override.validator_ctx, file, NULL, 0))
|
||||
return EFI_SUCCESS;
|
||||
|
||||
void *security = NULL;
|
||||
err = BS->LocateProtocol(&guid, NULL, &security);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status_stall(err, u"Error getting security arch protocol: %r", err);
|
||||
|
||||
err = BS->ReinstallProtocolInterface(handles[0], &guid, security, override);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status_stall(err, u"Error overriding security arch protocol: %r", err);
|
||||
|
||||
override->original = security;
|
||||
override->original_handle = handles[0];
|
||||
return EFI_SUCCESS;
|
||||
return security_override.original_hook(security_override.security, authentication_status, file);
|
||||
}
|
||||
|
||||
/* This replaces the platform provided security arch protocols (defined in the UEFI Platform Initialization
|
||||
* Specification) with the provided override instances. If not running in secure boot or the protocols are
|
||||
* not available nothing happens. The override instances are provided with the necessary info to undo this
|
||||
* in uninstall_security_override(). */
|
||||
void install_security_override(SecurityOverride *override, SecurityOverride *override2) {
|
||||
assert(override);
|
||||
assert(override2);
|
||||
static EFIAPI EFI_STATUS security2_hook(
|
||||
const EFI_SECURITY2_ARCH_PROTOCOL *this,
|
||||
const EFI_DEVICE_PATH *device_path,
|
||||
void *file_buffer,
|
||||
size_t file_size,
|
||||
BOOLEAN boot_policy) {
|
||||
|
||||
assert(security_override.validator);
|
||||
assert(security_override.security2);
|
||||
assert(security_override.original_hook2);
|
||||
|
||||
if (security_override.validator(security_override.validator_ctx, device_path, file_buffer, file_size))
|
||||
return EFI_SUCCESS;
|
||||
|
||||
return security_override.original_hook2(
|
||||
security_override.security2, device_path, file_buffer, file_size, boot_policy);
|
||||
}
|
||||
|
||||
/* This replaces the platform provided security arch protocols hooks (defined in the UEFI Platform
|
||||
* Initialization Specification) with our own that uses the given validator to decide if a image is to be
|
||||
* trusted. If not running in secure boot or the protocols are not available nothing happens. The override
|
||||
* must be removed with uninstall_security_override() after LoadImage() has been called.
|
||||
*
|
||||
* This is a hack as we do not own the security protocol instances and modifying them is not an official part
|
||||
* of their spec. But there is little else we can do to circumvent secure boot short of implementing our own
|
||||
* PE loader. We could replace the firmware instances with our own instance using
|
||||
* ReinstallProtocolInterface(), but some firmware will still use the old ones. */
|
||||
void install_security_override(security_validator_t validator, const void *validator_ctx) {
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(validator);
|
||||
|
||||
if (!secure_boot_enabled())
|
||||
return;
|
||||
|
||||
(void) install_security_override_one((EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID, override);
|
||||
(void) install_security_override_one((EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID, override2);
|
||||
security_override = (struct SecurityOverride) {
|
||||
.validator = validator,
|
||||
.validator_ctx = validator_ctx,
|
||||
};
|
||||
|
||||
EFI_SECURITY_ARCH_PROTOCOL *security = NULL;
|
||||
err = BS->LocateProtocol(&(EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID, NULL, (void **) &security);
|
||||
if (err == EFI_SUCCESS) {
|
||||
security_override.security = security;
|
||||
security_override.original_hook = security->FileAuthenticationState;
|
||||
security->FileAuthenticationState = security_hook;
|
||||
}
|
||||
|
||||
EFI_SECURITY2_ARCH_PROTOCOL *security2 = NULL;
|
||||
err = BS->LocateProtocol(&(EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID, NULL, (void **) &security2);
|
||||
if (err == EFI_SUCCESS) {
|
||||
security_override.security2 = security2;
|
||||
security_override.original_hook2 = security2->FileAuthentication;
|
||||
security2->FileAuthentication = security2_hook;
|
||||
}
|
||||
}
|
||||
|
||||
void uninstall_security_override(SecurityOverride *override, SecurityOverride *override2) {
|
||||
assert(override);
|
||||
assert(override2);
|
||||
|
||||
/* We use assert_se here to guarantee the system is not in a weird state in the unlikely case of an
|
||||
* error restoring the original protocols. */
|
||||
|
||||
if (override->original_handle)
|
||||
assert_se(BS->ReinstallProtocolInterface(
|
||||
override->original_handle,
|
||||
&(EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID,
|
||||
override,
|
||||
override->original) == EFI_SUCCESS);
|
||||
|
||||
if (override2->original_handle)
|
||||
assert_se(BS->ReinstallProtocolInterface(
|
||||
override2->original_handle,
|
||||
&(EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID,
|
||||
override2,
|
||||
override2->original) == EFI_SUCCESS);
|
||||
void uninstall_security_override(void) {
|
||||
if (security_override.original_hook)
|
||||
security_override.security->FileAuthenticationState = security_override.original_hook;
|
||||
if (security_override.original_hook2)
|
||||
security_override.security2->FileAuthentication = security_override.original_hook2;
|
||||
}
|
||||
|
||||
@@ -17,23 +17,11 @@ SecureBootMode secure_boot_mode(void);
|
||||
|
||||
EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path);
|
||||
|
||||
typedef struct {
|
||||
void *hook;
|
||||
typedef bool (*security_validator_t)(
|
||||
const void *ctx,
|
||||
const EFI_DEVICE_PATH *device_path,
|
||||
const void *file_buffer,
|
||||
size_t file_size);
|
||||
|
||||
/* End of EFI_SECURITY_ARCH(2)_PROTOCOL. The rest is our own protocol instance data. */
|
||||
|
||||
EFI_HANDLE original_handle;
|
||||
union {
|
||||
void *original;
|
||||
EFI_SECURITY_ARCH_PROTOCOL *original_security;
|
||||
EFI_SECURITY2_ARCH_PROTOCOL *original_security2;
|
||||
};
|
||||
|
||||
/* Used by the stub to identify the embedded image. */
|
||||
const void *payload;
|
||||
size_t payload_len;
|
||||
const EFI_DEVICE_PATH *payload_device_path;
|
||||
} SecurityOverride;
|
||||
|
||||
void install_security_override(SecurityOverride *override, SecurityOverride *override2);
|
||||
void uninstall_security_override(SecurityOverride *override, SecurityOverride *override2);
|
||||
void install_security_override(security_validator_t validator, const void *validator_ctx);
|
||||
void uninstall_security_override(void);
|
||||
|
||||
+35
-75
@@ -23,7 +23,7 @@
|
||||
#endif
|
||||
|
||||
struct ShimLock {
|
||||
EFI_STATUS __sysv_abi__ (*shim_verify) (void *buffer, uint32_t size);
|
||||
EFI_STATUS __sysv_abi__ (*shim_verify) (const void *buffer, uint32_t size);
|
||||
|
||||
/* context is actually a struct for the PE header, but it isn't needed so void is sufficient just do define the interface
|
||||
* see shim.c/shim.h and PeHeader.h in the github shim repo */
|
||||
@@ -41,79 +41,45 @@ bool shim_loaded(void) {
|
||||
return BS->LocateProtocol((EFI_GUID*) SHIM_LOCK_GUID, NULL, (void**) &shim_lock) == EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static bool shim_validate(void *data, uint32_t size) {
|
||||
struct ShimLock *shim_lock;
|
||||
|
||||
if (!data)
|
||||
return false;
|
||||
|
||||
if (BS->LocateProtocol((EFI_GUID*) SHIM_LOCK_GUID, NULL, (void**) &shim_lock) != EFI_SUCCESS)
|
||||
return false;
|
||||
|
||||
if (!shim_lock)
|
||||
return false;
|
||||
|
||||
return shim_lock->shim_verify(data, size) == EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static EFIAPI EFI_STATUS security2_hook(
|
||||
const SecurityOverride *this,
|
||||
const EFI_DEVICE_PATH *device_path,
|
||||
void *file_buffer,
|
||||
UINTN file_size,
|
||||
BOOLEAN boot_policy) {
|
||||
|
||||
assert(this);
|
||||
assert(this->hook == security2_hook);
|
||||
|
||||
if (shim_validate(file_buffer, file_size))
|
||||
return EFI_SUCCESS;
|
||||
|
||||
return this->original_security2->FileAuthentication(
|
||||
this->original_security2, device_path, file_buffer, file_size, boot_policy);
|
||||
}
|
||||
|
||||
static EFIAPI EFI_STATUS security_hook(
|
||||
const SecurityOverride *this,
|
||||
uint32_t authentication_status,
|
||||
const EFI_DEVICE_PATH *device_path) {
|
||||
static bool shim_validate(
|
||||
const void *ctx, const EFI_DEVICE_PATH *device_path, const void *file_buffer, size_t file_size) {
|
||||
|
||||
EFI_STATUS err;
|
||||
_cleanup_free_ char *file_buffer_owned = NULL;
|
||||
|
||||
assert(this);
|
||||
assert(this->hook == security_hook);
|
||||
if (!file_buffer) {
|
||||
if (!device_path)
|
||||
return false;
|
||||
|
||||
if (!device_path)
|
||||
return this->original_security->FileAuthenticationState(
|
||||
this->original_security, authentication_status, device_path);
|
||||
EFI_HANDLE device_handle;
|
||||
EFI_DEVICE_PATH *file_dp = (EFI_DEVICE_PATH *) device_path;
|
||||
err = BS->LocateDevicePath(&FileSystemProtocol, &file_dp, &device_handle);
|
||||
if (err != EFI_SUCCESS)
|
||||
return false;
|
||||
|
||||
EFI_HANDLE device_handle;
|
||||
EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *) device_path;
|
||||
err = BS->LocateDevicePath(&FileSystemProtocol, &dp, &device_handle);
|
||||
_cleanup_(file_closep) EFI_FILE *root = NULL;
|
||||
err = open_volume(device_handle, &root);
|
||||
if (err != EFI_SUCCESS)
|
||||
return false;
|
||||
|
||||
_cleanup_free_ char16_t *dp_str = NULL;
|
||||
err = device_path_to_str(file_dp, &dp_str);
|
||||
if (err != EFI_SUCCESS)
|
||||
return false;
|
||||
|
||||
err = file_read(root, dp_str, 0, 0, &file_buffer_owned, &file_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
return false;
|
||||
|
||||
file_buffer = file_buffer_owned;
|
||||
}
|
||||
|
||||
struct ShimLock *shim_lock;
|
||||
err = BS->LocateProtocol((EFI_GUID *) SHIM_LOCK_GUID, NULL, (void **) &shim_lock);
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
return false;
|
||||
|
||||
_cleanup_(file_closep) EFI_FILE *root = NULL;
|
||||
err = open_volume(device_handle, &root);
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
|
||||
_cleanup_free_ char16_t *dp_str = NULL;
|
||||
err = device_path_to_str(dp, &dp_str);
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
|
||||
char *file_buffer;
|
||||
size_t file_size;
|
||||
err = file_read(root, dp_str, 0, 0, &file_buffer, &file_size);
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
|
||||
if (shim_validate(file_buffer, file_size))
|
||||
return EFI_SUCCESS;
|
||||
|
||||
return this->original_security->FileAuthenticationState(
|
||||
this->original_security, authentication_status, device_path);
|
||||
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) {
|
||||
@@ -122,20 +88,14 @@ EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path
|
||||
|
||||
bool have_shim = shim_loaded();
|
||||
|
||||
SecurityOverride security_override = {
|
||||
.hook = security_hook,
|
||||
}, security2_override = {
|
||||
.hook = security2_hook,
|
||||
};
|
||||
|
||||
if (have_shim)
|
||||
install_security_override(&security_override, &security2_override);
|
||||
install_security_override(shim_validate, NULL);
|
||||
|
||||
EFI_STATUS ret = BS->LoadImage(
|
||||
/*BootPolicy=*/false, parent, (EFI_DEVICE_PATH *) device_path, NULL, 0, ret_image);
|
||||
|
||||
if (have_shim)
|
||||
uninstall_security_override(&security_override, &security2_override);
|
||||
uninstall_security_override();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+36
-4
@@ -772,19 +772,51 @@ EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DE
|
||||
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(&(EFI_GUID) EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID, NULL, (void **) &dp_to_text);
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
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. */
|
||||
|
||||
char16_t *str = dp_to_text->ConvertDevicePathToText(dp, false, false);
|
||||
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 = str;
|
||||
*ret = TAKE_PTR(str);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user