spl: Plumb in the Universal Payload handoff

Specify the FIT and include information about each loaded image, as
required by the UPL handoff.

Write the UPL handoff into the bloblist before jumping to the next phase.

Control this using a runtime flag to avoid conflicting with other
handoff mechanisms.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/boot/image-fit.c b/boot/image-fit.c
index 9253f81..7d56f0b 100644
--- a/boot/image-fit.c
+++ b/boot/image-fit.c
@@ -36,6 +36,7 @@
 #include <bootm.h>
 #include <image.h>
 #include <bootstage.h>
+#include <upl.h>
 #include <u-boot/crc.h>
 
 /*****************************************************************************/
@@ -2294,6 +2295,8 @@
 
 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD);
 
+	upl_add_image(fit, noffset, load, len);
+
 	*datap = load;
 	*lenp = len;
 	if (fit_unamep)
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 7794ddc..d6a364d 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -810,6 +810,14 @@
 			printf(SPL_TPL_PROMPT
 			       "SPL hand-off write failed (err=%d)\n", ret);
 	}
+	if (CONFIG_IS_ENABLED(UPL_OUT) && (gd->flags & GD_FLG_UPL)) {
+		ret = spl_write_upl_handoff(&spl_image);
+		if (ret) {
+			printf(SPL_TPL_PROMPT
+			       "UPL hand-off write failed (err=%d)\n", ret);
+			hang();
+		}
+	}
 	if (CONFIG_IS_ENABLED(BLOBLIST)) {
 		ret = bloblist_finish();
 		if (ret)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 527a569..1ad5a69 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -12,6 +12,7 @@
 #include <memalign.h>
 #include <mapmem.h>
 #include <spl.h>
+#include <upl.h>
 #include <sysinfo.h>
 #include <asm/global_data.h>
 #include <asm/io.h>
@@ -336,6 +337,8 @@
 			image_info->entry_point = FDT_ERROR;
 	}
 
+	upl_add_image(fit, node, load_addr, length);
+
 	return 0;
 }
 
@@ -847,6 +850,8 @@
 		spl_image->entry_point = spl_image->load_addr;
 
 	spl_image->flags |= SPL_FIT_FOUND;
+	upl_set_fit_info(map_to_sysmem(ctx.fit), ctx.conf_node,
+			 spl_image->entry_point);
 
 	return 0;
 }
@@ -943,5 +948,8 @@
 	}
 	spl_image->flags |= SPL_FIT_FOUND;
 
+	upl_set_fit_info(map_to_sysmem(header), conf_noffset,
+			 spl_image->entry_point);
+
 	return 0;
 }
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 94d054e..19c66e1 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -716,6 +716,10 @@
 	 * @GD_FLG_HUSH_MODERN_PARSER: Use hush 2021 parser.
 	 */
 	GD_FLG_HUSH_MODERN_PARSER = 0x2000000,
+	/**
+	 * @GD_FLG_UPL: Read/write a Universal Payload (UPL) handoff
+	 */
+	GD_FLG_UPL = 0x4000000,
 };
 
 #endif /* __ASSEMBLY__ */