PSA FF-A: add partition manifest parsing

Add PSA FF-A partition manifest structure to VM manifest. Add FF-A
partition package structure (comprises header + image dtb + image
payload). Parse FF-A partition manifest DT if requested by the
is_ffa_partition DTS boolean.

This assumes Hafnium entry point is directly fed with the hypervisor
manifest pointer address (rather than the initrd image).

For a regular VM, the entry point is the start address of the VM
workspace allocated by Hafnium from the mem ranges provided in
hypervisor manifest. If the VM is an FF-A compliant partition,
the VM entry point is extrapolated from the FF-A partition manifest
(start of the workspace as SP header load address plus entry point
offset from partition DTS).

Change-Id: I6947646d0cd6eb3c4d97a31aa589244b365c8486
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Signed-off-by: Louis Mayencourt <louis.mayencourt@arm.com>
diff --git a/src/init.c b/src/init.c
index 5652897..ccf496e 100644
--- a/src/init.c
+++ b/src/init.c
@@ -106,24 +106,39 @@
 			  pa_addr(params.mem_ranges[i].end) - 1);
 	}
 
-	dlog_info("Ramdisk range: %#x - %#x\n", pa_addr(params.initrd_begin),
-		  pa_addr(params.initrd_end) - 1);
+	/*
+	 * Hafnium manifest is either gathered from the ramdisk or passed
+	 * directly to Hafnium entry point by the earlier bootloader stage.
+	 * If the ramdisk start address is non-zero it hints the manifest
+	 * shall be looked up from the ramdisk. If zero, assume the address
+	 * passed to Hafnium entry point is the manifest address.
+	 */
+	if (pa_addr(params.initrd_begin)) {
+		dlog_info("Ramdisk range: %#x - %#x\n",
+			  pa_addr(params.initrd_begin),
+			  pa_addr(params.initrd_end) - 1);
 
-	/* Map initrd in, and initialise cpio parser. */
-	initrd = mm_identity_map(mm_stage1_locked, params.initrd_begin,
-				 params.initrd_end, MM_MODE_R, &ppool);
-	if (!initrd) {
-		panic("Unable to map initrd.");
+		/* Map initrd in, and initialise cpio parser. */
+		initrd = mm_identity_map(mm_stage1_locked, params.initrd_begin,
+					 params.initrd_end, MM_MODE_R, &ppool);
+		if (!initrd) {
+			panic("Unable to map initrd.");
+		}
+
+		memiter_init(
+			&cpio, initrd,
+			pa_difference(params.initrd_begin, params.initrd_end));
+
+		if (!cpio_get_file(&cpio, &manifest_fname, &manifest_it)) {
+			panic("Could not find manifest in initrd.");
+		}
+	} else {
+		manifest_it = fdt.buf;
 	}
 
-	memiter_init(&cpio, initrd,
-		     pa_difference(params.initrd_begin, params.initrd_end));
+	manifest_ret = manifest_init(mm_stage1_locked, &manifest, &manifest_it,
+				     &ppool);
 
-	if (!cpio_get_file(&cpio, &manifest_fname, &manifest_it)) {
-		panic("Could not find manifest in initrd.");
-	}
-
-	manifest_ret = manifest_init(&manifest, &manifest_it);
 	if (manifest_ret != MANIFEST_SUCCESS) {
 		panic("Could not parse manifest: %s.",
 		      manifest_strerror(manifest_ret));