[PATCH v3 13/21] upl: Add support for Universal Payload in SPL

Simon Glass sjg at chromium.org
Sun Jul 21 12:09:31 CEST 2024


Add the basic code to create a handoff structure in SPL, so it can be
passed to the next phase. For now this is not plumbed in.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

(no changes since v2)

Changes in v2:
- Add a function to init the UPL process in SPL

 MAINTAINERS          |   1 +
 boot/Kconfig         |  32 ++++++++
 common/spl/Makefile  |   2 +
 common/spl/spl_upl.c | 171 +++++++++++++++++++++++++++++++++++++++++++
 include/spl.h        |  16 ++++
 5 files changed, 222 insertions(+)
 create mode 100644 common/spl/spl_upl.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 538d975748d..efb557b2524 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1707,6 +1707,7 @@ S:	Maintained
 T:	git https://source.denx.de/u-boot/custodians/u-boot-dm.git
 F:	boot/upl*
 F:	cmd/upl.c
+F:	common/spl/spl_upl.c
 F:	doc/usage/cmd/upl.rst
 F:	include/upl.h
 F:	test/boot/upl.c
diff --git a/boot/Kconfig b/boot/Kconfig
index f9a44550ac4..1fdbb0755c5 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -741,6 +741,7 @@ config UPL
 	imply CMD_UPL
 	imply UPL_READ
 	imply UPL_WRITE
+	imply SPL_UPL if SPL
 	help
 	  Provides support for UPL payloads and handoff information. U-Boot
 	  supports generating and accepting handoff information. The mkimage
@@ -757,11 +758,42 @@ config UPL_READ
 
 config UPL_WRITE
 	bool "upl - Support writing a Universal Payload handoff"
+	help
+	  Provides support for encoding a UPL-format payload from a C structure
+	  so it can be passed to another program. This is just the writing
+	  implementation, useful for trying it out. See SPL_UPL_OUT
+	  for how to tell U-Boot SPL to actually write it before jumping to
+	  the next phase.
+
+if SPL
+
+config SPL_UPL
+	bool "Write a UPL handoff in SPL"
+	imply SPL_UPL_OUT
+	help
+	  This tells SPL to write a UPL handoff and pass it to the next phase
+	  (e.g. to U-Boot or another program which SPL loads and runs). THis
+	  provides information to help that program run correctly and
+	  efficiently on the machine.
+
+config SPL_UPL_WRITE
+	bool  # upl - Support writing a Universal Payload handoff in SPL
+	select SPL_BLOBLIST
 	help
 	  Provides support for encoding a UPL-format payload from a C structure
 	  so it can be passed to another program. This is just the writing
 	  implementation, useful for trying it out.
 
+config SPL_UPL_OUT
+	bool "upl - Support writing a Universal Payload handoff in SPL"
+	select SPL_UPL_WRITE
+	help
+	  Provides support for encoding a UPL-format payload and passing it to
+	  the next firmware phase. This allows U-Boot SPL to function as
+	  Platform Init in the meaning of the specification.
+
+endif  # SPL
+
 endif  # UPL
 
 endif # BOOTSTD
diff --git a/common/spl/Makefile b/common/spl/Makefile
index 4809f9c3ec1..137b18428bd 100644
--- a/common/spl/Makefile
+++ b/common/spl/Makefile
@@ -37,3 +37,5 @@ obj-$(CONFIG_$(SPL_TPL_)SPI_LOAD) += spl_spi.o
 obj-$(CONFIG_$(SPL_TPL_)RAM_SUPPORT) += spl_ram.o
 obj-$(CONFIG_$(SPL_TPL_)USB_SDP_SUPPORT) += spl_sdp.o
 endif
+
+obj-$(CONFIG_$(SPL_TPL_)UPL) += spl_upl.o
diff --git a/common/spl/spl_upl.c b/common/spl/spl_upl.c
new file mode 100644
index 00000000000..12337a05cc0
--- /dev/null
+++ b/common/spl/spl_upl.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * UPL handoff parsing
+ *
+ * Copyright 2024 Google LLC
+ * Written by Simon Glass <sjg at chromium.org>
+ */
+
+#define LOG_CATEGORY UCLASS_BOOTSTD
+
+#include <bloblist.h>
+#include <dm.h>
+#include <image.h>
+#include <mapmem.h>
+#include <serial.h>
+#include <spl.h>
+#include <upl.h>
+#include <video.h>
+#include <asm/global_data.h>
+#include <dm/read.h>
+#include <dm/uclass-internal.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct upl s_upl;
+
+void upl_set_fit_addr(ulong fit)
+{
+	struct upl *upl = &s_upl;
+
+	upl->fit = fit;
+}
+
+void upl_set_fit_info(ulong fit, int conf_offset, ulong entry_addr)
+{
+	struct upl *upl = &s_upl;
+
+	upl->fit = fit;
+	upl->conf_offset = conf_offset;
+	log_debug("upl: add fit %lx conf %x\n", fit, conf_offset);
+}
+
+int upl_add_image(int node, ulong load_addr, ulong size, const char *desc)
+{
+	struct upl *upl = &s_upl;
+	struct upl_image img;
+
+	img.load = load_addr;
+	img.size = size;
+	img.offset = node;
+	img.description = desc;
+	if (!alist_add(&upl->image, img, struct upl_image))
+		return -ENOMEM;
+	log_debug("upl: add image %s at %lx size %lx\n", desc, load_addr, size);
+
+	return 0;
+}
+
+static int write_serial(struct upl_serial *ser)
+{
+	struct udevice *dev = gd->cur_serial_dev;
+	struct serial_device_info info;
+	struct memregion region;
+	int ret;
+
+	if (!dev)
+		return log_msg_ret("ser", -ENOENT);
+	ret = serial_getinfo(dev, &info);
+	if (ret)
+		return log_msg_ret("inf", ret);
+
+	ser->compatible = ofnode_read_string(dev_ofnode(dev), "compatible");
+	ser->clock_frequency = info.clock;
+	ser->current_speed = gd->baudrate;
+	region.base = info.addr;
+	region.size = info.size;
+	alist_init_struct(&ser->reg, struct memregion);
+	if (!alist_add(&ser->reg, region, struct memregion))
+		return -ENOMEM;
+	ser->reg_io_shift = info.reg_shift;
+	ser->reg_offset = info.reg_offset;
+	ser->reg_io_width = info.reg_width;
+	ser->virtual_reg = 0;
+	ser->access_type = info.addr_space;
+
+	return 0;
+}
+
+static int write_graphics(struct upl_graphics *gra)
+{
+	struct video_uc_plat *plat;
+	struct video_priv *priv;
+	struct memregion region;
+	struct udevice *dev;
+
+	alist_init_struct(&gra->reg, struct memregion);
+	uclass_find_first_device(UCLASS_VIDEO, &dev);
+	if (!dev || !device_active(dev))
+		return log_msg_ret("vid", -ENOENT);
+
+	plat = dev_get_uclass_plat(dev);
+	region.base = plat->base;
+	region.size = plat->size;
+	if (!alist_add(&gra->reg, region, struct memregion))
+		return log_msg_ret("reg", -ENOMEM);
+
+	priv = dev_get_uclass_priv(dev);
+	gra->width = priv->xsize;
+	gra->height = priv->ysize;
+	gra->stride = priv->line_length;	/* private field */
+	switch (priv->format) {
+	case VIDEO_RGBA8888:
+	case VIDEO_X8R8G8B8:
+		gra->format = UPLGF_ARGB32;
+		break;
+	case VIDEO_X8B8G8R8:
+		gra->format = UPLGF_ABGR32;
+		break;
+	case VIDEO_X2R10G10B10:
+		log_debug("device '%s': VIDEO_X2R10G10B10 not supported\n",
+			  dev->name);
+		return log_msg_ret("for", -EPROTO);
+	case VIDEO_UNKNOWN:
+		log_debug("device '%s': Unknown video format\n", dev->name);
+		return log_msg_ret("for", -EPROTO);
+	}
+
+	return 0;
+}
+
+int spl_write_upl_handoff(struct spl_image_info *spl_image)
+{
+	struct upl *upl = &s_upl;
+	struct abuf buf;
+	ofnode root;
+	void *ptr;
+	int ret;
+
+	log_debug("UPL: Writing handoff - image_count=%d\n", upl->image.count);
+	upl->addr_cells = IS_ENABLED(CONFIG_PHYS_64BIT) ? 2 : 1;
+	upl->size_cells = IS_ENABLED(CONFIG_PHYS_64BIT) ? 2 : 1;
+	upl->bootmode = UPLBM_DEFAULT;
+	ret = write_serial(&upl->serial);
+	if (ret)
+		return log_msg_ret("ser", ret);
+	ret = write_graphics(&upl->graphics);
+	if (ret && ret != -ENOENT)
+		return log_msg_ret("gra", ret);
+
+	root = ofnode_root();
+	ret = upl_write_handoff(upl, root, true);
+	if (ret)
+		return log_msg_ret("wr", ret);
+
+	ret = oftree_to_fdt(oftree_default(), &buf);
+	if (ret)
+		return log_msg_ret("fdt", ret);
+	log_debug("FDT size %zx\n", abuf_size(&buf));
+
+	ptr = bloblist_add(BLOBLISTT_CONTROL_FDT, abuf_size(&buf), 0);
+	if (!ptr)
+		return log_msg_ret("blo", -ENOENT);
+	memcpy(ptr, abuf_data(&buf), abuf_size(&buf));
+
+	return 0;
+}
+
+void spl_upl_init(void)
+{
+	upl_init(&s_upl);
+}
diff --git a/include/spl.h b/include/spl.h
index 5dfdf778d2d..089b1864c57 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -1074,4 +1074,20 @@ static inline bool spl_decompression_enabled(void)
 {
 	return IS_ENABLED(CONFIG_SPL_GZIP) || IS_ENABLED(CONFIG_SPL_LZMA);
 }
+
+/**
+ * spl_write_upl_handoff() - Write a Universal Payload hand-off structure
+ *
+ * @spl_image: Information about the image being booted
+ * Return: 0 if OK, -ve on error
+ */
+int spl_write_upl_handoff(struct spl_image_info *spl_image);
+
+/**
+ * spl_upl_init() - Get UPL ready for information to be added
+ *
+ * This must be called before upl_add_image(), etc.
+ */
+void spl_upl_init(void);
+
 #endif
-- 
2.34.1



More information about the U-Boot mailing list