qemu/qemu_sbsa: enable secure variable storage

This implements support for UEFI secure variable storage
using standalone MM framework on qemu_sbsa platform.

Non-secure shared memory between UEFI and standalone MM
is allocated at the top of DRAM.
DRAM size of qemu_sbsa varies depends on the QEMU parameter,
so the non-secure shared memory is allocated by trusted firmware
and passed the base address and size to UEFI through device tree
"/reserved-memory" node.

Change-Id: I367191f408eb9850b7ec7761ee346b014c539767
Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
diff --git a/plat/qemu/common/qemu_common.c b/plat/qemu/common/qemu_common.c
index 7f8e4c4..7d2730d 100644
--- a/plat/qemu/common/qemu_common.c
+++ b/plat/qemu/common/qemu_common.c
@@ -94,6 +94,7 @@
 	MAP_DEVICE1,
 #endif
 #if SPM_MM
+	MAP_NS_DRAM0,
 	QEMU_SPM_BUF_EL3_MMAP,
 #else
 	MAP_BL32_MEM,
diff --git a/plat/qemu/common/qemu_spm.c b/plat/qemu/common/qemu_spm.c
index e9ab1a5..93dd2b3 100644
--- a/plat/qemu/common/qemu_spm.c
+++ b/plat/qemu/common/qemu_spm.c
@@ -3,7 +3,12 @@
  * Copyright (c) 2020, Linaro Limited and Contributors. All rights reserved.
  */
 
+#include <libfdt.h>
+
 #include <bl31/ehf.h>
+#include <common/debug.h>
+#include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <services/spm_mm_partition.h>
 
@@ -14,12 +19,13 @@
 					DEVICE1_SIZE,			\
 					MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
 
-const mmap_region_t plat_qemu_secure_partition_mmap[] = {
-	MAP_DEVICE1_EL0, /* for the UART */
+mmap_region_t plat_qemu_secure_partition_mmap[] = {
+	QEMU_SP_IMAGE_NS_BUF_MMAP,	/* must be placed at first entry */
+	MAP_DEVICE1_EL0,		/* for the UART */
 	QEMU_SP_IMAGE_MMAP,
 	QEMU_SPM_BUF_EL0_MMAP,
-	QEMU_SP_IMAGE_NS_BUF_MMAP,
 	QEMU_SP_IMAGE_RW_MMAP,
+	MAP_SECURE_VARSTORE,
 	{0}
 };
 
@@ -38,7 +44,7 @@
 	[7] = {0x80000007, 0}
 };
 
-const spm_mm_boot_info_t plat_qemu_secure_partition_boot_info = {
+spm_mm_boot_info_t plat_qemu_secure_partition_boot_info = {
 	.h.type              = PARAM_SP_IMAGE_BOOT_INFO,
 	.h.version           = VERSION_1,
 	.h.size              = sizeof(spm_mm_boot_info_t),
@@ -65,12 +71,63 @@
 	EHF_PRI_DESC(QEMU_PRI_BITS, PLAT_SP_PRI)
 };
 
+int dt_add_ns_buf_node(uintptr_t *base)
+{
+	uintptr_t addr;
+	size_t size;
+	uintptr_t ns_buf_addr;
+	int node;
+	int err;
+	void *fdt = (void *)ARM_PRELOADED_DTB_BASE;
+
+	err = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE);
+	if (err < 0) {
+		ERROR("Invalid Device Tree at %p: error %d\n", fdt, err);
+		return err;
+	}
+
+	/*
+	 * reserved-memory for standaloneMM non-secure buffer
+	 * is allocated at the top of the first system memory region.
+	 */
+	node = fdt_path_offset(fdt, "/memory");
+
+	err = fdt_get_reg_props_by_index(fdt, node, 0, &addr, &size);
+	if (err < 0) {
+		ERROR("Failed to get the memory node information\n");
+		return err;
+	}
+	INFO("System RAM @ 0x%lx - 0x%lx\n", addr, addr + size - 1);
+
+	ns_buf_addr = addr + (size - PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE);
+	INFO("reserved-memory for spm-mm @ 0x%lx - 0x%llx\n", ns_buf_addr,
+	     ns_buf_addr + PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE - 1);
+
+	err = fdt_add_reserved_memory(fdt, "ns-buf-spm-mm", ns_buf_addr,
+				      PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE);
+	if (err < 0) {
+		ERROR("Failed to add the reserved-memory node\n");
+		return err;
+	}
+
+	*base = ns_buf_addr;
+	return 0;
+}
+
 /* Plug in QEMU exceptions to Exception Handling Framework. */
 EHF_REGISTER_PRIORITIES(qemu_exceptions, ARRAY_SIZE(qemu_exceptions),
 			QEMU_PRI_BITS);
 
 const mmap_region_t *plat_get_secure_partition_mmap(void *cookie)
 {
+	uintptr_t ns_buf_base;
+
+	dt_add_ns_buf_node(&ns_buf_base);
+
+	plat_qemu_secure_partition_mmap[0].base_pa = ns_buf_base;
+	plat_qemu_secure_partition_mmap[0].base_va = ns_buf_base;
+	plat_qemu_secure_partition_boot_info.sp_ns_comm_buf_base = ns_buf_base;
+
 	return plat_qemu_secure_partition_mmap;
 }
 
diff --git a/plat/qemu/qemu_sbsa/include/platform_def.h b/plat/qemu/qemu_sbsa/include/platform_def.h
index 75851e3..db394c0 100644
--- a/plat/qemu/qemu_sbsa/include/platform_def.h
+++ b/plat/qemu/qemu_sbsa/include/platform_def.h
@@ -300,10 +300,13 @@
 /*
  * Shared memory between Normal world and S-EL0 for
  * passing data during service requests. It will be marked as RW and NS.
+ * This buffer is allocated at the top of NS_DRAM, the base address is
+ * overridden in SPM initialization.
  */
 #define PLAT_QEMU_SP_IMAGE_NS_BUF_BASE	(PLAT_QEMU_DT_BASE +		\
 						PLAT_QEMU_DT_MAX_SIZE)
-#define PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE	ULL(0x10000)
+#define PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE	ULL(0x200000)
+
 #define QEMU_SP_IMAGE_NS_BUF_MMAP	MAP_REGION2( \
 					PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \
 					PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \
@@ -334,6 +337,19 @@
 					MT_USER, \
 					PAGE_SIZE)
 
+/*
+ * Secure variable storage is located at Secure Flash.
+ */
+#if SPM_MM
+#define QEMU_SECURE_VARSTORE_BASE 0x01000000
+#define QEMU_SECURE_VARSTORE_SIZE 0x00100000
+#define MAP_SECURE_VARSTORE		MAP_REGION_FLAT( \
+					QEMU_SECURE_VARSTORE_BASE, \
+					QEMU_SECURE_VARSTORE_SIZE, \
+					MT_MEMORY | MT_RW | \
+					MT_SECURE | MT_USER)
+#endif
+
 /* Total number of memory regions with distinct properties */
 #define PLAT_QEMU_SP_IMAGE_NUM_MEM_REGIONS	6
 
diff --git a/plat/qemu/qemu_sbsa/platform.mk b/plat/qemu/qemu_sbsa/platform.mk
index acaa43f..98d1347 100644
--- a/plat/qemu/qemu_sbsa/platform.mk
+++ b/plat/qemu/qemu_sbsa/platform.mk
@@ -83,6 +83,8 @@
 				${PLAT_QEMU_COMMON_PATH}/topology.c		\
 				${PLAT_QEMU_COMMON_PATH}/aarch64/plat_helpers.S	\
 				${PLAT_QEMU_COMMON_PATH}/qemu_bl31_setup.c	\
+				common/fdt_fixup.c				\
+				common/fdt_wrappers.c				\
 				${QEMU_GIC_SOURCES}
 ifeq (${SPM_MM},1)
 	BL31_SOURCES		+=	${PLAT_QEMU_COMMON_PATH}/qemu_spm.c