diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 271b385edea6..cba81ffe75e4 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -358,6 +358,9 @@ static efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options)
 
 	free(load_options);
 
+	if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD))
+		efi_initrd_deregister();
+
 	return ret;
 }
 
diff --git a/include/efi_loader.h b/include/efi_loader.h
index eb11a8c7d4b1..0d4f5d9acc9f 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -431,6 +431,7 @@ efi_status_t efi_net_register(void);
 /* Called by bootefi to make the watchdog available */
 efi_status_t efi_watchdog_register(void);
 efi_status_t efi_initrd_register(void);
+void efi_initrd_deregister(void);
 /* Called by bootefi to make SMBIOS tables available */
 /**
  * efi_acpi_register() - write out ACPI tables
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index e729f727df11..029f0e515f57 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -317,16 +317,11 @@ config EFI_LOAD_FILE2_INITRD
 	bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk"
 	default n
 	help
-	  Expose a EFI_FILE_LOAD2_PROTOCOL that the Linux UEFI stub can
-	  use to load the initial ramdisk. Once this is enabled using
-	  initrd=<ramdisk> will stop working.
-
-config EFI_INITRD_FILESPEC
-	string "initramfs path"
-	default "host 0:1 initrd"
-	depends on EFI_LOAD_FILE2_INITRD
-	help
-	  Full path of the initramfs file, e.g. mmc 0:2 initramfs.cpio.gz.
+		Linux v5.7 and later can make use of this option. If the boot option
+		selected by the UEFI boot manager specifies an existing file to be used
+		as initial RAM disk, a Linux specific Load File2 protocol will be
+		installed and Linux 5.7+ will ignore any initrd=<ramdisk> command line
+		argument.
 
 config EFI_SECURE_BOOT
 	bool "Enable EFI secure boot support"
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index 25f5cebfdb67..d1baa8c71a4d 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -118,6 +118,9 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
 		ret = efi_set_variable_int(L"BootCurrent",
 					   &efi_global_variable_guid,
 					   attributes, sizeof(n), &n, false);
+		/* try to register load file2 for initrd's */
+		if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD))
+			ret |= efi_initrd_register();
 		if (ret != EFI_SUCCESS) {
 			if (EFI_CALL(efi_unload_image(*handle))
 			    != EFI_SUCCESS)
diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c
index b9ee8839054f..b11c5ee293fe 100644
--- a/lib/efi_loader/efi_load_initrd.c
+++ b/lib/efi_loader/efi_load_initrd.c
@@ -5,7 +5,9 @@
 
 #include <common.h>
 #include <efi_loader.h>
+#include <efi_helper.h>
 #include <efi_load_initrd.h>
+#include <efi_variable.h>
 #include <fs.h>
 #include <malloc.h>
 #include <mapmem.h>
@@ -39,41 +41,71 @@ static const struct efi_initrd_dp dp = {
 	}
 };
 
+static efi_handle_t efi_initrd_handle;
+
 /**
- * get_file_size() - retrieve the size of initramfs, set efi status on error
+ * get_initrd_fp() - Get initrd device path from a FilePathList device path
  *
- * @dev:			device to read from, e.g. "mmc"
- * @part:			device partition, e.g. "0:1"
- * @file:			name of file
- * @status:			EFI exit code in case of failure
+ * @initrd_fp:			the final initrd filepath
  *
- * Return:			size of file
+ * Return:			status code
  */
-static loff_t get_file_size(const char *dev, const char *part, const char *file,
-			    efi_status_t *status)
+static efi_status_t get_initrd_fp(struct efi_device_path **initrd_fp)
 {
-	loff_t sz = 0;
-	int ret;
+	const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID;
+	struct efi_device_path *cur = NULL;
+	struct efi_device_path *dp = NULL;
+	struct efi_device_path *tmp_dp;
+	efi_uintn_t ret;
+	efi_uintn_t size;
 
-	ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
-	if (ret) {
-		*status = EFI_NO_MEDIA;
+	/*
+	 * if bootmgr is setup with and initrd, the device path will be
+	 * in the FilePathList[] of our load options in Boot####.
+	 * The first device path of the multi instance device path will
+	 * start with a VenMedia and the initrds will follow.
+	 *
+	 * If the device path is not found return EFI_INVALID_PARAMETER.
+	 * We can then use this specific return value and not install the
+	 * protocol, while allowing the boot to continue
+	 */
+	dp = efi_get_dp_from_boot(lf2_initrd_guid);
+	if (!dp) {
+		ret = EFI_INVALID_PARAMETER;
 		goto out;
 	}
 
-	ret = fs_size(file, &sz);
-	if (ret) {
-		sz = 0;
-		*status = EFI_NOT_FOUND;
+	tmp_dp = dp;
+	cur = efi_dp_get_next_instance(&tmp_dp, &size);
+	if (!cur) {
+		ret = EFI_OUT_OF_RESOURCES;
 		goto out;
 	}
 
+	/*
+	 * We don't care if the file path is eventually NULL here. The
+	 * callers will try to load a file from it and eventually fail
+	 * but let's be explicit with our return values
+	 */
+	if (!tmp_dp) {
+		*initrd_fp = NULL;
+		ret = EFI_NOT_FOUND;
+	} else {
+		*initrd_fp = efi_dp_dup(tmp_dp);
+		if (*initrd_fp)
+			ret = EFI_SUCCESS;
+		else
+			ret = EFI_OUT_OF_RESOURCES;
+	}
+
 out:
-	return sz;
+	efi_free_pool(cur);
+	efi_free_pool(dp);
+	return ret;
 }
 
 /**
- * efi_load_file2initrd() - load initial RAM disk
+ * efi_load_file2_initrd() - load initial RAM disk
  *
  * This function implements the LoadFile service of the EFI_LOAD_FILE2_PROTOCOL
  * in order to load an initial RAM disk requested by the Linux kernel stub.
@@ -93,98 +125,131 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this,
 		      struct efi_device_path *file_path, bool boot_policy,
 		      efi_uintn_t *buffer_size, void *buffer)
 {
-	char *filespec;
-	efi_status_t status = EFI_NOT_FOUND;
-	loff_t file_sz = 0, read_sz = 0;
-	char *dev, *part, *file;
-	char *pos;
-	int ret;
+	struct efi_device_path *initrd_fp = NULL;
+	struct efi_file_info *info = NULL;
+	efi_status_t ret = EFI_NOT_FOUND;
+	struct efi_file_handle *f;
+	efi_uintn_t bs;
 
 	EFI_ENTRY("%p, %p, %d, %p, %p", this, file_path, boot_policy,
 		  buffer_size, buffer);
 
-	filespec = strdup(CONFIG_EFI_INITRD_FILESPEC);
-	if (!filespec)
-		goto out;
-	pos = filespec;
-
 	if (!this || this != &efi_lf2_protocol ||
 	    !buffer_size) {
-		status = EFI_INVALID_PARAMETER;
+		ret = EFI_INVALID_PARAMETER;
 		goto out;
 	}
 
 	if (file_path->type != dp.end.type ||
 	    file_path->sub_type != dp.end.sub_type) {
-		status = EFI_INVALID_PARAMETER;
+		ret = EFI_INVALID_PARAMETER;
 		goto out;
 	}
 
 	if (boot_policy) {
-		status = EFI_UNSUPPORTED;
+		ret = EFI_UNSUPPORTED;
 		goto out;
 	}
 
-	/*
-	 * expect a string with three space separated parts:
-	 *
-	 * * a block device type, e.g. "mmc"
-	 * * a device and partition identifier, e.g. "0:1"
-	 * * a file path on the block device, e.g. "/boot/initrd.cpio.gz"
-	 */
-	dev = strsep(&pos, " ");
-	if (!dev)
+	ret = get_initrd_fp(&initrd_fp);
+	if (ret != EFI_SUCCESS)
 		goto out;
-	part = strsep(&pos, " ");
-	if (!part)
+
+	/* Open file */
+	f = efi_file_from_path(initrd_fp);
+	if (!f) {
+		ret = EFI_NOT_FOUND;
 		goto out;
-	file = strsep(&pos, " ");
-	if (!file)
+	}
+
+	/* Get file size */
+	bs = 0;
+	EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
+				  &bs, info));
+	if (ret != EFI_BUFFER_TOO_SMALL) {
+		ret = EFI_DEVICE_ERROR;
 		goto out;
+	}
 
-	file_sz = get_file_size(dev, part, file, &status);
-	if (!file_sz)
+	info = malloc(bs);
+	EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid, &bs,
+				  info));
+	if (ret != EFI_SUCCESS)
 		goto out;
 
-	if (!buffer || *buffer_size < file_sz) {
-		status = EFI_BUFFER_TOO_SMALL;
-		*buffer_size = file_sz;
+	bs = info->file_size;
+	if (!buffer || *buffer_size < bs) {
+		ret = EFI_BUFFER_TOO_SMALL;
+		*buffer_size = bs;
 	} else {
-		ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
-		if (ret) {
-			status = EFI_NO_MEDIA;
-			goto out;
-		}
-
-		ret = fs_read(file, map_to_sysmem(buffer), 0, *buffer_size,
-			      &read_sz);
-		if (ret || read_sz != file_sz)
-			goto out;
-		*buffer_size = read_sz;
-
-		status = EFI_SUCCESS;
+		EFI_CALL(ret = f->read(f, &bs, (void *)(uintptr_t)buffer));
+		*buffer_size = bs;
 	}
 
 out:
-	free(filespec);
-	return EFI_EXIT(status);
+	free(info);
+	efi_free_pool(initrd_fp);
+	EFI_CALL(f->close(f));
+	return EFI_EXIT(ret);
+}
+
+/**
+ * check_initrd() - Determine if the file defined as an initrd in Boot####
+ *		    load_options device path is present
+ *
+ * Return:	status code
+ */
+static efi_status_t check_initrd(void)
+{
+	struct efi_device_path *initrd_fp = NULL;
+	struct efi_file_handle *f;
+	efi_status_t ret;
+
+	ret = get_initrd_fp(&initrd_fp);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	/*
+	 * If the file is not found, but the file path is set, return an error
+	 * and trigger the bootmgr fallback
+	 */
+	f = efi_file_from_path(initrd_fp);
+	if (!f) {
+		ret = EFI_NOT_FOUND;
+		goto out;
+	}
+
+	EFI_CALL(f->close(f));
+
+out:
+	efi_free_pool(initrd_fp);
+	return ret;
 }
 
 /**
  * efi_initrd_register() - create handle for loading initial RAM disk
  *
  * This function creates a new handle and installs a Linux specific vendor
- * device path and an EFI_LOAD_FILE_2_PROTOCOL. Linux uses the device path
+ * device path and an EFI_LOAD_FILE2_PROTOCOL. Linux uses the device path
  * to identify the handle and then calls the LoadFile service of the
- * EFI_LOAD_FILE_2_PROTOCOL to read the initial RAM disk.
+ * EFI_LOAD_FILE2_PROTOCOL to read the initial RAM disk.
  *
  * Return:	status code
  */
 efi_status_t efi_initrd_register(void)
 {
-	efi_handle_t efi_initrd_handle = NULL;
 	efi_status_t ret;
 
+	/*
+	 * Allow the user to continue if Boot#### file path is not set for
+	 * an initrd
+	 */
+	ret = check_initrd();
+	if (ret == EFI_INVALID_PARAMETER)
+		return EFI_SUCCESS;
+	if (ret != EFI_SUCCESS)
+		return ret;
+
 	ret = EFI_CALL(efi_install_multiple_protocol_interfaces
 		       (&efi_initrd_handle,
 			/* initramfs */
@@ -196,3 +261,9 @@ efi_status_t efi_initrd_register(void)
 
 	return ret;
 }
+
+void efi_initrd_deregister(void)
+{
+	efi_delete_handle(efi_initrd_handle);
+	efi_initrd_handle = NULL;
+}
