[U-Boot] [PATCH v2 01/11] fdtdec: Add cpu_to_fdt_{addr, size}() macros

From: Thierry Reding treding@nvidia.com
These macros are useful for converting the endianness of variables of type fdt_addr_t and fdt_size_t.
Reviewed-by: Simon Glass sjg@chromium.org Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v2: - add Reviewed-by from Simon
include/fdtdec.h | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/include/fdtdec.h b/include/fdtdec.h index b7e35cd87c55..a965c33157c9 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -27,11 +27,15 @@ typedef phys_size_t fdt_size_t; #define FDT_ADDR_T_NONE (-1U) #define fdt_addr_to_cpu(reg) be64_to_cpu(reg) #define fdt_size_to_cpu(reg) be64_to_cpu(reg) +#define cpu_to_fdt_addr(reg) cpu_to_be64(reg) +#define cpu_to_fdt_size(reg) cpu_to_be64(reg) typedef fdt64_t fdt_val_t; #else #define FDT_ADDR_T_NONE (-1U) #define fdt_addr_to_cpu(reg) be32_to_cpu(reg) #define fdt_size_to_cpu(reg) be32_to_cpu(reg) +#define cpu_to_fdt_addr(reg) cpu_to_be32(reg) +#define cpu_to_fdt_size(reg) cpu_to_be32(reg) typedef fdt32_t fdt_val_t; #endif

From: Thierry Reding treding@nvidia.com
These helpers can be used to unpack variables of type fdt_addr_t and fdt_size_t into a pair of 32-bit variables. This is useful in cases where such variables need to be written to properties (such as "reg") of a device tree node where they need to be split into cells.
Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v2: - new patch
include/fdtdec.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/include/fdtdec.h b/include/fdtdec.h index a965c33157c9..a0ba57c6318b 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -23,6 +23,31 @@ */ typedef phys_addr_t fdt_addr_t; typedef phys_size_t fdt_size_t; + +static inline fdt32_t fdt_addr_unpack(fdt_addr_t addr, fdt32_t *upper) +{ + if (upper) +#ifdef CONFIG_PHYS_64BIT + *upper = addr >> 32; +#else + *upper = 0; +#endif + + return addr; +} + +static inline fdt32_t fdt_size_unpack(fdt_size_t size, fdt32_t *upper) +{ + if (upper) +#ifdef CONFIG_PHYS_64BIT + *upper = size >> 32; +#else + *upper = 0; +#endif + + return size; +} + #ifdef CONFIG_PHYS_64BIT #define FDT_ADDR_T_NONE (-1U) #define fdt_addr_to_cpu(reg) be64_to_cpu(reg)

From: Thierry Reding treding@nvidia.com
This function generates a new, unused phandle by looking up the highest phandle value stored in a device tree and adding one.
Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v2: - rename to fdtdec_generate_phandle()
include/fdtdec.h | 12 ++++++++++++ lib/fdtdec.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+)
diff --git a/include/fdtdec.h b/include/fdtdec.h index a0ba57c6318b..b593c562584d 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -981,6 +981,18 @@ int fdtdec_setup_mem_size_base(void); */ int fdtdec_setup_memory_banksize(void);
+/** + * fdtdec_generate_phandle() - return a new, unused phandle for an FDT blob + * + * Returns a phandle that can be used to refer to a new device tree node. It + * is one higher than the currently highest phandle in the given FDT blob. + * + * @param blob FDT blob + * @param maxp return location for the new phandle + * @return 0 on success or a negative error code on failure + */ +int fdtdec_generate_phandle(const void *blob, uint32_t *phandle); + /** * Set up the device tree ready for use */ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 09a7e133a539..d384c84feb33 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1243,6 +1243,34 @@ __weak void *board_fdt_blob_setup(void) } #endif
+int fdtdec_generate_phandle(const void *blob, uint32_t *phandle) +{ + uint32_t max = 0; + int offset = -1; + + while (true) { + uint32_t value; + + offset = fdt_next_node(blob, offset, NULL); + if (offset < 0) { + if (offset == -FDT_ERR_NOTFOUND) + break; + + return offset; + } + + value = fdt_get_phandle(blob, offset); + + if (value > max) + max = value; + } + + if (phandle) + *phandle = max + 1; + + return 0; +} + int fdtdec_setup(void) { #if CONFIG_IS_ENABLED(OF_CONTROL)

From: Thierry Reding treding@nvidia.com
This function can be used to set a phandle for a given node.
Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v2: - don't emit deprecated linux,phandle property
include/fdtdec.h | 11 +++++++++++ lib/fdtdec.c | 7 +++++++ 2 files changed, 18 insertions(+)
diff --git a/include/fdtdec.h b/include/fdtdec.h index b593c562584d..eb076fc24bc9 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -993,6 +993,17 @@ int fdtdec_setup_memory_banksize(void); */ int fdtdec_generate_phandle(const void *blob, uint32_t *phandle);
+/** + * fdtdec_set_phandle() - sets the phandle of a given node + * + * @param blob FDT blob + * @param node offset in the FDT blob of the node whose phandle is to + * be set + * @param phandle phandle to set for the given node + * @return 0 on success or a negative error code on failure + */ +int fdtdec_set_phandle(void *blob, int node, uint32_t phandle); + /** * Set up the device tree ready for use */ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index d384c84feb33..04d242cdf38e 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1271,6 +1271,13 @@ int fdtdec_generate_phandle(const void *blob, uint32_t *phandle) return 0; }
+int fdtdec_set_phandle(void *blob, int node, uint32_t phandle) +{ + fdt32_t value = cpu_to_fdt32(phandle); + + return fdt_setprop(blob, node, "phandle", &value, sizeof(value)); +} + int fdtdec_setup(void) { #if CONFIG_IS_ENABLED(OF_CONTROL)

From: Thierry Reding treding@nvidia.com
This function can be used to add subnodes in the /reserved-memory node.
Reviewed-by: Simon Glass sjg@chromium.org Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v2: - split fdt_{addr,size}_unpack() helpers into separate patch - use name@x,y notation only if the upper cell is > 0 - use debug() instead of printf() to save code size - properly compute number of cells in reg property - fix carveout size computations, was off by one - use #size-cells where appropriate
include/fdtdec.h | 17 ++++++ lib/fdtdec.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+)
diff --git a/include/fdtdec.h b/include/fdtdec.h index eb076fc24bc9..5c23a9e5f104 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -1004,6 +1004,23 @@ int fdtdec_generate_phandle(const void *blob, uint32_t *phandle); */ int fdtdec_set_phandle(void *blob, int node, uint32_t phandle);
+/** + * fdtdec_add_reserved_memory() - add or find a reserved-memory node + * + * If a reserved-memory node already exists for the given carveout, a phandle + * for that node will be returned. Otherwise a new node will be created and a + * phandle corresponding to it will be returned. + * + * @param blob FDT blob + * @param basename base name of the node to create + * @param carveout information about the carveout region + * @param phandlep return location for the phandle of the carveout region + * @return 0 on success or a negative error code on failure + */ +int fdtdec_add_reserved_memory(void *blob, const char *basename, + const struct fdt_memory *carveout, + uint32_t *phandlep); + /** * Set up the device tree ready for use */ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 04d242cdf38e..bef331df9a08 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1278,6 +1278,137 @@ int fdtdec_set_phandle(void *blob, int node, uint32_t phandle) return fdt_setprop(blob, node, "phandle", &value, sizeof(value)); }
+static int fdtdec_init_reserved_memory(void *blob) +{ + int na, ns, node, err; + fdt32_t value; + + /* inherit #address-cells and #size-cells from the root node */ + na = fdt_address_cells(blob, 0); + ns = fdt_size_cells(blob, 0); + + node = fdt_add_subnode(blob, 0, "reserved-memory"); + if (node < 0) + return node; + + err = fdt_setprop(blob, node, "ranges", NULL, 0); + if (err < 0) + return err; + + value = cpu_to_fdt32(ns); + + err = fdt_setprop(blob, node, "#size-cells", &value, sizeof(value)); + if (err < 0) + return err; + + value = cpu_to_fdt32(na); + + err = fdt_setprop(blob, node, "#address-cells", &value, sizeof(value)); + if (err < 0) + return err; + + return node; +} + +int fdtdec_add_reserved_memory(void *blob, const char *basename, + const struct fdt_memory *carveout, + uint32_t *phandlep) +{ + fdt32_t cells[4] = {}, *ptr = cells; + uint32_t upper, lower, phandle; + int parent, node, na, ns, err; + char name[64]; + + /* create an empty /reserved-memory node if one doesn't exist */ + parent = fdt_path_offset(blob, "/reserved-memory"); + if (parent < 0) { + parent = fdtdec_init_reserved_memory(blob); + if (parent < 0) + return parent; + } + + /* only 1 or 2 #address-cells and #size-cells are supported */ + na = fdt_address_cells(blob, parent); + if (na < 1 || na > 2) + return -FDT_ERR_BADNCELLS; + + ns = fdt_size_cells(blob, parent); + if (ns < 1 || ns > 2) + return -FDT_ERR_BADNCELLS; + + /* find a matching node and return the phandle to that */ + fdt_for_each_subnode(node, blob, parent) { + const char *name = fdt_get_name(blob, node, NULL); + phys_addr_t addr, size; + + addr = fdtdec_get_addr_size(blob, node, "reg", &size); + if (addr == FDT_ADDR_T_NONE) { + debug("failed to read address/size for %s\n", name); + continue; + } + + if (addr == carveout->start && (addr + size) == carveout->end) { + *phandlep = fdt_get_phandle(blob, node); + return 0; + } + } + + /* + * Unpack the start address and generate the name of the new node + * base on the basename and the unit-address. + */ + lower = fdt_addr_unpack(carveout->start, &upper); + + if (na > 1 && upper > 0) + snprintf(name, sizeof(name), "%s@%x,%x", basename, upper, + lower); + else { + if (upper > 0) { + debug("address %08x:%08x exceeds addressable space\n", + upper, lower); + return -FDT_ERR_BADVALUE; + } + + snprintf(name, sizeof(name), "%s@%x", basename, lower); + } + + node = fdt_add_subnode(blob, parent, name); + if (node < 0) + return node; + + err = fdtdec_generate_phandle(blob, &phandle); + if (err < 0) + return err; + + err = fdtdec_set_phandle(blob, node, phandle); + if (err < 0) + return err; + + /* store one or two address cells */ + if (na > 1) + *ptr++ = cpu_to_fdt32(upper); + + *ptr++ = cpu_to_fdt32(lower); + + /* store one or two size cells */ + lower = fdt_size_unpack(carveout->end - carveout->start + 1, &upper); + + if (ns > 1) + *ptr++ = cpu_to_fdt32(upper); + + *ptr++ = cpu_to_fdt32(lower); + + err = fdt_setprop(blob, node, "reg", cells, (na + ns) * sizeof(*cells)); + if (err < 0) + return err; + + /* return the phandle for the new node for the caller to use */ + if (phandlep) + *phandlep = phandle; + + return 0; +} + int fdtdec_setup(void) { #if CONFIG_IS_ENABLED(OF_CONTROL)

From: Thierry Reding treding@nvidia.com
The fdtdec_get_carveout() and fdtdec_set_carveout() function can be used to read a carveout from a given node or add a carveout to a given node using the standard device tree bindings (involving reserved-memory nodes and the memory-region property).
Reviewed-by: Simon Glass sjg@chromium.org Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v2: - use debug() instead of printf() to save code size - fix carveout size computations, was off by one - use fdtdec_get_addr_size_auto_noparent()
include/fdtdec.h | 39 ++++++++++++++++++++++ lib/fdtdec.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+)
diff --git a/include/fdtdec.h b/include/fdtdec.h index 5c23a9e5f104..14fff6806df2 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -1021,6 +1021,45 @@ int fdtdec_add_reserved_memory(void *blob, const char *basename, const struct fdt_memory *carveout, uint32_t *phandlep);
+/** + * fdtdec_get_carveout() - reads a carveout from an FDT + * + * Reads information about a carveout region from an FDT. The carveout is a + * referenced by its phandle that is read from a given property in a given + * node. + * + * @param blob FDT blob + * @param node name of a node + * @param name name of the property in the given node that contains + * the phandle for the carveout + * @param index index of the phandle for which to read the carveout + * @param carveout return location for the carveout information + * @return 0 on success or a negative error code on failure + */ +int fdtdec_get_carveout(const void *blob, const char *node, const char *name, + unsigned int index, struct fdt_memory *carveout); + +/** + * fdtdec_set_carveout() - sets a carveout region for a given node + * + * Sets a carveout region for a given node. If a reserved-memory node already + * exists for the carveout, the phandle for that node will be reused. If no + * such node exists, a new one will be created and a phandle to it stored in + * a specified property of the given node. + * + * @param blob FDT blob + * @param node name of the node to add the carveout to + * @param prop_name name of the property in which to store the phandle of + * the carveout + * @param index index of the phandle to store + * @param name base name of the reserved-memory node to create + * @param carveout information about the carveout to add + * @return 0 on success or a negative error code on failure + */ +int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name, + unsigned int index, const char *name, + const struct fdt_memory *carveout); + /** * Set up the device tree ready for use */ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index bef331df9a08..8ab41682104e 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1409,6 +1409,93 @@ int fdtdec_add_reserved_memory(void *blob, const char *basename, return 0; }
+int fdtdec_get_carveout(const void *blob, const char *node, const char *name, + unsigned int index, struct fdt_memory *carveout) +{ + const fdt32_t *prop; + uint32_t phandle; + int offset, len; + fdt_size_t size; + + offset = fdt_path_offset(blob, node); + if (offset < 0) + return offset; + + prop = fdt_getprop(blob, offset, name, &len); + if (!prop) { + debug("failed to get %s for %s\n", name, node); + return -FDT_ERR_NOTFOUND; + } + + if ((len % sizeof(phandle)) != 0) { + debug("invalid phandle property\n"); + return -FDT_ERR_BADPHANDLE; + } + + if (len < (sizeof(phandle) * (index + 1))) { + debug("invalid phandle index\n"); + return -FDT_ERR_BADPHANDLE; + } + + phandle = fdt32_to_cpu(prop[index]); + + offset = fdt_node_offset_by_phandle(blob, phandle); + if (offset < 0) { + debug("failed to find node for phandle %u\n", phandle); + return offset; + } + + carveout->start = fdtdec_get_addr_size_auto_noparent(blob, offset, + "reg", 0, &size, + true); + if (carveout->start == FDT_ADDR_T_NONE) { + debug("failed to read address/size from "reg" property\n"); + return -FDT_ERR_NOTFOUND; + } + + carveout->end = carveout->start + size - 1; + + return 0; +} + +int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name, + unsigned int index, const char *name, + const struct fdt_memory *carveout) +{ + uint32_t phandle; + int err, offset; + fdt32_t value; + + /* XXX implement support for multiple phandles */ + if (index > 0) { + debug("invalid index %u\n", index); + return -FDT_ERR_BADOFFSET; + } + + err = fdtdec_add_reserved_memory(blob, name, carveout, &phandle); + if (err < 0) { + debug("failed to add reserved memory: %d\n", err); + return err; + } + + offset = fdt_path_offset(blob, node); + if (offset < 0) { + debug("failed to find offset for node %s: %d\n", node, offset); + return offset; + } + + value = cpu_to_fdt32(phandle); + + err = fdt_setprop(blob, offset, prop_name, &value, sizeof(value)); + if (err < 0) { + debug("failed to set %s property for node %s: %d\n", prop_name, + node, err); + return err; + } + + return 0; +} + int fdtdec_setup(void) { #if CONFIG_IS_ENABLED(OF_CONTROL)

From: Thierry Reding treding@nvidia.com
Runtime tests are provided as a test_fdtdec command implementation. Add a Kconfig symbol that allows this command to be built so that the tests can be used.
Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v2: - new patch
lib/Kconfig | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/lib/Kconfig b/lib/Kconfig index 366d164cd760..b1fccf7e8dff 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -423,4 +423,8 @@ source lib/efi/Kconfig source lib/efi_loader/Kconfig source lib/optee/Kconfig
+config TEST_FDTDEC + bool "enable fdtdec test" + depends on OF_LIBFDT + endmenu

From: Thierry Reding treding@nvidia.com
Hide the declaration of the "fd" variable When not building a DEBUG configuration, to avoid the variable being unused.
Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v2: - new patch
lib/fdtdec_test.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/lib/fdtdec_test.c b/lib/fdtdec_test.c index a82e27de942f..065fed278cf3 100644 --- a/lib/fdtdec_test.c +++ b/lib/fdtdec_test.c @@ -79,7 +79,9 @@ static int make_fdt(void *fdt, int size, const char *aliases, { char name[20], value[20]; const char *s; +#if defined(DEBUG) && defined(CONFIG_SANDBOX) int fd; +#endif
CHECK(fdt_create(fdt, size)); CHECK(fdt_finish_reservemap(fdt));

From: Thierry Reding treding@nvidia.com
This eliminates the need for intermediate helper functions and allow the macros to return a value so that it can be used subsequently.
Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v2: - new patch
lib/fdtdec_test.c | 64 ++++++++++++++++------------------------------- 1 file changed, 22 insertions(+), 42 deletions(-)
diff --git a/lib/fdtdec_test.c b/lib/fdtdec_test.c index 065fed278cf3..928950918413 100644 --- a/lib/fdtdec_test.c +++ b/lib/fdtdec_test.c @@ -15,48 +15,28 @@ /* The size of our test fdt blob */ #define FDT_SIZE (16 * 1024)
-/** - * Check if an operation failed, and if so, print an error - * - * @param oper_name Name of operation - * @param err Error code to check - * - * @return 0 if ok, -1 if there was an error - */ -static int fdt_checkerr(const char *oper_name, int err) -{ - if (err) { - printf("%s: %s: %s\n", __func__, oper_name, fdt_strerror(err)); - return -1; - } - - return 0; -} - -/** - * Check the result of an operation and if incorrect, print an error - * - * @param oper_name Name of operation - * @param expected Expected value - * @param value Actual value - * - * @return 0 if ok, -1 if there was an error - */ -static int checkval(const char *oper_name, int expected, int value) -{ - if (expected != value) { - printf("%s: %s: expected %d, but returned %d\n", __func__, - oper_name, expected, value); - return -1; - } - - return 0; -} +#define CHECK(op) ({ \ + int err = op; \ + if (err < 0) { \ + printf("%s: %s: %s\n", __func__, #op, \ + fdt_strerror(err)); \ + return err; \ + } \ + \ + err; \ + }) + +#define CHECKVAL(op, expected) ({ \ + int err = op; \ + if (err != expected) { \ + printf("%s: %s: expected %d, but returned %d\n",\ + __func__, #op, expected, err); \ + return err; \ + } \ + \ + err; \ + })
-#define CHECK(op) if (fdt_checkerr(#op, op)) return -1 -#define CHECKVAL(op, expected) \ - if (checkval(#op, expected, op)) \ - return -1 #define CHECKOK(op) CHECKVAL(op, 0)
/* maximum number of nodes / aliases to generate */ @@ -138,7 +118,7 @@ static int run_test(const char *aliases, const char *nodes, const char *expect) CHECKVAL(make_fdt(blob, FDT_SIZE, aliases, nodes), 0); CHECKVAL(fdtdec_find_aliases_for_id(blob, "i2c", COMPAT_UNKNOWN, - list, ARRAY_SIZE(list)), strlen(expect)); + list, ARRAY_SIZE(list)), (int)strlen(expect));
/* Check we got the right ones */ for (i = 0, s = expect; *s; s++, i++) {

From: Thierry Reding treding@nvidia.com
Implement carveout tests for 32-bit and 64-bit builds.
Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v2: - new patch
lib/fdtdec_test.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+)
diff --git a/lib/fdtdec_test.c b/lib/fdtdec_test.c index 928950918413..f6defe16c5a6 100644 --- a/lib/fdtdec_test.c +++ b/lib/fdtdec_test.c @@ -141,6 +141,156 @@ static int run_test(const char *aliases, const char *nodes, const char *expect) return 0; }
+static int make_fdt_carveout_device(void *fdt, uint32_t na, uint32_t ns) +{ + const char *basename = "/display"; + struct fdt_memory carveout = { +#ifdef CONFIG_PHYS_64BIT + .start = 0x180000000, + .end = 0x18fffffff, +#else + .start = 0x80000000, + .end = 0x8fffffff, +#endif + }; + fdt32_t cells[4], *ptr = cells; + uint32_t upper, lower; + char name[32]; + int offset; + + /* store one or two address cells */ + lower = fdt_addr_unpack(carveout.start, &upper); + + if (na > 1 && upper > 0) + snprintf(name, sizeof(name), "%s@%x,%x", basename, upper, + lower); + else + snprintf(name, sizeof(name), "%s@%x", basename, lower); + + if (na > 1) + *ptr++ = cpu_to_fdt32(upper); + + *ptr++ = cpu_to_fdt32(lower); + + /* store one or two size cells */ + lower = fdt_size_unpack(carveout.end - carveout.start + 1, &upper); + + if (ns > 1) + *ptr++ = cpu_to_fdt32(upper); + + *ptr++ = cpu_to_fdt32(lower); + + offset = CHECK(fdt_add_subnode(fdt, 0, name + 1)); + CHECK(fdt_setprop(fdt, offset, "reg", cells, (na + ns) * sizeof(*cells))); + + return fdtdec_set_carveout(fdt, name, "memory-region", 0, + "framebuffer", &carveout); +} + +static int check_fdt_carveout(void *fdt, uint32_t address_cells, + uint32_t size_cells) +{ +#ifdef CONFIG_PHYS_64BIT + const char *name = "/display@1,80000000"; + const struct fdt_memory expected = { + .start = 0x180000000, + .end = 0x18fffffff, + }; +#else + const char *name = "/display@80000000"; + const struct fdt_memory expected = { + .start = 0x80000000, + .end = 0x8fffffff, + }; +#endif + struct fdt_memory carveout; + + printf("carveout: %pap-%pap na=%u ns=%u: ", &expected.start, + &expected.end, address_cells, size_cells); + + CHECK(fdtdec_get_carveout(fdt, name, "memory-region", 0, &carveout)); + + if ((carveout.start != expected.start) || + (carveout.end != expected.end)) { + printf("carveout: %pap-%pap, expected %pap-%pap\n", + &carveout.start, &carveout.end, + &expected.start, &expected.end); + return 1; + } + + printf("pass\n"); + return 0; +} + +static int make_fdt_carveout(void *fdt, int size, uint32_t address_cells, + uint32_t size_cells) +{ + fdt32_t na = cpu_to_fdt32(address_cells); + fdt32_t ns = cpu_to_fdt32(size_cells); +#if defined(DEBUG) && defined(CONFIG_SANDBOX) + char filename[512]; + int fd; +#endif + int err; + + CHECK(fdt_create(fdt, size)); + CHECK(fdt_finish_reservemap(fdt)); + CHECK(fdt_begin_node(fdt, "")); + CHECK(fdt_property(fdt, "#address-cells", &na, sizeof(na))); + CHECK(fdt_property(fdt, "#size-cells", &ns, sizeof(ns))); + CHECK(fdt_end_node(fdt)); + CHECK(fdt_finish(fdt)); + CHECK(fdt_pack(fdt)); + + CHECK(fdt_open_into(fdt, fdt, FDT_SIZE)); + + err = make_fdt_carveout_device(fdt, address_cells, size_cells); + +#if defined(DEBUG) && defined(CONFIG_SANDBOX) + snprintf(filename, sizeof(filename), "/tmp/fdtdec-carveout-%u-%u.dtb", + address_cells, size_cells); + + fd = os_open(filename, OS_O_CREAT | OS_O_WRONLY); + if (fd < 0) { + printf("could not open .dtb file to write\n"); + goto out; + } + + os_write(fd, fdt, size); + os_close(fd); + +out: +#endif + return err; +} + +static int check_carveout(void) +{ + void *fdt; + + fdt = malloc(FDT_SIZE); + if (!fdt) { + printf("%s: out of memory\n", __func__); + return 1; + } + +#ifndef CONFIG_PHYS_64BIT + CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), 0); + CHECKOK(check_fdt_carveout(fdt, 1, 1)); + CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), 0); + CHECKOK(check_fdt_carveout(fdt, 1, 2)); +#else + CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), -FDT_ERR_BADVALUE); + CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), -FDT_ERR_BADVALUE); +#endif + CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 1), 0); + CHECKOK(check_fdt_carveout(fdt, 2, 1)); + CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 2), 0); + CHECKOK(check_fdt_carveout(fdt, 2, 2)); + + return 0; +} + static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -182,6 +332,8 @@ static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc, CHECKOK(run_test("2a 1a 0a", "a", " a")); CHECKOK(run_test("0a 1a 2a", "a", "a"));
+ CHECKOK(check_carveout()); + printf("Test passed\n"); return 0; }

From: Thierry Reding treding@nvidia.com
Enable fdtdec tests on sandbox configurations so that they can be run to validate the fdtdec implementation.
Signed-off-by: Thierry Reding treding@nvidia.com --- Changes in v2: - new patch
configs/sandbox64_defconfig | 1 + configs/sandbox_defconfig | 1 + 2 files changed, 2 insertions(+)
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index da4bdced3105..c04ecd915ae7 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -194,6 +194,7 @@ CONFIG_CMD_DHRYSTONE=y CONFIG_TPM=y CONFIG_LZ4=y CONFIG_ERRNO_STR=y +CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 193e41896cb7..bb508a8d02e2 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -215,6 +215,7 @@ CONFIG_CMD_DHRYSTONE=y CONFIG_TPM=y CONFIG_LZ4=y CONFIG_ERRNO_STR=y +CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y
participants (1)
-
Thierry Reding