[PATCH 66/67] upl: Add reserved memory for the ACPI and SMBIOS tables

Simon Glass sjg at chromium.org
Wed Jan 1 23:09:52 CET 2025


Mark these as reserved memory-regions so that the payload can find the
tables. Remove the upl-params properties which are no-longer in the
spec. Add a compatible string instead.

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

 boot/upl_common.c | 40 +++++++++++++++++++++++++++++++++++++++-
 boot/upl_read.c   | 25 ++++++++++++++++++-------
 boot/upl_write.c  | 38 +++++++++++++++++++++++++++++++-------
 include/alist.h   |  2 +-
 include/upl.h     | 21 +++++++++++++++++++--
 lib/alist.c       |  2 +-
 test/boot/upl.c   | 13 +++++++++----
 7 files changed, 118 insertions(+), 23 deletions(-)

diff --git a/boot/upl_common.c b/boot/upl_common.c
index e60f22f47e0..e07a07cc945 100644
--- a/boot/upl_common.c
+++ b/boot/upl_common.c
@@ -8,6 +8,7 @@
 
 #define LOG_CATEGORY UCLASS_BOOTSTD
 
+#include <bloblist.h>
 #include <cpu.h>
 #include <dm.h>
 #include <serial.h>
@@ -138,7 +139,8 @@ int upl_create(struct upl *upl)
 {
 	struct upl_mem mem;
 	ulong base, size;
-	int ret;
+	int ret, bsize;
+	void *ptr;
 
 	/* hard-code this for now to keep Tianocore happy */
 	upl->addr_cells = 2;
@@ -158,12 +160,28 @@ int upl_create(struct upl *upl)
 	if (!alist_add(&upl->mem, mem))
 		return log_msg_ret("arg", -ENOMEM);
 
+	ptr = bloblist_get_blob(BLOBLISTT_SMBIOS_TABLES, &bsize);
+	if (ptr) {
+		upl->smbios.base = map_to_sysmem(ptr);
+		upl->smbios.size = bsize;
+	}
+	ptr = bloblist_get_blob(BLOBLISTT_ACPI_TABLES, &bsize);
+	if (ptr) {
+		upl->acpi.base = map_to_sysmem(ptr);
+		upl->acpi.size = bsize;
+	}
+
 	ret = upl_add_serial(&upl->serial);
 	if (ret && ret != -ENOENT)
 		return log_msg_ret("ser", ret);
 	ret = upl_add_graphics(&upl->graphics, &base, &size);
 	if (ret && ret != -ENOENT)
 		return log_msg_ret("gra", ret);
+	if (!ret) {
+		ret = upl_add_memres(upl, UPLN_MEMORY, base, size, true);
+		if (ret)
+			return log_msg_ret("grr", ret);
+	}
 
 	return 0;
 }
@@ -201,6 +219,26 @@ int upl_add_region(struct alist *lst, u64 base, ulong size)
 	return 0;
 }
 
+int upl_add_memres(struct upl *upl, const char *name, u64 base, ulong size,
+		   bool no_map)
+{
+	struct upl_memres memres;
+	int ret;
+
+	log_debug("base = %llx size = %lx\n", base, size);
+	memset(&memres, '\0', sizeof(memres));
+	alist_init_struct(&memres.region, struct memregion);
+	memres.name = name;
+	memres.no_map = no_map;
+	ret = upl_add_region(&memres.region, base, size);
+	if (ret)
+		return log_msg_ret("uav", ret);
+	if (!alist_add(&upl->memres, memres))
+		return log_msg_ret("uaM", -ENOMEM);
+
+	return 0;
+}
+
 void upl_init(struct upl *upl)
 {
 	memset(upl, '\0', sizeof(struct upl));
diff --git a/boot/upl_read.c b/boot/upl_read.c
index 4f07204546e..05db559efdb 100644
--- a/boot/upl_read.c
+++ b/boot/upl_read.c
@@ -248,12 +248,6 @@ static int decode_upl_params(struct upl *upl, ofnode options)
 		return log_msg_ret("par", -EINVAL);
 	log_debug("decoding '%s'\n", ofnode_get_name(node));
 
-	ret = read_addr(upl, node, UPLP_SMBIOS, &upl->smbios);
-	if (ret)
-		return log_msg_ret("smb", ret);
-	ret = read_addr(upl, node, UPLP_ACPI, &upl->acpi);
-	if (ret)
-		return log_msg_ret("acp", ret);
 	ret = ofnode_read_bitmask(node, UPLP_BOOTMODE, bootmode_names,
 				  UPLBM_COUNT, &upl->bootmode);
 	if (ret)
@@ -416,7 +410,7 @@ static int decode_upl_memres(struct upl *upl, ofnode root)
 
 	ofnode_for_each_subnode(node, root) {
 		struct upl_memres memres;
-		const char *buf;
+		const char *buf, *compat;
 		int size, len;
 
 		log_debug("decoding '%s'\n", ofnode_get_name(node));
@@ -434,6 +428,23 @@ static int decode_upl_memres(struct upl *upl, ofnode root)
 			return log_msg_ret("buf", len);
 		memres.no_map = ofnode_read_bool(node, UPLP_NO_MAP);
 
+		compat = ofnode_read_string(node, UPLP_COMPATIBLE);
+		if (compat && memres.region.count == 1) {
+			const struct memregion *rgn;
+
+			rgn = alist_get(&memres.region, 0, struct memregion);
+			if (!strcmp(compat, UPLP_SMBIOS))
+				upl->smbios = *rgn;
+			else if (!strcmp(compat, UPLP_ACPI))
+				upl->acpi = *rgn;
+			else
+				log_warning("Ignoring compat '%s'\n", compat);
+
+			/* don't add this node to the memres list */
+			alist_uninit(&memres.region);
+			continue;
+		}
+
 		if (!alist_add(&upl->memres, memres))
 			return log_msg_ret("mre", -ENOMEM);
 	}
diff --git a/boot/upl_write.c b/boot/upl_write.c
index ce9f733b450..5db5d02e6e8 100644
--- a/boot/upl_write.c
+++ b/boot/upl_write.c
@@ -228,10 +228,6 @@ static int add_upl_params(const struct upl *upl, ofnode options)
 		return log_msg_ret("img", ret);
 
 	ret = ofnode_write_string(node, "compatible", UPLP_UPL_PARAMS_COMPAT);
-	if (!ret)
-		ret = write_addr(upl, node, UPLP_SMBIOS, upl->smbios);
-	if (!ret)
-		ret = write_addr(upl, node, UPLP_ACPI, upl->acpi);
 	if (!ret && upl->bootmode)
 		ret = ofnode_write_bitmask(node, UPLP_BOOTMODE, bootmode_names,
 					   UPLBM_COUNT, upl->bootmode);
@@ -350,6 +346,8 @@ static int write_mem_node(const struct upl *upl, ofnode parent,
 		return log_msg_ret("wmn", ret);
 
 	len = encode_reg(upl, buf, sizeof(buf), mem->count, mem);
+	if (len < 0)
+		return log_msg_ret("uer", ret);
 	ret = ofnode_write_prop(node, UPLP_REG, buf, len, true);
 	if (ret)
 		return log_msg_ret("wm1", ret);
@@ -437,7 +435,8 @@ static int add_upl_memres(const struct upl *upl, ofnode root,
 			  bool skip_existing)
 {
 	const struct upl_memres *memres;
-	ofnode mem_node;
+	struct alist region;
+	ofnode mem_node, node;
 	int ret;
 
 	if (!upl->memres.count)
@@ -453,8 +452,6 @@ static int add_upl_memres(const struct upl *upl, ofnode root,
 		return log_msg_ret("im2", ret);
 
 	alist_for_each(memres, &upl->memres) {
-		ofnode node;
-
 		ret = write_mem_node(upl, mem_node, &memres->region,
 				     memres->name, &node);
 		if (ret)
@@ -467,6 +464,33 @@ static int add_upl_memres(const struct upl *upl, ofnode root,
 			return log_msg_ret("lst", ret);
 	}
 
+	if (upl->smbios.base) {
+		alist_init_struct(&region, struct memregion);
+		if (!alist_add(&region, upl->smbios))
+			return log_msg_ret("ups", ret);
+		ret = write_mem_node(upl, mem_node, &region, UPLN_MEMORY,
+				     &node);
+		alist_uninit(&region);
+		if (ret)
+			return log_msg_ret("mrs", ret);
+		ret = ofnode_write_string(node, UPLP_COMPATIBLE, UPLP_SMBIOS);
+		if (ret)
+			return log_msg_ret("mrS", ret);
+	}
+	if (upl->acpi.base) {
+		alist_init_struct(&region, struct memregion);
+		if (!alist_add(&region, upl->acpi))
+			return log_msg_ret("upa", ret);
+		ret = write_mem_node(upl, mem_node, &region, UPLN_MEMORY,
+				     &node);
+		alist_uninit(&region);
+		if (ret)
+			return log_msg_ret("mra", ret);
+		ret = ofnode_write_string(node, UPLP_COMPATIBLE, UPLP_ACPI);
+		if (ret)
+			return log_msg_ret("mrA", ret);
+	}
+
 	return 0;
 }
 
diff --git a/include/alist.h b/include/alist.h
index b00d9ea97d6..8aac5cd46ec 100644
--- a/include/alist.h
+++ b/include/alist.h
@@ -184,7 +184,7 @@ void *alist_add_placeholder(struct alist *lst);
  * @obj: Pointer to object to copy in
  * Returns: pointer to where the object was copied, or NULL if out of memory
  */
-void *alist_add_ptr(struct alist *lst, void *obj);
+void *alist_add_ptr(struct alist *lst, const void *obj);
 
 /**
  * alist_expand_by() - Expand a list by the given amount
diff --git a/include/upl.h b/include/upl.h
index f210a39df0c..eb7ef463b9e 100644
--- a/include/upl.h
+++ b/include/upl.h
@@ -288,6 +288,8 @@ struct upl_pci {
  *
  * @addr_cells: Number of address cells used in the handoff
  * @size_cells: Number of size cells used in the handoff
+ * @smbios: SMBIOS region, base is 0 if none
+ * @acpi: ACPI region, base is 0 if none
  * @bootmode: Boot-mode mask (enum upl_boot_mode)
  * @fit: Address and size of FIT image that was loaded
  * @conf_offset: Offset in FIT of the configuration that was selected
@@ -301,8 +303,8 @@ struct upl {
 	int addr_cells;
 	int size_cells;
 
-	ulong smbios;
-	ulong acpi;
+	struct memregion smbios;
+	struct memregion acpi;
 	enum upl_boot_mode bootmode;
 	struct memregion fit;
 	uint conf_offset;
@@ -475,6 +477,21 @@ int upl_write_to_buf(struct upl *upl, ofnode root, struct abuf *buf);
  * Return: 0 if OK, -ve on error
  */
 int upl_add_region(struct alist *lst, u64 base, ulong size);
+
+/**
+ * upl_add_memres() - Add a new reserved-memory region
+ *
+ * Adds a new entry to the end of the memres list
+ *
+ * @upl: UPL to add to
+ * @name: Node name to use for new region)
+ * @base: Base address of new region
+ * @size: Size of new region
+ * @no_map: true if the no-map property should be enabled
+ * Return: 0 if OK, -ve on error
+ */
+int upl_add_memres(struct upl *upl, const char *name, u64 base, ulong size,
+		   bool no_map);
 #endif
 
 /**
diff --git a/lib/alist.c b/lib/alist.c
index 4ce651f5c45..05399c78a92 100644
--- a/lib/alist.c
+++ b/lib/alist.c
@@ -167,7 +167,7 @@ void *alist_add_placeholder(struct alist *lst)
 	return alist_ensure_ptr(lst, lst->count);
 }
 
-void *alist_add_ptr(struct alist *lst, void *obj)
+void *alist_add_ptr(struct alist *lst, const void *obj)
 {
 	void *ptr;
 
diff --git a/test/boot/upl.c b/test/boot/upl.c
index 91b7baa75e2..ae7abed72f1 100644
--- a/test/boot/upl.c
+++ b/test/boot/upl.c
@@ -26,6 +26,7 @@ static int add_region(struct unit_test_state *uts, struct alist *lst,
 {
 	struct memregion region;
 
+	memset(&region, '\0', sizeof(region));
 	region.base = base;
 	region.size = size;
 	ut_assertnonnull(alist_add(lst, region));
@@ -44,8 +45,10 @@ int upl_get_test_data(struct unit_test_state *uts, struct upl *upl)
 
 	upl->addr_cells = 1;
 	upl->size_cells = 1;
-	upl->smbios = 0x123;
-	upl->acpi = 0x456;
+	upl->smbios.base = 0x123;
+	upl->smbios.size = 0x321;
+	upl->acpi.base = 0x456;
+	upl->acpi.size = 0x654;
 	upl->bootmode = BIT(UPLBM_DEFAULT) | BIT(UPLBM_S3);
 	upl->fit.base = 0x789;
 	upl->fit.size = 0xabc;
@@ -294,8 +297,10 @@ static int compare_upl(struct unit_test_state *uts, struct upl *base,
 	ut_asserteq(base->addr_cells, cmp->addr_cells);
 	ut_asserteq(base->size_cells, cmp->size_cells);
 
-	ut_asserteq(base->smbios, cmp->smbios);
-	ut_asserteq(base->acpi, cmp->acpi);
+	ut_asserteq(base->smbios.base, cmp->smbios.base);
+	ut_asserteq(base->smbios.size, cmp->smbios.size);
+	ut_asserteq(base->acpi.base, cmp->acpi.base);
+	ut_asserteq(base->acpi.size, cmp->acpi.size);
 	ut_asserteq(base->bootmode, cmp->bootmode);
 	ut_asserteq(base->fit.base, cmp->fit.base);
 	ut_asserteq(base->fit.size, cmp->fit.size);
-- 
2.43.0



More information about the U-Boot mailing list