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 <[email protected]>
---

 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

Reply via email to