[U-Boot] [RFC v2 03/15] efi_loader: image_loader: aligned with DM
AKASHI Takahiro
takahiro.akashi at linaro.org
Fri Feb 8 08:15:30 UTC 2019
Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
---
cmd/bootefi.c | 61 ++++++++++++++-----------------
include/efi_loader.h | 4 +-
lib/efi_loader/efi_image_loader.c | 61 +++++++++++++++++++------------
3 files changed, 67 insertions(+), 59 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index ebe149dffa1f..d2130d5ac323 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -249,12 +249,12 @@ static efi_status_t efi_install_fdt(ulong fdt_addr)
static efi_status_t bootefi_run_prepare(const char *load_options_path,
struct efi_device_path *device_path,
struct efi_device_path *image_path,
- struct efi_loaded_image_obj **image_objp,
+ efi_handle_t *handlep,
struct efi_loaded_image **loaded_image_infop)
{
efi_status_t ret;
- ret = efi_setup_loaded_image(device_path, image_path, image_objp,
+ ret = efi_setup_loaded_image(device_path, image_path, handlep,
loaded_image_infop);
if (ret != EFI_SUCCESS)
return ret;
@@ -268,15 +268,15 @@ static efi_status_t bootefi_run_prepare(const char *load_options_path,
/**
* bootefi_run_finish() - finish up after running an EFI test
*
+ * @handle: Handle to the loaded image object
* @loaded_image_info: Pointer to a struct which holds the loaded image info
- * @image_objj: Pointer to a struct which holds the loaded image object
*/
-static void bootefi_run_finish(struct efi_loaded_image_obj *image_obj,
+static void bootefi_run_finish(efi_handle_t handle,
struct efi_loaded_image *loaded_image_info)
{
efi_restore_gd();
free(loaded_image_info->load_options);
- efi_delete_handle(&image_obj->header);
+ efi_delete_handle(handle);
}
static int efi_handle_fdt(char *fdt_opt)
@@ -319,10 +319,10 @@ static efi_status_t do_bootefi_exec(void *efi,
struct efi_device_path *device_path,
struct efi_device_path *image_path)
{
- efi_handle_t mem_handle = NULL;
struct efi_device_path *memdp = NULL;
+ efi_handle_t handle;
efi_status_t ret;
- struct efi_loaded_image_obj *image_obj = NULL;
+ struct efi_loaded_image_obj *image_obj;
struct efi_loaded_image *loaded_image_info = NULL;
EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
@@ -342,28 +342,27 @@ static efi_status_t do_bootefi_exec(void *efi,
* Grub expects that the device path of the loaded image is
* installed on a handle.
*/
- ret = efi_create_handle(&mem_handle);
- if (ret != EFI_SUCCESS)
- return ret; /* TODO: leaks device_path */
- ret = efi_add_protocol(mem_handle, &efi_guid_device_path,
- device_path);
- if (ret != EFI_SUCCESS)
- goto err_add_protocol;
+ /*
+ * CHECK: device path protocol will be added to handle
+ * in efi_setup_loaded_image() anyway.
+ */
} else {
assert(device_path && image_path);
}
ret = bootefi_run_prepare("bootargs", device_path, image_path,
- &image_obj, &loaded_image_info);
+ &handle, &loaded_image_info);
if (ret)
goto err_prepare;
/* Load the EFI payload */
- entry = efi_load_pe(image_obj, efi, loaded_image_info);
- if (!entry) {
+ image_obj = handle->platdata;
+ ret = efi_load_pe(image_obj, efi, loaded_image_info);
+ if (ret) {
ret = EFI_LOAD_ERROR;
goto err_prepare;
}
+ entry = image_obj->entry;
if (memdp) {
struct efi_device_path_memory *mdp = (void *)memdp;
@@ -393,7 +392,7 @@ static efi_status_t do_bootefi_exec(void *efi,
/* Move into EL2 and keep running there */
armv8_switch_to_el2((ulong)entry,
- (ulong)&image_obj->header,
+ 0,
(ulong)&systab, 0, (ulong)efi_run_in_el2,
ES_TO_AARCH64);
@@ -410,7 +409,7 @@ static efi_status_t do_bootefi_exec(void *efi,
secure_ram_addr(_do_nonsec_entry)(
efi_run_in_hyp,
(uintptr_t)entry,
- (uintptr_t)&image_obj->header,
+ 0,
(uintptr_t)&systab);
/* Should never reach here, efi exits with longjmp */
@@ -418,15 +417,11 @@ static efi_status_t do_bootefi_exec(void *efi,
}
#endif
- ret = efi_do_enter(&image_obj->header, &systab, entry);
+ ret = efi_do_enter(handle, &systab, entry);
err_prepare:
/* image has returned, loaded-image obj goes *poof*: */
- bootefi_run_finish(image_obj, loaded_image_info);
-
-err_add_protocol:
- if (mem_handle)
- efi_delete_handle(mem_handle);
+ bootefi_run_finish(handle, loaded_image_info);
return ret;
}
@@ -438,9 +433,7 @@ err_add_protocol:
* This sets things up so we can call EFI functions. This involves preparing
* the 'gd' pointer and setting up the load ed image data structures.
*
- * @image_objp: loaded_image_infop: Pointer to a struct which will hold the
- * loaded image object. This struct will be inited by this function before
- * use.
+ * @handlep: Pointer to a handle of the loaded image object
* @loaded_image_infop: Pointer to a struct which will hold the loaded image
* info. This struct will be inited by this function before use.
* @path: File path to the test being run (often just the test name with a
@@ -450,7 +443,7 @@ err_add_protocol:
* @return 0 if OK, -ve on error
*/
static efi_status_t bootefi_test_prepare
- (struct efi_loaded_image_obj **image_objp,
+ (efi_handle_t *handlep,
struct efi_loaded_image **loaded_image_infop, const char *path,
ulong test_func, const char *load_options_path)
{
@@ -465,7 +458,7 @@ static efi_status_t bootefi_test_prepare
return EFI_OUT_OF_RESOURCES;
return bootefi_run_prepare(load_options_path, bootefi_device_path,
- bootefi_image_path, image_objp,
+ bootefi_image_path, handlep,
loaded_image_infop);
}
@@ -558,20 +551,20 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#endif
#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
if (!strcmp(argv[1], "selftest")) {
- struct efi_loaded_image_obj *image_obj;
+ efi_handle_t handle;
struct efi_loaded_image *loaded_image_info;
if (efi_handle_fdt(argc > 2 ? argv[2] : NULL))
return CMD_RET_FAILURE;
- if (bootefi_test_prepare(&image_obj, &loaded_image_info,
+ if (bootefi_test_prepare(&handle, &loaded_image_info,
"\\selftest", (uintptr_t)&efi_selftest,
"efi_selftest"))
return CMD_RET_FAILURE;
/* Execute the test */
- r = efi_selftest(&image_obj->header, &systab);
- bootefi_run_finish(image_obj, loaded_image_info);
+ r = efi_selftest(handle, &systab);
+ bootefi_run_finish(handle, loaded_image_info);
return r != EFI_SUCCESS;
} else
#endif
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 5882cd7dd3b0..86cf91a6feca 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -274,8 +274,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout);
/* Called from places to check whether a timer expired */
void efi_timer_check(void);
/* PE loader implementation */
-void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
- struct efi_loaded_image *loaded_image_info);
+efi_status_t efi_load_pe(struct efi_loaded_image_obj *obj, void *efi,
+ struct efi_loaded_image *loaded_image_info);
/* Called once to store the pristine gd pointer */
void efi_save_gd(void);
/* Special case handler for error/abort that just tries to dtrt to get
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index a18ce0a5705e..332dd5db199c 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -8,6 +8,7 @@
*/
#include <common.h>
+#include <dm.h>
#include <efi_loader.h>
#include <pe.h>
@@ -66,6 +67,7 @@ static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj,
if (image->file_path)
printf(" '%pD'", image->file_path);
printf("\n");
+
return EFI_SUCCESS;
}
@@ -76,17 +78,27 @@ static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj,
*/
void efi_print_image_infos(void *pc)
{
- struct efi_object *efiobj;
+ struct uclass *uc;
+ struct udevice *dev, *protocol;
+ struct efi_loaded_image_obj *obj;
struct efi_handler *handler;
+ efi_status_t ret;
- list_for_each_entry(efiobj, &efi_obj_list, link) {
- list_for_each_entry(handler, &efiobj->protocols, link) {
- if (!guidcmp(handler->guid, &efi_guid_loaded_image)) {
- efi_print_image_info(
- (struct efi_loaded_image_obj *)efiobj,
- handler->protocol_interface, pc);
- }
- }
+ if (uclass_get(UCLASS_EFI_OBJECT, &uc))
+ return;
+
+ uclass_foreach_dev(dev, uc) {
+ if (strcmp(dev->driver->name, "efi_loaded_image"))
+ continue;
+
+ ret = efi_search_protocol(dev, &efi_guid_loaded_image,
+ &protocol);
+ if (ret != EFI_SUCCESS)
+ continue;
+
+ obj = dev->platdata;
+ handler = protocol->uclass_platdata;
+ efi_print_image_info(obj, handler->protocol_interface, pc);
}
}
@@ -198,8 +210,8 @@ static void efi_set_code_and_data_type(
* piece of memory. On successful load it then returns the entry point for
* the binary. Otherwise NULL.
*/
-void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
- struct efi_loaded_image *loaded_image_info)
+efi_status_t efi_load_pe(struct efi_loaded_image_obj *obj, void *efi,
+ struct efi_loaded_image *loaded_image_info)
{
IMAGE_NT_HEADERS32 *nt;
IMAGE_DOS_HEADER *dos;
@@ -215,17 +227,18 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
uint64_t image_size;
unsigned long virt_size = 0;
int supported = 0;
+ efi_status_t ret;
dos = efi;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
printf("%s: Invalid DOS Signature\n", __func__);
- return NULL;
+ return EFI_INVALID_PARAMETER;
}
nt = (void *) ((char *)efi + dos->e_lfanew);
if (nt->Signature != IMAGE_NT_SIGNATURE) {
printf("%s: Invalid NT Signature\n", __func__);
- return NULL;
+ return EFI_INVALID_PARAMETER;
}
for (i = 0; machines[i]; i++)
@@ -237,7 +250,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
if (!supported) {
printf("%s: Machine type 0x%04x is not supported\n",
__func__, nt->FileHeader.Machine);
- return NULL;
+ return EFI_UNSUPPORTED;
}
/* Calculate upper virtual address boundary */
@@ -263,7 +276,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
if (!efi_reloc) {
printf("%s: Could not allocate %lu bytes\n",
__func__, virt_size);
- return NULL;
+ return EFI_OUT_OF_RESOURCES;
}
entry = efi_reloc + opt->AddressOfEntryPoint;
rel_size = opt->DataDirectory[rel_idx].Size;
@@ -279,7 +292,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
if (!efi_reloc) {
printf("%s: Could not allocate %lu bytes\n",
__func__, virt_size);
- return NULL;
+ return EFI_OUT_OF_RESOURCES;
}
entry = efi_reloc + opt->AddressOfEntryPoint;
rel_size = opt->DataDirectory[rel_idx].Size;
@@ -288,7 +301,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
} else {
printf("%s: Invalid optional header magic %x\n", __func__,
nt->OptionalHeader.Magic);
- return NULL;
+ return EFI_INVALID_PARAMETER;
}
/* Load sections into RAM */
@@ -302,11 +315,12 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
}
/* Run through relocations */
- if (efi_loader_relocate(rel, rel_size, efi_reloc,
- (unsigned long)image_base) != EFI_SUCCESS) {
+ ret = efi_loader_relocate(rel, rel_size, efi_reloc,
+ (unsigned long)image_base);
+ if (ret != EFI_SUCCESS) {
efi_free_pages((uintptr_t) efi_reloc,
(virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT);
- return NULL;
+ return ret;
}
/* Flush cache */
@@ -317,8 +331,9 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi,
/* Populate the loaded image interface bits */
loaded_image_info->image_base = efi;
loaded_image_info->image_size = image_size;
- handle->reloc_base = efi_reloc;
- handle->reloc_size = virt_size;
+ obj->reloc_base = efi_reloc;
+ obj->reloc_size = virt_size;
+ obj->entry = entry;
- return entry;
+ return EFI_SUCCESS;
}
--
2.19.1
More information about the U-Boot
mailing list