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:
@@ -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>
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -5,3 +5,4 @@
|
||||
|
||||
obj-y += basename.o
|
||||
obj-y += device_path.o
|
||||
obj-y += run.o
|
||||
|
||||
139
lib/efi/run.c
Normal file
139
lib/efi/run.c
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user