efi: Move efi_bootflow_run() to a common file

Move this function and some dependencies into the lib/efi directory so
that it can be used by the app, which does not enable CONFIG_EFI_LOADER

Since the networking has an #ifdef add CONFIG_EFI_LOADER to it, since
the definitions are in efi_loader.h for now.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass
2025-08-05 13:07:33 -06:00
parent 5ce96f0139
commit 73ad2d9909
5 changed files with 181 additions and 137 deletions

View File

@@ -7,6 +7,7 @@
#ifndef BLK_H
#define BLK_H
#include <linux/types.h>
#include <bouncebuf.h>
#include <dm/uclass-id.h>
#include <efi.h>

View File

@@ -737,4 +737,40 @@ static inline bool efi_use_host_arch(void)
*/
int efi_get_pxe_arch(void);
/**
* 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);
/**
* efi_binary_run_dp() - run loaded UEFI image
*
* @image: memory address of the UEFI image
* @size: size of the UEFI image
* @fdt: device-tree
* @initrd: initrd
* @initrd_sz: initrd size
* @dp_dev: EFI device-path
* @dp_img: EFI image-path
*
* Execute an EFI binary image loaded at @image.
* @size may be zero if the binary is loaded with U-Boot load command.
*
* Return: status code
*/
efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt,
void *initrd, size_t initrd_sz,
struct efi_device_path *dp_dev,
struct efi_device_path *dp_img);
#endif /* _LINUX_EFI_H */

View File

@@ -5,3 +5,4 @@
obj-y += basename.o
obj-y += device_path.o
obj-y += run.o

139
lib/efi/run.c Normal file
View File

@@ -0,0 +1,139 @@
// 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
ret = efi_dp_from_name(dev, devnr, path, &device, &image);
if (ret != EFI_SUCCESS)
return ret;
*device_pathp = device;
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);
}
*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);
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";
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);
}
if (IS_ENABLED(CONFIG_EFI_APP))
return EFI_UNSUPPORTED;
ret = efi_binary_run_dp(bflow->buf, bflow->size, fdt, NULL, 0, device,
image);
return ret;
}

View File

@@ -49,52 +49,6 @@ void efi_clear_bootdev(void)
image_size = 0;
}
/**
* 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
*/
static 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)
if (!strcmp(dev, "Net") || !strcmp(dev, "Http")) {
ret = efi_net_new_dp(dev, devnr, eth_get_dev());
if (ret != EFI_SUCCESS)
return ret;
}
#endif
ret = efi_dp_from_name(dev, devnr, path, &device, &image);
if (ret != EFI_SUCCESS)
return ret;
*device_pathp = device;
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);
}
*image_pathp = image;
log_debug("- boot device %pD\n", device);
if (image)
log_debug("- image %pD\n", image);
return EFI_SUCCESS;
}
/**
* efi_set_bootdev() - set boot device
*
@@ -199,26 +153,10 @@ out:
return ret;
}
/**
* efi_binary_run_dp() - run loaded UEFI image
*
* @image: memory address of the UEFI image
* @size: size of the UEFI image
* @fdt: device-tree
* @initrd: initrd
* @initrd_sz: initrd size
* @dp_dev: EFI device-path
* @dp_img: EFI image-path
*
* Execute an EFI binary image loaded at @image.
* @size may be zero if the binary is loaded with U-Boot load command.
*
* Return: status code
*/
static efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt,
void *initrd, size_t initrd_sz,
struct efi_device_path *dp_dev,
struct efi_device_path *dp_img)
efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt,
void *initrd, size_t initrd_sz,
struct efi_device_path *dp_dev,
struct efi_device_path *dp_img)
{
efi_status_t ret;
@@ -301,74 +239,3 @@ out:
return ret;
}
/**
* 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);
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";
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;
}