Merge git://git.denx.de/u-boot-x86

- Allow x86 boards to use TPL, SPL and U-Boot proper
- Update sysreset x86 driver to utilize ACPI registers to do power off
- Add a new chromebook_samus_tpl board for TPL support
- Several minor changes in binman tool
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index f1d7d8b..52116b3 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -6,7 +6,6 @@
  */
 
 #include <common.h>
-#include <bootm.h>
 #include <charset.h>
 #include <command.h>
 #include <dm.h>
@@ -17,9 +16,7 @@
 #include <linux/libfdt_env.h>
 #include <mapmem.h>
 #include <memalign.h>
-#include <asm/global_data.h>
 #include <asm-generic/sections.h>
-#include <asm-generic/unaligned.h>
 #include <linux/linkage.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -28,15 +25,6 @@
 static struct efi_device_path *bootefi_device_path;
 
 /*
- * Allow unaligned memory access.
- *
- * This routine is overridden by architectures providing this feature.
- */
-void __weak allow_unaligned(void)
-{
-}
-
-/*
  * Set the load options of an image from an environment variable.
  *
  * @handle:	the image handle
@@ -338,11 +326,6 @@
 	efi_handle_t handle;
 	efi_status_t ret;
 
-	/* Allow unaligned memory access */
-	allow_unaligned();
-
-	switch_to_non_secure_mode();
-
 	/* Initialize EFI drivers */
 	ret = efi_init_obj_list();
 	if (ret != EFI_SUCCESS) {
@@ -391,11 +374,6 @@
 	efi_handle_t mem_handle = NULL, handle;
 	efi_status_t ret;
 
-	/* Allow unaligned memory access */
-	allow_unaligned();
-
-	switch_to_non_secure_mode();
-
 	/* Initialize EFI drivers */
 	ret = efi_init_obj_list();
 	if (ret != EFI_SUCCESS) {
@@ -582,11 +560,6 @@
 	struct efi_loaded_image *loaded_image_info;
 	efi_status_t ret;
 
-	/* Allow unaligned memory access */
-	allow_unaligned();
-
-	switch_to_non_secure_mode();
-
 	/* Initialize EFI drivers */
 	ret = efi_init_obj_list();
 	if (ret != EFI_SUCCESS) {
diff --git a/include/efi_api.h b/include/efi_api.h
index 472160c..755c405 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -128,7 +128,8 @@
 				    efi_status_t exit_status,
 				    efi_uintn_t exitdata_size, u16 *exitdata);
 	efi_status_t (EFIAPI *unload_image)(efi_handle_t image_handle);
-	efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t, unsigned long);
+	efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t image_handle,
+						  efi_uintn_t map_key);
 
 	efi_status_t (EFIAPI *get_next_monotonic_count)(u64 *count);
 	efi_status_t (EFIAPI *stall)(unsigned long usecs);
@@ -348,7 +349,7 @@
 	aligned_u64 image_size;
 	unsigned int image_code_type;
 	unsigned int image_data_type;
-	unsigned long unload;
+	efi_status_t (EFIAPI *unload)(efi_handle_t image_handle);
 };
 
 #define EFI_DEVICE_PATH_PROTOCOL_GUID \
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 7af3f16..07ef14b 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -180,6 +180,19 @@
 };
 
 /**
+ * enum efi_object_type - type of EFI object
+ *
+ * In UnloadImage we must be able to identify if the handle relates to a
+ * started image.
+ */
+enum efi_object_type {
+	EFI_OBJECT_TYPE_UNDEFINED = 0,
+	EFI_OBJECT_TYPE_U_BOOT_FIRMWARE,
+	EFI_OBJECT_TYPE_LOADED_IMAGE,
+	EFI_OBJECT_TYPE_STARTED_IMAGE,
+};
+
+/**
  * struct efi_object - dereferenced EFI handle
  *
  * @link:	pointers to put the handle into a linked list
@@ -201,6 +214,7 @@
 	struct list_head link;
 	/* The list of protocols */
 	struct list_head protocols;
+	enum efi_object_type type;
 };
 
 /**
@@ -221,6 +235,7 @@
 	struct jmp_buf_data exit_jmp;
 	EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
 				     struct efi_system_table *st);
+	u16 image_type;
 };
 
 /**
@@ -257,6 +272,25 @@
 /* List of all events */
 extern struct list_head efi_events;
 
+/**
+ * efi_register_notify_event - event registered by RegisterProtocolNotify()
+ *
+ * The address of this structure serves as registration value.
+ *
+ * @link:		link to list of all registered events
+ * @event:		registered event. The same event may registered for
+ *			multiple GUIDs.
+ * @protocol:		protocol for which the event is registered
+ */
+struct efi_register_notify_event {
+	struct list_head link;
+	struct efi_event *event;
+	efi_guid_t protocol;
+};
+
+/* List of all events registered by RegisterProtocolNotify() */
+extern struct list_head efi_register_notify_events;
+
 /* Initialize efi execution environment */
 efi_status_t efi_init_obj_list(void);
 /* Called by bootefi to initialize root node */
diff --git a/include/efi_selftest.h b/include/efi_selftest.h
index dd42e49..eaee188 100644
--- a/include/efi_selftest.h
+++ b/include/efi_selftest.h
@@ -93,17 +93,6 @@
 u16 *efi_st_translate_code(u16 code);
 
 /*
- * Compare memory.
- * We cannot use lib/string.c due to different CFLAGS values.
- *
- * @buf1:	first buffer
- * @buf2:	second buffer
- * @length:	number of bytes to compare
- * @return:	0 if both buffers contain the same bytes
- */
-int efi_st_memcmp(const void *buf1, const void *buf2, size_t length);
-
-/*
  * Compare an u16 string to a char string.
  *
  * @buf1:	u16 string
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index e5c46e9..b97d55c 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -13,6 +13,7 @@
 #include <linux/libfdt_env.h>
 #include <u-boot/crc.h>
 #include <bootm.h>
+#include <pe.h>
 #include <watchdog.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -26,6 +27,9 @@
 /* List of all events */
 LIST_HEAD(efi_events);
 
+/* List of all events registered by RegisterProtocolNotify() */
+LIST_HEAD(efi_register_notify_events);
+
 /* Handle of the currently executing image */
 static efi_handle_t current_image;
 
@@ -238,7 +242,7 @@
 			if (evt->is_queued)
 				efi_queue_event(evt, check_tpl);
 		}
-	} else if (!event->is_signaled) {
+	} else {
 		event->is_signaled = true;
 		if (event->type & EVT_NOTIFY_SIGNAL)
 			efi_queue_event(event, check_tpl);
@@ -263,7 +267,7 @@
 	EFI_ENTRY("0x%zx", new_tpl);
 
 	if (new_tpl < efi_tpl)
-		debug("WARNING: new_tpl < current_tpl in %s\n", __func__);
+		EFI_PRINT("WARNING: new_tpl < current_tpl in %s\n", __func__);
 	efi_tpl = new_tpl;
 	if (efi_tpl > TPL_HIGH_LEVEL)
 		efi_tpl = TPL_HIGH_LEVEL;
@@ -286,7 +290,7 @@
 	EFI_ENTRY("0x%zx", old_tpl);
 
 	if (old_tpl > efi_tpl)
-		debug("WARNING: old_tpl > current_tpl in %s\n", __func__);
+		EFI_PRINT("WARNING: old_tpl > current_tpl in %s\n", __func__);
 	efi_tpl = old_tpl;
 	if (efi_tpl > TPL_HIGH_LEVEL)
 		efi_tpl = TPL_HIGH_LEVEL;
@@ -664,10 +668,26 @@
 					efi_guid_t *event_group,
 					struct efi_event **event)
 {
+	efi_status_t ret;
+
 	EFI_ENTRY("%d, 0x%zx, %p, %p, %pUl", type, notify_tpl, notify_function,
 		  notify_context, event_group);
-	return EFI_EXIT(efi_create_event(type, notify_tpl, notify_function,
-					 notify_context, event_group, event));
+
+	/*
+	 * The allowable input parameters are the same as in CreateEvent()
+	 * except for the following two disallowed event types.
+	 */
+	switch (type) {
+	case EVT_SIGNAL_EXIT_BOOT_SERVICES:
+	case EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE:
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	ret = efi_create_event(type, notify_tpl, notify_function,
+			       notify_context, event_group, event);
+out:
+	return EFI_EXIT(ret);
 }
 
 /**
@@ -891,9 +911,21 @@
  */
 static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
 {
+	struct efi_register_notify_event *item, *next;
+
 	EFI_ENTRY("%p", event);
 	if (efi_is_event(event) != EFI_SUCCESS)
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	/* Remove protocol notify registrations for the event */
+	list_for_each_entry_safe(item, next, &efi_register_notify_events,
+				 link) {
+		if (event == item->event) {
+			list_del(&item->link);
+			free(item);
+		}
+	}
+
 	list_del(&event->link);
 	free(event);
 	return EFI_EXIT(EFI_SUCCESS);
@@ -939,11 +971,13 @@
 {
 	struct efi_object *efiobj;
 
+	if (!handle)
+		return NULL;
+
 	list_for_each_entry(efiobj, &efi_obj_list, link) {
 		if (efiobj == handle)
 			return efiobj;
 	}
-
 	return NULL;
 }
 
@@ -997,6 +1031,7 @@
 	struct efi_object *efiobj;
 	struct efi_handler *handler;
 	efi_status_t ret;
+	struct efi_register_notify_event *event;
 
 	efiobj = efi_search_obj(handle);
 	if (!efiobj)
@@ -1011,6 +1046,13 @@
 	handler->protocol_interface = protocol_interface;
 	INIT_LIST_HEAD(&handler->open_infos);
 	list_add_tail(&handler->link, &efiobj->protocols);
+
+	/* Notify registered events */
+	list_for_each_entry(event, &efi_register_notify_events, link) {
+		if (!guidcmp(protocol, &event->protocol))
+			efi_signal_event(event->event, true);
+	}
+
 	if (!guidcmp(&efi_guid_device_path, protocol))
 		EFI_PRINT("installed device path '%pD'\n", protocol_interface);
 	return EFI_SUCCESS;
@@ -1051,11 +1093,9 @@
 		r = efi_create_handle(handle);
 		if (r != EFI_SUCCESS)
 			goto out;
-		debug("%sEFI: new handle %p\n", indent_string(nesting_level),
-		      *handle);
+		EFI_PRINT("new handle %p\n", *handle);
 	} else {
-		debug("%sEFI: handle %p\n", indent_string(nesting_level),
-		      *handle);
+		EFI_PRINT("handle %p\n", *handle);
 	}
 	/* Add new protocol */
 	r = efi_add_protocol(*handle, protocol, protocol_interface);
@@ -1274,8 +1314,30 @@
 						struct efi_event *event,
 						void **registration)
 {
+	struct efi_register_notify_event *item;
+	efi_status_t ret = EFI_SUCCESS;
+
 	EFI_ENTRY("%pUl, %p, %p", protocol, event, registration);
-	return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+	if (!protocol || !event || !registration) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	item = calloc(1, sizeof(struct efi_register_notify_event));
+	if (!item) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+
+	item->event = event;
+	memcpy(&item->protocol, protocol, sizeof(efi_guid_t));
+
+	list_add_tail(&item->link, &efi_register_notify_events);
+
+	*registration = item;
+out:
+	return EFI_EXIT(ret);
 }
 
 /**
@@ -1290,8 +1352,7 @@
  * Return: 0 if the handle implements the protocol
  */
 static int efi_search(enum efi_locate_search_type search_type,
-		      const efi_guid_t *protocol, void *search_key,
-		      efi_handle_t handle)
+		      const efi_guid_t *protocol, efi_handle_t handle)
 {
 	efi_status_t ret;
 
@@ -1299,8 +1360,6 @@
 	case ALL_HANDLES:
 		return 0;
 	case BY_REGISTER_NOTIFY:
-		/* TODO: RegisterProtocolNotify is not implemented yet */
-		return -1;
 	case BY_PROTOCOL:
 		ret = efi_search_protocol(handle, protocol, NULL);
 		return (ret != EFI_SUCCESS);
@@ -1312,11 +1371,12 @@
 
 /**
  * efi_locate_handle() - locate handles implementing a protocol
- * @search_type: selection criterion
- * @protocol:    GUID of the protocol
- * @search_key: registration key
- * @buffer_size: size of the buffer to receive the handles in bytes
- * @buffer:      buffer to receive the relevant handles
+ *
+ * @search_type:	selection criterion
+ * @protocol:		GUID of the protocol
+ * @search_key:		registration key
+ * @buffer_size:	size of the buffer to receive the handles in bytes
+ * @buffer:		buffer to receive the relevant handles
  *
  * This function is meant for U-Boot internal calls. For the API implementation
  * of the LocateHandle service see efi_locate_handle_ext.
@@ -1330,6 +1390,7 @@
 {
 	struct efi_object *efiobj;
 	efi_uintn_t size = 0;
+	struct efi_register_notify_event *item, *event = NULL;
 
 	/* Check parameters */
 	switch (search_type) {
@@ -1338,8 +1399,19 @@
 	case BY_REGISTER_NOTIFY:
 		if (!search_key)
 			return EFI_INVALID_PARAMETER;
+		/* Check that the registration key is valid */
+		list_for_each_entry(item, &efi_register_notify_events, link) {
+			if (item ==
+			    (struct efi_register_notify_event *)search_key) {
+				event = item;
+				break;
+			}
+		}
+		if (!event)
+			return EFI_INVALID_PARAMETER;
-		/* RegisterProtocolNotify is not implemented yet */
-		return EFI_UNSUPPORTED;
+
+		protocol = &event->protocol;
+		break;
 	case BY_PROTOCOL:
 		if (!protocol)
 			return EFI_INVALID_PARAMETER;
@@ -1348,32 +1420,32 @@
 		return EFI_INVALID_PARAMETER;
 	}
 
-	/*
-	 * efi_locate_handle_buffer uses this function for
-	 * the calculation of the necessary buffer size.
-	 * So do not require a buffer for buffersize == 0.
-	 */
-	if (!buffer_size || (*buffer_size && !buffer))
-		return EFI_INVALID_PARAMETER;
-
 	/* Count how much space we need */
 	list_for_each_entry(efiobj, &efi_obj_list, link) {
-		if (!efi_search(search_type, protocol, search_key, efiobj))
+		if (!efi_search(search_type, protocol, efiobj))
 			size += sizeof(void *);
 	}
 
+	if (size == 0)
+		return EFI_NOT_FOUND;
+
+	if (!buffer_size)
+		return EFI_INVALID_PARAMETER;
+
 	if (*buffer_size < size) {
 		*buffer_size = size;
 		return EFI_BUFFER_TOO_SMALL;
 	}
 
 	*buffer_size = size;
-	if (size == 0)
-		return EFI_NOT_FOUND;
+
+	/* The buffer size is sufficient but there is not buffer */
+	if (!buffer)
+		return EFI_INVALID_PARAMETER;
 
 	/* Then fill the array */
 	list_for_each_entry(efiobj, &efi_obj_list, link) {
-		if (!efi_search(search_type, protocol, search_key, efiobj))
+		if (!efi_search(search_type, protocol, efiobj))
 			*buffer++ = efiobj;
 	}
 
@@ -1538,6 +1610,7 @@
 		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);
@@ -1687,7 +1760,7 @@
 	EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
 		  file_path, source_buffer, source_size, image_handle);
 
-	if (!image_handle || !parent_image) {
+	if (!image_handle || !efi_search_obj(parent_image)) {
 		ret = EFI_INVALID_PARAMETER;
 		goto error;
 	}
@@ -1696,6 +1769,11 @@
 		ret = EFI_NOT_FOUND;
 		goto error;
 	}
+	/* The parent image handle must refer to a loaded image */
+	if (!parent_image->type) {
+		ret = EFI_INVALID_PARAMETER;
+		goto error;
+	}
 
 	if (!source_buffer) {
 		ret = efi_load_image_from_path(file_path, &dest_buffer,
@@ -1703,6 +1781,10 @@
 		if (ret != EFI_SUCCESS)
 			goto error;
 	} else {
+		if (!source_size) {
+			ret = EFI_LOAD_ERROR;
+			goto error;
+		}
 		dest_buffer = source_buffer;
 	}
 	/* split file_path which contains both the device and file parts */
@@ -1728,29 +1810,6 @@
 }
 
 /**
- * efi_unload_image() - unload an EFI image
- * @image_handle: handle of the image to be unloaded
- *
- * This function implements the UnloadImage service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
- *
- * Return: status code
- */
-efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle)
-{
-	struct efi_object *efiobj;
-
-	EFI_ENTRY("%p", image_handle);
-	efiobj = efi_search_obj(image_handle);
-	if (efiobj)
-		list_del(&efiobj->link);
-
-	return EFI_EXIT(EFI_SUCCESS);
-}
-
-/**
  * efi_exit_caches() - fix up caches for EFI payloads if necessary
  */
 static void efi_exit_caches(void)
@@ -1782,11 +1841,11 @@
  * Return: status code
  */
 static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
-						  unsigned long map_key)
+						  efi_uintn_t map_key)
 {
 	struct efi_event *evt;
 
-	EFI_ENTRY("%p, %ld", image_handle, map_key);
+	EFI_ENTRY("%p, %zx", image_handle, map_key);
 
 	/* Check that the caller has read the current memory map */
 	if (map_key != efi_memory_map_key)
@@ -1932,7 +1991,8 @@
 	EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, agent_handle,
 		  controller_handle);
 
-	if (!agent_handle) {
+	if (!efi_search_obj(agent_handle) ||
+	    (controller_handle && !efi_search_obj(controller_handle))) {
 		r = EFI_INVALID_PARAMETER;
 		goto out;
 	}
@@ -2585,8 +2645,15 @@
 	}
 
 	r = efi_search_protocol(handle, protocol, &handler);
-	if (r != EFI_SUCCESS)
+	switch (r) {
+	case EFI_SUCCESS:
+		break;
+	case EFI_NOT_FOUND:
+		r = EFI_UNSUPPORTED;
+		goto out;
+	default:
 		goto out;
+	}
 
 	r = efi_protocol_open(handler, protocol_interface, agent_handle,
 			      controller_handle, attributes);
@@ -2653,15 +2720,15 @@
 		 * missed out steps of EFI_CALL.
 		 */
 		assert(__efi_entry_check());
-		debug("%sEFI: %lu returned by started image\n",
-		      __efi_nesting_dec(),
-		      (unsigned long)((uintptr_t)image_obj->exit_status &
-				      ~EFI_ERROR_MASK));
+		EFI_PRINT("%lu returned by started image\n",
+			  (unsigned long)((uintptr_t)image_obj->exit_status &
+			  ~EFI_ERROR_MASK));
 		current_image = parent_image;
 		return EFI_EXIT(image_obj->exit_status);
 	}
 
 	current_image = image_handle;
+	image_obj->header.type = EFI_OBJECT_TYPE_STARTED_IMAGE;
 	EFI_PRINT("Jumping into 0x%p\n", image_obj->entry);
 	ret = EFI_CALL(image_obj->entry(image_handle, &systab));
 
@@ -2675,6 +2742,76 @@
 }
 
 /**
+ * efi_delete_image() - delete loaded image from memory)
+ *
+ * @image_obj:			handle of the loaded image
+ * @loaded_image_protocol:	loaded image protocol
+ */
+static void efi_delete_image(struct efi_loaded_image_obj *image_obj,
+			     struct efi_loaded_image *loaded_image_protocol)
+{
+	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);
+}
+
+/**
+ * efi_unload_image() - unload an EFI image
+ * @image_handle: handle of the image to be unloaded
+ *
+ * This function implements the UnloadImage service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle)
+{
+	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_guid_loaded_image,
+					 (void **)&loaded_image_protocol,
+					 NULL, NULL,
+					 EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+	if (ret != EFI_SUCCESS) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+	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
@@ -2733,7 +2870,7 @@
 	 *	 image protocol.
 	 */
 	efi_status_t ret;
-	void *info;
+	struct efi_loaded_image *loaded_image_protocol;
 	struct efi_loaded_image_obj *image_obj =
 		(struct efi_loaded_image_obj *)image_handle;
 
@@ -2741,13 +2878,33 @@
 		  exit_data_size, exit_data);
 
 	/* Check parameters */
-	if (image_handle != current_image)
-		goto out;
 	ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image,
-					 &info, NULL, NULL,
+					 (void **)&loaded_image_protocol,
+					 NULL, NULL,
 					 EFI_OPEN_PROTOCOL_GET_PROTOCOL));
-	if (ret != EFI_SUCCESS)
+	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) {
@@ -2757,6 +2914,9 @@
 		if (ret != EFI_SUCCESS)
 			EFI_PRINT("%s: out of memory\n", __func__);
 	}
+	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);
@@ -2772,7 +2932,7 @@
 
 	panic("EFI application exited");
 out:
-	return EFI_EXIT(EFI_INVALID_PARAMETER);
+	return EFI_EXIT(ret);
 }
 
 /**
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index f8092b6..13541cf 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -273,6 +273,7 @@
 		IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader;
 		image_base = opt->ImageBase;
 		efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
+		handle->image_type = opt->Subsystem;
 		efi_reloc = efi_alloc(virt_size,
 				      loaded_image_info->image_code_type);
 		if (!efi_reloc) {
@@ -288,6 +289,7 @@
 		IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
 		image_base = opt->ImageBase;
 		efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
+		handle->image_type = opt->Subsystem;
 		efi_reloc = efi_alloc(virt_size,
 				      loaded_image_info->image_code_type);
 		if (!efi_reloc) {
diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c
index e0fcbb8..38514e0 100644
--- a/lib/efi_loader/efi_root_node.c
+++ b/lib/efi_loader/efi_root_node.c
@@ -28,6 +28,7 @@
  */
 efi_status_t efi_root_node_register(void)
 {
+	efi_status_t ret;
 	struct efi_root_dp *dp;
 
 	/* Create device path protocol */
@@ -47,28 +48,31 @@
 	dp->end.length = sizeof(struct efi_device_path);
 
 	/* Create root node and install protocols */
-	return EFI_CALL(efi_install_multiple_protocol_interfaces(&efi_root,
-		       /* Device path protocol */
-		       &efi_guid_device_path, dp,
-		       /* Device path to text protocol */
-		       &efi_guid_device_path_to_text_protocol,
-		       (void *)&efi_device_path_to_text,
-		       /* Device path utilities protocol */
-		       &efi_guid_device_path_utilities_protocol,
-		       (void *)&efi_device_path_utilities,
-		       /* Unicode collation protocol */
-		       &efi_guid_unicode_collation_protocol,
-		       (void *)&efi_unicode_collation_protocol,
+	ret = EFI_CALL(efi_install_multiple_protocol_interfaces
+			(&efi_root,
+			 /* Device path protocol */
+			 &efi_guid_device_path, dp,
+			 /* Device path to text protocol */
+			 &efi_guid_device_path_to_text_protocol,
+			 (void *)&efi_device_path_to_text,
+			 /* Device path utilities protocol */
+			 &efi_guid_device_path_utilities_protocol,
+			 (void *)&efi_device_path_utilities,
+			 /* Unicode collation protocol */
+			 &efi_guid_unicode_collation_protocol,
+			 (void *)&efi_unicode_collation_protocol,
 #if CONFIG_IS_ENABLED(EFI_LOADER_HII)
-		       /* HII string protocol */
-		       &efi_guid_hii_string_protocol,
-		       (void *)&efi_hii_string,
-		       /* HII database protocol */
-		       &efi_guid_hii_database_protocol,
-		       (void *)&efi_hii_database,
-		       /* HII configuration routing protocol */
-		       &efi_guid_hii_config_routing_protocol,
-		       (void *)&efi_hii_config_routing,
+			 /* HII string protocol */
+			 &efi_guid_hii_string_protocol,
+			 (void *)&efi_hii_string,
+			 /* HII database protocol */
+			 &efi_guid_hii_database_protocol,
+			 (void *)&efi_hii_database,
+			 /* HII configuration routing protocol */
+			 &efi_guid_hii_config_routing_protocol,
+			 (void *)&efi_hii_config_routing,
 #endif
-		       NULL));
+			 NULL));
+	efi_root->type = EFI_OBJECT_TYPE_U_BOOT_FIRMWARE;
+	return ret;
 }
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 87db51c..8691d68 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -6,12 +6,22 @@
  */
 
 #include <common.h>
+#include <bootm.h>
 #include <efi_loader.h>
 
 #define OBJ_LIST_NOT_INITIALIZED 1
 
 static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED;
 
+/*
+ * Allow unaligned memory access.
+ *
+ * This routine is overridden by architectures providing this feature.
+ */
+void __weak allow_unaligned(void)
+{
+}
+
 /**
  * efi_init_platform_lang() - define supported languages
  *
@@ -86,6 +96,12 @@
 	if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED)
 		return efi_obj_list_initialized;
 
+	/* Allow unaligned memory access */
+	allow_unaligned();
+
+	/* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
+	switch_to_non_secure_mode();
+
 	/* Define supported languages */
 	ret = efi_init_platform_lang();
 	if (ret != EFI_SUCCESS)
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 4945691..c69ad7a 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -27,6 +27,7 @@
 efi_selftest_loaded_image.o \
 efi_selftest_manageprotocols.o \
 efi_selftest_memory.o \
+efi_selftest_register_notify.o \
 efi_selftest_rtc.o \
 efi_selftest_snp.o \
 efi_selftest_textinput.o \
diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c
index 29ac0ce..644c5ad 100644
--- a/lib/efi_selftest/efi_selftest_block_device.c
+++ b/lib/efi_selftest/efi_selftest_block_device.c
@@ -337,7 +337,7 @@
 		}
 		if (len >= dp_size(dp_partition))
 			continue;
-		if (efi_st_memcmp(dp, dp_partition, len))
+		if (memcmp(dp, dp_partition, len))
 			continue;
 		handle_partition = handles[i];
 		break;
@@ -409,7 +409,7 @@
 			     (unsigned int)buf_size);
 		return EFI_ST_FAILURE;
 	}
-	if (efi_st_memcmp(buf, "ello world!", 11)) {
+	if (memcmp(buf, "ello world!", 11)) {
 		efi_st_error("Unexpected file content\n");
 		return EFI_ST_FAILURE;
 	}
@@ -480,7 +480,7 @@
 			     (unsigned int)buf_size);
 		return EFI_ST_FAILURE;
 	}
-	if (efi_st_memcmp(buf, "U-Boot", 7)) {
+	if (memcmp(buf, "U-Boot", 7)) {
 		efi_st_error("Unexpected file content %s\n", buf);
 		return EFI_ST_FAILURE;
 	}
diff --git a/lib/efi_selftest/efi_selftest_config_table.c b/lib/efi_selftest/efi_selftest_config_table.c
index 0bc5da6..4467f49 100644
--- a/lib/efi_selftest/efi_selftest_config_table.c
+++ b/lib/efi_selftest/efi_selftest_config_table.c
@@ -153,8 +153,8 @@
 	}
 	table = NULL;
 	for (i = 0; i < sys_table->nr_tables; ++i) {
-		if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
-				   sizeof(efi_guid_t)))
+		if (!memcmp(&sys_table->tables[i].guid, &table_guid,
+			    sizeof(efi_guid_t)))
 			table = sys_table->tables[i].table;
 	}
 	if (!table) {
@@ -192,8 +192,8 @@
 	table = NULL;
 	tabcnt = 0;
 	for (i = 0; i < sys_table->nr_tables; ++i) {
-		if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
-				   sizeof(efi_guid_t))) {
+		if (!memcmp(&sys_table->tables[i].guid, &table_guid,
+			    sizeof(efi_guid_t))) {
 			table = sys_table->tables[i].table;
 			++tabcnt;
 		}
@@ -235,8 +235,8 @@
 	}
 	table = NULL;
 	for (i = 0; i < sys_table->nr_tables; ++i) {
-		if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid,
-				   sizeof(efi_guid_t))) {
+		if (!memcmp(&sys_table->tables[i].guid, &table_guid,
+			    sizeof(efi_guid_t))) {
 			table = sys_table->tables[i].table;
 		}
 	}
diff --git a/lib/efi_selftest/efi_selftest_loaded_image.c b/lib/efi_selftest/efi_selftest_loaded_image.c
index ea2b380..5889ab1 100644
--- a/lib/efi_selftest/efi_selftest_loaded_image.c
+++ b/lib/efi_selftest/efi_selftest_loaded_image.c
@@ -60,9 +60,8 @@
 	efi_st_printf("%u protocols installed on image handle\n",
 		      (unsigned int)protocol_buffer_count);
 	for (i = 0; i < protocol_buffer_count; ++i) {
-		if (efi_st_memcmp(protocol_buffer[i],
-				  &loaded_image_protocol_guid,
-				  sizeof(efi_guid_t)))
+		if (memcmp(protocol_buffer[i], &loaded_image_protocol_guid,
+			   sizeof(efi_guid_t)))
 			found = true;
 	}
 	if (!found) {
diff --git a/lib/efi_selftest/efi_selftest_loadimage.c b/lib/efi_selftest/efi_selftest_loadimage.c
index 449b6bf..06a87df 100644
--- a/lib/efi_selftest/efi_selftest_loadimage.c
+++ b/lib/efi_selftest/efi_selftest_loadimage.c
@@ -322,8 +322,7 @@
 	 efi_uintn_t *buffer_size, void *buffer)
 {
 	if (this == &file) {
-		if (efi_st_memcmp(info_type, &guid_file_info,
-				  sizeof(efi_guid_t)))
+		if (memcmp(info_type, &guid_file_info, sizeof(efi_guid_t)))
 			return EFI_INVALID_PARAMETER;
 		if (*buffer_size >= sizeof(struct file_info)) {
 			boottime->copy_mem(buffer, file_info,
@@ -333,8 +332,8 @@
 			return EFI_BUFFER_TOO_SMALL;
 		}
 	} else if (this == &volume) {
-		if (efi_st_memcmp(info_type, &guid_file_system_info,
-				  sizeof(efi_guid_t)))
+		if (memcmp(info_type, &guid_file_system_info,
+			   sizeof(efi_guid_t)))
 			return EFI_INVALID_PARAMETER;
 		if (*buffer_size >= sizeof(struct file_system_info)) {
 			boottime->copy_mem(buffer, file_system_info,
diff --git a/lib/efi_selftest/efi_selftest_manageprotocols.c b/lib/efi_selftest/efi_selftest_manageprotocols.c
index 0ff35ce..8edb1e4 100644
--- a/lib/efi_selftest/efi_selftest_manageprotocols.c
+++ b/lib/efi_selftest/efi_selftest_manageprotocols.c
@@ -332,13 +332,13 @@
 		efi_st_error("Failed to get protocols per handle\n");
 		return EFI_ST_FAILURE;
 	}
-	if (efi_st_memcmp(prot_buffer[0], &guid1, 16) &&
-	    efi_st_memcmp(prot_buffer[1], &guid1, 16)) {
+	if (memcmp(prot_buffer[0], &guid1, 16) &&
+	    memcmp(prot_buffer[1], &guid1, 16)) {
 		efi_st_error("Failed to get protocols per handle\n");
 		return EFI_ST_FAILURE;
 	}
-	if (efi_st_memcmp(prot_buffer[0], &guid3, 16) &&
-	    efi_st_memcmp(prot_buffer[1], &guid3, 16)) {
+	if (memcmp(prot_buffer[0], &guid3, 16) &&
+	    memcmp(prot_buffer[1], &guid3, 16)) {
 		efi_st_error("Failed to get protocols per handle\n");
 		return EFI_ST_FAILURE;
 	}
diff --git a/lib/efi_selftest/efi_selftest_memory.c b/lib/efi_selftest/efi_selftest_memory.c
index 5eeb42a..e71732d 100644
--- a/lib/efi_selftest/efi_selftest_memory.c
+++ b/lib/efi_selftest/efi_selftest_memory.c
@@ -33,8 +33,8 @@
 	boottime = systable->boottime;
 
 	for (i = 0; i < systable->nr_tables; ++i) {
-		if (!efi_st_memcmp(&systable->tables[i].guid, &fdt_guid,
-				   sizeof(efi_guid_t))) {
+		if (!memcmp(&systable->tables[i].guid, &fdt_guid,
+			    sizeof(efi_guid_t))) {
 			if (fdt_addr) {
 				efi_st_error("Duplicate device tree\n");
 				return EFI_ST_FAILURE;
diff --git a/lib/efi_selftest/efi_selftest_register_notify.c b/lib/efi_selftest/efi_selftest_register_notify.c
new file mode 100644
index 0000000..ee0ef39
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_register_notify.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_register_notify
+ *
+ * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the following protocol services:
+ * InstallProtocolInterface, UninstallProtocolInterface,
+ * RegisterProtocolNotify, CreateEvent, CloseEvent.
+ */
+
+#include <efi_selftest.h>
+
+/*
+ * The test currently does not actually call the interface function.
+ * So this is just a dummy structure.
+ */
+struct interface {
+	void (EFIAPI * inc)(void);
+};
+
+struct context {
+	void *registration_key;
+	efi_uintn_t notify_count;
+	efi_uintn_t handle_count;
+	efi_handle_t *handles;
+};
+
+static struct efi_boot_services *boottime;
+static efi_guid_t guid1 =
+	EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a,
+		 0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf);
+static efi_guid_t guid2 =
+	EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77,
+		 0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f);
+static struct context context;
+static struct efi_event *event;
+
+/*
+ * Notification function, increments the notification count if parameter
+ * context is provided.
+ *
+ * @event	notified event
+ * @context	pointer to the notification count
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+	struct context *cp = context;
+	efi_status_t ret;
+
+	cp->notify_count++;
+
+	ret = boottime->locate_handle_buffer(BY_REGISTER_NOTIFY, NULL,
+					     cp->registration_key,
+					     &cp->handle_count,
+					     &cp->handles);
+	if (ret != EFI_SUCCESS)
+		cp->handle_count = 0;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle:	handle of the loaded image
+ * @systable:	system table
+ */
+static int setup(const efi_handle_t img_handle,
+		 const struct efi_system_table *systable)
+{
+	efi_status_t ret;
+
+	boottime = systable->boottime;
+
+	ret = boottime->create_event(EVT_NOTIFY_SIGNAL,
+				     TPL_CALLBACK, notify, &context,
+				     &event);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("could not create event\n");
+		return EFI_ST_FAILURE;
+	}
+
+	ret = boottime->register_protocol_notify(&guid1, event,
+						 &context.registration_key);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("could not register event\n");
+		return EFI_ST_FAILURE;
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ */
+static int teardown(void)
+{
+	efi_status_t ret;
+
+	if (event) {
+		ret = boottime->close_event(event);
+		event = NULL;
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("could not close event\n");
+			return EFI_ST_FAILURE;
+		}
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ */
+static int execute(void)
+{
+	efi_status_t ret;
+	efi_handle_t handle1 = NULL, handle2 = NULL;
+	struct interface interface1, interface2;
+
+	ret = boottime->install_protocol_interface(&handle1, &guid1,
+						   EFI_NATIVE_INTERFACE,
+						   &interface1);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("could not install interface\n");
+		return EFI_ST_FAILURE;
+	}
+	if (!context.notify_count) {
+		efi_st_error("install was not notified\n");
+		return EFI_ST_FAILURE;
+	}
+	if (context.notify_count > 1) {
+		efi_st_error("install was notified too often\n");
+		return EFI_ST_FAILURE;
+	}
+	if (context.handle_count != 1) {
+		efi_st_error("LocateHandle failed\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->free_pool(context.handles);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("FreePool failed\n");
+		return EFI_ST_FAILURE;
+	}
+	context.notify_count = 0;
+	ret = boottime->install_protocol_interface(&handle1, &guid2,
+						   EFI_NATIVE_INTERFACE,
+						   &interface1);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("could not install interface\n");
+		return EFI_ST_FAILURE;
+	}
+	if (context.notify_count) {
+		efi_st_error("wrong protocol was notified\n");
+		return EFI_ST_FAILURE;
+	}
+	context.notify_count = 0;
+	ret = boottime->reinstall_protocol_interface(handle1, &guid1,
+						     &interface1, &interface2);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("could not reinstall interface\n");
+		return EFI_ST_FAILURE;
+	}
+	if (!context.notify_count) {
+		efi_st_error("reinstall was not notified\n");
+		return EFI_ST_FAILURE;
+	}
+	if (context.notify_count > 1) {
+		efi_st_error("reinstall was notified too often\n");
+		return EFI_ST_FAILURE;
+	}
+	if (context.handle_count != 1) {
+		efi_st_error("LocateHandle failed\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->free_pool(context.handles);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("FreePool failed\n");
+		return EFI_ST_FAILURE;
+	}
+	context.notify_count = 0;
+	ret = boottime->install_protocol_interface(&handle2, &guid1,
+						   EFI_NATIVE_INTERFACE,
+						   &interface1);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("could not install interface\n");
+		return EFI_ST_FAILURE;
+	}
+	if (!context.notify_count) {
+		efi_st_error("install was not notified\n");
+		return EFI_ST_FAILURE;
+	}
+	if (context.notify_count > 1) {
+		efi_st_error("install was notified too often\n");
+		return EFI_ST_FAILURE;
+	}
+	if (context.handle_count != 2) {
+		efi_st_error("LocateHandle failed\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->free_pool(context.handles);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("FreePool failed\n");
+		return EFI_ST_FAILURE;
+	}
+
+	ret = boottime->uninstall_multiple_protocol_interfaces
+			(handle1, &guid1, &interface2,
+			 &guid2, &interface1, NULL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->uninstall_multiple_protocol_interfaces
+			(handle2, &guid1, &interface1, NULL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
+		return EFI_ST_FAILURE;
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(regprotnot) = {
+	.name = "register protocol notify",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+	.teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c
index d7350e2..4c26619 100644
--- a/lib/efi_selftest/efi_selftest_snp.c
+++ b/lib/efi_selftest/efi_selftest_snp.c
@@ -334,9 +334,8 @@
 		 * Unfortunately QEMU ignores the broadcast flag.
 		 * So we have to check for broadcasts too.
 		 */
-		if (efi_st_memcmp(&destaddr, &net->mode->current_address,
-				  ARP_HLEN) &&
-		    efi_st_memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
+		if (memcmp(&destaddr, &net->mode->current_address, ARP_HLEN) &&
+		    memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
 			continue;
 		/*
 		 * Check this is a DHCP reply
@@ -360,7 +359,7 @@
 	addr = (u8 *)&buffer.p.ip_udp.ip_src;
 	efi_st_printf("DHCP reply received from %u.%u.%u.%u (%pm) ",
 		      addr[0], addr[1], addr[2], addr[3], &srcaddr);
-	if (!efi_st_memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
+	if (!memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN))
 		efi_st_printf("as broadcast message.\n");
 	else
 		efi_st_printf("as unicast message.\n");
diff --git a/lib/efi_selftest/efi_selftest_startimage_exit.c b/lib/efi_selftest/efi_selftest_startimage_exit.c
index 96049de..11207b8 100644
--- a/lib/efi_selftest/efi_selftest_startimage_exit.c
+++ b/lib/efi_selftest/efi_selftest_startimage_exit.c
@@ -139,7 +139,7 @@
 		return EFI_ST_FAILURE;
 	}
 	if (!exit_data || exit_data_size != sizeof(expected_text) ||
-	    efi_st_memcmp(exit_data, expected_text, sizeof(expected_text))) {
+	    memcmp(exit_data, expected_text, sizeof(expected_text))) {
 		efi_st_error("Incorrect exit data\n");
 		return EFI_ST_FAILURE;
 	}
diff --git a/lib/efi_selftest/efi_selftest_util.c b/lib/efi_selftest/efi_selftest_util.c
index 96a964c..ea73c25 100644
--- a/lib/efi_selftest/efi_selftest_util.c
+++ b/lib/efi_selftest/efi_selftest_util.c
@@ -102,20 +102,6 @@
 	return efi_st_unknown;
 }
 
-int efi_st_memcmp(const void *buf1, const void *buf2, size_t length)
-{
-	const u8 *pos1 = buf1;
-	const u8 *pos2 = buf2;
-
-	for (; length; --length) {
-		if (*pos1 != *pos2)
-			return *pos1 - *pos2;
-		++pos1;
-		++pos2;
-	}
-	return 0;
-}
-
 int efi_st_strcmp_16_8(const u16 *buf1, const char *buf2)
 {
 	for (; *buf1 || *buf2; ++buf1, ++buf2) {
diff --git a/lib/efi_selftest/efi_selftest_variables.c b/lib/efi_selftest/efi_selftest_variables.c
index 47a8e7f..b028c64 100644
--- a/lib/efi_selftest/efi_selftest_variables.c
+++ b/lib/efi_selftest/efi_selftest_variables.c
@@ -78,7 +78,7 @@
 		efi_st_error("GetVariable failed\n");
 		return EFI_ST_FAILURE;
 	}
-	if (efi_st_memcmp(data, v + 4, 3)) {
+	if (memcmp(data, v + 4, 3)) {
 		efi_st_error("GetVariable returned wrong value\n");
 		return EFI_ST_FAILURE;
 	}
@@ -106,7 +106,7 @@
 			     (unsigned int)len);
 		return EFI_ST_FAILURE;
 	}
-	if (efi_st_memcmp(data, v, 8)) {
+	if (memcmp(data, v, 8)) {
 		efi_st_error("GetVariable returned wrong value\n");
 		return EFI_ST_FAILURE;
 	}
@@ -129,7 +129,7 @@
 	if (len != 15)
 		efi_st_todo("GetVariable returned wrong length %u\n",
 			    (unsigned int)len);
-	if (efi_st_memcmp(data, v, len))
+	if (memcmp(data, v, len))
 		efi_st_todo("GetVariable returned wrong value\n");
 	/* Enumerate variables */
 	boottime->set_mem(&guid, 16, 0);
@@ -145,10 +145,10 @@
 				     (unsigned int)ret);
 			return EFI_ST_FAILURE;
 		}
-		if (!efi_st_memcmp(&guid, &guid_vendor0, sizeof(efi_guid_t)) &&
+		if (!memcmp(&guid, &guid_vendor0, sizeof(efi_guid_t)) &&
 		    !efi_st_strcmp_16_8(varname, "efi_st_var0"))
 			flag |= 1;
-		if (!efi_st_memcmp(&guid, &guid_vendor1, sizeof(efi_guid_t)) &&
+		if (!memcmp(&guid, &guid_vendor1, sizeof(efi_guid_t)) &&
 		    !efi_st_strcmp_16_8(varname, "efi_st_var1"))
 			flag |= 2;
 	}