Add FF-A v1.1 boot protocol

Implement parsing of the FF-A v1.1 boot protocol. The patch is backwards
compatible since the used boot protocol version can be identified by the
signature field.

Signed-off-by: Balint Dobszay <balint.dobszay@arm.com>
Change-Id: I831d69aadd6bf40f9931bf695e173f1870bf8900
diff --git a/components/config/loader/sp/sp_config_loader.c b/components/config/loader/sp/sp_config_loader.c
index 6aaff4b..5c7c552 100644
--- a/components/config/loader/sp/sp_config_loader.c
+++ b/components/config/loader/sp/sp_config_loader.c
@@ -295,6 +295,55 @@
 	return true;
 }
 
+static bool sp_config_load_v1_1(struct ffa_boot_info_header_v1_1 *boot_info_header)
+{
+	size_t desc_end = 0;
+	size_t total_desc_size = 0;
+	struct ffa_boot_info_desc_v1_1 *boot_info_desc = NULL;
+	uint32_t expected_version = SHIFT_U32(1, FFA_VERSION_MAJOR_SHIFT) |
+				    SHIFT_U32(1, FFA_VERSION_MINOR_SHIFT);
+
+	if (boot_info_header->version != expected_version) {
+		EMSG("Invalid FF-A boot info version");
+		return false;
+	}
+
+	if (boot_info_header->desc_size != sizeof(struct ffa_boot_info_desc_v1_1)) {
+		EMSG("Boot info descriptor size mismatch");
+		return false;
+	}
+
+	if (MUL_OVERFLOW(boot_info_header->desc_size, boot_info_header->desc_cnt,
+			 &total_desc_size)) {
+		EMSG("Boot info descriptor overflow");
+		return false;
+	}
+
+	if (ADD_OVERFLOW(boot_info_header->desc_offs, total_desc_size, &desc_end) ||
+	    boot_info_header->size < desc_end) {
+		EMSG("Boot info descriptor overflow");
+		return false;
+	}
+
+	boot_info_desc = (struct ffa_boot_info_desc_v1_1 *)((uintptr_t)boot_info_header +
+							    boot_info_header->desc_offs);
+
+	for (unsigned int i = 0; i < boot_info_header->desc_cnt; i++) {
+		uint16_t flags = FFA_BOOT_INFO_CONTENT_FMT_ADDR << FFA_BOOT_INFO_CONTENT_FMT_SHIFT;
+		uint16_t type = FFA_BOOT_INFO_TYPE_STD << FFA_BOOT_INFO_TYPE_SHIFT |
+				FFA_BOOT_INFO_ID_STD_FDT << FFA_BOOT_INFO_ID_SHIFT;
+
+		if (boot_info_desc[i].flags == flags && boot_info_desc[i].type == type) {
+			if (!load_fdt((void *)boot_info_desc->contents, boot_info_desc->size)) {
+				EMSG("Failed to load SP config FDT");
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
 bool sp_config_load(union ffa_boot_info *boot_info)
 {
 	if (!boot_info)
@@ -303,6 +352,9 @@
 	switch (boot_info->signature) {
 	case FFA_BOOT_INFO_SIGNATURE_V1_0:
 		return sp_config_load_v1_0((struct ffa_boot_info_v1_0 *)&boot_info->boot_info_v1_0);
+	case FFA_BOOT_INFO_SIGNATURE_V1_1:
+		return sp_config_load_v1_1((struct ffa_boot_info_header_v1_1 *)
+					   &boot_info->boot_info_v1_1);
 	default:
 		EMSG("Invalid FF-A boot info signature");
 		return false;