[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