diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index 576e95b395dc..f450518c9e83 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -264,6 +264,10 @@ static const struct {
 		"SMBIOS table",
 		SMBIOS_TABLE_GUID,
 	},
+	{
+		"Load File2",
+		EFI_LOAD_FILE2_PROTOCOL_GUID,
+	},
 };
 
 /**
diff --git a/include/efi_api.h b/include/efi_api.h
index 22396172e15f..8ffed1334b84 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -319,6 +319,14 @@ struct efi_runtime_services {
 	EFI_GUID(0xeb9d2d31, 0x2d88, 0x11d3,  \
 		 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
 
+#define EFI_LOAD_FILE_PROTOCOL_GUID \
+	EFI_GUID(0x56ec3091, 0x954c, 0x11d2, \
+		 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_LOAD_FILE2_PROTOCOL_GUID \
+	EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e, \
+		 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d)
+
 struct efi_configuration_table {
 	efi_guid_t guid;
 	void *table;
@@ -474,6 +482,7 @@ struct efi_device_path_nvme {
 #define DEVICE_PATH_TYPE_MEDIA_DEVICE		0x04
 #  define DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH	0x01
 #  define DEVICE_PATH_SUB_TYPE_CDROM_PATH	0x02
+#  define DEVICE_PATH_SUB_TYPE_VENDOR_PATH	0x03
 #  define DEVICE_PATH_SUB_TYPE_FILE_PATH	0x04
 
 struct efi_device_path_hard_drive_path {
@@ -1607,6 +1616,14 @@ struct efi_unicode_collation_protocol {
 	char *supported_languages;
 };
 
+struct efi_load_file_protocol {
+	efi_status_t (EFIAPI *load_file)(struct efi_load_file_protocol *this,
+					 struct efi_device_path *file_path,
+					 bool boot_policy,
+					 efi_uintn_t *buffer_size,
+					 void *buffer);
+};
+
 /* Boot manager load options */
 #define LOAD_OPTION_ACTIVE		0x00000001
 #define LOAD_OPTION_FORCE_RECONNECT	0x00000002
diff --git a/include/efi_load_initrd.h b/include/efi_load_initrd.h
new file mode 100644
index 000000000000..478ae807c685
--- /dev/null
+++ b/include/efi_load_initrd.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2020, Linaro Limited
+ */
+
+#if !defined _EFI_LOAD_INITRD_H_
+#define _EFI_LOAD_INITRD_H_
+
+#include <efi.h>
+#include <efi_api.h>
+
+/*
+ * Vendor GUID used by Linux to identify the handle with the
+ * EFI_LOAD_FILE2_PROTOCOL and load an initial ramdisk.
+ */
+#define EFI_INITRD_MEDIA_GUID \
+	EFI_GUID(0x5568e427, 0x68fc, 0x4f3d, \
+		 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68)
+
+struct efi_initrd_dp {
+	struct efi_device_path_vendor vendor;
+	struct efi_device_path end;
+} __packed;
+
+#endif
diff --git a/include/efi_loader.h b/include/efi_loader.h
index d4c59b54c48b..8e3437983391 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -378,6 +378,7 @@ efi_status_t efi_gop_register(void);
 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);
 /* 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 a7afa3f29e88..50d4f81e6207 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -130,4 +130,19 @@ config EFI_RNG_PROTOCOL
 	  "Support for EFI_RNG_PROTOCOL implementation. Uses the rng
 	   device on the platform"
 
+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.
+
 endif
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 04dc8648512b..9b3b70447336 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -43,3 +43,4 @@ obj-$(CONFIG_NET) += efi_net.o
 obj-$(CONFIG_GENERATE_ACPI_TABLE) += efi_acpi.o
 obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o
 obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o
+obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_load_initrd.o
diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c
new file mode 100644
index 000000000000..574a83d7e308
--- /dev/null
+++ b/lib/efi_loader/efi_load_initrd.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020, Linaro Limited
+ */
+
+#include <common.h>
+#include <env.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <dm.h>
+#include <fs.h>
+#include <efi_loader.h>
+#include <efi_load_initrd.h>
+
+static const efi_guid_t efi_guid_load_file2_protocol =
+		EFI_LOAD_FILE2_PROTOCOL_GUID;
+
+static efi_status_t EFIAPI
+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);
+
+static const struct efi_load_file_protocol efi_lf2_protocol = {
+	.load_file = efi_load_file2_initrd,
+};
+
+/*
+ * Device path defined by Linux to identify the handle providing the
+ * EFI_LOAD_FILE2_PROTOCOL used for loading the initial ramdisk.
+ */
+static const struct efi_initrd_dp dp = {
+	.vendor = {
+		{
+		   DEVICE_PATH_TYPE_MEDIA_DEVICE,
+		   DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
+		   sizeof(dp.vendor),
+		},
+		EFI_INITRD_MEDIA_GUID,
+	},
+	.end = {
+		DEVICE_PATH_TYPE_END,
+		DEVICE_PATH_SUB_TYPE_END,
+		sizeof(dp.end),
+	}
+};
+
+/**
+ * get_file_size() - retrieve the size of initramfs, set efi status on error
+ *
+ * @dev:			device to read from. i.e "mmc"
+ * @part:			device partition. i.e "0:1"
+ * @file:			name fo file
+ * @status:			EFI exit code in case of failure
+ *
+ * Return:			size of file
+ */
+static loff_t get_file_size(const char *dev, const char *part, const char *file,
+			    efi_status_t *status)
+{
+	loff_t sz = 0;
+	int ret;
+
+	ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY);
+	if (ret) {
+		*status = EFI_NO_MEDIA;
+		goto out;
+	}
+
+	ret = fs_size(file, &sz);
+	if (ret) {
+		sz = 0;
+		*status = EFI_NOT_FOUND;
+		goto out;
+	}
+
+out:
+	return sz;
+}
+
+/**
+ * load_file2() - get information about random number generation
+ *
+ * This function implement the LoadFile2() service in order to load an initram
+ * disk requested by the Linux kernel stub.
+ * See the UEFI spec for details.
+ *
+ * @this:			loadfile2 protocol instance
+ * @file_path:			relative path of the file. "" in this case
+ * @boot_policy:		must be false for Loadfile2
+ * @buffer_size:		size of allocated buffer
+ * @buffer:			buffer to load the file
+ *
+ * Return:			status code
+ */
+static efi_status_t EFIAPI
+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)
+{
+	const char *filespec = CONFIG_EFI_INITRD_FILESPEC;
+	efi_status_t status = EFI_NOT_FOUND;
+	loff_t file_sz = 0, read_sz = 0;
+	char *dev, *part, *file;
+	char *s;
+	int ret;
+
+	EFI_ENTRY("%p, %p, %d, %p, %p", this, file_path, boot_policy,
+		  buffer_size, buffer);
+
+	s = strdup(filespec);
+	if (!s)
+		goto out;
+
+	if (!this || this != &efi_lf2_protocol ||
+	    !buffer_size) {
+		status = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	if (file_path->type != dp.end.type ||
+	    file_path->sub_type != dp.end.sub_type) {
+		status = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	if (boot_policy) {
+		status = EFI_UNSUPPORTED;
+		goto out;
+	}
+
+	/* expect something like 'mmc 0:1 initrd.cpio.gz' */
+	dev = strsep(&s, " ");
+	if (!dev)
+		goto out;
+	part = strsep(&s, " ");
+	if (!part)
+		goto out;
+	file = strsep(&s, " ");
+	if (!file)
+		goto out;
+
+	file_sz = get_file_size(dev, part, file, &status);
+	if (!file_sz)
+		goto out;
+
+	if (!buffer || *buffer_size < file_sz) {
+		status = EFI_BUFFER_TOO_SMALL;
+		*buffer_size = file_sz;
+	} 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;
+	}
+
+out:
+	free(s);
+	return EFI_EXIT(status);
+}
+
+/**
+ * efi_initrd_register() - Register a handle and loadfile2 protocol
+ *
+ * This function creates a new handle and installs a linux specific GUID
+ * to handle initram disk loading during boot.
+ * See the UEFI spec for details.
+ *
+ * Return:			status code
+ */
+efi_status_t efi_initrd_register(void)
+{
+	efi_handle_t efi_initrd_handle = NULL;
+	efi_status_t ret;
+
+	/*
+	 * Set up the handle with the EFI_LOAD_FILE2_PROTOCOL which Linux may
+	 * use to load the initial ramdisk.
+	 */
+	ret = EFI_CALL(efi_install_multiple_protocol_interfaces
+		       (&efi_initrd_handle,
+			/* initramfs */
+			&efi_guid_device_path, &dp,
+			/* LOAD_FILE2 */
+			&efi_guid_load_file2_protocol,
+			(void *)&efi_lf2_protocol,
+			NULL));
+
+	return ret;
+}
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index de7b616c6daa..f03685b11559 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -155,6 +155,11 @@ efi_status_t efi_init_obj_list(void)
 	if (ret != EFI_SUCCESS)
 		goto out;
 #endif
+#ifdef CONFIG_EFI_LOAD_FILE2_INITRD
+	ret = efi_initrd_register();
+	if (ret != EFI_SUCCESS)
+		goto out;
+#endif
 #ifdef CONFIG_NET
 	ret = efi_net_register();
 	if (ret != EFI_SUCCESS)
