Files
u-boot/lib/efi/run.c
Simon Glass a2759428a9 efi: Correct calculate_paths() when an image is used
The device path is updated if an image is used, so move the setting of
*device_pathp lower, to take account of this.

Signed-off-by: Simon Glass <sjg@chromium.org>
Fixes: 73ad2d9909 ("efi: Move efi_bootflow_run() to a common file")
2025-09-02 06:41:27 -06:00

143 lines
3.5 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2016 Alexander Graf
* Copyright 2023 Google LLC
*/
#define LOG_CATEGORY LOGC_EFI
#include <blk.h>
#include <bootflow.h>
#include <dm.h>
#include <efi.h>
#include <efi_device_path.h>
#include <efi_loader.h>
#include <malloc.h>
#include <mapmem.h>
#include <net-common.h>
/**
* calculate_paths() - Calculate the device and image patch from strings
*
* @dev: device, e.g. "MMC"
* @devnr: number of the device, e.g. "1:2"
* @path: path to file loaded
* @device_pathp: returns EFI device path
* @image_pathp: returns EFI image path
* Return: EFI_SUCCESS on success, else error code
*/
efi_status_t calculate_paths(const char *dev, const char *devnr,
const char *path,
struct efi_device_path **device_pathp,
struct efi_device_path **image_pathp)
{
struct efi_device_path *image, *device;
efi_status_t ret;
#if IS_ENABLED(CONFIG_NETDEVICES) && IS_ENABLED(CONFIG_EFI_LOADER)
if (!strcmp(dev, "Net") || !strcmp(dev, "Http")) {
ret = efi_net_new_dp(dev, devnr, eth_get_dev());
if (ret != EFI_SUCCESS)
return ret;
}
#endif
log_debug("dev '%s' devnr '%s' path '%s'\n", dev, devnr, path);
ret = efi_dp_from_name(dev, devnr, path, &device, &image);
if (ret != EFI_SUCCESS)
return ret;
if (image) {
/* FIXME: image should not contain device */
struct efi_device_path *image_tmp = image;
efi_dp_split_file_path(image, &device, &image);
efi_free_pool(image_tmp);
}
*device_pathp = device;
*image_pathp = image;
log_debug("- boot device %pD\n", device);
if (image)
log_debug("- image %pD\n", image);
return EFI_SUCCESS;
}
/**
* calc_dev_name() - Calculate the device name to give to EFI
*
* If not supported, this shows an error.
*
* Return name, or NULL if not supported
*/
static const char *calc_dev_name(struct bootflow *bflow)
{
const struct udevice *media_dev;
media_dev = dev_get_parent(bflow->dev);
log_debug("bflow->dev='%s', media_dev='%s', uclass_id=%d\n",
bflow->dev->name, media_dev->name,
device_get_uclass_id(media_dev));
if (!bflow->blk) {
if (device_get_uclass_id(media_dev) == UCLASS_ETH)
return "Net";
log_err("Cannot boot EFI app on media '%s'\n",
dev_get_uclass_name(media_dev));
return NULL;
}
if (device_get_uclass_id(media_dev) == UCLASS_MASS_STORAGE)
return "usb";
if (device_get_uclass_id(media_dev) == UCLASS_EFI_MEDIA)
return "efi";
return blk_get_uclass_name(device_get_uclass_id(media_dev));
}
efi_status_t efi_bootflow_run(struct bootflow *bflow)
{
struct efi_device_path *device, *image;
const struct udevice *media_dev;
struct blk_desc *desc = NULL;
const char *dev_name;
char devnum_str[9];
efi_status_t ret;
void *fdt;
media_dev = dev_get_parent(bflow->dev);
if (bflow->blk) {
desc = dev_get_uclass_plat(bflow->blk);
snprintf(devnum_str, sizeof(devnum_str), "%x:%x",
desc ? desc->devnum : dev_seq(media_dev), bflow->part);
} else {
*devnum_str = '\0';
}
dev_name = calc_dev_name(bflow);
log_debug("dev_name '%s' devnum_str '%s' fname '%s' media_dev '%s'\n",
dev_name, devnum_str, bflow->fname, media_dev->name);
if (!dev_name)
return EFI_UNSUPPORTED;
ret = calculate_paths(dev_name, devnum_str, bflow->fname, &device,
&image);
if (ret)
return EFI_UNSUPPORTED;
if (bflow->flags & BOOTFLOWF_USE_BUILTIN_FDT) {
log_debug("Booting with built-in fdt\n");
fdt = EFI_FDT_USE_INTERNAL;
} else {
log_debug("Booting with external fdt\n");
fdt = map_sysmem(bflow->fdt_addr, 0);
}
ret = efi_binary_run_dp(bflow->buf, bflow->size, fdt, NULL, 0, device,
image);
return ret;
}