feat(versal2): parse reserve memory subnodes

In Versal Gen 2, TF-A parses the device tree to identify secure and
non-secure memory regions, which are then used to validate the
non-secure entry point address during a hot plug event

Change-Id: I8cdb098509bd3b06f0df5ea647220bdbb8a4bf35
Signed-off-by: Maheedhar Bollapalli <maheedharsai.bollapalli@amd.com>
diff --git a/plat/amd/common/plat_fdt.c b/plat/amd/common/plat_fdt.c
index 194d538..095527d 100644
--- a/plat/amd/common/plat_fdt.c
+++ b/plat/amd/common/plat_fdt.c
@@ -16,6 +16,9 @@
 
 #define FIT_CONFS_PATH	"/configurations"
 
+static struct reserve_mem_range rsvnodes[MAX_RESERVE_ADDR_INDICES] = {};
+static uint32_t rsv_count;
+
 static bool is_fit_image(void *dtb)
 {
 	int64_t confs_noffset = 0;
@@ -72,3 +75,64 @@
 
 	return (uintptr_t)dtb;
 }
+
+struct reserve_mem_range *get_reserved_entries_fdt(uint32_t *reserve_nodes)
+{
+	struct reserve_mem_range *rsvmr = NULL;
+
+	if ((rsv_count > 0) && (reserve_nodes != NULL)) {
+		rsvmr = &rsvnodes[0];
+		*reserve_nodes = rsv_count;
+	}
+
+	return rsvmr;
+}
+
+/* TODO: Parse TL overlays for updated tf-a and op-tee reserved nodes */
+uint32_t retrieve_reserved_entries(void)
+{
+	uint32_t ret = 1;
+	void *dtb = NULL;
+	int offset, node;
+	uint32_t i = 0;
+	const fdt32_t *reg_prop;
+
+
+	/* Get DT blob address */
+	dtb = (void *)plat_retrieve_dt_addr();
+
+	/* Check if DT is valid */
+	if (is_valid_dtb(dtb) >= 0) {
+		/* Find reserved memory node */
+		offset = fdt_path_offset(dtb, "/reserved-memory");
+		if (offset >= 0) {
+
+			/* Parse subnodes of reserved-memory */
+			fdt_for_each_subnode(node, dtb, offset) {
+				if (fdt_getprop(dtb, node, "no-map", NULL) == NULL) {
+					continue;
+				}
+
+				if (rsv_count == MAX_RESERVE_ADDR_INDICES) {
+					break;
+				}
+
+				reg_prop = fdt_getprop(dtb, node, "reg", NULL);
+				if (reg_prop == NULL) {
+					INFO("No valid reg prop found for subnode\n");
+					continue;
+				}
+
+				rsvnodes[i].base = (((uint64_t)fdt32_to_cpu(reg_prop[0]) << 32) |
+						fdt32_to_cpu(reg_prop[1]));
+				rsvnodes[i].size = (((uint64_t)fdt32_to_cpu(reg_prop[2]) << 32) |
+						fdt32_to_cpu(reg_prop[3]));
+				i++;
+			}
+			ret = 0;
+			rsv_count = i;
+		}
+	}
+
+	return ret;
+}
diff --git a/plat/amd/versal2/bl31_setup.c b/plat/amd/versal2/bl31_setup.c
index 28bcaa1..0726c26 100644
--- a/plat/amd/versal2/bl31_setup.c
+++ b/plat/amd/versal2/bl31_setup.c
@@ -261,6 +261,7 @@
 {
 	uint32_t flags = 0;
 	int32_t rc;
+	uint32_t rre_ret = 0;
 
 	set_interrupt_rm_flag(flags, NON_SECURE);
 	rc = register_interrupt_type_handler(INTR_TYPE_EL3,
@@ -269,6 +270,13 @@
 		panic();
 	}
 
+	/* Instead of calling for each time fill in structure early. */
+	rre_ret = retrieve_reserved_entries();
+
+	if (rre_ret != 0) {
+		INFO("Runtime FDT reserve node retreival failed");
+	}
+
 	console_switch_state(CONSOLE_FLAG_RUNTIME);
 }
 
diff --git a/plat/xilinx/common/include/plat_fdt.h b/plat/xilinx/common/include/plat_fdt.h
index 48ffff3..0c2b1df 100644
--- a/plat/xilinx/common/include/plat_fdt.h
+++ b/plat/xilinx/common/include/plat_fdt.h
@@ -11,4 +11,29 @@
 uintptr_t plat_retrieve_dt_addr(void);
 int32_t is_valid_dtb(void *fdt);
 
+#define MAX_RESERVE_ADDR_INDICES 32
+struct reserve_mem_range {
+	uintptr_t base;
+	size_t size;
+};
+
+#if (TRANSFER_LIST == 1)
+uint32_t retrieve_reserved_entries(void);
+struct reserve_mem_range *get_reserved_entries_fdt(uint32_t *reserve_nodes);
+#else
+static inline uint32_t retrieve_reserved_entries(void)
+{
+	return 0;
+}
+
+static inline struct reserve_mem_range *get_reserved_entries_fdt(uint32_t *reserve_nodes)
+{
+	if (reserve_nodes) {
+		*reserve_nodes = 0;
+	}
+
+	return NULL;
+}
+#endif
+
 #endif /* PLAT_FDT_H */