mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH v1 26/54] efi: loader: boot: implement LoadImage BootService
Date: Thu, 18 Dec 2025 11:37:46 +0100	[thread overview]
Message-ID: <20251218111242.1527495-27-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20251218111242.1527495-1-a.fatoum@pengutronix.de>

We now have everything in place, so we can actually start images like
the barebox EFI payload itself, even if ExitBootServices is not yet
supported.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 efi/loader/boot.c    | 591 ++++++++++++++++++++++++++++++++++++++++++-
 include/efi/loader.h |   4 +
 2 files changed, 591 insertions(+), 4 deletions(-)

diff --git a/efi/loader/boot.c b/efi/loader/boot.c
index 263165135944..2d208c4cafbd 100644
--- a/efi/loader/boot.c
+++ b/efi/loader/boot.c
@@ -20,6 +20,8 @@
 #include <efi/loader/devicepath.h>
 #include <efi/loader/debug.h>
 #include <efi/loader/image.h>
+#include <efi/loader/file.h>
+#include <efi/loader/pe.h>
 #include <efi/protocol/file.h>
 #include <efi/guid.h>
 #include <efi/error.h>
@@ -58,6 +60,9 @@ static bool timers_enabled = true;
 /* List of all events registered by RegisterProtocolNotify() */
 static LIST_HEAD(efi_register_notify_events);
 
+/* Handle of the currently executing image */
+static efi_handle_t current_image;
+
 efi_status_t efi_uninstall_protocol
 		(efi_handle_t handle, const efi_guid_t *protocol,
 		 void *protocol_interface, bool preserve);
@@ -1652,6 +1657,88 @@ EFIAPI efi_install_configuration_table_ext(const efi_guid_t *guid,
 	return EFI_EXIT(efi_install_configuration_table(guid, table));
 }
 
+/**
+ * efi_setup_loaded_image() - initialize a loaded image
+ *
+ * Initialize a loaded_image_info and loaded_image_info object with correct
+ * protocols, boot-device, etc.
+ *
+ * In case of an error \*handle_ptr and \*info_ptr are set to NULL and an error
+ * code is returned.
+ *
+ * @device_path:	device path of the loaded image
+ * @file_path:		file path of the loaded image
+ * @handle_ptr:		handle of the loaded image
+ * @info_ptr:		loaded image protocol
+ * Return:		status code
+ */
+static efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path,
+					   struct efi_device_path *file_path,
+					   struct efi_loaded_image_obj **handle_ptr,
+					   struct efi_loaded_image **info_ptr)
+{
+	efi_status_t ret;
+	struct efi_loaded_image *info = NULL;
+	struct efi_loaded_image_obj *obj = NULL;
+	struct efi_device_path *dp;
+
+	/* In case of EFI_OUT_OF_RESOURCES avoid illegal free by caller. */
+	*handle_ptr = NULL;
+	*info_ptr = NULL;
+
+	info = calloc(1, sizeof(*info));
+	if (!info)
+		return EFI_OUT_OF_RESOURCES;
+	obj = calloc(1, sizeof(*obj));
+	if (!obj) {
+		free(info);
+		return EFI_OUT_OF_RESOURCES;
+	}
+	obj->header.type = EFI_OBJECT_TYPE_LOADED_IMAGE;
+
+	/* Add internal object to object list */
+	efi_add_handle(&obj->header);
+
+	info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
+	info->file_path = file_path;
+	info->system_table = &systab;
+
+	if (device_path) {
+		info->device_handle = efi_dp_find_obj(device_path, NULL, NULL);
+
+		dp = efi_dp_concat(device_path, file_path, 0);
+		if (!dp) {
+			ret = EFI_OUT_OF_RESOURCES;
+			goto failure;
+		}
+	} else {
+		dp = NULL;
+	}
+	ret = efi_add_protocol(&obj->header,
+			       &efi_loaded_image_device_path_guid, dp);
+	if (ret != EFI_SUCCESS)
+		goto failure;
+
+	/*
+	 * When asking for the loaded_image interface, just
+	 * return handle which points to loaded_image_info
+	 */
+	ret = efi_add_protocol(&obj->header,
+			       &efi_loaded_image_protocol_guid, info);
+	if (ret != EFI_SUCCESS)
+		goto failure;
+
+	*info_ptr = info;
+	*handle_ptr = obj;
+
+	return ret;
+failure:
+	pr_err("Failure to install protocols for loaded image\n");
+	efi_delete_handle(&obj->header);
+	free(info);
+	return ret;
+}
+
 /**
  * efi_locate_device_path() - Get the device path and handle of an device
  *                            implementing a protocol
@@ -1733,6 +1820,216 @@ static efi_status_t EFIAPI efi_locate_device_path(const efi_guid_t *protocol,
 	return EFI_EXIT2(ret, *device_path);
 }
 
+/**
+ * efi_load_image_from_file() - load an image from file system
+ *
+ * Read a file into a buffer allocated as EFI_BOOT_SERVICES_DATA. It is the
+ * callers obligation to update the memory type as needed.
+ *
+ * @file_path:		the path of the image to load
+ * @buffer:		buffer containing the loaded image
+ * @size:		size of the loaded image
+ * Return:		status code
+ */
+static
+efi_status_t efi_load_image_from_file(struct efi_device_path *file_path,
+				      void **buffer, efi_uintn_t *size)
+{
+	struct efi_file_handle *f;
+	efi_status_t ret;
+	u64 addr;
+	efi_uintn_t bs;
+
+	/* Open file */
+	f = efi_file_from_path(file_path);
+	if (!f)
+		return EFI_NOT_FOUND;
+
+	ret = efi_file_size(f, &bs);
+	if (ret != EFI_SUCCESS)
+		goto error;
+
+	/*
+	 * When reading the file we do not yet know if it contains an
+	 * application, a boottime driver, or a runtime driver. So here we
+	 * allocate a buffer as EFI_BOOT_SERVICES_DATA. The caller has to
+	 * update the reservation according to the image type.
+	 */
+	ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				 EFI_BOOT_SERVICES_DATA,
+				 efi_size_in_pages(bs), &addr,
+				 "loadimage");
+	if (ret != EFI_SUCCESS) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto error;
+	}
+
+	/* Read file */
+	EFI_CALL(ret = f->read(f, &bs, (void *)(uintptr_t)addr));
+	if (ret != EFI_SUCCESS)
+		efi_free_pages(addr, efi_size_in_pages(bs));
+	*buffer = (void *)(uintptr_t)addr;
+	*size = bs;
+error:
+	EFI_CALL(f->close(f));
+	return ret;
+}
+
+/**
+ * efi_load_image_from_path() - load an image using a file path
+ *
+ * Read a file into a buffer allocated as EFI_BOOT_SERVICES_DATA. It is the
+ * callers obligation to update the memory type as needed.
+ *
+ * @boot_policy:	true for request originating from the boot manager
+ * @file_path:		the path of the image to load
+ * @buffer:		buffer containing the loaded image
+ * @size:		size of the loaded image
+ * Return:		status code
+ */
+static
+efi_status_t efi_load_image_from_path(bool boot_policy,
+				      struct efi_device_path *file_path,
+				      void **buffer, efi_uintn_t *size)
+{
+	efi_handle_t device;
+	efi_status_t ret;
+	struct efi_device_path *dp, *rem;
+	struct efi_load_file_protocol *load_file_protocol = NULL;
+	efi_uintn_t buffer_size;
+	uint64_t addr, pages;
+	const efi_guid_t *guid;
+	struct efi_handler *handler;
+
+	/* In case of failure nothing is returned */
+	*buffer = NULL;
+	*size = 0;
+
+	dp = file_path;
+	device = efi_dp_find_obj(dp, NULL, &rem);
+	ret = efi_search_protocol(device, &efi_simple_file_system_protocol_guid,
+				  NULL);
+	if (ret == EFI_SUCCESS)
+		return efi_load_image_from_file(file_path, buffer, size);
+
+	ret = efi_search_protocol(device, &efi_load_file_protocol_guid, NULL);
+	if (ret == EFI_SUCCESS) {
+		guid = &efi_load_file_protocol_guid;
+	} else if (!boot_policy) {
+		guid = &efi_load_file2_protocol_guid;
+		ret = efi_search_protocol(device, guid, NULL);
+	}
+	if (ret != EFI_SUCCESS)
+		return EFI_NOT_FOUND;
+	ret = efi_search_protocol(device, guid, &handler);
+	if (ret != EFI_SUCCESS)
+		return EFI_NOT_FOUND;
+	buffer_size = 0;
+	load_file_protocol = handler->protocol_interface;
+	ret = EFI_CALL(load_file_protocol->load_file(
+					load_file_protocol, rem, boot_policy,
+					&buffer_size, NULL));
+	if (ret != EFI_BUFFER_TOO_SMALL)
+		goto out;
+	pages = efi_size_in_pages(buffer_size);
+	ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, EFI_BOOT_SERVICES_DATA,
+				 pages, &addr, "loadimage");
+	if (ret != EFI_SUCCESS) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+	ret = EFI_CALL(load_file_protocol->load_file(
+					load_file_protocol, rem, boot_policy,
+					&buffer_size, (void *)(uintptr_t)addr));
+	if (ret != EFI_SUCCESS)
+		efi_free_pages(addr, pages);
+out:
+	efi_close_protocol(device, guid, efi_root, NULL);
+	if (ret == EFI_SUCCESS) {
+		*buffer = (void *)(uintptr_t)addr;
+		*size = buffer_size;
+	}
+
+	return ret;
+}
+
+/**
+ * efiloader_load_image() - load an EFI image into memory
+ * @boot_policy:   true for request originating from the boot manager
+ * @parent_image:  the caller's image handle
+ * @file_path:     the path of the image to load
+ * @source_buffer: memory location from which the image is installed
+ * @source_size:   size of the memory area from which the image is installed
+ * @image_handle:  handle for the newly installed image
+ *
+ * This function implements the LoadImage service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * Return: status code
+ */
+efi_status_t EFIAPI efiloader_load_image(bool boot_policy,
+				   efi_handle_t parent_image,
+				   struct efi_device_path *file_path,
+				   void *source_buffer,
+				   efi_uintn_t source_size,
+				   efi_handle_t *image_handle)
+{
+	struct efi_device_path *dp, *fp;
+	struct efi_loaded_image *info = NULL;
+	struct efi_loaded_image_obj **image_obj =
+		(struct efi_loaded_image_obj **)image_handle;
+	efi_status_t ret;
+	void *dest_buffer;
+
+	EFI_ENTRY("%d, %p, %pD, %p, %zu, %p", boot_policy, parent_image,
+		  file_path, source_buffer, source_size, image_handle);
+
+	if (!image_handle || (!source_buffer && !file_path) ||
+	    !efi_search_obj(parent_image) ||
+	    /* The parent image handle must refer to a loaded image */
+	    !parent_image->type) {
+		ret = EFI_INVALID_PARAMETER;
+		goto error;
+	}
+
+	if (!source_buffer) {
+		ret = efi_load_image_from_path(boot_policy, file_path,
+					       &dest_buffer, &source_size);
+		if (ret != EFI_SUCCESS)
+			goto error;
+	} else {
+		dest_buffer = source_buffer;
+	}
+	/* split file_path which contains both the device and file parts */
+	efi_dp_split_file_path(file_path, &dp, &fp);
+	ret = efi_setup_loaded_image(dp, fp, image_obj, &info);
+	if (ret == EFI_SUCCESS)
+		ret = efi_load_pe(*image_obj, dest_buffer, source_size, info);
+	if (!source_buffer)
+		/* Release buffer to which file was loaded */
+		efi_free_pages((uintptr_t)dest_buffer,
+			       efi_size_in_pages(source_size));
+	if (ret == EFI_SUCCESS || ret == EFI_SECURITY_VIOLATION) {
+		info->system_table = &systab;
+		info->parent_handle = parent_image;
+	} else {
+		/* The image is invalid. Release all associated resources. */
+		efi_delete_handle(*image_handle);
+		*image_handle = NULL;
+		free(info);
+	}
+
+	if (IS_ENABLED(CONFIG_EFI_LOADER_DEBUG_SUPPORT) && *image_handle)
+		efi_core_new_debug_image_info_entry(EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL,
+						    info,
+						    *image_handle);
+
+error:
+	return EFI_EXIT2(ret, *image_handle);
+}
+
 /**
  * efi_exit_boot_services() - stop all boot services
  * @image_handle: handle of the loaded image
@@ -2666,6 +2963,104 @@ static efi_status_t EFIAPI efi_open_protocol
 	return EFI_EXIT(r);
 }
 
+/**
+ * __efi_start_image() - call the entry point of an image
+ * @image_handle:   handle of the image
+ * @exit_data_size: size of the buffer
+ * @exit_data:      buffer to receive the exit data of the called image
+ * @flags:          boot flags
+ *
+ * This function implements the StartImage service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+efi_status_t __efi_start_image(efi_handle_t image_handle,
+			       efi_uintn_t *exit_data_size,
+			       u16 **exit_data, int flags)
+{
+	struct efi_loaded_image_obj *image_obj =
+		(struct efi_loaded_image_obj *)image_handle;
+	efi_status_t ret;
+	struct efi_loaded_image *info;
+	efi_handle_t parent_image = current_image;
+	efi_status_t exit_status;
+	struct jmp_buf_data exit_jmp;
+	EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
+				     struct efi_system_table *st);
+
+	if (!efi_search_obj(image_handle))
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	/* Check parameters */
+	if (image_obj->header.type != EFI_OBJECT_TYPE_LOADED_IMAGE)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	ret = EFI_CALL(efi_open_protocol(image_handle, &efi_loaded_image_protocol_guid,
+					 (void **)&info, NULL, NULL,
+					 EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+	if (ret != EFI_SUCCESS)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	image_obj->exit_data_size = exit_data_size;
+	image_obj->exit_data = exit_data;
+	image_obj->exit_status = &exit_status;
+	image_obj->exit_jmp = &exit_jmp;
+
+	/* call the image! */
+	if (setjmp(&exit_jmp)) {
+		/*
+		 * We called the entry point of the child image with EFI_CALL
+		 * in the lines below. The child image called the Exit() boot
+		 * service efi_exit() which executed the long jump that brought
+		 * us to the current line. This implies that the second half
+		 * of the EFI_CALL macro has not been executed.
+		 */
+		/*
+		 * To get ready to call EFI_EXIT below we have to execute the
+		 * missed out steps of EFI_CALL.
+		 */
+		EFI_RETURN(exit_status);
+
+		current_image = parent_image;
+
+		return EFI_EXIT(exit_status);
+	}
+
+	current_image = image_handle;
+	image_obj->header.type = EFI_OBJECT_TYPE_STARTED_IMAGE;
+
+	if (flags & EFI_DRYRUN) {
+		pr_info("Dryrun. Aborted\n");
+		ret = EFI_SUCCESS;
+		goto exit;
+	}
+
+	entry = image_obj->entry;
+
+	pr_info("Starting EFI payload at %p\n", entry);
+
+	// FIXME: we need the below if we enable CONFIG_ARM_MMU_PERMISSIONS...
+	// remap_range(info->image_base, info->image_size, MAP_ARCH(2));
+	sync_caches_for_execution();
+
+	efi_set_variable_usec("LoaderTimeExecUSec", &efi_systemd_vendor_guid,
+			      ktime_to_us(ktime_get()));
+
+	ret = EFI_CALL(entry(image_handle, &systab));
+
+exit:
+	/*
+	 * Control is returned from a started UEFI image either by calling
+	 * Exit() (where exit data can be provided) or by simply returning from
+	 * the entry point. In the latter case call Exit() on behalf of the
+	 * image.
+	 */
+	return EFI_CALL(systab.boottime->exit(image_handle, ret, 0, NULL));
+}
+
 /**
  * efi_start_image() - call the entry point of an image
  * @image_handle:   handle of the image
@@ -2685,7 +3080,54 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
 {
 	EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
 
-	return EFI_EXIT(EFI_UNSUPPORTED);
+	return __efi_start_image(image_handle, exit_data_size, exit_data, 0);
+}
+
+/**
+ * efi_delete_image() - delete loaded image from memory)
+ *
+ * @image_obj:			handle of the loaded image
+ * @loaded_image_protocol:	loaded image protocol
+ */
+static efi_status_t efi_delete_image
+			(struct efi_loaded_image_obj *image_obj,
+			 struct efi_loaded_image *loaded_image_protocol)
+{
+	struct efi_object *efiobj;
+	efi_status_t r, ret = EFI_SUCCESS;
+
+close_next:
+	list_for_each_entry(efiobj, &efi_obj_list, link) {
+		struct efi_handler *protocol;
+
+		list_for_each_entry(protocol, &efiobj->protocols, link) {
+			struct efi_open_protocol_info_item *info;
+
+			list_for_each_entry(info, &protocol->open_infos, link) {
+				if (info->info.agent_handle !=
+				    (efi_handle_t)image_obj)
+					continue;
+				r = efi_close_protocol(
+						efiobj, &protocol->guid,
+						info->info.agent_handle,
+						info->info.controller_handle);
+				if (r !=  EFI_SUCCESS)
+					ret = r;
+				/*
+				 * Closing protocols may results in further
+				 * items being deleted. To play it safe loop
+				 * over all elements again.
+				 */
+				goto close_next;
+			}
+		}
+	}
+
+	efi_free_pages((uintptr_t)loaded_image_protocol->image_base,
+		       efi_size_in_pages(loaded_image_protocol->image_size));
+	efi_delete_handle(&image_obj->header);
+
+	return ret;
 }
 
 /**
@@ -2701,7 +3143,87 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
  */
 static efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle)
 {
-	return EFI_EXIT(EFI_UNSUPPORTED);
+	efi_status_t ret = EFI_SUCCESS;
+	struct efi_object *efiobj;
+	struct efi_loaded_image *loaded_image_protocol;
+
+	EFI_ENTRY("%p", image_handle);
+
+	efiobj = efi_search_obj(image_handle);
+	if (!efiobj) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+	/* Find the loaded image protocol */
+	ret = EFI_CALL(efi_open_protocol(image_handle, &efi_loaded_image_protocol_guid,
+					 (void **)&loaded_image_protocol,
+					 NULL, NULL,
+					 EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+	if (ret != EFI_SUCCESS) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	if (IS_ENABLED(CONFIG_EFI_LOADER_DEBUG_SUPPORT))
+		efi_core_remove_debug_image_info_entry(image_handle);
+
+	switch (efiobj->type) {
+	case EFI_OBJECT_TYPE_STARTED_IMAGE:
+		/* Call the unload function */
+		if (!loaded_image_protocol->unload) {
+			ret = EFI_UNSUPPORTED;
+			goto out;
+		}
+		ret = EFI_CALL(loaded_image_protocol->unload(image_handle));
+		if (ret != EFI_SUCCESS)
+			goto out;
+		break;
+	case EFI_OBJECT_TYPE_LOADED_IMAGE:
+		break;
+	default:
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+	efi_delete_image((struct efi_loaded_image_obj *)efiobj,
+			 loaded_image_protocol);
+out:
+	return EFI_EXIT(ret);
+}
+
+/**
+ * efi_update_exit_data() - fill exit data parameters of StartImage()
+ *
+ * @image_obj:		image handle
+ * @exit_data_size:	size of the exit data buffer
+ * @exit_data:		buffer with data returned by UEFI payload
+ * Return:		status code
+ */
+static efi_status_t efi_update_exit_data(struct efi_loaded_image_obj *image_obj,
+					 efi_uintn_t exit_data_size,
+					 u16 *exit_data)
+{
+	efi_status_t ret;
+
+	/*
+	 * If exit_data is not provided to StartImage(), exit_data_size must be
+	 * ignored.
+	 */
+	if (!image_obj->exit_data)
+		return EFI_SUCCESS;
+	if (image_obj->exit_data_size)
+		*image_obj->exit_data_size = exit_data_size;
+	if (exit_data_size && exit_data) {
+		ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA,
+					exit_data_size,
+					(void **)image_obj->exit_data,
+					"exitdata");
+		if (ret != EFI_SUCCESS)
+			return ret;
+		memcpy(*image_obj->exit_data, exit_data, exit_data_size);
+	} else {
+		image_obj->exit_data = NULL;
+	}
+	return EFI_SUCCESS;
 }
 
 /**
@@ -2723,10 +3245,71 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
 				    efi_uintn_t exit_data_size,
 				    u16 *exit_data)
 {
+	/*
+	 * TODO: We should call the unload procedure of the loaded
+	 *	 image protocol.
+	 */
+	efi_status_t ret;
+	struct efi_loaded_image *loaded_image_protocol;
+	struct efi_loaded_image_obj *image_obj =
+		(struct efi_loaded_image_obj *)image_handle;
+	struct jmp_buf_data *exit_jmp;
+
 	EFI_ENTRY("%p, %ld, %zu, %p", image_handle, exit_status,
 		  exit_data_size, exit_data);
 
-	return EFI_EXIT(EFI_UNSUPPORTED);
+	/* Check parameters */
+	ret = EFI_CALL(efi_open_protocol(image_handle, &efi_loaded_image_protocol_guid,
+					 (void **)&loaded_image_protocol,
+					 NULL, NULL,
+					 EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+	if (ret != EFI_SUCCESS) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	/* Unloading of unstarted images */
+	switch (image_obj->header.type) {
+	case EFI_OBJECT_TYPE_STARTED_IMAGE:
+		break;
+	case EFI_OBJECT_TYPE_LOADED_IMAGE:
+		efi_delete_image(image_obj, loaded_image_protocol);
+		ret = EFI_SUCCESS;
+		goto out;
+	default:
+		/* Handle does not refer to loaded image */
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+	/* A started image can only be unloaded it is the last one started. */
+	if (image_handle != current_image) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	/* Exit data is only foreseen in case of failure. */
+	if (exit_status != EFI_SUCCESS) {
+		ret = efi_update_exit_data(image_obj, exit_data_size,
+					   exit_data);
+		/* Exiting has priority. Don't return error to caller. */
+		if (ret != EFI_SUCCESS)
+			EFI_PRINT("%s: out of memory\n", __func__);
+	}
+	/* efi_delete_image() frees image_obj. Copy before the call. */
+	exit_jmp = image_obj->exit_jmp;
+	*image_obj->exit_status = exit_status;
+	if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION ||
+	    exit_status != EFI_SUCCESS)
+		efi_delete_image(image_obj, loaded_image_protocol);
+
+	/* Make sure entry/exit counts for EFI world cross-overs match */
+	EFI_EXIT(exit_status);
+
+	longjmp(exit_jmp, 1);
+
+	panic("EFI application exited");
+out:
+	return EFI_EXIT(ret);
 }
 
 /**
@@ -3170,7 +3753,7 @@ static struct efi_boot_services efi_boot_services = {
 	.locate_handle = efi_locate_handle_ext,
 	.locate_device_path = efi_locate_device_path,
 	.install_configuration_table = efi_install_configuration_table_ext,
-	.load_image = (void *)efi_unimplemented,
+	.load_image = efiloader_load_image,
 	.start_image = efi_start_image,
 	.exit = efi_exit,
 	.unload_image = efi_unload_image,
diff --git a/include/efi/loader.h b/include/efi/loader.h
index 466541c1e2b5..74d177568353 100644
--- a/include/efi/loader.h
+++ b/include/efi/loader.h
@@ -29,6 +29,10 @@ efi_status_t efi_initialize_system_table(void);
 /* Called by efi_set_watchdog_timer to reset the timer */
 efi_status_t efi_set_watchdog(unsigned long timeout);
 
+efi_status_t __efi_start_image(efi_handle_t image_handle,
+			       efi_uintn_t *exit_data_size,
+			       u16 **exit_data, int flags);
+
 /* Allocate boot service data pool memory */
 void *efi_alloc(size_t len, const char *name);
 /* Reallocate boot service data pool memory */
-- 
2.47.3




  parent reply	other threads:[~2025-12-18 11:38 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-18 10:37 [PATCH v1 00/54] efi: implement EFI loader support in barebox Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 01/54] efi: payload: initrd: fix type mismatch on 32-bit Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 02/54] efi: loader: switch over event/memory key type to efi_uintn_t Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 03/54] lib: vsprintf: print human-readable EFI GUIDs with %pUs Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 04/54] fs: fat: don't duplicate dentries when resolving differently cased paths Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 05/54] efi: loader: add memory accounting Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 06/54] efi: loader: add pool allocator Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 07/54] efi: types: add EFI_RUNTIME_SECTION Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 08/54] resource: assign memory banks a default type and attr Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 09/54] ARM: lds: add EFI runtime service section Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 10/54] ARM: move needed assembly routines into EFI runtime section Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 11/54] crypto: crc32: implement position independent CRC32 Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 12/54] efi: loader: add support for tracing calls back into UEFI Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 13/54] efi: loader: add table utility functions Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 14/54] lib: add charset helpers Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 15/54] efi: loader: add object handling API Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 16/54] efi: loader: add devicepath support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 17/54] efi: loader: add debug support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 18/54] efi: loader: add boot services support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 19/54] efi: loader: add support for runtime services before ExitBootServices Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 20/54] efi: loader: setup root node Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 21/54] efi: loader: add watchdog support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 22/54] efi: loader: move PE implementation out of common code Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 23/54] efi: loader: protocol: add file protocol support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 24/54] efi: loader: protocol: add Block IO support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 25/54] efi: loader: protocol: implement efi_file_from_path Ahmad Fatoum
2025-12-18 10:37 ` Ahmad Fatoum [this message]
2025-12-18 10:37 ` [PATCH v1 27/54] efi: loader: add EFI load option handling Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 28/54] efi: loader: protocol: add graphical output protocol support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 29/54] efi: loader: protocol: add console support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 30/54] efi: loader: protocol: add HII support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 31/54] efi: loader: protocol: add unicode collation support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 32/54] efi: loader: protocol: add random number generator protocol Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 33/54] efi: loader: protocol: add device_path_utilities Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 34/54] efi: loader: support formatting only first device path node to text Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 35/54] efi: loader: protocol: add efi_device_path_to_text support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 36/54] restart: allow drivers to register runtime restart handler Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 37/54] poweroff: allow drivers to register runtime poweroff handler Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 38/54] ARM: psci: client: register runtime service " Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 39/54] ARM: psci: client: register runtime service restart handler Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 40/54] hardening: disable some features when EFI runtime support is enabled Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 41/54] filetype: add new filetype for efi-stubbed ARM zImages Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 42/54] bootm: add global.bootm.efi toggle Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 43/54] efi: loader: add ESP boot entry provider Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 44/54] efi: loader: add rudimentary EFI boot manager Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 45/54] efi: loader: implement bootm handler Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 46/54] efi: runtime: add EFI variable support Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 47/54] efi: loader: populate OsIndicationsSupported/PlatformLang variables Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 48/54] ARM: don't disable MMU when EFI booting Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 49/54] efi: runtime: add runtime service support after ExitBootServices Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 50/54] efi: runtime: add relocation check Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 51/54] efi: loader: CONFIG_EFI_RT_VOLATILE_STORE Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 52/54] efi: loader: support ExitBootServices Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 53/54] efi: loader: pass along SMBIOS table Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 54/54] ARM: configs: add multi_v7/8_efiloader_defconfig Ahmad Fatoum

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251218111242.1527495-27-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox