===8<===
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 30ad2f085d1f..feda5cbdc6bf 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -214,13 +214,8 @@ static void __init request_standard_resources(void)
 
 	for_each_memblock(memory, region) {
 		res = alloc_bootmem_low(sizeof(*res));
-		if (memblock_is_nomap(region)) {
-			res->name  = "reserved";
-			res->flags = IORESOURCE_MEM;
-		} else {
-			res->name  = "System RAM";
-			res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
-		}
+		res->name  = "System RAM";
+		res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
 		res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
 		res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
 
@@ -239,6 +234,9 @@ static void __init request_standard_resources(void)
 			request_resource(res, &crashk_res);
 #endif
 	}
+
+	/* Add firmware-reserved memory */
+	efi_arch_request_resources();
 }
 
 u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 80d1a885def5..308143e69db4 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -13,8 +13,10 @@
 
 #define pr_fmt(fmt)	"efi: " fmt
 
+#include <linux/bootmem.h>
 #include <linux/efi.h>
 #include <linux/init.h>
+#include <linux/ioport.h>
 #include <linux/memblock.h>
 #include <linux/mm_types.h>
 #include <linux/of.h>
@@ -280,3 +282,97 @@ static int __init register_gop_device(void)
 	return PTR_ERR_OR_ZERO(pd);
 }
 subsys_initcall(register_gop_device);
+
+static unsigned long __init efi_memattr_to_iores_type(u64 addr)
+{
+	if (efi_mem_attributes(addr) &
+			(EFI_MEMORY_WB|EFI_MEMORY_WT|EFI_MEMORY_WC))
+		return IORESOURCE_SYSTEM_RAM;
+	else
+		return IORESOURCE_MEM;
+}
+
+static unsigned long __init efi_type_to_iores_desc(u64 addr)
+{
+	/* TODO */
+	return IORES_DESC_NONE;
+}
+
+static struct resource * __init _efi_arch_request_resource(u64 start, u64 end,
+					char *name, struct resource *prev)
+{
+	struct resource *conflict, *res;
+
+	res = alloc_bootmem_low(sizeof(*res));
+
+	res->start = start;
+	res->end = end;
+	res->flags = efi_memattr_to_iores_type(res->start);
+	res->desc = efi_type_to_iores_desc(res->start);
+	res->name = name;
+
+	conflict = request_resource_conflict(&iomem_resource, res);
+	if (conflict) {
+		if (prev && (prev->parent == conflict) &&
+				((prev->end + 1) == start)) {
+			/* merge consecutive regions */
+			adjust_resource(prev, prev->start,
+							end - prev->start + 1);
+			free_bootmem((unsigned long)res, sizeof(*res));
+			res = prev;
+		} else
+			insert_resource(conflict, res);
+	}
+
+	return res;
+}
+
+/* Kexec expects those resources to be preserved */
+void __init efi_arch_request_resources(void)
+{
+	struct resource *res = NULL;
+	efi_memory_desc_t *md;
+	u64 paddr, npages, size;
+
+	/* EFI Memory Map */
+	/* FIXME */
+	_efi_arch_request_resource(efi.memmap.phys_map,
+			efi.memmap.phys_map
+			+ efi.memmap.desc_size * efi.memmap.nr_map - 1,
+			"EFI Memory Map", res);
+
+	/* generic EFI Configuration Tables */
+	efi_request_config_table_resources(_efi_arch_request_resource);
+
+	/* architecture-specifc Configuration Tables */
+	if (screen_info.lfb_size)
+		_efi_arch_request_resource(screen_info.lfb_base,
+				screen_info.lfb_base + screen_info.lfb_size - 1,
+				"EFI Screen Info Table", res);
+
+	/* architecture-specific EFI resources */
+	/* FIXME */
+	efi_memmap_install(efi.memmap.phys_map, efi.memmap.nr_map);
+
+	res = NULL;
+	for_each_efi_memory_desc(md) {
+		paddr = md->phys_addr;
+		npages = md->num_pages;
+
+		memrange_efi_to_native(&paddr, &npages);
+		size = npages << PAGE_SHIFT;
+
+		if (is_memory(md)) {
+			if (!is_usable_memory(md))
+				res = _efi_arch_request_resource(paddr,
+						paddr + size - 1,
+						"EFI Resources", res);
+
+			if (md->type == EFI_ACPI_RECLAIM_MEMORY)
+				res = _efi_arch_request_resource(paddr,
+						paddr + size - 1,
+						"EFI Resources", res);
+		}
+	}
+	efi_memmap_unmap();
+}
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index cd42f66a7c85..b13c9461278b 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -603,6 +603,33 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
 	return ret;
 }
 
+void __init efi_request_config_table_resources(struct resource *(*fn)(u64 start,
+				u64 end, char *name, struct resource *prev))
+{
+	struct resource *prev = NULL;
+	char *name = "EFI Configuration Tables";
+
+	if (efi.config_table_size)
+		prev = fn(efi.config_table,
+			efi.config_table + efi.config_table_size - 1, name,
+									prev);
+
+	if (efi.mem_attr_table_size)
+		prev = fn(efi.mem_attr_table,
+			efi.mem_attr_table + efi.mem_attr_table_size - 1, name,
+									prev);
+
+	if (efi.esrt_size)
+		prev = fn(efi.esrt, efi.esrt + efi.esrt_size - 1, name, prev);
+
+	if (efi.tpm_log_size)
+		prev = fn(efi.tpm_log, efi.tpm_log + efi.tpm_log_size - 1, name,
+									prev);
+
+
+	/* TODO: BGRT */
+}
+
 #ifdef CONFIG_EFI_VARS_MODULE
 static int __init efi_load_efivars(void)
 {
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index c47e0c6ec00f..61f66c139afb 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -330,6 +330,7 @@ void __init efi_esrt_init(void)
 
 	esrt_data = (phys_addr_t)efi.esrt;
 	esrt_data_size = size;
+	efi.esrt_size = size;
 
 	end = esrt_data + size;
 	pr_info("Reserving ESRT space from %pa to %pa.\n", &esrt_data, &end);
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c
index 8986757eafaf..dc2c7608793a 100644
--- a/drivers/firmware/efi/memattr.c
+++ b/drivers/firmware/efi/memattr.c
@@ -42,6 +42,7 @@ int __init efi_memattr_init(void)
 	}
 
 	tbl_size = sizeof(*tbl) + tbl->num_entries * tbl->desc_size;
+	efi.mem_attr_table_size = tbl_size;
 	memblock_reserve(efi.mem_attr_table, tbl_size);
 	set_bit(EFI_MEM_ATTR, &efi.flags);
 
diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c
index 0cbeb3d46b18..53cfb12513fa 100644
--- a/drivers/firmware/efi/tpm.c
+++ b/drivers/firmware/efi/tpm.c
@@ -33,6 +33,7 @@ int __init efi_tpm_eventlog_init(void)
 	}
 
 	tbl_size = sizeof(*log_tbl) + log_tbl->size;
+	efi.tpm_log_size = tbl_size;
 	memblock_reserve(efi.tpm_log, tbl_size);
 	early_memunmap(log_tbl, sizeof(*log_tbl));
 	return 0;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index f5083aa72eae..9c3f8d284b36 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -942,11 +942,15 @@ extern struct efi {
 	unsigned long fw_vendor;	/* fw_vendor */
 	unsigned long runtime;		/* runtime table */
 	unsigned long config_table;	/* config tables */
+	unsigned long config_table_size;
 	unsigned long esrt;		/* ESRT table */
+	unsigned long esrt_size;
 	unsigned long properties_table;	/* properties table */
 	unsigned long mem_attr_table;	/* memory attributes table */
+	unsigned long mem_attr_table_size;
 	unsigned long rng_seed;		/* UEFI firmware random seed */
 	unsigned long tpm_log;		/* TPM2 Event Log table */
+	unsigned long tpm_log_size;
 	efi_get_time_t *get_time;
 	efi_set_time_t *set_time;
 	efi_get_wakeup_time_t *get_wakeup_time;
@@ -980,6 +984,9 @@ efi_guid_to_str(efi_guid_t *guid, char *out)
 }
 
 extern void efi_init (void);
+extern void efi_arch_request_resources(void);
+extern void efi_request_config_table_resources(struct resource *
+		(*fn)(u64 start, u64 end, char *name, struct resource *prev));
 extern void *efi_get_pal_addr (void);
 extern void efi_map_pal_code (void);
 extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
