feat(qemu): support s-el2 spmc

Supports S-EL2 SPMC + S-EL1 SP on qemu. S-EL1 SPs packaged in .pkg files
are added to the FIP as blob with an UUID. BL2 parses TB_FW_CONFIG to
know which SP blobs to load into memory.

Co-developed-by: Olivier Deprez <olivier.deprez@arm.com>
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Change-Id: I4b61c4c048f31540d4f1ef9e05f0b12deb341e06
diff --git a/plat/qemu/common/qemu_bl2_setup.c b/plat/qemu/common/qemu_bl2_setup.c
index 6afa3a4..be55877 100644
--- a/plat/qemu/common/qemu_bl2_setup.c
+++ b/plat/qemu/common/qemu_bl2_setup.c
@@ -16,6 +16,7 @@
 #include <common/debug.h>
 #include <common/desc_image_load.h>
 #include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
 #include <lib/optee_utils.h>
 #include <lib/utils.h>
 #include <plat/common/platform.h>
@@ -140,6 +141,48 @@
 	return spsr;
 }
 
+#if defined(SPD_spmd) && SPMD_SPM_AT_SEL2
+static int load_sps_from_tb_fw_config(struct image_info *image_info)
+{
+	void *dtb = (void *)image_info->image_base;
+	const char *compat_str = "arm,sp";
+	const struct fdt_property *uuid;
+	uint32_t load_addr;
+	const char *name;
+	int sp_node;
+	int node;
+
+	node = fdt_node_offset_by_compatible(dtb, -1, compat_str);
+	if (node < 0) {
+		ERROR("Can't find %s in TB_FW_CONFIG", compat_str);
+		return -1;
+	}
+
+	fdt_for_each_subnode(sp_node, dtb, node) {
+		name = fdt_get_name(dtb, sp_node, NULL);
+		if (name == NULL) {
+			ERROR("Can't get name of node in dtb\n");
+			return -1;
+		}
+		uuid = fdt_get_property(dtb, sp_node, "uuid", NULL);
+		if (uuid == NULL) {
+			ERROR("Can't find property uuid in node %s", name);
+			return -1;
+		}
+		if (fdt_read_uint32(dtb, sp_node, "load-address",
+				    &load_addr) < 0) {
+			ERROR("Can't read load-address in node %s", name);
+			return -1;
+		}
+		if (qemu_io_register_sp_pkg(name, uuid->data, load_addr) < 0) {
+			return -1;
+		}
+	}
+
+	return 0;
+}
+#endif /*defined(SPD_spmd) && SPMD_SPM_AT_SEL2*/
+
 static int qemu_bl2_handle_post_image_load(unsigned int image_id)
 {
 	int err = 0;
@@ -224,7 +267,12 @@
 
 		bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl33_entry();
 		break;
-#if defined(SPD_spmd)
+#ifdef SPD_spmd
+#if SPMD_SPM_AT_SEL2
+	case TB_FW_CONFIG_ID:
+		err = load_sps_from_tb_fw_config(&bl_mem_params->image_info);
+		break;
+#endif
 	case TOS_FW_CONFIG_ID:
 		/* An SPMC expects TOS_FW_CONFIG in x0/r0 */
 		bl32_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);