[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(®ion, struct memregion);
+ if (!alist_add(®ion, upl->smbios))
+ return log_msg_ret("ups", ret);
+ ret = write_mem_node(upl, mem_node, ®ion, UPLN_MEMORY,
+ &node);
+ alist_uninit(®ion);
+ 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(®ion, struct memregion);
+ if (!alist_add(®ion, upl->acpi))
+ return log_msg_ret("upa", ret);
+ ret = write_mem_node(upl, mem_node, ®ion, UPLN_MEMORY,
+ &node);
+ alist_uninit(®ion);
+ 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(®ion, '\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