efi_loader: fix efi_dp_from_file()

* When called from efi_dp_from_name() we miss to append the filename
  for non-block devices.
* expand_media_path() could be simplified by using efi_dp_from_file to
  prepend the device path of the boot device.

This can be avoided by passing a device path to efi_dp_from_file() instead
of a block device descriptor and a partition number.

Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
This commit is contained in:
Heinrich Schuchardt 2023-05-13 10:36:21 +02:00
parent e1273ea2ec
commit c7c0ca3767
4 changed files with 18 additions and 38 deletions

View file

@ -589,7 +589,7 @@ static efi_status_t bootefi_test_prepare
if (!bootefi_device_path) if (!bootefi_device_path)
return EFI_OUT_OF_RESOURCES; return EFI_OUT_OF_RESOURCES;
bootefi_image_path = efi_dp_from_file(NULL, 0, path); bootefi_image_path = efi_dp_from_file(NULL, path);
if (!bootefi_image_path) { if (!bootefi_image_path) {
ret = EFI_OUT_OF_RESOURCES; ret = EFI_OUT_OF_RESOURCES;
goto failure; goto failure;

View file

@ -810,7 +810,7 @@ bool efi_dp_is_multi_instance(const struct efi_device_path *dp);
struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part); struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part);
/* Create a device node for a block device partition. */ /* Create a device node for a block device partition. */
struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part); struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part);
struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part, struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp,
const char *path); const char *path);
struct efi_device_path *efi_dp_from_eth(void); struct efi_device_path *efi_dp_from_eth(void);
struct efi_device_path *efi_dp_from_mem(uint32_t mem_type, struct efi_device_path *efi_dp_from_mem(uint32_t mem_type,

View file

@ -47,7 +47,7 @@ const efi_guid_t efi_guid_bootmenu_auto_generated =
static static
struct efi_device_path *expand_media_path(struct efi_device_path *device_path) struct efi_device_path *expand_media_path(struct efi_device_path *device_path)
{ {
struct efi_device_path *dp, *rem, *full_path; struct efi_device_path *rem, *full_path;
efi_handle_t handle; efi_handle_t handle;
if (!device_path) if (!device_path)
@ -58,15 +58,12 @@ struct efi_device_path *expand_media_path(struct efi_device_path *device_path)
* simple file system protocol, append a default file name to support * simple file system protocol, append a default file name to support
* booting from removable media. * booting from removable media.
*/ */
dp = device_path; handle = efi_dp_find_obj(device_path,
handle = efi_dp_find_obj(dp, &efi_simple_file_system_protocol_guid, &efi_simple_file_system_protocol_guid, &rem);
&rem);
if (handle) { if (handle) {
if (rem->type == DEVICE_PATH_TYPE_END) { if (rem->type == DEVICE_PATH_TYPE_END) {
dp = efi_dp_from_file(NULL, 0, full_path = efi_dp_from_file(device_path,
"/EFI/BOOT/" BOOTEFI_NAME); "/EFI/BOOT/" BOOTEFI_NAME);
full_path = efi_dp_append(device_path, dp);
efi_free_pool(dp);
} else { } else {
full_path = efi_dp_dup(device_path); full_path = efi_dp_dup(device_path);
} }

View file

@ -1002,47 +1002,31 @@ static void path_to_uefi(void *uefi, const char *src)
} }
/** /**
* efi_dp_from_file() - create device path for file * efi_dp_from_file() - append file path node to device path.
* *
* The function creates a device path from the block descriptor @desc and the * @dp: device path or NULL
* partition number @part and appends a device path node created describing the * @path: file path or NULL
* file path @path.
*
* If @desc is NULL, the device path will not contain nodes describing the
* partition.
* If @path is an empty string "", the device path will not contain a node
* for the file path.
*
* @desc: block device descriptor or NULL
* @part: partition number
* @path: file path on partition or ""
* Return: device path or NULL in case of an error * Return: device path or NULL in case of an error
*/ */
struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part, struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp,
const char *path) const char *path)
{ {
struct efi_device_path_file_path *fp; struct efi_device_path_file_path *fp;
void *buf, *pos; void *buf, *pos;
size_t dpsize = 0, fpsize; size_t dpsize, fpsize;
if (desc)
dpsize = dp_part_size(desc, part);
dpsize = efi_dp_size(dp);
fpsize = sizeof(struct efi_device_path) + fpsize = sizeof(struct efi_device_path) +
2 * (utf8_utf16_strlen(path) + 1); 2 * (utf8_utf16_strlen(path) + 1);
if (fpsize > U16_MAX) if (fpsize > U16_MAX)
return NULL; return NULL;
dpsize += fpsize; buf = efi_alloc(dpsize + fpsize + sizeof(END));
buf = efi_alloc(dpsize + sizeof(END));
if (!buf) if (!buf)
return NULL; return NULL;
if (desc) memcpy(buf, dp, dpsize);
pos = dp_part_fill(buf, desc, part); pos = buf + dpsize;
else
pos = buf;
/* add file-path: */ /* add file-path: */
if (*path) { if (*path) {
@ -1218,8 +1202,7 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
if (!path) if (!path)
return EFI_SUCCESS; return EFI_SUCCESS;
*file = efi_dp_from_file(desc, part, path); *file = efi_dp_from_file(dp, path);
if (!*file) if (!*file)
return EFI_OUT_OF_RESOURCES; return EFI_OUT_OF_RESOURCES;