From 73d6e9ecb4179b510408bc526240f829262df361 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 5 Mar 2020 15:04:45 +0100 Subject: [PATCH 001/298] libfdt: fix undefined behaviour in fdt_splice_() libfdt: fix undefined behaviour in fdt_splice_() Along the lines of commit d0b3ab0a0f46 ("libfdt: Fix undefined behaviour in fdt_offset_ptr()"), fdt_splice_() similarly may not use pointer arithmetic to do overflow checks. (The left side of the checks added by d4c7c25c9ed1 ["libfdt: check for potential overrun in _fdt_splice()"] doesn't really lend itself to similar replacement though.) Signed-off-by: Jan Beulich Message-Id: Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 1385425..524b520 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -46,7 +46,7 @@ static int fdt_rw_probe_(void *fdt) return err_; \ } -static inline int fdt_data_size_(void *fdt) +static inline unsigned int fdt_data_size_(void *fdt) { return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); } @@ -54,15 +54,16 @@ static inline int fdt_data_size_(void *fdt) static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) { char *p = splicepoint; - char *end = (char *)fdt + fdt_data_size_(fdt); + unsigned int dsize = fdt_data_size_(fdt); + size_t soff = p - (char *)fdt; - if (((p + oldlen) < p) || ((p + oldlen) > end)) + if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize)) return -FDT_ERR_BADOFFSET; - if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) + if ((p < (char *)fdt) || (dsize + newlen < oldlen)) return -FDT_ERR_BADOFFSET; - if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) + if (dsize - oldlen + newlen > fdt_totalsize(fdt)) return -FDT_ERR_NOSPACE; - memmove(p + newlen, p + oldlen, end - p - oldlen); + memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen)); return 0; } From 87a656ae5ff96c4903e68eb2f999532a3b98e3a7 Mon Sep 17 00:00:00 2001 From: Arkadiusz Drabczyk Date: Sun, 8 Mar 2020 17:56:43 +0100 Subject: [PATCH 002/298] check: Inform about missing ranges In check_unit_address_vs_reg() warning message already says 'reg _or_ ranges' when reg or ranges are present but unit name is missing. Add this message for compatibility to say "reg _or_ ranges" when unit name is present but neither reg nor ranges are present. Signed-off-by: Arkadiusz Drabczyk Message-Id: <20200308165643.19281-1-arkadiusz@drabczyk.org> Signed-off-by: David Gibson --- checks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks.c b/checks.c index 8acbc05..4b3c486 100644 --- a/checks.c +++ b/checks.c @@ -352,7 +352,7 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti, FAIL(c, dti, node, "node has a reg or ranges property, but no unit name"); } else { if (unitname[0]) - FAIL(c, dti, node, "node has a unit name, but no reg property"); + FAIL(c, dti, node, "node has a unit name, but no reg or ranges property"); } } WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL); From b28464a550c536296439b5785ed8852d1e15b35b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 14 Apr 2020 15:02:51 +1000 Subject: [PATCH 003/298] Fix some potential unaligned accesses in dtc Because of the convention of packed representations in property layouts, it's not uncommon to have integer values in properties which aren't naturally aligned. Thus, there are several places in the dtc code where we cast a potentially unaligned byte pointer into an integer pointer and load it directly. On a number of architectures (including sparc64 and arm) this won't work and will cause a fault. In some cases it may be trapped and emulated by the kernel, but not always. Therefore, replace such direct unaligned reads with a helper which will handle unaligned data reads (a variant on the fdtXX_ld() functions already used in libfdt). Signed-off-by: David Gibson --- dtc.h | 31 +++++++++++++++++++++++++++++++ flattree.c | 2 +- treesource.c | 6 +++--- yamltree.c | 6 +++--- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/dtc.h b/dtc.h index 6e74ece..a08f415 100644 --- a/dtc.h +++ b/dtc.h @@ -51,6 +51,37 @@ extern int annotate; /* annotate .dts with input source location */ typedef uint32_t cell_t; +static inline uint16_t dtb_ld16(const void *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint16_t)bp[0] << 8) + | bp[1]; +} + +static inline uint32_t dtb_ld32(const void *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint32_t)bp[0] << 24) + | ((uint32_t)bp[1] << 16) + | ((uint32_t)bp[2] << 8) + | bp[3]; +} + +static inline uint64_t dtb_ld64(const void *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint64_t)bp[0] << 56) + | ((uint64_t)bp[1] << 48) + | ((uint64_t)bp[2] << 40) + | ((uint64_t)bp[3] << 32) + | ((uint64_t)bp[4] << 24) + | ((uint64_t)bp[5] << 16) + | ((uint64_t)bp[6] << 8) + | bp[7]; +} #define streq(a, b) (strcmp((a), (b)) == 0) #define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0) diff --git a/flattree.c b/flattree.c index bd6977e..07f10d2 100644 --- a/flattree.c +++ b/flattree.c @@ -156,7 +156,7 @@ static void asm_emit_data(void *e, struct data d) emit_offset_label(f, m->ref, m->offset); while ((d.len - off) >= sizeof(uint32_t)) { - asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off)))); + asm_emit_cell(e, dtb_ld32(d.val + off)); off += sizeof(uint32_t); } diff --git a/treesource.c b/treesource.c index c9d980c..2acb920 100644 --- a/treesource.c +++ b/treesource.c @@ -110,13 +110,13 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) fprintf(f, "%02"PRIx8, *(const uint8_t*)p); break; case 2: - fprintf(f, "0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); + fprintf(f, "0x%02"PRIx16, dtb_ld16(p)); break; case 4: - fprintf(f, "0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); + fprintf(f, "0x%02"PRIx32, dtb_ld32(p)); break; case 8: - fprintf(f, "0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); + fprintf(f, "0x%02"PRIx64, dtb_ld64(p)); break; } if (p + width < end) diff --git a/yamltree.c b/yamltree.c index 5b6ea8e..4e93c12 100644 --- a/yamltree.c +++ b/yamltree.c @@ -59,10 +59,10 @@ static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, ch sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off)); break; case 2: - sprintf(buf, "0x%"PRIx16, fdt16_to_cpu(*(fdt16_t*)(data + off))); + sprintf(buf, "0x%"PRIx16, dtb_ld16(data + off)); break; case 4: - sprintf(buf, "0x%"PRIx32, fdt32_to_cpu(*(fdt32_t*)(data + off))); + sprintf(buf, "0x%"PRIx32, dtb_ld32(data + off)); m = markers; is_phandle = false; for_each_marker_of_type(m, REF_PHANDLE) { @@ -73,7 +73,7 @@ static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, ch } break; case 8: - sprintf(buf, "0x%"PRIx64, fdt64_to_cpu(*(fdt64_t*)(data + off))); + sprintf(buf, "0x%"PRIx64, dtb_ld64(data + off)); break; } From 85e5d839847af54efab170f2b1331b2a6421e647 Mon Sep 17 00:00:00 2001 From: Claudio Fontana Date: Tue, 12 May 2020 12:33:15 +0200 Subject: [PATCH 004/298] Makefile: when building libfdt only, do not add unneeded deps implemented originally for the QEMU consumer of libfdt. Signed-off-by: Claudio Fontana Message-Id: <20200512103315.1926-1-cfontana@suse.de> Signed-off-by: David Gibson --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index f02aa19..cb256e8 100644 --- a/Makefile +++ b/Makefile @@ -176,6 +176,7 @@ endif ifneq ($(DEPTARGETS),) +ifneq ($(MAKECMDGOALS),libfdt) -include $(DTC_OBJS:%.o=%.d) -include $(CONVERT_OBJS:%.o=%.d) -include $(FDTDUMP_OBJS:%.o=%.d) @@ -183,6 +184,7 @@ ifneq ($(DEPTARGETS),) -include $(FDTPUT_OBJS:%.o=%.d) -include $(FDTOVERLAY_OBJS:%.o=%.d) endif +endif @@ -318,7 +320,9 @@ ifeq ($(NO_PYTHON),0) TESTS_PYLIBFDT += maybe_pylibfdt endif +ifneq ($(MAKECMDGOALS),libfdt) include tests/Makefile.tests +endif # # Clean rules From 81e0919a3e211844245a3c19be28610f930c13c0 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 15 May 2020 15:18:25 +0100 Subject: [PATCH 005/298] checks: Add interrupt provider test An interrupt provider (an actual interrupt-controller node or an interrupt nexus) should have both #address-cells and #interrupt-cells properties explicitly defined. Add an extra test for this. We check for the #interrupt-cells property already, but this does not cover every controller so far, only those that get referenced by an interrupts property in some node. Also we miss interrupt nexus nodes. A missing #address-cells property is less critical, but creates ambiguities when used in interrupt-map properties, so warn about this as well now. This removes the now redundant warning in the existing interrupts test. Signed-off-by: Andre Przywara Message-Id: <20200515141827.27957-2-andre.przywara@arm.com> Signed-off-by: David Gibson --- checks.c | 25 ++++++++++++++++++++++++- tests/bad-interrupt-controller.dts | 7 +++++++ tests/run_tests.sh | 1 + 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 tests/bad-interrupt-controller.dts diff --git a/checks.c b/checks.c index 4b3c486..a8213c0 100644 --- a/checks.c +++ b/checks.c @@ -1547,6 +1547,28 @@ static bool node_is_interrupt_provider(struct node *node) return false; } + +static void check_interrupt_provider(struct check *c, + struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + if (!node_is_interrupt_provider(node)) + return; + + prop = get_property(node, "#interrupt-cells"); + if (!prop) + FAIL(c, dti, node, + "Missing #interrupt-cells in interrupt provider"); + + prop = get_property(node, "#address-cells"); + if (!prop) + FAIL(c, dti, node, + "Missing #address-cells in interrupt provider"); +} +WARNING(interrupt_provider, check_interrupt_provider, NULL); + static void check_interrupts_property(struct check *c, struct dt_info *dti, struct node *node) @@ -1604,7 +1626,7 @@ static void check_interrupts_property(struct check *c, prop = get_property(irq_node, "#interrupt-cells"); if (!prop) { - FAIL(c, dti, irq_node, "Missing #interrupt-cells in interrupt-parent"); + /* We warn about that already in another test. */ return; } @@ -1828,6 +1850,7 @@ static struct check *check_table[] = { &deprecated_gpio_property, &gpios_property, &interrupts_property, + &interrupt_provider, &alias_paths, diff --git a/tests/bad-interrupt-controller.dts b/tests/bad-interrupt-controller.dts new file mode 100644 index 0000000..62fa118 --- /dev/null +++ b/tests/bad-interrupt-controller.dts @@ -0,0 +1,7 @@ +/dts-v1/; + +/ { + intc: interrupt-controller { + interrupt-controller; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index eccb85d..294585b 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -714,6 +714,7 @@ dtc_tests () { check_tests "$SRCDIR/bad-graph.dts" graph_endpoint run_sh_test "$SRCDIR/dtc-checkfails.sh" deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/bad-gpio.dts" check_tests "$SRCDIR/bad-interrupt-cells.dts" interrupts_property + check_tests "$SRCDIR/bad-interrupt-controller.dts" interrupt_provider run_sh_test "$SRCDIR/dtc-checkfails.sh" node_name_chars -- -I dtb -O dtb bad_node_char.dtb run_sh_test "$SRCDIR/dtc-checkfails.sh" node_name_format -- -I dtb -O dtb bad_node_format.dtb run_sh_test "$SRCDIR/dtc-checkfails.sh" property_name_chars -- -I dtb -O dtb bad_prop_char.dtb From 7be250b4d059771c47be00ec8d4df7f47e4ac77c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Jun 2020 10:00:33 -0600 Subject: [PATCH 006/298] libfdt: Correct condition for reordering blocks This condition uses bitwise OR but should be logical OR. Fix it. Signed-off-by: Simon Glass Reported-by: kernel test robot Message-Id: <20200615160033.87328-1-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 524b520..93e4a2b 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -436,7 +436,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) return struct_size; } - if (can_assume(LIBFDT_ORDER) | + if (can_assume(LIBFDT_ORDER) || !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { /* no further work necessary */ err = fdt_move(fdt, buf, bufsize); From f68bfc2668b2e090b5b2f55cce93aad42fb08c6c Mon Sep 17 00:00:00 2001 From: Patrick Oppenlander Date: Thu, 18 Jun 2020 14:21:17 +1000 Subject: [PATCH 007/298] libfdt: trivial typo fix Signed-off-by: Patrick Oppenlander Message-Id: <20200618042117.131731-1-patrick.oppenlander@gmail.com> Signed-off-by: David Gibson --- libfdt/fdt_sw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 26759d5..94ce4bb 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -32,7 +32,7 @@ static int fdt_sw_probe_(void *fdt) /* 'memrsv' state: Initial state after fdt_create() * * Allowed functions: - * fdt_add_reservmap_entry() + * fdt_add_reservemap_entry() * fdt_finish_reservemap() [moves to 'struct' state] */ static int fdt_sw_probe_memrsv_(void *fdt) From 2478b1652c8d39ce7921cda83eaba9c86cadbd36 Mon Sep 17 00:00:00 2001 From: Patrick Oppenlander Date: Tue, 16 Jun 2020 11:12:17 +1000 Subject: [PATCH 008/298] libfdt: add extern "C" for C++ Signed-off-by: Patrick Oppenlander Message-Id: <20200616011217.15253-1-patrick.oppenlander@gmail.com> Signed-off-by: David Gibson --- libfdt/libfdt.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 48f375c..544d3ef 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -9,6 +9,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define FDT_FIRST_SUPPORTED_VERSION 0x02 #define FDT_LAST_SUPPORTED_VERSION 0x11 @@ -2069,4 +2073,8 @@ int fdt_overlay_apply(void *fdt, void *fdto); const char *fdt_strerror(int errval); +#ifdef __cplusplus +} +#endif + #endif /* LIBFDT_H */ From fdabcf2980a467bb255ea6661eba7273cfa7d708 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Mon, 22 Jun 2020 12:40:04 +0930 Subject: [PATCH 009/298] checks: Remove warning for I2C_OWN_SLAVE_ADDRESS dtc does a sanity check on reg properties that they are within the 10 bit address range for i2c slave addresses. In the case of multi-master buses or devices that act as a slave, the binding may describe an address that the bus will listen on as a device. Do not warn when this flag is set. See Documentation/devicetree/bindings/i2c/i2c.txt. This fixes the following build warnings reported by Stephen and by Arnd: arch/arm/boot/dts/aspeed-bmc-facebook-yosemitev2.dts:126.11-130.4: Warning (i2c_bus_reg): /ahb/apb/bus@1e78a000/i2c-bus@80/ipmb1@10: I2C bus unit address format error, expected "40000010" arch/arm/boot/dts/aspeed-bmc-facebook-yosemitev2.dts:128.3-30: Warning (i2c_bus_reg): /ahb/apb/bus@1e78a000/i2c-bus@80/ipmb1@10:reg: I2C address must be less than 10-bits, got "0x40000010" Reported-by: Stephen Rothwell Reported-by: Arnd Bergmann Signed-off-by: Joel Stanley Message-Id: <20200622031005.1890039-2-joel@jms.id.au> Signed-off-by: David Gibson --- checks.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/checks.c b/checks.c index a8213c0..69b0156 100644 --- a/checks.c +++ b/checks.c @@ -1022,6 +1022,8 @@ static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct no } WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells); +#define I2C_OWN_SLAVE_ADDRESS (1U << 30) + static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node) { struct property *prop; @@ -1044,6 +1046,8 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node } reg = fdt32_to_cpu(*cells); + /* Ignore I2C_OWN_SLAVE_ADDRESS */ + reg &= ~I2C_OWN_SLAVE_ADDRESS; snprintf(unit_addr, sizeof(unit_addr), "%x", reg); if (!streq(unitname, unit_addr)) FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"", @@ -1051,6 +1055,8 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node for (len = prop->val.len; len > 0; len -= 4) { reg = fdt32_to_cpu(*(cells++)); + /* Ignore I2C_OWN_SLAVE_ADDRESS */ + reg &= ~I2C_OWN_SLAVE_ADDRESS; if (reg > 0x3ff) FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"", reg); From 8259d59f59def85194bd71e855176a3b2ef8702f Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Mon, 22 Jun 2020 12:40:05 +0930 Subject: [PATCH 010/298] checks: Improve i2c reg property checking The i2c bindings in the kernel tree describe support for 10 bit addressing, which must be indicated with the I2C_TEN_BIT_ADDRESS flag. When this is set the address can be up to 10 bits. When it is not set the address is a maximum of 7 bits. See Documentation/devicetree/bindings/i2c/i2c.txt. Take into account this flag when checking the address is valid. Signed-off-by: Joel Stanley Message-Id: <20200622031005.1890039-3-joel@jms.id.au> Signed-off-by: David Gibson --- checks.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/checks.c b/checks.c index 69b0156..b7955db 100644 --- a/checks.c +++ b/checks.c @@ -1023,6 +1023,7 @@ static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct no WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells); #define I2C_OWN_SLAVE_ADDRESS (1U << 30) +#define I2C_TEN_BIT_ADDRESS (1U << 31) static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node) { @@ -1057,10 +1058,13 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node reg = fdt32_to_cpu(*(cells++)); /* Ignore I2C_OWN_SLAVE_ADDRESS */ reg &= ~I2C_OWN_SLAVE_ADDRESS; - if (reg > 0x3ff) + + if ((reg & I2C_TEN_BIT_ADDRESS) && ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff)) FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"", reg); - + else if (reg > 0x7f) + FAIL_PROP(c, dti, node, prop, "I2C address must be less than 7-bits, got \"0x%x\". Set I2C_TEN_BIT_ADDRESS for 10 bit addresses or fix the property", + reg); } } WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, ®_format, &i2c_bus_bridge); From 9d7888cbf19c2930992844e69a097dc71e5a7354 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 23 Jun 2020 11:43:43 +0200 Subject: [PATCH 011/298] dtc: Consider one-character strings as strings When using overlays, a target-path property pointing to the root node is quite common. However, "dtc -O dts" prints it as a byte array: target-path = [2f 00]; instead of a string: target-path = "/"; For guess_value_type() to consider a value to be a string, it must contain less nul bytes than non-nul bytes, thus ruling out strings containing only a single character. Allow printing such strings by relaxing the condition slightly. Signed-off-by: Geert Uytterhoeven Message-Id: <20200623094343.26010-1-geert+renesas@glider.be> Signed-off-by: David Gibson --- treesource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/treesource.c b/treesource.c index 2acb920..061ba8c 100644 --- a/treesource.c +++ b/treesource.c @@ -183,7 +183,7 @@ static enum markertype guess_value_type(struct property *prop) nnotcelllbl++; } - if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) + if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul)) && (nnotstringlbl == 0)) { return TYPE_STRING; } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { From 3e3138b4a9565934487d7b39019282e75a894487 Mon Sep 17 00:00:00 2001 From: Patrick Oppenlander Date: Thu, 9 Jul 2020 14:14:51 +1000 Subject: [PATCH 012/298] libfdt: fix fdt_check_full buffer overrun fdt_check_header assumes that its argument points to a complete header and can read data beyond the FDT_V1_SIZE bytes which fdt_check_full can provide. fdt_header_size can safely return a header size with FDT_V1_SIZE bytes available and will return a usable value even for a corrupted header. Signed-off-by: Patrick Oppenlander Message-Id: <20200709041451.338548-1-patrick.oppenlander@gmail.com> Signed-off-by: David Gibson --- libfdt/fdt_check.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libfdt/fdt_check.c b/libfdt/fdt_check.c index 7f6a96c..9ddfdbf 100644 --- a/libfdt/fdt_check.c +++ b/libfdt/fdt_check.c @@ -22,6 +22,8 @@ int fdt_check_full(const void *fdt, size_t bufsize) if (bufsize < FDT_V1_SIZE) return -FDT_ERR_TRUNCATED; + if (bufsize < fdt_header_size(fdt)) + return -FDT_ERR_TRUNCATED; err = fdt_check_header(fdt); if (err != 0) return err; From 808cdaaf524f6beb95e0ea87fc42711dbddef21a Mon Sep 17 00:00:00 2001 From: Andrei Ziureaev Date: Tue, 14 Jul 2020 16:45:37 +0100 Subject: [PATCH 013/298] dtc: Avoid UB when shifting Prevent undefined behavior when shifting by a number that's bigger than or equal to the width of the first operand. Signed-off-by: Andrei Ziureaev Message-Id: <20200714154542.18064-2-andrei.ziureaev@arm.com> Signed-off-by: David Gibson --- dtc-parser.y | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 40dcf4f..a0316a3 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -476,8 +476,8 @@ integer_rela: ; integer_shift: - integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; } - | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; } + integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; } + | integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; } | integer_add ; From 3d522abc7571e1851ce71fcf0c3452ef287b1bab Mon Sep 17 00:00:00 2001 From: Andrei Ziureaev Date: Tue, 21 Jul 2020 16:58:57 +0100 Subject: [PATCH 014/298] dtc: Include stdlib.h in util.h If used on its own, util.h needs stdlib.h for exit(), malloc() and realloc(). Signed-off-by: Andrei Ziureaev Message-Id: <20200721155900.9147-2-andrei.ziureaev@arm.com> Signed-off-by: David Gibson --- util.h | 1 + 1 file changed, 1 insertion(+) diff --git a/util.h b/util.h index 5a4172d..a771b46 100644 --- a/util.h +++ b/util.h @@ -2,6 +2,7 @@ #ifndef UTIL_H #define UTIL_H +#include #include #include #include From 7bb86f1c09563f502c6ab0166feacf346e4e8c40 Mon Sep 17 00:00:00 2001 From: Frank Mehnert Date: Thu, 13 Aug 2020 17:26:26 +0200 Subject: [PATCH 015/298] libfdt: fix fdt_check_node_offset_ w/ VALID_INPUT fdt_check_node_offset_() checks for a valid offset but also changes the offset by calling fdt_next_tag(). Hence, do not skip this function if ASSUME_VALID_INPUT is set but only omit the initial offset check in that case. As this function works very similar to fdt_check_prop_offset_(), do the offset check there as well depending on ASSUME_VALID_INPUT. Message-Id: <1913141.TlUzK5foHS@noys4> Signed-off-by: David Gibson --- libfdt/fdt.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index c28fcc1..37b7b93 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -206,10 +206,11 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) int fdt_check_node_offset_(const void *fdt, int offset) { - if (can_assume(VALID_INPUT)) - return offset; - if ((offset < 0) || (offset % FDT_TAGSIZE) - || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) + if (!can_assume(VALID_INPUT) + && ((offset < 0) || (offset % FDT_TAGSIZE))) + return -FDT_ERR_BADOFFSET; + + if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE) return -FDT_ERR_BADOFFSET; return offset; @@ -217,8 +218,11 @@ int fdt_check_node_offset_(const void *fdt, int offset) int fdt_check_prop_offset_(const void *fdt, int offset) { - if ((offset < 0) || (offset % FDT_TAGSIZE) - || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) + if (!can_assume(VALID_INPUT) + && ((offset < 0) || (offset % FDT_TAGSIZE))) + return -FDT_ERR_BADOFFSET; + + if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP) return -FDT_ERR_BADOFFSET; return offset; From ca19c3db2bf62000101ae8f83c37cd6e0d44d218 Mon Sep 17 00:00:00 2001 From: Emmanuel Vadot Date: Tue, 25 Aug 2020 12:34:18 +0200 Subject: [PATCH 016/298] Makefile: Specify cflags for libyaml Some systems don't install third party software includes in a default path (like FreeBSD), add yaml cflags to fix compilation. Signed-off-by: Emmanuel Vadot --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index cb256e8..c187d5f 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,7 @@ ifeq ($(NO_YAML),1) CFLAGS += -DNO_YAML else LDLIBS_dtc += $(shell $(PKG_CONFIG) --libs yaml-0.1) + CFLAGS += $(shell $(PKG_CONFIG) --cflags yaml-0.1) endif ifeq ($(HOSTOS),darwin) From 442ea3dd157906ce23df8001095562d3492a471c Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 21 Sep 2020 17:52:50 +0100 Subject: [PATCH 017/298] libfdt: fdt_offset_ptr(): Fix comparison warnings With -Wsign-compare, compilers warn about mismatching signedness in comparisons in fdt_offset_ptr(). This mostly stems from "offset" being passed in as a signed integer, even though the function would not really tolerate negative values. Short of changing the prototype, check that offset is not negative, and use an unsigned type internally. Signed-off-by: Andre Przywara Message-Id: <20200921165303.9115-2-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 37b7b93..04e1e06 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -134,16 +134,20 @@ int fdt_check_header(const void *fdt) const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { - unsigned absoffset = offset + fdt_off_dt_struct(fdt); + unsigned int uoffset = offset; + unsigned int absoffset = offset + fdt_off_dt_struct(fdt); + + if (offset < 0) + return NULL; if (!can_assume(VALID_INPUT)) - if ((absoffset < offset) + if ((absoffset < uoffset) || ((absoffset + len) < absoffset) || (absoffset + len) > fdt_totalsize(fdt)) return NULL; if (can_assume(LATEST) || fdt_version(fdt) >= 0x11) - if (((offset + len) < offset) + if (((uoffset + len) < uoffset) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; From 0c43d4d7bf5a3a2e83d2005daf1e44ea5bd7f069 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 21 Sep 2020 17:52:51 +0100 Subject: [PATCH 018/298] libfdt: fdt_mem_rsv(): Fix comparison warnings With -Wsign-compare, compilers warn about a mismatching signedness in comparisons in fdt_mem_rsv(). Since all involved values must be positive, change the used types to be unsigned. Signed-off-by: Andre Przywara Message-Id: <20200921165303.9115-3-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index e03570a..3c8d143 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -157,8 +157,8 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle) static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) { - int offset = n * sizeof(struct fdt_reserve_entry); - int absoffset = fdt_off_mem_rsvmap(fdt) + offset; + unsigned int offset = n * sizeof(struct fdt_reserve_entry); + unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset; if (!can_assume(VALID_INPUT)) { if (absoffset < fdt_off_mem_rsvmap(fdt)) From f8e11e61624e7ea9307655fe4b5bb66f2d0c1be8 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 21 Sep 2020 17:52:52 +0100 Subject: [PATCH 019/298] libfdt: fdt_grab_space_(): Fix comparison warning With -Wsign-compare, compilers warn about a mismatching signedness in a comparison in fdt_grab_space_(). All the involved values cannot be negative, so let's switch the types of the local variables to unsigned to make the compiler happy. Signed-off-by: Andre Przywara Message-Id: <20200921165303.9115-4-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt_sw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 94ce4bb..d10a720 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -93,8 +93,8 @@ static inline uint32_t sw_flags(void *fdt) static void *fdt_grab_space_(void *fdt, size_t len) { - int offset = fdt_size_dt_struct(fdt); - int spaceleft; + unsigned int offset = fdt_size_dt_struct(fdt); + unsigned int spaceleft; spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) - fdt_size_dt_strings(fdt); From 54dca098531699dc8beeaf97e3525b9b5eb23b0a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Sep 2020 17:52:55 +0100 Subject: [PATCH 020/298] libfdt: fdt_get_string(): Fix comparison warnings With -Wsign-compare, compilers warn about a mismatching signedness in comparisons in fdt_get_string(). In the first two cases, we have just established that the signed values are not negative, so it's safe to cast the values to an unsigned type. Signed-off-by: Simon Glass Signed-off-by: Andre Przywara Message-Id: <20200921165303.9115-7-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 3c8d143..ddb5a2d 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -53,7 +53,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) err = -FDT_ERR_BADOFFSET; absoffset = stroffset + fdt_off_dt_strings(fdt); - if (absoffset >= totalsize) + if (absoffset >= (unsigned)totalsize) goto fail; len = totalsize - absoffset; @@ -61,7 +61,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) if (stroffset < 0) goto fail; if (can_assume(LATEST) || fdt_version(fdt) >= 17) { - if (stroffset >= fdt_size_dt_strings(fdt)) + if ((unsigned)stroffset >= fdt_size_dt_strings(fdt)) goto fail; if ((fdt_size_dt_strings(fdt) - stroffset) < len) len = fdt_size_dt_strings(fdt) - stroffset; From faa76fc10bc5819899d6bc78535d212acaccbd6a Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 21 Sep 2020 17:52:56 +0100 Subject: [PATCH 021/298] libfdt: fdt_splice_(): Fix comparison warning With -Wsign-compare, compilers warn about a mismatching signedness in a comparison in fdt_splice_(). Since we just established that oldlen is not negative, we can safely cast it to an unsigned type. Signed-off-by: Andre Przywara Message-Id: <20200921165303.9115-8-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 93e4a2b..68887b9 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -59,7 +59,7 @@ static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize)) return -FDT_ERR_BADOFFSET; - if ((p < (char *)fdt) || (dsize + newlen < oldlen)) + if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen)) return -FDT_ERR_BADOFFSET; if (dsize - oldlen + newlen > fdt_totalsize(fdt)) return -FDT_ERR_NOSPACE; From ce9e1f25a7de457734d0fb314224c99102e7ebbe Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 21 Sep 2020 17:52:58 +0100 Subject: [PATCH 022/298] libfdt: fdt_resize(): Fix comparison warning With -Wsign-compare, compilers warn about a mismatching signedness in a comparison in fdt_resize(). A negative buffer size will surely do us no good, so let's rule this case out first. In the actual comparison we then know that a cast to an unsigned type is safe. Signed-off-by: Andre Przywara Message-Id: <20200921165303.9115-10-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt_sw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index d10a720..8de18fd 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -152,6 +152,9 @@ int fdt_resize(void *fdt, void *buf, int bufsize) FDT_SW_PROBE(fdt); + if (bufsize < 0) + return -FDT_ERR_NOSPACE; + headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); tailsize = fdt_size_dt_strings(fdt); @@ -159,7 +162,7 @@ int fdt_resize(void *fdt, void *buf, int bufsize) headsize + tailsize > fdt_totalsize(fdt)) return -FDT_ERR_INTERNAL; - if ((headsize + tailsize) > bufsize) + if ((headsize + tailsize) > (unsigned)bufsize) return -FDT_ERR_NOSPACE; oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; From 07158f4cf2a2fa2267b7a86f138a4f16ecb54172 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 21 Sep 2020 17:53:00 +0100 Subject: [PATCH 023/298] libfdt: overlay: Fix comparison warning With -Wsign-compare, compilers warn about a mismatching signedness in a comparison in overlay_update_local_node_references(). This happens because the division of a signed int by an unsigned int promotes the dividend to unsigned first (ANSI C standard 6.1.3.8). As in this case we basically just divide by 4, we can do the division separately earlier, which preserves the original type. Signed-off-by: Andre Przywara Message-Id: <20200921165303.9115-12-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index b310e49..d217e79 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -241,6 +241,7 @@ static int overlay_update_local_node_references(void *fdto, if (fixup_len % sizeof(uint32_t)) return -FDT_ERR_BADOVERLAY; + fixup_len /= sizeof(uint32_t); tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); if (!tree_val) { @@ -250,7 +251,7 @@ static int overlay_update_local_node_references(void *fdto, return tree_len; } - for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) { + for (i = 0; i < fixup_len; i++) { fdt32_t adj_val; uint32_t poffset; From 10f682788c3023d319cdc14f59ffe9d91cb6d2fc Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 21 Sep 2020 17:53:02 +0100 Subject: [PATCH 024/298] libfdt: fdt_node_offset_by_phandle(): Fix comparison warning With -Wsign-compare, compilers warn about a mismatching signedness in a comparison in fdt_node_offset_by_phandle(). Uses a better suited bitwise NOT operator to denote the special value of -1, which automatically results in an unsigned type. Signed-off-by: Andre Przywara Message-Id: <20200921165303.9115-14-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index ddb5a2d..e192184 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -680,7 +680,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) { int offset; - if ((phandle == 0) || (phandle == -1)) + if ((phandle == 0) || (phandle == ~0U)) return -FDT_ERR_BADPHANDLE; FDT_RO_PROBE(fdt); From 3d7c6f44195a78dfa52b1b8c9efd7efd706b0dd9 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 1 Oct 2020 17:46:25 +0100 Subject: [PATCH 025/298] libfdt: fdt_add_string_(): Fix comparison warning With -Wsign-compare, compilers warn about a mismatching signedness in a comparison in fdt_add_string_(). Make all variables unsigned, and express the negative offset trick via subtractions in the code. Signed-off-by: Andre Przywara Message-Id: <20201001164630.4980-2-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt_sw.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 8de18fd..354f466 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -250,18 +250,18 @@ int fdt_end_node(void *fdt) static int fdt_add_string_(void *fdt, const char *s) { char *strtab = (char *)fdt + fdt_totalsize(fdt); - int strtabsize = fdt_size_dt_strings(fdt); - int len = strlen(s) + 1; - int struct_top, offset; + unsigned int strtabsize = fdt_size_dt_strings(fdt); + unsigned int len = strlen(s) + 1; + unsigned int struct_top, offset; - offset = -strtabsize - len; + offset = strtabsize + len; struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); - if (fdt_totalsize(fdt) + offset < struct_top) + if (fdt_totalsize(fdt) - offset < struct_top) return 0; /* no more room :( */ - memcpy(strtab + offset, s, len); + memcpy(strtab - offset, s, len); fdt_set_size_dt_strings(fdt, strtabsize + len); - return offset; + return -offset; } /* Must only be used to roll back in case of error */ From f28aa271000bfeaa765b824a8a3e7b170da12925 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 1 Oct 2020 17:46:26 +0100 Subject: [PATCH 026/298] libfdt: fdt_move(): Fix comparison warnings With -Wsign-compare, compilers warn about a mismatching signedness in comparisons in fdt_move(). This stems from "bufsize" being passed in as a signed integer, even though we would expect a buffer size to be positive. Short of changing the prototype, check that bufsize is not negative, and cast it to an unsigned type in the comparison. Signed-off-by: Andre Przywara Message-Id: <20201001164630.4980-3-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 04e1e06..6cf2fa0 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -314,9 +314,12 @@ const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) int fdt_move(const void *fdt, void *buf, int bufsize) { + if (!can_assume(VALID_INPUT) && bufsize < 0) + return -FDT_ERR_NOSPACE; + FDT_RO_PROBE(fdt); - if (fdt_totalsize(fdt) > bufsize) + if (fdt_totalsize(fdt) > (unsigned int)bufsize) return -FDT_ERR_NOSPACE; memmove(buf, fdt, fdt_totalsize(fdt)); From fb1f65f158327895acd360683e5c6da56d6944ea Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 1 Oct 2020 17:46:27 +0100 Subject: [PATCH 027/298] libfdt: fdt_create_with_flags(): Fix comparison warning With -Wsign-compare, compilers warn about a mismatching signedness in a comparison in fdt_create_with_flags(). By making hdrsize a signed integer (we are sure it's a very small number), we avoid all the casts and have matching types. Signed-off-by: Andre Przywara Message-Id: <20201001164630.4980-4-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt_sw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 354f466..68b543c 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -108,8 +108,8 @@ static void *fdt_grab_space_(void *fdt, size_t len) int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags) { - const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header), - sizeof(struct fdt_reserve_entry)); + const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry)); void *fdt = buf; if (bufsize < hdrsize) From 82525f41d59ec57a4e9325796a6f1baefc036236 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 1 Oct 2020 17:46:28 +0100 Subject: [PATCH 028/298] libfdt: libfdt_wip: Fix comparison warning With -Wsign-compare, compilers warn about a mismatching signedness in a comparison in fdt_setprop_inplace_namelen_partial(). fdt_getprop_namelen() will only return negative error values in "proplen" if the return value is NULL. So we can rely on "proplen" being positive in our case and can safely cast it to an unsigned type. Signed-off-by: Andre Przywara Message-Id: <20201001164630.4980-5-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt_wip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c index f64139e..c2d7566 100644 --- a/libfdt/fdt_wip.c +++ b/libfdt/fdt_wip.c @@ -23,7 +23,7 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, if (!propval) return proplen; - if (proplen < (len + idx)) + if ((unsigned)proplen < (len + idx)) return -FDT_ERR_NOSPACE; memcpy((char *)propval + idx, val, len); From 6c2be7d85315008be974984c0c86a8c8e55adeea Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 1 Oct 2020 17:46:29 +0100 Subject: [PATCH 029/298] libfdt: fdt_get_string(): Fix sequential write comparison warnings With -Wsign-compare, compilers warn about a mismatching signedness in comparisons in fdt_get_string(). Introduce a new usigned variable, which holds the actual (negated) stroffset value, so we avoid negating all the other variables and have proper types everywhere. Signed-off-by: Andre Przywara Message-Id: <20201001164630.4980-6-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index e192184..91cc6fe 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -67,11 +67,13 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) len = fdt_size_dt_strings(fdt) - stroffset; } } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { - if ((stroffset >= 0) - || (stroffset < -fdt_size_dt_strings(fdt))) + unsigned int sw_stroffset = -stroffset; + + if ((stroffset >= 0) || + (sw_stroffset > fdt_size_dt_strings(fdt))) goto fail; - if ((-stroffset) < len) - len = -stroffset; + if (sw_stroffset < len) + len = sw_stroffset; } else { err = -FDT_ERR_INTERNAL; goto fail; From 73e0f143b73d80889124e209548ee46834c6b559 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 1 Oct 2020 17:46:30 +0100 Subject: [PATCH 030/298] libfdt: fdt_strerror(): Fix comparison warning With -Wsign-compare, compilers warn about a mismatching signedness in a comparison in fdt_strerror(). Force FDT_ERRTABSIZE to be signed (it's surely small enough to fit), so that the types match. Also move the minus sign to errval, as this is actually what we use in the next line. Signed-off-by: Andre Przywara Message-Id: <20201001164630.4980-7-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/fdt_strerror.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c index 768db66..b435693 100644 --- a/libfdt/fdt_strerror.c +++ b/libfdt/fdt_strerror.c @@ -40,7 +40,7 @@ static struct fdt_errtabent fdt_errtable[] = { FDT_ERRTABENT(FDT_ERR_NOPHANDLES), FDT_ERRTABENT(FDT_ERR_BADFLAGS), }; -#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) +#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))) const char *fdt_strerror(int errval) { @@ -48,7 +48,7 @@ const char *fdt_strerror(int errval) return ""; else if (errval == 0) return ""; - else if (errval > -FDT_ERRTABSIZE) { + else if (-errval < FDT_ERRTABSIZE) { const char *s = fdt_errtable[-errval].str; if (s) From cbca977ea121d7483b0c2351b17dca08a21cb1ca Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 28 Sep 2020 15:19:41 -0500 Subject: [PATCH 031/298] checks: Allow PCI bridge child nodes without an address Some PCI bridge nodes have child nodes such as an interrupt controller which are not PCI devices. Allow these nodes which don't have a unit-address. Signed-off-by: Rob Herring Message-Id: <20200928201942.3242124-1-robh@kernel.org> Signed-off-by: David Gibson --- checks.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/checks.c b/checks.c index b7955db..17cb689 100644 --- a/checks.c +++ b/checks.c @@ -891,10 +891,8 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no return; prop = get_property(node, "reg"); - if (!prop) { - FAIL(c, dti, node, "missing PCI reg property"); + if (!prop) return; - } cells = (cell_t *)prop->val.val; if (cells[1] || cells[2]) From b30013edb878a0e4fbe7235f38d8fd6e644479e5 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 12 Oct 2020 17:53:31 +0100 Subject: [PATCH 032/298] libfdt: Fix kernel-doc comments The API documentation in libfdt.h seems to follow the Linux kernel's kernel-doc format[1]. Running "scripts/kernel-doc -v -none" on the file reports some problems, mostly missing return values and missing parameter descriptions. Fix those up by providing the missing bits, and fixing the other small issues reported by the script. Signed-off-by: Andre Przywara [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/doc-guide/kernel-doc.rst Message-Id: <20201012165331.25016-1-andre.przywara@arm.com> Signed-off-by: David Gibson --- libfdt/libfdt.h | 111 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 75 insertions(+), 36 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 544d3ef..5979832 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -184,23 +184,23 @@ int fdt_next_node(const void *fdt, int offset, int *depth); /** * fdt_first_subnode() - get offset of first direct subnode - * * @fdt: FDT blob * @offset: Offset of node to check - * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none + * + * Return: offset of first subnode, or -FDT_ERR_NOTFOUND if there is none */ int fdt_first_subnode(const void *fdt, int offset); /** * fdt_next_subnode() - get offset of next direct subnode + * @fdt: FDT blob + * @offset: Offset of previous subnode * * After first calling fdt_first_subnode(), call this function repeatedly to * get direct subnodes of a parent node. * - * @fdt: FDT blob - * @offset: Offset of previous subnode - * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more - * subnodes + * Return: offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more + * subnodes */ int fdt_next_subnode(const void *fdt, int offset); @@ -225,7 +225,6 @@ int fdt_next_subnode(const void *fdt, int offset); * Note that this is implemented as a macro and @node is used as * iterator in the loop. The parent variable be constant or even a * literal. - * */ #define fdt_for_each_subnode(node, fdt, parent) \ for (node = fdt_first_subnode(fdt, parent); \ @@ -269,17 +268,21 @@ fdt_set_hdr_(size_dt_struct); /** * fdt_header_size - return the size of the tree's header * @fdt: pointer to a flattened device tree + * + * Return: size of DTB header in bytes */ size_t fdt_header_size(const void *fdt); /** - * fdt_header_size_ - internal function which takes a version number + * fdt_header_size_ - internal function to get header size from a version number + * @version: devicetree version number + * + * Return: size of DTB header in bytes */ size_t fdt_header_size_(uint32_t version); /** * fdt_check_header - sanity check a device tree header - * @fdt: pointer to data which might be a flattened device tree * * fdt_check_header() checks that the given buffer contains what @@ -404,8 +407,7 @@ static inline uint32_t fdt_get_max_phandle(const void *fdt) * highest phandle value in the device tree blob) will be returned in the * @phandle parameter. * - * Returns: - * 0 on success or a negative error-code on failure + * Return: 0 on success or a negative error-code on failure */ int fdt_generate_phandle(const void *fdt, uint32_t *phandle); @@ -425,9 +427,11 @@ int fdt_num_mem_rsv(const void *fdt); /** * fdt_get_mem_rsv - retrieve one memory reserve map entry * @fdt: pointer to the device tree blob - * @address, @size: pointers to 64-bit variables + * @n: index of reserve map entry + * @address: pointer to 64-bit variable to hold the start address + * @size: pointer to 64-bit variable to hold the size of the entry * - * On success, *address and *size will contain the address and size of + * On success, @address and @size will contain the address and size of * the n-th reserve map entry from the device tree blob, in * native-endian format. * @@ -450,6 +454,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); * namelen characters of name for matching the subnode name. This is * useful for finding subnodes based on a portion of a larger string, * such as a full path. + * + * Return: offset of the subnode or -FDT_ERR_NOTFOUND if name not found. */ #ifndef SWIG /* Not available in Python */ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, @@ -489,6 +495,8 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); * * Identical to fdt_path_offset(), but only consider the first namelen * characters of path as the path name. + * + * Return: offset of the node or negative libfdt error value otherwise */ #ifndef SWIG /* Not available in Python */ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); @@ -588,9 +596,9 @@ int fdt_next_property_offset(const void *fdt, int offset); /** * fdt_for_each_property_offset - iterate over all properties of a node * - * @property_offset: property offset (int, lvalue) - * @fdt: FDT blob (const void *) - * @node: node offset (int) + * @property: property offset (int, lvalue) + * @fdt: FDT blob (const void *) + * @node: node offset (int) * * This is actually a wrapper around a for loop and would be used like so: * @@ -653,6 +661,9 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, * * Identical to fdt_get_property(), but only examine the first namelen * characters of name for matching the property name. + * + * Return: pointer to the structure representing the property, or NULL + * if not found */ #ifndef SWIG /* Not available in Python */ const struct fdt_property *fdt_get_property_namelen(const void *fdt, @@ -745,6 +756,8 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, * * Identical to fdt_getprop(), but only examine the first namelen * characters of name for matching the property name. + * + * Return: pointer to the property's value or NULL on error */ #ifndef SWIG /* Not available in Python */ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, @@ -766,10 +779,10 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, * @lenp: pointer to an integer variable (will be overwritten) or NULL * * fdt_getprop() retrieves a pointer to the value of the property - * named 'name' of the node at offset nodeoffset (this will be a + * named @name of the node at offset @nodeoffset (this will be a * pointer to within the device blob itself, not a copy of the value). - * If lenp is non-NULL, the length of the property value is also - * returned, in the integer pointed to by lenp. + * If @lenp is non-NULL, the length of the property value is also + * returned, in the integer pointed to by @lenp. * * returns: * pointer to the property's value @@ -814,8 +827,11 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); * @name: name of the alias th look up * @namelen: number of characters of name to consider * - * Identical to fdt_get_alias(), but only examine the first namelen - * characters of name for matching the alias name. + * Identical to fdt_get_alias(), but only examine the first @namelen + * characters of @name for matching the alias name. + * + * Return: a pointer to the expansion of the alias named @name, if it exists, + * NULL otherwise */ #ifndef SWIG /* Not available in Python */ const char *fdt_get_alias_namelen(const void *fdt, @@ -828,7 +844,7 @@ const char *fdt_get_alias_namelen(const void *fdt, * @name: name of the alias th look up * * fdt_get_alias() retrieves the value of a given alias. That is, the - * value of the property named 'name' in the node /aliases. + * value of the property named @name in the node /aliases. * * returns: * a pointer to the expansion of the alias named 'name', if it exists @@ -1004,14 +1020,13 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); /** - * fdt_node_check_compatible: check a node's compatible property + * fdt_node_check_compatible - check a node's compatible property * @fdt: pointer to the device tree blob * @nodeoffset: offset of a tree node * @compatible: string to match against * - * * fdt_node_check_compatible() returns 0 if the given node contains a - * 'compatible' property with the given string as one of its elements, + * @compatible property with the given string as one of its elements, * it returns non-zero otherwise, or on error. * * returns: @@ -1075,7 +1090,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, * one or more strings, each terminated by \0, as is found in a device tree * "compatible" property. * - * @return: 1 if the string is found in the list, 0 not found, or invalid list + * Return: 1 if the string is found in the list, 0 not found, or invalid list */ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); @@ -1084,7 +1099,8 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); * @fdt: pointer to the device tree blob * @nodeoffset: offset of a tree node * @property: name of the property containing the string list - * @return: + * + * Return: * the number of strings in the given property * -FDT_ERR_BADVALUE if the property value is not NUL-terminated * -FDT_ERR_NOTFOUND if the property does not exist @@ -1104,7 +1120,7 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); * small-valued cell properties, such as #address-cells, when searching for * the empty string. * - * @return: + * return: * the index of the string in the list of strings * -FDT_ERR_BADVALUE if the property value is not NUL-terminated * -FDT_ERR_NOTFOUND if the property does not exist or does not contain @@ -1128,7 +1144,7 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, * If non-NULL, the length of the string (on success) or a negative error-code * (on failure) will be stored in the integer pointer to by lenp. * - * @return: + * Return: * A pointer to the string at the given index in the string list or NULL on * failure. On success the length of the string will be stored in the memory * location pointed to by the lenp parameter, if non-NULL. On failure one of @@ -1217,6 +1233,8 @@ int fdt_size_cells(const void *fdt, int nodeoffset); * starting from the given index, and using only the first characters * of the name. It is useful when you want to manipulate only one value of * an array and you have a string that doesn't end with \0. + * + * Return: 0 on success, negative libfdt error value otherwise */ #ifndef SWIG /* Not available in Python */ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, @@ -1330,8 +1348,13 @@ static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, /** * fdt_setprop_inplace_cell - change the value of a single-cell property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node containing the property + * @name: name of the property to change the value of + * @val: new value of the 32-bit cell * * This is an alternative name for fdt_setprop_inplace_u32() + * Return: 0 on success, negative libfdt error number otherwise. */ static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, const char *name, uint32_t val) @@ -1403,7 +1426,7 @@ int fdt_nop_node(void *fdt, int nodeoffset); /** * fdt_create_with_flags - begin creation of a new fdt - * @fdt: pointer to memory allocated where fdt will be created + * @buf: pointer to memory allocated where fdt will be created * @bufsize: size of the memory space at fdt * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0. * @@ -1421,7 +1444,7 @@ int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags); /** * fdt_create - begin creation of a new fdt - * @fdt: pointer to memory allocated where fdt will be created + * @buf: pointer to memory allocated where fdt will be created * @bufsize: size of the memory space at fdt * * fdt_create() is equivalent to fdt_create_with_flags() with flags=0. @@ -1486,7 +1509,8 @@ int fdt_pack(void *fdt); /** * fdt_add_mem_rsv - add one memory reserve map entry * @fdt: pointer to the device tree blob - * @address, @size: 64-bit values (native endian) + * @address: 64-bit start address of the reserve map entry + * @size: 64-bit size of the reserved region * * Adds a reserve map entry to the given blob reserving a region at * address address of length size. @@ -1691,8 +1715,14 @@ static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, /** * fdt_setprop_cell - set a property to a single cell value + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value for the property (native endian) * * This is an alternative name for fdt_setprop_u32() + * + * Return: 0 on success, negative libfdt error value otherwise. */ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, uint32_t val) @@ -1863,8 +1893,14 @@ static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, /** * fdt_appendprop_cell - append a single cell value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value to append to the property (native endian) * * This is an alternative name for fdt_appendprop_u32() + * + * Return: 0 on success, negative libfdt error value otherwise. */ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, const char *name, uint32_t val) @@ -1967,13 +2003,16 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name); * fdt_add_subnode_namelen - creates a new node based on substring * @fdt: pointer to the device tree blob * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate + * @name: name of the subnode to create * @namelen: number of characters of name to consider * - * Identical to fdt_add_subnode(), but use only the first namelen - * characters of name as the name of the new node. This is useful for + * Identical to fdt_add_subnode(), but use only the first @namelen + * characters of @name as the name of the new node. This is useful for * creating subnodes based on a portion of a larger string, such as a * full path. + * + * Return: structure block offset of the created subnode (>=0), + * negative libfdt error value otherwise */ #ifndef SWIG /* Not available in Python */ int fdt_add_subnode_namelen(void *fdt, int parentoffset, @@ -1992,7 +2031,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, * * This function will insert data into the blob, and will therefore * change the offsets of some existing nodes. - + * * returns: * structure block offset of the created nodeequested subnode (>=0), on * success From 04cf1fdc0fcf471c2e77376101bda65f727b3812 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 12 Oct 2020 17:19:39 +0100 Subject: [PATCH 033/298] convert-dtsv0: Fix signedness comparisons warning With -Wsign-compare, compilers warn about a mismatching signedness in comparisons in the generated lexer code. In this case we walk over an array, and never use negative indicies, so we can change the loop counter variable to be unsigned. This fixes "make convert-dtsv0", when compiled with -Wsign-compare. Signed-off-by: Andre Przywara Message-Id: <20201012161948.23994-3-andre.przywara@arm.com> Signed-off-by: David Gibson --- convert-dtsv0-lexer.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index f52e8a1..7a66f57 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -94,7 +94,7 @@ static const struct { [0-9a-fA-F]+ { unsigned long long val; int obase = 16, width = 0; - int i; + unsigned int i; val = strtoull(yytext, NULL, cbase); From e1147b159e9209e1c3102f350445ba9927048b4d Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 12 Oct 2020 17:19:43 +0100 Subject: [PATCH 034/298] dtc: Fix signedness comparisons warnings: change types With -Wsign-compare, compilers warn about a mismatching signedness in comparisons in various parts of dtc. Many variables are using signed types unnecessarily, as we never use negative value in them. Change their types to be unsigned, to prevent issues with comparisons. Signed-off-by: Andre Przywara Message-Id: <20201012161948.23994-7-andre.przywara@arm.com> Signed-off-by: David Gibson --- data.c | 4 ++-- dtc.h | 8 ++++---- flattree.c | 8 ++++---- livetree.c | 2 +- yamltree.c | 6 +++--- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/data.c b/data.c index 0a43b6d..fdb0407 100644 --- a/data.c +++ b/data.c @@ -21,10 +21,10 @@ void data_free(struct data d) free(d.val); } -struct data data_grow_for(struct data d, int xlen) +struct data data_grow_for(struct data d, unsigned int xlen) { struct data nd; - int newsize; + unsigned int newsize; if (xlen == 0) return d; diff --git a/dtc.h b/dtc.h index a08f415..d3e82fb 100644 --- a/dtc.h +++ b/dtc.h @@ -105,13 +105,13 @@ extern const char *markername(enum markertype markertype); struct marker { enum markertype type; - int offset; + unsigned int offset; char *ref; struct marker *next; }; struct data { - int len; + unsigned int len; char *val; struct marker *markers; }; @@ -129,7 +129,7 @@ size_t type_marker_length(struct marker *m); void data_free(struct data d); -struct data data_grow_for(struct data d, int xlen); +struct data data_grow_for(struct data d, unsigned int xlen); struct data data_copy_mem(const char *mem, int len); struct data data_copy_escape_string(const char *s, int len); @@ -253,7 +253,7 @@ void append_to_property(struct node *node, const char *get_unitname(struct node *node); struct property *get_property(struct node *node, const char *propname); cell_t propval_cell(struct property *prop); -cell_t propval_cell_n(struct property *prop, int n); +cell_t propval_cell_n(struct property *prop, unsigned int n); struct property *get_property_by_label(struct node *tree, const char *label, struct node **node); struct marker *get_marker_label(struct node *tree, const char *label, diff --git a/flattree.c b/flattree.c index 07f10d2..4659afb 100644 --- a/flattree.c +++ b/flattree.c @@ -149,7 +149,7 @@ static void asm_emit_align(void *e, int a) static void asm_emit_data(void *e, struct data d) { FILE *f = e; - int off = 0; + unsigned int off = 0; struct marker *m = d.markers; for_each_marker_of_type(m, LABEL) @@ -219,7 +219,7 @@ static struct emitter asm_emitter = { static int stringtable_insert(struct data *d, const char *str) { - int i; + unsigned int i; /* FIXME: do this more efficiently? */ @@ -345,7 +345,7 @@ static void make_fdt_header(struct fdt_header *fdt, void dt_to_blob(FILE *f, struct dt_info *dti, int version) { struct version_info *vi = NULL; - int i; + unsigned int i; struct data blob = empty_data; struct data reservebuf = empty_data; struct data dtbuf = empty_data; @@ -446,7 +446,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf) void dt_to_asm(FILE *f, struct dt_info *dti, int version) { struct version_info *vi = NULL; - int i; + unsigned int i; struct data strbuf = empty_data; struct reserve_info *re; const char *symprefix = "dt"; diff --git a/livetree.c b/livetree.c index 032df58..7eacd02 100644 --- a/livetree.c +++ b/livetree.c @@ -438,7 +438,7 @@ cell_t propval_cell(struct property *prop) return fdt32_to_cpu(*((fdt32_t *)prop->val.val)); } -cell_t propval_cell_n(struct property *prop, int n) +cell_t propval_cell_n(struct property *prop, unsigned int n) { assert(prop->val.len / sizeof(cell_t) >= n); return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n)); diff --git a/yamltree.c b/yamltree.c index 4e93c12..e63d32f 100644 --- a/yamltree.c +++ b/yamltree.c @@ -29,11 +29,11 @@ char *yaml_error_name[] = { (emitter)->problem, __func__, __LINE__); \ }) -static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width) +static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, unsigned int len, int width) { yaml_event_t event; void *tag; - int off, start_offset = markers->offset; + unsigned int off, start_offset = markers->offset; switch(width) { case 1: tag = "!u8"; break; @@ -112,7 +112,7 @@ static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len) static void yaml_propval(yaml_emitter_t *emitter, struct property *prop) { yaml_event_t event; - int len = prop->val.len; + unsigned int len = prop->val.len; struct marker *m = prop->val.markers; /* Emit the property name */ From 3bc3a6b9fe0cba171bef7d1cc2b04a362228dd1c Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 12 Oct 2020 17:19:45 +0100 Subject: [PATCH 035/298] dtc: Fix signedness comparisons warnings: Wrap (-1) With -Wsign-compare, compilers warn about a mismatching signedness in a comparison in dtc's data_copy_file(). Even though maxlen is of an unsigned type, we compare against "-1", which is passed in from the parser to indicate an unknown size. Cast the "-1" to an unsigned size to make the comparison match. Signed-off-by: Andre Przywara Message-Id: <20201012161948.23994-9-andre.przywara@arm.com> Signed-off-by: David Gibson --- data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data.c b/data.c index fdb0407..1473423 100644 --- a/data.c +++ b/data.c @@ -84,7 +84,7 @@ struct data data_copy_file(FILE *f, size_t maxlen) while (!feof(f) && (d.len < maxlen)) { size_t chunksize, ret; - if (maxlen == -1) + if (maxlen == (size_t)-1) chunksize = 4096; else chunksize = maxlen - d.len; From 05874d08212d23dafd753ab52a5762c9b69b25de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 12 Oct 2020 11:34:03 +0400 Subject: [PATCH 036/298] pylibfdt: allow build out of tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With meson, we have to support out-of-tree build. Introduce a --top-builddir option, which will default to the current directory to lookup generated filed such as version_gen.h and output directories. Other source paths are derived from the location of the setup.py script in the source tree. --build-lib is changed to be relative to the current directory, instead of relative to setup.py. This has less surprising results! Signed-off-by: Marc-André Lureau Message-Id: <20201012073405.1682782-2-marcandre.lureau@redhat.com> Signed-off-by: David Gibson --- pylibfdt/Makefile.pylibfdt | 4 ++-- pylibfdt/setup.py | 27 +++++++++++++++++++-------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 6866a0b..1b5f236 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -10,7 +10,7 @@ PYLIBFDT_CLEANDIRS_L = build __pycache__ PYLIBFDT_CLEANDIRS = $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%) SETUP = $(PYLIBFDT_dir)/setup.py -SETUPFLAGS = +SETUPFLAGS = --top-builddir . ifndef V SETUPFLAGS += --quiet @@ -18,7 +18,7 @@ endif $(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE) @$(VECHO) PYMOD $@ - $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=../$(PYLIBFDT_dir) + $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=$(PYLIBFDT_dir) install_pylibfdt: $(PYMODULE) @$(VECHO) INSTALL-PYLIB diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py index 53f2bef..ef40f15 100755 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -19,23 +19,33 @@ import sys VERSION_PATTERN = '^#define DTC_VERSION "DTC ([^"]*)"$' +def get_top_builddir(): + if '--top-builddir' in sys.argv: + index = sys.argv.index('--top-builddir') + sys.argv.pop(index) + return sys.argv.pop(index) + else: + return os.getcwd() + + +srcdir = os.path.dirname(os.path.abspath(sys.argv[0])) +top_builddir = get_top_builddir() + + def get_version(): - version_file = "../version_gen.h" + version_file = os.path.join(top_builddir, 'version_gen.h') f = open(version_file, 'rt') m = re.match(VERSION_PATTERN, f.readline()) return m.group(1) -setupdir = os.path.dirname(os.path.abspath(sys.argv[0])) -os.chdir(setupdir) - libfdt_module = Extension( '_libfdt', - sources=['libfdt.i'], - include_dirs=['../libfdt'], + sources=[os.path.join(srcdir, 'libfdt.i')], + include_dirs=[os.path.join(srcdir, '../libfdt')], libraries=['fdt'], - library_dirs=['../libfdt'], - swig_opts=['-I../libfdt'], + library_dirs=[os.path.join(top_builddir, 'libfdt')], + swig_opts=['-I' + os.path.join(srcdir, '../libfdt')], ) setup( @@ -44,5 +54,6 @@ setup( author='Simon Glass ', description='Python binding for libfdt', ext_modules=[libfdt_module], + package_dir={'': srcdir}, py_modules=['libfdt'], ) From 67849a327927e1028010e973b36f7b1280ce8184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 12 Oct 2020 11:34:04 +0400 Subject: [PATCH 037/298] build-sys: add meson build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The meson build system allows projects to "vendor" dtc easily, thanks to subproject(). QEMU has recently switched to meson, and adding meson support to dtc will help to handle the QEMU submodule. meson rules are arguably simpler to write and maintain than the hand-crafted/custom Makefile. meson support various backends, and default build options (including coverage, sanitizer, debug/release etc, see: https://mesonbuild.com/Builtin-options.html) Compare to the Makefiles, the same build targets should be built and installed and the same tests should be run ("meson test" can be provided extra test arguments for running the equivalent of checkm/checkv). There is no support EXTRAVERSION/LOCAL_VERSION/CONFIG_LOCALVERSION, instead the version is simply set with project(), and vcs_tag() is used for git/dirty version reporting (This is most common and is hopefully enough. If necessary, configure-time options could be added for extra versioning.). libfdt shared library is build following regular naming conventions: instead of libfdt.so.1 -> libfdt-1.6.0.so (with current build-sys), libfdt.so.1 -> libfdt.so.1.6.0. I am not sure why the current build system use an uncommon naming pattern. I also included a libfdt.pc pkg-config file, as convenience. Both Linux native build and mingw cross-build pass. CI pass. Tests are only run on native build. The current Makefiles are left in-tree, and make/check still work. Eventually, the Makefiles could be marked as deprecated, to start a transition period and avoid having to maintain 2 build systems in the near future. (run_tests.sh could eventually be replaced by the meson test runner, which would have several advantages in term of flexibility/features, but this is left for another day) Signed-off-by: Marc-André Lureau Message-Id: <20201012073405.1682782-3-marcandre.lureau@redhat.com> Signed-off-by: David Gibson --- libfdt/meson.build | 50 +++++++++++++++++ meson.build | 127 ++++++++++++++++++++++++++++++++++++++++++ meson_options.txt | 10 ++++ pylibfdt/meson.build | 13 +++++ tests/meson.build | 130 +++++++++++++++++++++++++++++++++++++++++++ version_gen.h.in | 1 + 6 files changed, 331 insertions(+) create mode 100644 libfdt/meson.build create mode 100644 meson.build create mode 100644 meson_options.txt create mode 100644 pylibfdt/meson.build create mode 100644 tests/meson.build create mode 100644 version_gen.h.in diff --git a/libfdt/meson.build b/libfdt/meson.build new file mode 100644 index 0000000..0307ffb --- /dev/null +++ b/libfdt/meson.build @@ -0,0 +1,50 @@ +version_script = '-Wl,--version-script=@0@'.format(meson.current_source_dir() / 'version.lds') +if not cc.has_link_argument(version_script) + version_script = [] +endif + +sources = files( + 'fdt.c', + 'fdt_addresses.c', + 'fdt_check.c', + 'fdt_empty_tree.c', + 'fdt_overlay.c', + 'fdt_ro.c', + 'fdt_rw.c', + 'fdt_strerror.c', + 'fdt_sw.c', + 'fdt_wip.c', +) + +libfdt = library( + 'fdt', sources, + version: '1.6.0', + link_args: ['-Wl,--no-undefined', version_script], + link_depends: 'version.lds', + install: true, +) + +libfdt_inc = include_directories('.') + +libfdt_dep = declare_dependency( + include_directories: libfdt_inc, + link_with: libfdt, +) + +install_headers( + files( + 'fdt.h', + 'libfdt.h', + 'libfdt_env.h', + ) +) + +pkgconfig = import('pkgconfig') + +pkgconfig.generate( + libraries: libfdt, + version: meson.project_version(), + filebase: 'libfdt', + name: 'libfdt', + description: 'Flat Device Tree manipulation', +) diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..2c65104 --- /dev/null +++ b/meson.build @@ -0,0 +1,127 @@ +project('dtc', 'c', + version: '1.6.0', + license: ['GPL2+', 'BSD-2'], + default_options: 'werror=true', +) + +cc = meson.get_compiler('c') + +add_project_arguments(cc.get_supported_arguments([ + '-Wall', + '-Wpointer-arith', + '-Wcast-qual', + '-Wnested-externs', + '-Wstrict-prototypes', + '-Wmissing-prototypes', + '-Wredundant-decls', + '-Wshadow' +]),language: 'c') + +if host_machine.system() == 'windows' + add_project_arguments( + '-D__USE_MINGW_ANSI_STDIO=1', + language: 'c' + ) +endif + +add_project_arguments( + '-DFDT_ASSUME_MASK=' + get_option('assume-mask').to_string(), + language: 'c' +) + +yamltree = 'yamltree.c' +yaml = dependency('yaml-0.1', required: get_option('yaml')) +if not yaml.found() + add_project_arguments('-DNO_YAML', language: 'c') + yamltree = [] +endif + +valgrind = dependency('valgrind', required: get_option('valgrind')) +if not valgrind.found() + add_project_arguments('-DNO_VALGRIND', language: 'c') +endif + +py = import('python') +py = py.find_installation(required: get_option('python')) +swig = find_program('swig', required: get_option('python')) + +version_gen_h = vcs_tag( + input: 'version_gen.h.in', + output: 'version_gen.h', +) + +subdir('libfdt') + +if get_option('tools') + flex = find_program('flex', required: true) + bison = find_program('bison', required: true) + + util_dep = declare_dependency( + sources: ['util.c', version_gen_h], + include_directories: '.', + dependencies: libfdt_dep + ) + + lgen = generator( + flex, + output: '@PLAINNAME@.lex.c', + arguments: ['-o', '@OUTPUT@', '@INPUT@'], + ) + + pgen = generator( + bison, + output: ['@BASENAME@.tab.c', '@BASENAME@.tab.h'], + arguments: ['@INPUT@', '--defines=@OUTPUT1@', '--output=@OUTPUT0@'], + ) + + if cc.check_header('fnmatch.h') + executable( + 'convert-dtsv0', + [ + lgen.process('convert-dtsv0-lexer.l'), + 'srcpos.c', + ], + dependencies: util_dep, + install: true, + ) + endif + + executable( + 'dtc', + [ + lgen.process('dtc-lexer.l'), + pgen.process('dtc-parser.y'), + 'checks.c', + 'data.c', + 'dtc.c', + 'flattree.c', + 'fstree.c', + 'livetree.c', + 'srcpos.c', + 'treesource.c', + yamltree, + ], + dependencies: [util_dep, yaml], + install: true, + ) + + foreach e: ['fdtdump', 'fdtget', 'fdtput', 'fdtoverlay'] + executable(e, files(e + '.c'), dependencies: util_dep, install: true) + endforeach + + install_data( + 'dtdiff', + install_dir: get_option('prefix') / get_option('bindir'), + install_mode: 'rwxr-xr-x', + ) +endif + +if not meson.is_cross_build() + if py.found() and swig.found() + subdir('pylibfdt') + endif + + if get_option('tools') + subdir('tests') + endif +endif diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..ea59c28 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,10 @@ +option('tools', type: 'boolean', value: true, + description: 'Build tools') +option('assume-mask', type: 'integer', value: 0, + description: 'Control the assumptions made (e.g. risking security issues) in the code.') +option('yaml', type: 'feature', value: 'auto', + description: 'YAML support') +option('valgrind', type: 'feature', value: 'auto', + description: 'Valgrind support') +option('python', type: 'feature', value: 'auto', + description: 'Build pylibfdt Python library') diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build new file mode 100644 index 0000000..088f249 --- /dev/null +++ b/pylibfdt/meson.build @@ -0,0 +1,13 @@ +setup_py = find_program('setup.py') +setup_py = [setup_py.path(), '--quiet', '--top-builddir', meson.current_build_dir() / '..'] + +custom_target( + 'pylibfdt', + input: 'libfdt.i', + output: '_libfdt.so', + depends: version_gen_h, + command: [setup_py, 'build_ext', '--build-lib=' + meson.current_build_dir()], + build_by_default: true, +) + +meson.add_install_script(setup_py, 'install', '--prefix=' + get_option('prefix'), '--root=$DESTDIR') diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 0000000..8976dc1 --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,130 @@ +trees = static_library('trees', files('trees.S'), c_args: '-D__ASSEMBLY__', + include_directories: libfdt_inc) + +dumptrees = executable('dumptrees', files('dumptrees.c'), + link_with: trees, dependencies: libfdt_dep) + +dumptrees_dtb = custom_target( + 'dumptrees', + command: [dumptrees, meson.current_build_dir()], + output: [ + 'test_tree1.dtb', + 'bad_node_char.dtb', + 'bad_node_format.dtb', + 'bad_prop_char.dtb', + 'ovf_size_strings.dtb', + 'truncated_property.dtb', + 'truncated_string.dtb', + 'truncated_memrsv.dtb', + ] +) + +testutil_dep = declare_dependency(sources: ['testutils.c'], link_with: trees) + +tests = [ + 'add_subnode_with_nops', + 'addr_size_cells', + 'addr_size_cells2', + 'appendprop1', + 'appendprop2', + 'appendprop_addrrange', + 'boot-cpuid', + 'char_literal', + 'check_full', + 'check_header', + 'check_path', + 'del_node', + 'del_property', + 'dtb_reverse', + 'dtbs_equal_ordered', + 'dtbs_equal_unordered', + 'extra-terminating-null', + 'find_property', + 'fs_tree1', + 'get_alias', + 'get_mem_rsv', + 'get_name', + 'get_path', + 'get_phandle', + 'get_prop_offset', + 'getprop', + 'incbin', + 'integer-expressions', + 'mangle-layout', + 'move_and_save', + 'node_check_compatible', + 'node_offset_by_compatible', + 'node_offset_by_phandle', + 'node_offset_by_prop_value', + 'nop_node', + 'nop_property', + 'nopulate', + 'notfound', + 'open_pack', + 'overlay', + 'overlay_bad_fixup', + 'parent_offset', + 'path-references', + 'path_offset', + 'path_offset_aliases', + 'phandle_format', + 'property_iterate', + 'propname_escapes', + 'references', + 'root_node', + 'rw_oom', + 'rw_tree1', + 'set_name', + 'setprop', + 'setprop_inplace', + 'sized_cells', + 'string_escapes', + 'stringlist', + 'subnode_iterate', + 'subnode_offset', + 'supernode_atdepth_offset', + 'sw_states', + 'sw_tree1', + 'utilfdt_test', +] + +tests += [ + 'truncated_memrsv', + 'truncated_property', + 'truncated_string', +] + +dl = cc.find_library('dl', required: false) +if dl.found() + tests += [ + 'asm_tree_dump', + 'value-labels', + ] +endif + +foreach t: tests + executable(t, files(t + '.c'), dependencies: [testutil_dep, util_dep, libfdt_dep, dl]) +endforeach + +run_tests = find_program('run_tests.sh') + + +env = [ + 'PYTHON=' + py.path(), + 'PYTHONPATH=' + meson.source_root() / 'pylibfdt', +] + +if not py.found() + env += 'NO_PYTHON=1' +endif +if not yaml.found() + env += 'NO_YAML=1' +endif + +test( + 'run-test', + run_tests, + workdir: meson.current_build_dir(), + depends: dumptrees_dtb, + env: env, +) diff --git a/version_gen.h.in b/version_gen.h.in new file mode 100644 index 0000000..7771abb --- /dev/null +++ b/version_gen.h.in @@ -0,0 +1 @@ +#define DTC_VERSION "DTC @VCS_TAG@" From 5e735860c4786418c12751de639b519891a61192 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Wed, 4 Nov 2020 08:06:05 -0500 Subject: [PATCH 038/298] libfdt: Check for 8-byte address alignment in fdt_ro_probe_() The device tree must be loaded in to memory at an 8-byte aligned address. Add a check for this condition in fdt_ro_probe_() and a new error code to return if we are not. Signed-off-by: Tom Rini Message-Id: <20201104130605.28874-1-trini@konsulko.com> Signed-off-by: David Gibson --- libfdt/fdt.c | 4 ++++ libfdt/libfdt.h | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 6cf2fa0..3e89307 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -22,6 +22,10 @@ int32_t fdt_ro_probe_(const void *fdt) if (can_assume(VALID_DTB)) return totalsize; + /* The device tree must be at an 8-byte aligned address */ + if ((uintptr_t)fdt & 7) + return -FDT_ERR_ALIGNMENT; + if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ if (!can_assume(LATEST)) { diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 5979832..89adee3 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -101,7 +101,11 @@ extern "C" { /* FDT_ERR_BADFLAGS: The function was passed a flags field that * contains invalid flags or an invalid combination of flags. */ -#define FDT_ERR_MAX 18 +#define FDT_ERR_ALIGNMENT 19 + /* FDT_ERR_ALIGNMENT: The device tree base address is not 8-byte + * aligned. */ + +#define FDT_ERR_MAX 19 /* constants */ #define FDT_MAX_PHANDLE 0xfffffffe From 30a56bce4f0bdf59ca52af244d4da5250924bfdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 7 Dec 2020 17:00:51 +0400 Subject: [PATCH 039/298] meson: fix -Wall warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Meson already handles Wall via the built-in warning_level option. Signed-off-by: Marc-André Lureau Message-Id: <20201207130055.462734-2-marcandre.lureau@redhat.com> Signed-off-by: David Gibson --- meson.build | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/meson.build b/meson.build index 2c65104..b23ea1b 100644 --- a/meson.build +++ b/meson.build @@ -6,16 +6,18 @@ project('dtc', 'c', cc = meson.get_compiler('c') -add_project_arguments(cc.get_supported_arguments([ - '-Wall', - '-Wpointer-arith', - '-Wcast-qual', - '-Wnested-externs', - '-Wstrict-prototypes', - '-Wmissing-prototypes', - '-Wredundant-decls', - '-Wshadow' -]),language: 'c') +add_project_arguments( + cc.get_supported_arguments([ + '-Wpointer-arith', + '-Wcast-qual', + '-Wnested-externs', + '-Wstrict-prototypes', + '-Wmissing-prototypes', + '-Wredundant-decls', + '-Wshadow' + ]), + language: 'c' +) if host_machine.system() == 'windows' add_project_arguments( From f8b46098824d846675103d9b1ce0a3f7b4548623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 7 Dec 2020 17:00:52 +0400 Subject: [PATCH 040/298] meson: do not assume python is installed, skip tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20201207130055.462734-3-marcandre.lureau@redhat.com> Signed-off-by: David Gibson --- tests/meson.build | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/meson.build b/tests/meson.build index 8976dc1..9d3a4e7 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -108,14 +108,14 @@ endforeach run_tests = find_program('run_tests.sh') - -env = [ - 'PYTHON=' + py.path(), - 'PYTHONPATH=' + meson.source_root() / 'pylibfdt', -] - +env = [] if not py.found() env += 'NO_PYTHON=1' +else + env += [ + 'PYTHON=' + py.path(), + 'PYTHONPATH=' + meson.source_root() / 'pylibfdt', + ] endif if not yaml.found() env += 'NO_YAML=1' From bab85e48a6f4c32a9e8ab201cdaf4a0568c74da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 7 Dec 2020 17:00:53 +0400 Subject: [PATCH 041/298] meson: increase default timeout for tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20201207130055.462734-4-marcandre.lureau@redhat.com> Signed-off-by: David Gibson --- tests/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/meson.build b/tests/meson.build index 9d3a4e7..fa06824 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -127,4 +127,5 @@ test( workdir: meson.current_build_dir(), depends: dumptrees_dtb, env: env, + timeout: 1800, # mostly for valgrind ) From a7c40409934971ac1bd934ccc411bc6932b86564 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Thu, 10 Dec 2020 21:27:36 -0500 Subject: [PATCH 042/298] libfdt: Internally perform potentially unaligned loads Commits 6dcb8ba4 "libfdt: Add helpers for accessing unaligned words" introduced changes to support unaligned reads for ARM platforms and 11738cf01f15 "libfdt: Don't use memcpy to handle unaligned reads on ARM" improved the performance of these helpers. On further discussion, while there are potential cases where we could be used on platforms that do not fixup unaligned reads for us, making this choice the default is very expensive in terms of binary size and access time. To address this, introduce and use new fdt{32,64}_ld_ functions that call fdt{32,64}_to_cpu() as was done prior to the above mentioned commits. Leave the existing load functions as unaligned-safe and include comments in both cases. Reviewed-by: Rob Herring Signed-off-by: Tom Rini Message-Id: <20201211022736.31657-1-trini@konsulko.com> Tested-by: John Paul Adrian Glaubitz Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 20 ++++++++++---------- libfdt/libfdt.h | 8 +++----- libfdt/libfdt_internal.h | 19 +++++++++++++++++++ 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 91cc6fe..17584da 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -181,8 +181,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) if (!can_assume(VALID_INPUT) && !re) return -FDT_ERR_BADOFFSET; - *address = fdt64_ld(&re->address); - *size = fdt64_ld(&re->size); + *address = fdt64_ld_(&re->address); + *size = fdt64_ld_(&re->size); return 0; } @@ -192,7 +192,7 @@ int fdt_num_mem_rsv(const void *fdt) const struct fdt_reserve_entry *re; for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) { - if (fdt64_ld(&re->size) == 0) + if (fdt64_ld_(&re->size) == 0) return i; } return -FDT_ERR_TRUNCATED; @@ -370,7 +370,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, prop = fdt_offset_ptr_(fdt, offset); if (lenp) - *lenp = fdt32_ld(&prop->len); + *lenp = fdt32_ld_(&prop->len); return prop; } @@ -408,7 +408,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, offset = -FDT_ERR_INTERNAL; break; } - if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff), + if (fdt_string_eq_(fdt, fdt32_ld_(&prop->nameoff), name, namelen)) { if (poffset) *poffset = offset; @@ -461,7 +461,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, /* Handle realignment */ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && - (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) + (poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8) return prop->data + 4; return prop->data; } @@ -479,7 +479,7 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, int namelen; if (!can_assume(VALID_INPUT)) { - name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), + name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff), &namelen); if (!name) { if (lenp) @@ -488,13 +488,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, } *namep = name; } else { - *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff)); + *namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff)); } } /* Handle realignment */ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && - (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) + (offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8) return prop->data + 4; return prop->data; } @@ -519,7 +519,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) return 0; } - return fdt32_ld(php); + return fdt32_ld_(php); } const char *fdt_get_alias_namelen(const void *fdt, diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 89adee3..2bc16a8 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -126,12 +126,10 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); /* - * Alignment helpers: - * These helpers access words from a device tree blob. They're - * built to work even with unaligned pointers on platforms (ike - * ARM) that don't like unaligned loads and stores + * External helpers to access words from a device tree blob. They're built + * to work even with unaligned pointers on platforms (such as ARMv5) that don't + * like unaligned loads and stores. */ - static inline uint32_t fdt32_ld(const fdt32_t *p) { const uint8_t *bp = (const uint8_t *)p; diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index d4e0bd4..8b580aa 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -46,6 +46,25 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n); } +/* + * Internal helpers to access tructural elements of the device tree blob + * (rather than for exaple reading integers from within property values). We + * assume that we are either given a naturally aligned address for the platform + * or if we are not, we are on a platform where unaligned memory reads will be + * handled in a graceful manner. If this is not the case there are _unaligned + * versions of these functions that follow and can be used. + * + */ +static inline uint32_t fdt32_ld_(const fdt32_t *p) +{ + return fdt32_to_cpu(*p); +} + +static inline uint64_t fdt64_ld_(const fdt64_t *p) +{ + return fdt64_to_cpu(*p); +} + #define FDT_SW_MAGIC (~FDT_MAGIC) /**********************************************************************/ From 7cd5d5fe43d56e3017397fa3a086096e11920c3e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 16 Dec 2020 16:51:38 +1100 Subject: [PATCH 043/298] libfdt: Tweak description of assume-aligned load helpers There's a small inaccuracy in the comment describing these new helpers. This corrects it, and reformats while we're there. Fixes: f98f28ab ("libfdt: Internally perform potentially unaligned loads") Signed-off-by: David Gibson --- libfdt/libfdt_internal.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 8b580aa..16bda19 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -47,13 +47,13 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) } /* - * Internal helpers to access tructural elements of the device tree blob - * (rather than for exaple reading integers from within property values). We - * assume that we are either given a naturally aligned address for the platform - * or if we are not, we are on a platform where unaligned memory reads will be - * handled in a graceful manner. If this is not the case there are _unaligned - * versions of these functions that follow and can be used. - * + * Internal helpers to access tructural elements of the device tree + * blob (rather than for exaple reading integers from within property + * values). We assume that we are either given a naturally aligned + * address for the platform or if we are not, we are on a platform + * where unaligned memory reads will be handled in a graceful manner. + * If not the external helpers fdtXX_ld() from libfdt.h can be used + * instead. */ static inline uint32_t fdt32_ld_(const fdt32_t *p) { From f7e5737f26aa7198db476c94463766910db48941 Mon Sep 17 00:00:00 2001 From: Paul Barker Date: Sat, 19 Dec 2020 14:35:21 +0000 Subject: [PATCH 044/298] tests: Fix overlay_overlay_nosugar test case This test was accidentally skipped as the wrong test dts file was built. The fragment numbering in this sugar-free test case needed adjusting to match the numbering generated by dtc for overlay_overlay.dts. Signed-off-by: Paul Barker Message-Id: <20201219143521.2118-1-pbarker@konsulko.com> Signed-off-by: David Gibson --- tests/overlay_overlay_nosugar.dts | 8 ++++---- tests/run_tests.sh | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/overlay_overlay_nosugar.dts b/tests/overlay_overlay_nosugar.dts index b6d841b..b5947e9 100644 --- a/tests/overlay_overlay_nosugar.dts +++ b/tests/overlay_overlay_nosugar.dts @@ -48,7 +48,7 @@ }; }; - fragment@5 { + fragment@4 { target = <&test>; __overlay__ { @@ -58,7 +58,7 @@ }; }; - fragment@6 { + fragment@5 { target = <&test>; __overlay__ { @@ -66,7 +66,7 @@ }; }; - fragment@7 { + fragment@6 { target = <&test>; __overlay__ { @@ -74,7 +74,7 @@ }; }; - fragment@8 { + fragment@7 { target = <&test>; __overlay__ { diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 294585b..4b8dada 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -288,7 +288,7 @@ dtc_overlay_tests () { run_test check_path overlay_overlay.test.dtb exists "/__local_fixups__" # Without syntactic sugar - run_dtc_test -I dts -O dtb -o overlay_overlay_nosugar.test.dtb "$SRCDIR/overlay_overlay.dts" + run_dtc_test -I dts -O dtb -o overlay_overlay_nosugar.test.dtb "$SRCDIR/overlay_overlay_nosugar.dts" run_test check_path overlay_overlay_nosugar.test.dtb not-exists "/__symbols__" run_test check_path overlay_overlay_nosugar.test.dtb exists "/__fixups__" run_test check_path overlay_overlay_nosugar.test.dtb exists "/__local_fixups__" From 3b01518e688d7c7d9d46ac41b11dd2b0c4788775 Mon Sep 17 00:00:00 2001 From: Justin Covell Date: Mon, 28 Dec 2020 20:17:49 -0800 Subject: [PATCH 045/298] Set last_comp_version correctly in new dtb and fix potential version issues in fdt_open_into Changes in v3: - Remove noop version sets - Set version correctly on loaded fdt in fdt_open_into Fixes: f1879e1a50eb ("Add limited read-only support for older (V2 and V3) device tree to libfdt.") Signed-off-by: Justin Covell Message-Id: <20201229041749.2187-1-jujugoboom@gmail.com> Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 4 +++- libfdt/fdt_sw.c | 2 +- libfdt/libfdt.h | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 68887b9..f13458d 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -428,12 +428,14 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) if (can_assume(LATEST) || fdt_version(fdt) >= 17) { struct_size = fdt_size_dt_struct(fdt); - } else { + } else if (fdt_version(fdt) == 16) { struct_size = 0; while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) ; if (struct_size < 0) return struct_size; + } else { + return -FDT_ERR_BADVERSION; } if (can_assume(LIBFDT_ORDER) || diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 68b543c..4c569ee 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -377,7 +377,7 @@ int fdt_finish(void *fdt) fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); /* And fix up fields that were keeping intermediate state. */ - fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); + fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION); fdt_set_magic(fdt, FDT_MAGIC); return 0; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 2bc16a8..73467f7 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -14,6 +14,7 @@ extern "C" { #endif #define FDT_FIRST_SUPPORTED_VERSION 0x02 +#define FDT_LAST_COMPATIBLE_VERSION 0x10 #define FDT_LAST_SUPPORTED_VERSION 0x11 /* Error codes: informative error codes */ From 163f0469bf2ed8b2fe5aa15bc796b93c70243ddc Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 6 Jan 2021 15:26:08 +0530 Subject: [PATCH 046/298] dtc: Allow overlays to have .dtbo extension Allow the overlays to have .dtbo extension instead of just .dtb. This allows them to be identified easily by tools as well as humans. Allow the dtbo outform in dtc.c for the same. Signed-off-by: Viresh Kumar Message-Id: <30fd0e5f2156665c713cf191c5fea9a5548360c0.1609926856.git.viresh.kumar@linaro.org> Signed-off-by: David Gibson --- dtc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dtc.c b/dtc.c index bdb3f59..838c5df 100644 --- a/dtc.c +++ b/dtc.c @@ -122,6 +122,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback) return "dts"; if (!strcasecmp(s, ".yaml")) return "yaml"; + if (!strcasecmp(s, ".dtbo")) + return "dtb"; if (!strcasecmp(s, ".dtb")) return "dtb"; return fallback; @@ -357,6 +359,8 @@ int main(int argc, char *argv[]) #endif } else if (streq(outform, "dtb")) { dt_to_blob(outf, dti, outversion); + } else if (streq(outform, "dtbo")) { + dt_to_blob(outf, dti, outversion); } else if (streq(outform, "asm")) { dt_to_asm(outf, dti, outversion); } else if (streq(outform, "null")) { From 64990a272e8f7cbbdfd5a53f752b5a0db7ddf41c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacy=20Kuchci=C5=84ski?= Date: Wed, 13 Jan 2021 00:13:23 +0100 Subject: [PATCH 047/298] srcpos: increase MAX_SRCFILE_DEPTH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some kernels require the MAX_SRCFILE_DEPTH to be bigger than 100, and since it's just a sanity check to detect infinite recursion it shouldn't hurt increasing it to 200. Signed-off-by: Ignacy Kuchciński Message-Id: Signed-off-by: David Gibson --- srcpos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcpos.c b/srcpos.c index f5205fb..4fdb22a 100644 --- a/srcpos.c +++ b/srcpos.c @@ -20,7 +20,7 @@ struct search_path { static struct search_path *search_path_head, **search_path_tail; /* Detect infinite include recursion. */ -#define MAX_SRCFILE_DEPTH (100) +#define MAX_SRCFILE_DEPTH (200) static int srcfile_depth; /* = 0 */ static char *get_dirname(const char *path) From ca16a723fa9dde9c5da80dba567f48715000e77c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 6 Jan 2021 14:52:26 +1100 Subject: [PATCH 048/298] fdtdump: Fix gcc11 warning In one place, fdtdump abuses fdt_set_magic(), passing it just a small char array instead of the full fdt header it expects. That's relying on the fact that in fact fdt_set_magic() will only actually access the first 4 bytes of the buffer. This trips a new warning in GCC 11 - and it's entirely possible it was always UB. So, don't do that. Signed-off-by: David Gibson --- fdtdump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdtdump.c b/fdtdump.c index 9613bef..d9fb374 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -217,7 +217,7 @@ int main(int argc, char *argv[]) char *p = buf; char *endp = buf + len; - fdt_set_magic(smagic, FDT_MAGIC); + fdt32_st(smagic, FDT_MAGIC); /* poor man's memmem */ while ((endp - p) >= FDT_MAGIC_SIZE) { From 307afa1a7be8af23dee81af5c10a8a44009a768e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 28 Jan 2021 11:24:20 +1100 Subject: [PATCH 049/298] Update Jon Loeliger's email At Jon's request update to a more current address. Signed-off-by: David Gibson --- Documentation/manual.txt | 2 +- README | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/manual.txt b/Documentation/manual.txt index adf5ccb..97e53b9 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -45,7 +45,7 @@ The gitweb interface for the upstream repository is: Patches should be sent to the maintainers: David Gibson - Jon Loeliger + Jon Loeliger and CCed to . 2) Description diff --git a/README b/README index 9465ee5..d9bf850 100644 --- a/README +++ b/README @@ -5,7 +5,7 @@ utility library for reading and manipulating the binary format. DTC and LIBFDT are maintained by: David Gibson -Jon Loeliger +Jon Loeliger Python library From 0db6d09584e19b1f313ebfc21c3da32a7e77ca82 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 3 Feb 2021 13:14:22 +0530 Subject: [PATCH 050/298] gitignore: Add cscope files Add cscope files in gitignore. Signed-off-by: Viresh Kumar Message-Id: <3c39a6324ef2be64f839e6e6205f4afc63486216.1612338199.git.viresh.kumar@linaro.org> Signed-off-by: David Gibson --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 1f2a0f2..cfea8a4 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,7 @@ lex.yy.c /fdtoverlay /patches /.pc + +# cscope files +cscope.* +ncscope.* From 183df9e9c2b9e49f14f130fd7a4c0eae8f44288d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 3 Feb 2021 15:26:36 +0530 Subject: [PATCH 051/298] gitignore: Ignore the swp files Ignore the temporary .*.swp files. Signed-off-by: Viresh Kumar Message-Id: <15496f8669ac2bb3b4b61a1a7c978947623cb7c3.1612346186.git.viresh.kumar@linaro.org> Signed-off-by: David Gibson --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index cfea8a4..8e332d8 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ *.tab.[ch] lex.yy.c *.lex.c +.*.swp /dtc /fdtdump /convert-dtsv0 From f527c867a8c6db6d787a0fc30c00415d9c59131e Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Sat, 6 Feb 2021 21:01:10 +1100 Subject: [PATCH 052/298] util: limit gnu_printf format attribute to gcc >= 4.4.0 The gnu_printf format attribute was introduced in gcc 4.4.0 https://gcc.gnu.org/legacy-ml/gcc-help/2012-02/msg00225.html. Use the printf format attribute on earlier versions of gcc and clang (which claims to be gcc 4.2.1 in builtin defines) to fix the build with gcc 4.2.1. Fixes: 588a29f ("util: use gnu_printf format attribute") Signed-off-by: Jonathan Gray Message-Id: <20210206100110.75228-1-jsg@jsg.id.au> Signed-off-by: David Gibson --- util.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util.h b/util.h index a771b46..c45b2c2 100644 --- a/util.h +++ b/util.h @@ -13,10 +13,10 @@ */ #ifdef __GNUC__ -#ifdef __clang__ -#define PRINTF(i, j) __attribute__((format (printf, i, j))) -#else +#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) #define PRINTF(i, j) __attribute__((format (gnu_printf, i, j))) +#else +#define PRINTF(i, j) __attribute__((format (printf, i, j))) #endif #define NORETURN __attribute__((noreturn)) #else From 9d2279e7e6ee937d7c47250720c92dd58fa1aa68 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 9 Feb 2021 12:46:41 -0600 Subject: [PATCH 053/298] checks: Change node-name check to match devicetree spec The devicetree spec limits the valid character set to: A-Z a-z 0-9 ,._+- while property can additionally have '?#'. Change the check to match the spec. Signed-off-by: Kumar Gala Message-Id: <20210209184641.63052-1-kumar.gala@linaro.org> Signed-off-by: David Gibson --- checks.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/checks.c b/checks.c index 17cb689..48e7fe9 100644 --- a/checks.c +++ b/checks.c @@ -297,7 +297,8 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL); #define LOWERCASE "abcdefghijklmnopqrstuvwxyz" #define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define DIGITS "0123456789" -#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-" +#define NODECHARS LOWERCASE UPPERCASE DIGITS ",._+-@" +#define PROPCHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-" #define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-" static void check_node_name_chars(struct check *c, struct dt_info *dti, @@ -309,7 +310,7 @@ static void check_node_name_chars(struct check *c, struct dt_info *dti, FAIL(c, dti, node, "Bad character '%c' in node name", node->name[n]); } -ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@"); +ERROR(node_name_chars, check_node_name_chars, NODECHARS); static void check_node_name_chars_strict(struct check *c, struct dt_info *dti, struct node *node) @@ -370,7 +371,7 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti, prop->name[n]); } } -ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS); +ERROR(property_name_chars, check_property_name_chars, PROPCHARS); static void check_property_name_chars_strict(struct check *c, struct dt_info *dti, From 88875268c05c9cf342d958a5c65973b0ee45888e Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 10 Feb 2021 13:39:12 -0600 Subject: [PATCH 054/298] checks: Warn on node-name and property name being the same Treat a node-name and property name at the same level of tree as a warning Signed-off-by: Kumar Gala Message-Id: <20210210193912.799544-1-kumar.gala@linaro.org> Signed-off-by: David Gibson --- checks.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/checks.c b/checks.c index 48e7fe9..c420772 100644 --- a/checks.c +++ b/checks.c @@ -331,6 +331,20 @@ static void check_node_name_format(struct check *c, struct dt_info *dti, } ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars); +static void check_node_name_vs_property_name(struct check *c, + struct dt_info *dti, + struct node *node) +{ + if (!node->parent) + return; + + if (get_property(node->parent, node->name)) { + FAIL(c, dti, node, "node name and property name conflict"); + } +} +WARNING(node_name_vs_property_name, check_node_name_vs_property_name, + NULL, &node_name_chars); + static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti, struct node *node) { @@ -1797,7 +1811,7 @@ WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes); static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &node_name_chars, &node_name_format, &property_name_chars, - &name_is_string, &name_properties, + &name_is_string, &name_properties, &node_name_vs_property_name, &duplicate_label, From 8e7ff260f755548f5b039ab4e0a970dfff8073b2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 9 Mar 2021 14:49:35 +1100 Subject: [PATCH 055/298] libfdt: Fix a possible "unchecked return value" warning Apparently the unchecked return value of the first fdt_next_tag() call in fdt_add_subnode_namelen() is tripping Coverity Scan in some circumstances, although it appears not to for the scan on our project itself. This fdt_next_tag() should always return FDT_BEGIN_NODE, since otherwise the fdt_subnode_offset_namelen() above would have returned BADOFFSET or BADSTRUCTURE. Still, add a check to shut Coverity up, gated by a can_assume() to avoid bloat in small builds. Reported-by: Ryan Long Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index f13458d..2fbb545 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -349,7 +349,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, return offset; /* Try to place the new node after the parent's properties */ - fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ + tag = fdt_next_tag(fdt, parentoffset, &nextoffset); + /* the fdt_subnode_offset_namelen() should ensure this never hits */ + if (!can_assume(LIBFDT_FLAWLESS) && (tag != FDT_BEGIN_NODE)) + return -FDT_ERR_INTERNAL; do { offset = nextoffset; tag = fdt_next_tag(fdt, offset, &nextoffset); From 34d708249a91e0d4b89f29e7b52b21b213ce7c54 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 11 Mar 2021 18:49:55 +0900 Subject: [PATCH 056/298] dtc: Remove -O dtbo support This partially reverts 163f0469bf2e ("dtc: Allow overlays to have .dtbo extension"). I think accepting "dtbo" as --out-format is strange. This is not shown by --help, at least. *.dtb and *.dtbo should have the same format, "dtb". Signed-off-by: Masahiro Yamada Message-Id: <20210311094956.924310-1-masahiroy@kernel.org> Signed-off-by: David Gibson --- dtc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/dtc.c b/dtc.c index 838c5df..3962d3f 100644 --- a/dtc.c +++ b/dtc.c @@ -359,8 +359,6 @@ int main(int argc, char *argv[]) #endif } else if (streq(outform, "dtb")) { dt_to_blob(outf, dti, outversion); - } else if (streq(outform, "dtbo")) { - dt_to_blob(outf, dti, outversion); } else if (streq(outform, "asm")) { dt_to_asm(outf, dti, outversion); } else if (streq(outform, "null")) { From 4ca61f84dc210ae78376d992c1ce6ebe40ecb5be Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 23 Mar 2021 13:09:25 +1300 Subject: [PATCH 057/298] libfdt: Check that there is only one root node At present it is possible to have two root nodes and even access nodes in the 'second' root. Such trees should not be considered valid. This was discovered as part of a security investigation into U-Boot verified boot. Add a check for this to fdt_check_full(). Signed-off-by: Simon Glass Reported-by: Arie Haenel Reported-by: Julien Lenoir Message-Id: <20210323000926.3210733-1-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/fdt_check.c | 7 +++++++ tests/Makefile.tests | 4 +++- tests/dumptrees.c | 1 + tests/run_tests.sh | 2 +- tests/testdata.h | 1 + tests/trees.S | 19 +++++++++++++++++++ 6 files changed, 32 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt_check.c b/libfdt/fdt_check.c index 9ddfdbf..13595a2 100644 --- a/libfdt/fdt_check.c +++ b/libfdt/fdt_check.c @@ -19,6 +19,7 @@ int fdt_check_full(const void *fdt, size_t bufsize) unsigned int depth = 0; const void *prop; const char *propname; + bool expect_end = false; if (bufsize < FDT_V1_SIZE) return -FDT_ERR_TRUNCATED; @@ -41,6 +42,10 @@ int fdt_check_full(const void *fdt, size_t bufsize) if (nextoffset < 0) return nextoffset; + /* If we see two root nodes, something is wrong */ + if (expect_end && tag != FDT_END) + return -FDT_ERR_BADSTRUCTURE; + switch (tag) { case FDT_NOP: break; @@ -60,6 +65,8 @@ int fdt_check_full(const void *fdt, size_t bufsize) if (depth == 0) return -FDT_ERR_BADSTRUCTURE; depth--; + if (depth == 0) + expect_end = true; break; case FDT_PROP: diff --git a/tests/Makefile.tests b/tests/Makefile.tests index cb66c9f..fe5cae8 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -32,7 +32,9 @@ LIB_TESTS_L = get_mem_rsv \ fs_tree1 LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) -LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv +LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv \ + two_roots + LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%) DL_LIB_TESTS_L = asm_tree_dump value-labels diff --git a/tests/dumptrees.c b/tests/dumptrees.c index aecb326..02ca092 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -24,6 +24,7 @@ static struct { TREE(ovf_size_strings), TREE(truncated_property), TREE(truncated_string), TREE(truncated_memrsv), + TREE(two_roots) }; #define NUM_TREES (sizeof(trees) / sizeof(trees[0])) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 4b8dada..82543fc 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -518,7 +518,7 @@ libfdt_tests () { run_test check_full $good done for bad in truncated_property.dtb truncated_string.dtb \ - truncated_memrsv.dtb; do + truncated_memrsv.dtb two_roots.dtb; do run_test check_full -n $bad done } diff --git a/tests/testdata.h b/tests/testdata.h index 0d08efb..d03f352 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -55,4 +55,5 @@ extern struct fdt_header bad_prop_char; extern struct fdt_header ovf_size_strings; extern struct fdt_header truncated_string; extern struct fdt_header truncated_memrsv; +extern struct fdt_header two_roots; #endif /* ! __ASSEMBLY */ diff --git a/tests/trees.S b/tests/trees.S index efab287..e2380b7 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -279,3 +279,22 @@ truncated_memrsv_rsvmap: truncated_memrsv_rsvmap_end: truncated_memrsv_end: + + + /* two root nodes */ + TREE_HDR(two_roots) + EMPTY_RSVMAP(two_roots) + +two_roots_struct: + BEGIN_NODE("") + END_NODE + BEGIN_NODE("") + END_NODE + FDTLONG(FDT_END) +two_roots_struct_end: + +two_roots_strings: +two_roots_strings_end: + +two_roots_end: + From a2def5479950d066dcf829b8c1a22874d0aea9a4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 23 Mar 2021 14:04:10 +1300 Subject: [PATCH 058/298] libfdt: Check that the root-node name is empty The root node is supposed to have an empty name, but at present this is not checked. The behaviour of such a tree is not well defined. Most software rightly assumes that the root node is at offset 0 and does not check the name. This oddity was discovered as part of a security investigation into U-Boot verified boot. Add a check for this to fdt_check_full(). Signed-off-by: Simon Glass Reported-by: Arie Haenel Reported-by: Julien Lenoir Message-Id: <20210323010410.3222701-2-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/fdt_check.c | 10 ++++++++++ tests/Makefile.tests | 2 +- tests/dumptrees.c | 3 ++- tests/run_tests.sh | 2 +- tests/testdata.h | 1 + tests/trees.S | 15 +++++++++++++++ 6 files changed, 30 insertions(+), 3 deletions(-) diff --git a/libfdt/fdt_check.c b/libfdt/fdt_check.c index 13595a2..fa410a8 100644 --- a/libfdt/fdt_check.c +++ b/libfdt/fdt_check.c @@ -59,6 +59,16 @@ int fdt_check_full(const void *fdt, size_t bufsize) depth++; if (depth > INT_MAX) return -FDT_ERR_BADSTRUCTURE; + + /* The root node must have an empty name */ + if (depth == 1) { + const char *name; + int len; + + name = fdt_get_name(fdt, offset, &len); + if (*name || len) + return -FDT_ERR_BADSTRUCTURE; + } break; case FDT_END_NODE: diff --git a/tests/Makefile.tests b/tests/Makefile.tests index fe5cae8..2b47627 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -33,7 +33,7 @@ LIB_TESTS_L = get_mem_rsv \ LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv \ - two_roots + two_roots named_root LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%) diff --git a/tests/dumptrees.c b/tests/dumptrees.c index 02ca092..f1e0ea9 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -24,7 +24,8 @@ static struct { TREE(ovf_size_strings), TREE(truncated_property), TREE(truncated_string), TREE(truncated_memrsv), - TREE(two_roots) + TREE(two_roots), + TREE(named_root) }; #define NUM_TREES (sizeof(trees) / sizeof(trees[0])) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 82543fc..5c2b1e8 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -518,7 +518,7 @@ libfdt_tests () { run_test check_full $good done for bad in truncated_property.dtb truncated_string.dtb \ - truncated_memrsv.dtb two_roots.dtb; do + truncated_memrsv.dtb two_roots.dtb named_root.dtb; do run_test check_full -n $bad done } diff --git a/tests/testdata.h b/tests/testdata.h index d03f352..4f9e3ba 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -56,4 +56,5 @@ extern struct fdt_header ovf_size_strings; extern struct fdt_header truncated_string; extern struct fdt_header truncated_memrsv; extern struct fdt_header two_roots; +extern struct fdt_header named_root; #endif /* ! __ASSEMBLY */ diff --git a/tests/trees.S b/tests/trees.S index e2380b7..95d599d 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -298,3 +298,18 @@ two_roots_strings_end: two_roots_end: + + /* root node with a non-empty name */ + TREE_HDR(named_root) + EMPTY_RSVMAP(named_root) + +named_root_struct: + BEGIN_NODE("fake") + END_NODE + FDTLONG(FDT_END) +named_root_struct_end: + +named_root_strings: +named_root_strings_end: + +named_root_end: From b07b62ee3342db3af74a8bd056dce810764cc7f1 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 6 Apr 2021 14:07:12 -0500 Subject: [PATCH 059/298] libfdt: Add FDT alignment check to fdt_check_header() Only checking the FDT alignment in fdt_ro_probe_() means that fdt_check_header() can pass, but then subsequent API calls fail on alignment checks. Let's add an alignment check to fdt_check_header() so alignment errors are found up front. Cc: Tom Rini Cc: Frank Rowand Signed-off-by: Rob Herring Message-Id: <20210406190712.2118098-1-robh@kernel.org> Signed-off-by: David Gibson --- libfdt/fdt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 3e89307..9fe7cf4 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -90,6 +90,10 @@ int fdt_check_header(const void *fdt) { size_t hdrsize; + /* The device tree must be at an 8-byte aligned address */ + if ((uintptr_t)fdt & 7) + return -FDT_ERR_ALIGNMENT; + if (fdt_magic(fdt) != FDT_MAGIC) return -FDT_ERR_BADMAGIC; if (!can_assume(LATEST)) { From 9bb9b8d0b4a03d119162221cbdfd91354653d902 Mon Sep 17 00:00:00 2001 From: Ilya Lipnitskiy Date: Mon, 3 May 2021 20:59:41 -0700 Subject: [PATCH 060/298] checks: tigthen up nr-gpios prop exception There are no instances of nr-gpio in the Linux kernel tree, only "[,]nr-gpios", so make the check stricter. nr-gpios without a "vendor," prefix is also invalid, according to the DT spec[0], and there are no DT files in the Linux kernel tree with non-vendor nr-gpios. There are some drivers, but they are not DT spec compliant, so don't suppress the check for them. [0]: Link: https://github.com/devicetree-org/dt-schema/blob/cb53a16a1eb3e2169ce170c071e47940845ec26e/schemas/gpio/gpio-consumer.yaml#L20 Signed-off-by: Ilya Lipnitskiy Cc: Rob Herring Message-Id: <20210504035944.8453-2-ilya.lipnitskiy@gmail.com> Signed-off-by: David Gibson --- checks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks.c b/checks.c index c420772..7e9d73a 100644 --- a/checks.c +++ b/checks.c @@ -1494,7 +1494,7 @@ static bool prop_is_gpio(struct property *prop) * *-gpios and *-gpio can appear in property names, * so skip over any false matches (only one known ATM) */ - if (strstr(prop->name, "nr-gpio")) + if (strstr(prop->name, ",nr-gpios")) return false; str = strrchr(prop->name, '-'); From 09c6a6e88718de6b2ef646a015187605caa5789f Mon Sep 17 00:00:00 2001 From: Ilya Lipnitskiy Date: Mon, 3 May 2021 20:59:42 -0700 Subject: [PATCH 061/298] dtc.h: add strends for suffix matching Logic is similar to strcmp_suffix in /drivers/of/property.c with the exception that strends allows string length to equal suffix length. Signed-off-by: Ilya Lipnitskiy Message-Id: <20210504035944.8453-3-ilya.lipnitskiy@gmail.com> Signed-off-by: David Gibson --- dtc.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dtc.h b/dtc.h index d3e82fb..6296361 100644 --- a/dtc.h +++ b/dtc.h @@ -86,6 +86,16 @@ static inline uint64_t dtb_ld64(const void *p) #define streq(a, b) (strcmp((a), (b)) == 0) #define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0) #define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0)) +static inline bool strends(const char *str, const char *suffix) +{ + unsigned int len, suffix_len; + + len = strlen(str); + suffix_len = strlen(suffix); + if (len < suffix_len) + return false; + return streq(str + len - suffix_len, suffix); +} #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) From ad4abfadb687060d047a9cff664b471c7effb3b1 Mon Sep 17 00:00:00 2001 From: Ilya Lipnitskiy Date: Mon, 3 May 2021 20:59:43 -0700 Subject: [PATCH 062/298] checks: replace strstr and strrchr with strends Makes the logic more clear Signed-off-by: Ilya Lipnitskiy Message-Id: <20210504035944.8453-4-ilya.lipnitskiy@gmail.com> Signed-off-by: David Gibson --- checks.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/checks.c b/checks.c index 7e9d73a..eb91c8e 100644 --- a/checks.c +++ b/checks.c @@ -687,8 +687,7 @@ static void check_names_is_string_list(struct check *c, struct dt_info *dti, struct property *prop; for_each_property(node, prop) { - const char *s = strrchr(prop->name, '-'); - if (!s || !streq(s, "-names")) + if (!strends(prop->name, "-names")) continue; c->data = prop->name; @@ -1488,24 +1487,17 @@ WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sen static bool prop_is_gpio(struct property *prop) { - char *str; - /* * *-gpios and *-gpio can appear in property names, * so skip over any false matches (only one known ATM) */ - if (strstr(prop->name, ",nr-gpios")) + if (strends(prop->name, ",nr-gpios")) return false; - str = strrchr(prop->name, '-'); - if (str) - str++; - else - str = prop->name; - if (!(streq(str, "gpios") || streq(str, "gpio"))) - return false; - - return true; + return strends(prop->name, "-gpios") || + streq(prop->name, "gpios") || + strends(prop->name, "-gpio") || + streq(prop->name, "gpio"); } static void check_gpios_property(struct check *c, @@ -1540,13 +1532,10 @@ static void check_deprecated_gpio_property(struct check *c, struct property *prop; for_each_property(node, prop) { - char *str; - if (!prop_is_gpio(prop)) continue; - str = strstr(prop->name, "gpio"); - if (!streq(str, "gpio")) + if (!strends(prop->name, "gpio")) continue; FAIL_PROP(c, dti, node, prop, From c8bddd1060957ed0a5c95ea364cc13891742b09f Mon Sep 17 00:00:00 2001 From: Ilya Lipnitskiy Date: Mon, 3 May 2021 20:59:44 -0700 Subject: [PATCH 063/298] tests: add a positive gpio test case Ensure that properly named properties don't trigger warnings Signed-off-by: Ilya Lipnitskiy Message-Id: <20210504035944.8453-5-ilya.lipnitskiy@gmail.com> Signed-off-by: David Gibson --- tests/good-gpio.dts | 12 ++++++++++++ tests/run_tests.sh | 2 ++ 2 files changed, 14 insertions(+) create mode 100644 tests/good-gpio.dts diff --git a/tests/good-gpio.dts b/tests/good-gpio.dts new file mode 100644 index 0000000..65d1c17 --- /dev/null +++ b/tests/good-gpio.dts @@ -0,0 +1,12 @@ +/dts-v1/; + +/ { + gpio: gpio-controller { + #gpio-cells = <3>; + }; + + node { + foo,nr-gpios = <1>; + foo-gpios = <&gpio 1 2 3>; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 5c2b1e8..0e8ecdb 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -709,10 +709,12 @@ dtc_tests () { check_tests "$SRCDIR/unit-addr-unique.dts" unique_unit_address check_tests "$SRCDIR/bad-phandle-cells.dts" interrupts_extended_property check_tests "$SRCDIR/bad-gpio.dts" gpios_property + check_tests "$SRCDIR/good-gpio.dts" -n gpios_property check_tests "$SRCDIR/bad-graph.dts" graph_child_address check_tests "$SRCDIR/bad-graph.dts" graph_port check_tests "$SRCDIR/bad-graph.dts" graph_endpoint run_sh_test "$SRCDIR/dtc-checkfails.sh" deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/bad-gpio.dts" + run_sh_test "$SRCDIR/dtc-checkfails.sh" -n deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/good-gpio.dts" check_tests "$SRCDIR/bad-interrupt-cells.dts" interrupts_property check_tests "$SRCDIR/bad-interrupt-controller.dts" interrupt_provider run_sh_test "$SRCDIR/dtc-checkfails.sh" node_name_chars -- -I dtb -O dtb bad_node_char.dtb From 61e513439e408035b4da9ce7120a91297371a308 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Mon, 24 May 2021 11:49:10 -0400 Subject: [PATCH 064/298] pylibfdt: Rework "avoid unused variable warning" lines Clang has -Wself-assign enabled by default under -Wall and so when building with -Werror we would get an error here. Inspired by Linux kernel git commit a21151b9d81a ("tools/build: tweak unused value workaround") make use of the fact that both Clang and GCC support casting to `void` as the method to note that something is intentionally unused. Signed-off-by: Tom Rini Message-Id: <20210524154910.30523-1-trini@konsulko.com> Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 3e09d3a..51ee801 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -1009,7 +1009,7 @@ typedef uint32_t fdt32_t; } $1 = (void *)PyByteArray_AsString($input); fdt = $1; - fdt = fdt; /* avoid unused variable warning */ + (void)fdt; /* avoid unused variable warning */ } /* Some functions do change the device tree, so use void * */ @@ -1020,7 +1020,7 @@ typedef uint32_t fdt32_t; } $1 = PyByteArray_AsString($input); fdt = $1; - fdt = fdt; /* avoid unused variable warning */ + (void)fdt; /* avoid unused variable warning */ } /* typemap used for fdt_get_property_by_offset() */ From 2dffc192a77fda9d9eeb393894e686c98246e8f3 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 25 May 2021 20:03:31 -0500 Subject: [PATCH 065/298] yamltree: Remove marker ordering dependency The check for phandle markers is fragile because the phandle marker must be after a type marker. The only guarantee for markers is they are in offset order. The order at a specific offset is undefined. Rework yaml_propval_int() to get the full marker list, so it can find a phandle marker no matter the ordering. Signed-off-by: Rob Herring Message-Id: <20210526010335.860787-2-robh@kernel.org> Signed-off-by: David Gibson --- yamltree.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/yamltree.c b/yamltree.c index e63d32f..55908c8 100644 --- a/yamltree.c +++ b/yamltree.c @@ -29,11 +29,12 @@ char *yaml_error_name[] = { (emitter)->problem, __func__, __LINE__); \ }) -static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, unsigned int len, int width) +static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, + char *data, unsigned int seq_offset, unsigned int len, int width) { yaml_event_t event; void *tag; - unsigned int off, start_offset = markers->offset; + unsigned int off; switch(width) { case 1: tag = "!u8"; break; @@ -66,7 +67,7 @@ static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, ch m = markers; is_phandle = false; for_each_marker_of_type(m, REF_PHANDLE) { - if (m->offset == (start_offset + off)) { + if (m->offset == (seq_offset + off)) { is_phandle = true; break; } @@ -114,6 +115,7 @@ static void yaml_propval(yaml_emitter_t *emitter, struct property *prop) yaml_event_t event; unsigned int len = prop->val.len; struct marker *m = prop->val.markers; + struct marker *markers = prop->val.markers; /* Emit the property name */ yaml_scalar_event_initialize(&event, NULL, @@ -151,19 +153,19 @@ static void yaml_propval(yaml_emitter_t *emitter, struct property *prop) switch(m->type) { case TYPE_UINT16: - yaml_propval_int(emitter, m, data, chunk_len, 2); + yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 2); break; case TYPE_UINT32: - yaml_propval_int(emitter, m, data, chunk_len, 4); + yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 4); break; case TYPE_UINT64: - yaml_propval_int(emitter, m, data, chunk_len, 8); + yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 8); break; case TYPE_STRING: yaml_propval_string(emitter, data, chunk_len); break; default: - yaml_propval_int(emitter, m, data, chunk_len, 1); + yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 1); break; } } From 6b3081abc4ac6b0b084ebb8a09e76854dffa797c Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 25 May 2021 20:03:32 -0500 Subject: [PATCH 066/298] checks: Add check_is_cell() for all phandle+arg properties There's already a check for '#.*-cells' properties, so let's enable it for all the ones we already know about. Signed-off-by: Rob Herring Message-Id: <20210526010335.860787-3-robh@kernel.org> Signed-off-by: David Gibson --- checks.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/checks.c b/checks.c index eb91c8e..6a01a24 100644 --- a/checks.c +++ b/checks.c @@ -1466,7 +1466,8 @@ static void check_provider_cells_property(struct check *c, } #define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \ static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \ - WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references); + WARNING_IF_NOT_CELL(nm##_is_cell, cells_name); \ + WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &nm##_is_cell, &phandle_references); WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells"); WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells"); @@ -1843,21 +1844,37 @@ static struct check *check_table[] = { &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path, &clocks_property, + &clocks_is_cell, &cooling_device_property, + &cooling_device_is_cell, &dmas_property, + &dmas_is_cell, &hwlocks_property, + &hwlocks_is_cell, &interrupts_extended_property, + &interrupts_extended_is_cell, &io_channels_property, + &io_channels_is_cell, &iommus_property, + &iommus_is_cell, &mboxes_property, + &mboxes_is_cell, &msi_parent_property, + &msi_parent_is_cell, &mux_controls_property, + &mux_controls_is_cell, &phys_property, + &phys_is_cell, &power_domains_property, + &power_domains_is_cell, &pwms_property, + &pwms_is_cell, &resets_property, + &resets_is_cell, &sound_dai_property, + &sound_dai_is_cell, &thermal_sensors_property, + &thermal_sensors_is_cell, &deprecated_gpio_property, &gpios_property, From 0c3fd9b6acebc980e5e881385afd265fa7665270 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 25 May 2021 20:03:33 -0500 Subject: [PATCH 067/298] checks: Drop interrupt_cells_is_cell check With the prior commit, this check is now redundant. Signed-off-by: Rob Herring Message-Id: <20210526010335.860787-4-robh@kernel.org> Signed-off-by: David Gibson --- checks.c | 3 +-- tests/run_tests.sh | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/checks.c b/checks.c index 6a01a24..7ff044d 100644 --- a/checks.c +++ b/checks.c @@ -672,7 +672,6 @@ ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &pa */ WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells"); WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells"); -WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells"); WARNING_IF_NOT_STRING(device_type_is_string, "device_type"); WARNING_IF_NOT_STRING(model_is_string, "model"); @@ -1809,7 +1808,7 @@ static struct check *check_table[] = { &phandle_references, &path_references, &omit_unused_nodes, - &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell, + &address_cells_is_cell, &size_cells_is_cell, &device_type_is_string, &model_is_string, &status_is_string, &label_is_string, diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 0e8ecdb..0e270fe 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -691,7 +691,7 @@ dtc_tests () { run_sh_test "$SRCDIR/dtc-fatal.sh" -I dts -O dtb "$SRCDIR/nonexist-node-ref2.dts" check_tests "$SRCDIR/bad-name-property.dts" name_properties - check_tests "$SRCDIR/bad-ncells.dts" address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell + check_tests "$SRCDIR/bad-ncells.dts" address_cells_is_cell size_cells_is_cell interrupts_extended_is_cell check_tests "$SRCDIR/bad-string-props.dts" device_type_is_string model_is_string status_is_string label_is_string compatible_is_string_list names_is_string_list check_tests "$SRCDIR/bad-chosen.dts" chosen_node_is_root check_tests "$SRCDIR/bad-chosen.dts" chosen_node_bootargs @@ -740,7 +740,7 @@ dtc_tests () { # Check warning options - run_sh_test "$SRCDIR/dtc-checkfails.sh" address_cells_is_cell interrupt_cells_is_cell -n size_cells_is_cell -- -Wno_size_cells_is_cell -I dts -O dtb "$SRCDIR/bad-ncells.dts" + run_sh_test "$SRCDIR/dtc-checkfails.sh" address_cells_is_cell interrupts_extended_is_cell -n size_cells_is_cell -- -Wno_size_cells_is_cell -I dts -O dtb "$SRCDIR/bad-ncells.dts" run_sh_test "$SRCDIR/dtc-fails.sh" -n test-warn-output.test.dtb -I dts -O dtb "$SRCDIR/bad-ncells.dts" run_sh_test "$SRCDIR/dtc-fails.sh" test-error-output.test.dtb -I dts -O dtb bad-ncells.dts -Esize_cells_is_cell run_sh_test "$SRCDIR/dtc-checkfails.sh" always_fail -- -Walways_fail -I dts -O dtb "$SRCDIR/test_tree1.dts" From e59ca36fb70e32f8b4850135ab94fdf44cd22557 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 Jun 2021 14:15:25 +1000 Subject: [PATCH 068/298] Make handling of cpp line information more tolerant At least some cpp implementations, in at least some circumstances place multiple numbers after the file name when they put line number information into the output. We don't really care what the content of these is, but we want the dtc lexer not to choke on this, so adjust the rule for handling cpp line number information accordingly. Signed-off-by: David Gibson --- dtc-lexer.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index b3b7270..5568b4a 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -57,7 +57,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...); push_input_file(name); } -<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? { +<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)* { char *line, *fnstart, *fnend; struct data fn; /* skip text before line # */ From 4c2ef8f4d14ca411b41b9c6891028d58d2079bf7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 Jun 2021 15:17:11 +1000 Subject: [PATCH 069/298] checks: Introduce is_multiple_of() In a number of places we check if one number is a multiple of another, using a modulus. In some of those cases the divisor is potentially zero, which needs special handling or we could trigger a divide by zero. Introduce an is_multiple_of() helper to safely handle this case, and use it in a bunch of places. This should close Coverity issue 1501687, maybe others as well. Signed-off-by: David Gibson --- checks.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/checks.c b/checks.c index 7ff044d..e6c7c3e 100644 --- a/checks.c +++ b/checks.c @@ -143,6 +143,14 @@ static void check_nodes_props(struct check *c, struct dt_info *dti, struct node check_nodes_props(c, dti, child); } +static bool is_multiple_of(int multiple, int divisor) +{ + if (divisor == 0) + return multiple == 0; + else + return (multiple % divisor) == 0; +} + static bool run_check(struct check *c, struct dt_info *dti) { struct node *dt = dti->dt; @@ -766,7 +774,7 @@ static void check_reg_format(struct check *c, struct dt_info *dti, size_cells = node_size_cells(node->parent); entrylen = (addr_cells + size_cells) * sizeof(cell_t); - if (!entrylen || (prop->val.len % entrylen) != 0) + if (!is_multiple_of(prop->val.len, entrylen)) FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) " "(#address-cells == %d, #size-cells == %d)", prop->val.len, addr_cells, size_cells); @@ -807,7 +815,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti, "#size-cells (%d) differs from %s (%d)", ranges, c_size_cells, node->parent->fullpath, p_size_cells); - } else if ((prop->val.len % entrylen) != 0) { + } else if (!is_multiple_of(prop->val.len, entrylen)) { FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) " "(parent #address-cells == %d, child #address-cells == %d, " "#size-cells == %d)", ranges, prop->val.len, @@ -1382,7 +1390,7 @@ static void check_property_phandle_args(struct check *c, struct node *root = dti->dt; int cell, cellsize = 0; - if (prop->val.len % sizeof(cell_t)) { + if (!is_multiple_of(prop->val.len, sizeof(cell_t))) { FAIL_PROP(c, dti, node, prop, "property size (%d) is invalid, expected multiple of %zu", prop->val.len, sizeof(cell_t)); @@ -1594,7 +1602,7 @@ static void check_interrupts_property(struct check *c, if (!irq_prop) return; - if (irq_prop->val.len % sizeof(cell_t)) + if (!is_multiple_of(irq_prop->val.len, sizeof(cell_t))) FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu", irq_prop->val.len, sizeof(cell_t)); @@ -1643,7 +1651,7 @@ static void check_interrupts_property(struct check *c, } irq_cells = propval_cell(prop); - if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) { + if (!is_multiple_of(irq_prop->val.len, irq_cells * sizeof(cell_t))) { FAIL_PROP(c, dti, node, prop, "size is (%d), expected multiple of %d", irq_prop->val.len, (int)(irq_cells * sizeof(cell_t))); From 21d61d18f9682de69d7cc1632003fb4e476af43a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 Jun 2021 15:28:55 +1000 Subject: [PATCH 070/298] Fix CID 1461557 Coverity gets a bit confused by loading fdt_size_dt_strings() and using it in a memmove(). In fact this is safe because the callers have verified this information (via FDT_RW_PROBE() in fdt_pack() or construction in fdt_open_into()). Passing in strings_size like we already do struct_size seems to get Coverity to follow what's going on here. Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 2fbb545..3621d36 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -394,7 +394,9 @@ int fdt_del_node(void *fdt, int nodeoffset) } static void fdt_packblocks_(const char *old, char *new, - int mem_rsv_size, int struct_size) + int mem_rsv_size, + int struct_size, + int strings_size) { int mem_rsv_off, struct_off, strings_off; @@ -409,8 +411,7 @@ static void fdt_packblocks_(const char *old, char *new, fdt_set_off_dt_struct(new, struct_off); fdt_set_size_dt_struct(new, struct_size); - memmove(new + strings_off, old + fdt_off_dt_strings(old), - fdt_size_dt_strings(old)); + memmove(new + strings_off, old + fdt_off_dt_strings(old), strings_size); fdt_set_off_dt_strings(new, strings_off); fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); } @@ -470,7 +471,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) return -FDT_ERR_NOSPACE; } - fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size); + fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size, + fdt_size_dt_strings(fdt)); memmove(buf, tmp, newsize); fdt_set_magic(buf, FDT_MAGIC); @@ -490,7 +492,8 @@ int fdt_pack(void *fdt) mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); - fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); + fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt), + fdt_size_dt_strings(fdt)); fdt_set_totalsize(fdt, fdt_data_size_(fdt)); return 0; From b6910bec11614980a21e46fbccc35934b671bd81 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 Jun 2021 17:00:49 +1000 Subject: [PATCH 071/298] Bump version to v1.6.1 A number of fixes have accumulated, so rolling up another release. Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c187d5f..ea8c659 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ # VERSION = 1 PATCHLEVEL = 6 -SUBLEVEL = 0 +SUBLEVEL = 1 EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = From 24e7f511fd4acaf48d25374f88dbdbdb277e6a26 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 11 Jun 2021 18:10:34 +0100 Subject: [PATCH 072/298] fdtdump: Fix signedness comparisons warnings With -Wsign-compare, compilers warn about a mismatching signedness in comparisons in fdtdump.c. The "len" parameter to valid_header() refers to a memory size, not a file offset, so the (unsigned) size_t is better fit, and fixes the warning nicely. In the main function we compare the difference between two pointers, which produces a signed ptrdiff_t type. However the while loop above the comparison makes sure that "p" always points before "endp" (by virtue of the limit in the memchr() call). This means "endp - p" is never negative, so we can safely cast this expression to an unsigned type. This fixes "make fdtdump", when compiled with -Wsign-compare. Signed-off-by: Andre Przywara Message-Id: <20210611171040.25524-3-andre.przywara@arm.com> Signed-off-by: David Gibson --- fdtdump.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fdtdump.c b/fdtdump.c index d9fb374..bdc0f94 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -18,7 +18,7 @@ #include "util.h" #define FDT_MAGIC_SIZE 4 -#define MAX_VERSION 17 +#define MAX_VERSION 17U #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) #define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) @@ -163,7 +163,7 @@ static const char * const usage_opts_help[] = { USAGE_COMMON_OPTS_HELP }; -static bool valid_header(char *p, off_t len) +static bool valid_header(char *p, size_t len) { if (len < sizeof(struct fdt_header) || fdt_magic(p) != FDT_MAGIC || @@ -235,7 +235,7 @@ int main(int argc, char *argv[]) } ++p; } - if (!p || endp - p < sizeof(struct fdt_header)) + if (!p || (size_t)(endp - p) < sizeof(struct fdt_header)) die("%s: could not locate fdt magic\n", file); printf("%s: found fdt at offset %#tx\n", file, p - buf); buf = p; From 5bec74a6d13519381a40b5433ede7849a75a8d79 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 11 Jun 2021 18:10:37 +0100 Subject: [PATCH 073/298] dtc: Fix signedness comparisons warnings: reservednum With -Wsign-compare, compilers warn about a mismatching signedness in comparisons in code using the "reservednum" variable. There is obviously little sense in having a negative number of reserved memory entries, so let's make this variable and all its users unsigned. Signed-off-by: Andre Przywara Message-Id: <20210611171040.25524-6-andre.przywara@arm.com> Signed-off-by: David Gibson --- dtc.c | 4 ++-- dtc.h | 2 +- flattree.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dtc.c b/dtc.c index 3962d3f..bc786c5 100644 --- a/dtc.c +++ b/dtc.c @@ -12,7 +12,7 @@ * Command line options */ int quiet; /* Level of quietness */ -int reservenum; /* Number of memory reservation slots */ +unsigned int reservenum;/* Number of memory reservation slots */ int minsize; /* Minimum blob size */ int padsize; /* Additional padding to blob */ int alignsize; /* Additional padding to blob accroding to the alignsize */ @@ -197,7 +197,7 @@ int main(int argc, char *argv[]) depname = optarg; break; case 'R': - reservenum = strtol(optarg, NULL, 0); + reservenum = strtoul(optarg, NULL, 0); break; case 'S': minsize = strtol(optarg, NULL, 0); diff --git a/dtc.h b/dtc.h index 6296361..47664f2 100644 --- a/dtc.h +++ b/dtc.h @@ -35,7 +35,7 @@ * Command line options */ extern int quiet; /* Level of quietness */ -extern int reservenum; /* Number of memory reservation slots */ +extern unsigned int reservenum; /* Number of memory reservation slots */ extern int minsize; /* Minimum blob size */ extern int padsize; /* Additional padding to blob */ extern int alignsize; /* Additional padding to blob accroding to the alignsize */ diff --git a/flattree.c b/flattree.c index 4659afb..3d0204f 100644 --- a/flattree.c +++ b/flattree.c @@ -295,7 +295,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist, { struct reserve_info *re; struct data d = empty_data; - int j; + unsigned int j; for (re = reservelist; re; re = re->next) { d = data_append_re(d, re->address, re->size); From ecfb438c07fa468a129e81c7d84c7c293c7b0150 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 11 Jun 2021 18:10:38 +0100 Subject: [PATCH 074/298] dtc: Fix signedness comparisons warnings: pointer diff With -Wsign-compare, compilers warn about a mismatching signedness in comparisons in the function get_node_by_path(). Taking the difference between two pointers results in a signed ptrdiff_t type, which mismatches the unsigned type returned by strlen(). Since "p" has been returned by a call to strchr() with "path" as its argument, we know for sure that it's bigger than "path", so the difference must be positive. So a cast to an unsigned type is valid. Signed-off-by: Andre Przywara Message-Id: <20210611171040.25524-7-andre.przywara@arm.com> Signed-off-by: David Gibson --- livetree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/livetree.c b/livetree.c index 7eacd02..dfbae65 100644 --- a/livetree.c +++ b/livetree.c @@ -526,7 +526,7 @@ struct node *get_node_by_path(struct node *tree, const char *path) p = strchr(path, '/'); for_each_child(tree, child) { - if (p && strprefixeq(path, p - path, child->name)) + if (p && strprefixeq(path, (size_t)(p - path), child->name)) return get_node_by_path(child, p+1); else if (!p && streq(path, child->name)) return child; From d966f08fcd21ded2ed6608097e9832e9466857fd Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 18 Jun 2021 18:20:26 +0100 Subject: [PATCH 075/298] tests: Fix signedness comparisons warnings With -Wsign-compare, compilers warn about a mismatching signedness in comparisons in various files in the tests/ directory. For about half of the cases we can simply change the signed variable to be of an unsigned type, because they will never need to store negative values (which is the best fix of the problem). In the remaining cases we can cast the signed variable to an unsigned type, provided we know for sure it is not negative. We see two different scenarios here: - We either just explicitly checked for this variable to be positive (if (rc < 0) FAIL();), or - We rely on a function returning only positive values in the "length" pointer if the function returned successfully: which we just checked. At two occassions we compare with a constant "-1" (even though the variable is unsigned), so we just change this to ~0U to create an unsigned comparison value. Since this is about the tests, let's also add explicit tests for those values really not being negative. This fixes "make tests" (but not "make check" yet), when compiled with -Wsign-compare. Signed-off-by: Andre Przywara Message-Id: <20210618172030.9684-2-andre.przywara@arm.com> Signed-off-by: David Gibson --- tests/dumptrees.c | 2 +- tests/fs_tree1.c | 2 +- tests/get_name.c | 4 +++- tests/integer-expressions.c | 2 +- tests/nopulate.c | 3 ++- tests/overlay.c | 6 +++++- tests/phandle_format.c | 2 +- tests/property_iterate.c | 2 +- tests/references.c | 2 +- tests/set_name.c | 10 ++++++++-- tests/subnode_iterate.c | 2 +- tests/tests.h | 2 +- tests/testutils.c | 12 +++++++++--- 13 files changed, 35 insertions(+), 16 deletions(-) diff --git a/tests/dumptrees.c b/tests/dumptrees.c index f1e0ea9..08967b3 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -32,7 +32,7 @@ static struct { int main(int argc, char *argv[]) { - int i; + unsigned int i; if (argc != 2) { fprintf(stderr, "Missing output directory argument\n"); diff --git a/tests/fs_tree1.c b/tests/fs_tree1.c index dff3880..978f6a3 100644 --- a/tests/fs_tree1.c +++ b/tests/fs_tree1.c @@ -54,7 +54,7 @@ static void mkfile(const char *name, void *data, size_t len) rc = write(fd, data, len); if (rc < 0) FAIL("write(\"%s\"): %s", name, strerror(errno)); - if (rc != len) + if ((unsigned)rc != len) FAIL("write(\"%s\"): short write", name); rc = close(fd); diff --git a/tests/get_name.c b/tests/get_name.c index 5a35103..d20bf30 100644 --- a/tests/get_name.c +++ b/tests/get_name.c @@ -34,12 +34,14 @@ static void check_name(void *fdt, const char *path) offset, getname, len); if (!getname) FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len)); + if (len < 0) + FAIL("negative name length (%d) for returned node name\n", len); if (strcmp(getname, checkname) != 0) FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"", path, getname, checkname); - if (len != strlen(getname)) + if ((unsigned)len != strlen(getname)) FAIL("fdt_get_name(%s) returned length %d instead of %zd", path, len, strlen(getname)); diff --git a/tests/integer-expressions.c b/tests/integer-expressions.c index 6f33d81..2f164d9 100644 --- a/tests/integer-expressions.c +++ b/tests/integer-expressions.c @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) void *fdt; const fdt32_t *res; int reslen; - int i; + unsigned int i; test_init(argc, argv); diff --git a/tests/nopulate.c b/tests/nopulate.c index 2ae1753..e06a0b3 100644 --- a/tests/nopulate.c +++ b/tests/nopulate.c @@ -43,7 +43,8 @@ static int nopulate_struct(char *buf, const char *fdt) int main(int argc, char *argv[]) { char *fdt, *fdt2, *buf; - int newsize, struct_start, struct_end_old, struct_end_new, delta; + int newsize, struct_end_old, struct_end_new, delta; + unsigned int struct_start; const char *inname; char outname[PATH_MAX]; diff --git a/tests/overlay.c b/tests/overlay.c index 91afa72..f3dd310 100644 --- a/tests/overlay.c +++ b/tests/overlay.c @@ -35,7 +35,11 @@ static int fdt_getprop_u32_by_poffset(void *fdt, const char *path, return node_off; val = fdt_getprop(fdt, node_off, name, &len); - if (!val || (len < (sizeof(uint32_t) * (poffset + 1)))) + if (val && len < 0) + FAIL("fdt_getprop() returns negative length"); + if (!val && len < 0) + return len; + if (!val || ((unsigned)len < (sizeof(uint32_t) * (poffset + 1)))) return -FDT_ERR_NOTFOUND; *out = fdt32_to_cpu(*(val + poffset)); diff --git a/tests/phandle_format.c b/tests/phandle_format.c index d00618f..0febb32 100644 --- a/tests/phandle_format.c +++ b/tests/phandle_format.c @@ -45,7 +45,7 @@ int main(int argc, char *argv[]) FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4)); h4 = fdt_get_phandle(fdt, n4); - if ((h4 == 0) || (h4 == -1)) + if ((h4 == 0) || (h4 == ~0U)) FAIL("/node4 has bad phandle 0x%x\n", h4); if (phandle_format & PHANDLE_LEGACY) diff --git a/tests/property_iterate.c b/tests/property_iterate.c index 9a67f49..0b6af9b 100644 --- a/tests/property_iterate.c +++ b/tests/property_iterate.c @@ -23,7 +23,7 @@ static void test_node(void *fdt, int parent_offset) uint32_t properties; const fdt32_t *prop; int offset, property; - int count; + unsigned int count; int len; /* diff --git a/tests/references.c b/tests/references.c index d18e722..cb1daaa 100644 --- a/tests/references.c +++ b/tests/references.c @@ -106,7 +106,7 @@ int main(int argc, char *argv[]) if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0)) FAIL("/node4 has bad phandle, 0x%x", h4); - if ((h5 == 0) || (h5 == -1)) + if ((h5 == 0) || (h5 == ~0U)) FAIL("/node5 has bad phandle, 0x%x", h5); if ((h5 == h4) || (h5 == h2) || (h5 == h1)) FAIL("/node5 has duplicate phandle, 0x%x", h5); diff --git a/tests/set_name.c b/tests/set_name.c index a62cb58..5020305 100644 --- a/tests/set_name.c +++ b/tests/set_name.c @@ -39,7 +39,11 @@ static void check_set_name(void *fdt, const char *path, const char *newname) FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"", path, getname, oldname); - if (len != strlen(getname)) + if (len < 0) + FAIL("fdt_get_name(%s) returned negative length: %d", + path, len); + + if ((unsigned)len != strlen(getname)) FAIL("fdt_get_name(%s) returned length %d instead of %zd", path, len, strlen(getname)); @@ -51,12 +55,14 @@ static void check_set_name(void *fdt, const char *path, const char *newname) getname = fdt_get_name(fdt, offset, &len); if (!getname) FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len)); + if (len < 0) + FAIL("negative name length (%d) for returned node name\n", len); if (strcmp(getname, newname) != 0) FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"", path, getname, newname); - if (len != strlen(getname)) + if ((unsigned)len != strlen(getname)) FAIL("fdt_get_name(%s) returned length %d instead of %zd", path, len, strlen(getname)); } diff --git a/tests/subnode_iterate.c b/tests/subnode_iterate.c index 2dc9b2d..2553a51 100644 --- a/tests/subnode_iterate.c +++ b/tests/subnode_iterate.c @@ -23,7 +23,7 @@ static void test_node(void *fdt, int parent_offset) uint32_t subnodes; const fdt32_t *prop; int offset; - int count; + unsigned int count; int len; /* This property indicates the number of subnodes to expect */ diff --git a/tests/tests.h b/tests/tests.h index 1017366..bf8f23c 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -83,7 +83,7 @@ void cleanup(void); void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size); void check_property(void *fdt, int nodeoffset, const char *name, - int len, const void *val); + unsigned int len, const void *val); #define check_property_cell(fdt, nodeoffset, name, val) \ ({ \ fdt32_t x = cpu_to_fdt32(val); \ diff --git a/tests/testutils.c b/tests/testutils.c index 5e494c5..10129c0 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -88,7 +88,7 @@ void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size) } void check_property(void *fdt, int nodeoffset, const char *name, - int len, const void *val) + unsigned int len, const void *val) { const struct fdt_property *prop; int retlen, namelen; @@ -101,6 +101,9 @@ void check_property(void *fdt, int nodeoffset, const char *name, if (! prop) FAIL("Error retrieving \"%s\" pointer: %s", name, fdt_strerror(retlen)); + if (retlen < 0) + FAIL("negative name length (%d) for returned property\n", + retlen); tag = fdt32_to_cpu(prop->tag); nameoff = fdt32_to_cpu(prop->nameoff); @@ -112,13 +115,16 @@ void check_property(void *fdt, int nodeoffset, const char *name, propname = fdt_get_string(fdt, nameoff, &namelen); if (!propname) FAIL("Couldn't get property name: %s", fdt_strerror(namelen)); - if (namelen != strlen(propname)) + if (namelen < 0) + FAIL("negative name length (%d) for returned string\n", + namelen); + if ((unsigned)namelen != strlen(propname)) FAIL("Incorrect prop name length: %d instead of %zd", namelen, strlen(propname)); if (!streq(propname, name)) FAIL("Property name mismatch \"%s\" instead of \"%s\"", propname, name); - if (proplen != retlen) + if (proplen != (unsigned)retlen) FAIL("Length retrieved for \"%s\" by fdt_get_property()" " differs from stored length (%d != %d)", name, retlen, proplen); From 910221185560fe0c5dc0997dd7d3b472a0a7cdea Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 18 Jun 2021 18:20:27 +0100 Subject: [PATCH 076/298] fdtget: Fix signedness comparisons warnings With -Wsign-compare, compilers warn about a mismatching signedness in the different legs of the conditional operator, in fdtget.c. In the questionable expression, we are constructing a 16-bit value out of two unsigned 8-bit values, however are relying on the compiler's automatic expansion of the uint8_t to a larger type, to survive the left shift. This larger type happens to be an "int", so this part of the expression becomes signed. Fix this by explicitly blowing up the uint8_t to a larger *unsigned* type, before doing the left shift. And while we are at it, convert the hardly readable conditional operator usage into a sane switch/case expression. This fixes "make fdtget", when compiled with -Wsign-compare. Signed-off-by: Andre Przywara Message-Id: <20210618172030.9684-3-andre.przywara@arm.com> Signed-off-by: David Gibson --- fdtget.c | 10 ++++++++-- libfdt/libfdt.h | 7 +++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/fdtget.c b/fdtget.c index 777582e..54fc6a0 100644 --- a/fdtget.c +++ b/fdtget.c @@ -62,8 +62,14 @@ static int show_cell_list(struct display_info *disp, const char *data, int len, for (i = 0; i < len; i += size, p += size) { if (i) printf(" "); - value = size == 4 ? fdt32_ld((const fdt32_t *)p) : - size == 2 ? (*p << 8) | p[1] : *p; + switch (size) { + case 4: value = fdt32_ld((const fdt32_t *)p); break; + case 2: value = fdt16_ld((const fdt16_t *)p); break; + case 1: + default: + value = *p; + break; + } printf(fmt, value); } diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 73467f7..7f117e8 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -131,6 +131,13 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); * to work even with unaligned pointers on platforms (such as ARMv5) that don't * like unaligned loads and stores. */ +static inline uint16_t fdt16_ld(const fdt16_t *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint16_t)bp[0] << 8) | bp[1]; +} + static inline uint32_t fdt32_ld(const fdt32_t *p) { const uint8_t *bp = (const uint8_t *)p; From 69bed6c2418f484561263aadbb886ffb925e6b38 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 18 Jun 2021 18:20:28 +0100 Subject: [PATCH 077/298] dtc: Wrap phandle validity check In several places we check for a returned phandle value to be valid, for that it must not be 0 or "-1". Wrap this check in a static inline function in dtc.h, and use ~0U instead of -1 on the way, to keep everything in the unsigned realm. Signed-off-by: Andre Przywara Message-Id: <20210618172030.9684-4-andre.przywara@arm.com> Signed-off-by: David Gibson --- checks.c | 10 +++++----- dtc.h | 5 +++++ livetree.c | 4 ++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/checks.c b/checks.c index e6c7c3e..cb71c73 100644 --- a/checks.c +++ b/checks.c @@ -520,7 +520,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti, phandle = propval_cell(prop); - if ((phandle == 0) || (phandle == -1)) { + if (!phandle_is_valid(phandle)) { FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property", phandle, prop->name); return 0; @@ -1400,14 +1400,14 @@ static void check_property_phandle_args(struct check *c, for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) { struct node *provider_node; struct property *cellprop; - int phandle; + cell_t phandle; phandle = propval_cell_n(prop, cell); /* * Some bindings use a cell value 0 or -1 to skip over optional * entries when each index position has a specific definition. */ - if (phandle == 0 || phandle == -1) { + if (!phandle_is_valid(phandle)) { /* Give up if this is an overlay with external references */ if (dti->dtsflags & DTSF_PLUGIN) break; @@ -1615,7 +1615,7 @@ static void check_interrupts_property(struct check *c, prop = get_property(parent, "interrupt-parent"); if (prop) { phandle = propval_cell(prop); - if ((phandle == 0) || (phandle == -1)) { + if (!phandle_is_valid(phandle)) { /* Give up if this is an overlay with * external references */ if (dti->dtsflags & DTSF_PLUGIN) @@ -1772,7 +1772,7 @@ static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti, phandle = propval_cell(prop); /* Give up if this is an overlay with external references */ - if (phandle == 0 || phandle == -1) + if (!phandle_is_valid(phandle)) return NULL; node = get_node_by_phandle(dti->dt, phandle); diff --git a/dtc.h b/dtc.h index 47664f2..cf2c6ac 100644 --- a/dtc.h +++ b/dtc.h @@ -51,6 +51,11 @@ extern int annotate; /* annotate .dts with input source location */ typedef uint32_t cell_t; +static inline bool phandle_is_valid(cell_t phandle) +{ + return phandle != 0 && phandle != ~0U; +} + static inline uint16_t dtb_ld16(const void *p) { const uint8_t *bp = (const uint8_t *)p; diff --git a/livetree.c b/livetree.c index dfbae65..cc61237 100644 --- a/livetree.c +++ b/livetree.c @@ -559,7 +559,7 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle) { struct node *child, *node; - if ((phandle == 0) || (phandle == -1)) { + if (!phandle_is_valid(phandle)) { assert(generate_fixups); return NULL; } @@ -594,7 +594,7 @@ cell_t get_node_phandle(struct node *root, struct node *node) static cell_t phandle = 1; /* FIXME: ick, static local */ struct data d = empty_data; - if ((node->phandle != 0) && (node->phandle != -1)) + if (phandle_is_valid(node->phandle)) return node->phandle; while (get_node_by_phandle(root, phandle)) From b587787ef38802e43972e1b7a36a8358ae25db86 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 18 Jun 2021 18:20:29 +0100 Subject: [PATCH 078/298] checks: Fix signedness comparisons warnings With -Wsign-compare, compilers warn about a mismatching signedness in comparisons in various parts in checks.c. Fix those by making all affected variables unsigned. This covers return values of the (unsigned) size_t type, phandles, variables holding sizes in general and loop counters only ever counting positives values. Signed-off-by: Andre Przywara Message-Id: <20210618172030.9684-5-andre.przywara@arm.com> Signed-off-by: David Gibson --- checks.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/checks.c b/checks.c index cb71c73..e2690e9 100644 --- a/checks.c +++ b/checks.c @@ -312,7 +312,7 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL); static void check_node_name_chars(struct check *c, struct dt_info *dti, struct node *node) { - int n = strspn(node->name, c->data); + size_t n = strspn(node->name, c->data); if (n < strlen(node->name)) FAIL(c, dti, node, "Bad character '%c' in node name", @@ -386,7 +386,7 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti, struct property *prop; for_each_property(node, prop) { - int n = strspn(prop->name, c->data); + size_t n = strspn(prop->name, c->data); if (n < strlen(prop->name)) FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name", @@ -403,7 +403,7 @@ static void check_property_name_chars_strict(struct check *c, for_each_property(node, prop) { const char *name = prop->name; - int n = strspn(name, c->data); + size_t n = strspn(name, c->data); if (n == strlen(prop->name)) continue; @@ -579,7 +579,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti, if (!prop) return; /* No name property, that's fine */ - if ((prop->val.len != node->basenamelen+1) + if ((prop->val.len != node->basenamelen + 1U) || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) { FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead" " of base node name)", prop->val.val); @@ -1388,7 +1388,7 @@ static void check_property_phandle_args(struct check *c, const struct provider *provider) { struct node *root = dti->dt; - int cell, cellsize = 0; + unsigned int cell, cellsize = 0; if (!is_multiple_of(prop->val.len, sizeof(cell_t))) { FAIL_PROP(c, dti, node, prop, @@ -1596,7 +1596,7 @@ static void check_interrupts_property(struct check *c, struct node *root = dti->dt; struct node *irq_node = NULL, *parent = node; struct property *irq_prop, *prop = NULL; - int irq_cells, phandle; + cell_t irq_cells, phandle; irq_prop = get_property(node, "interrupts"); if (!irq_prop) @@ -1762,7 +1762,7 @@ WARNING(graph_port, check_graph_port, NULL, &graph_nodes); static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti, struct node *endpoint) { - int phandle; + cell_t phandle; struct node *node; struct property *prop; @@ -1910,7 +1910,7 @@ static void enable_warning_error(struct check *c, bool warn, bool error) static void disable_warning_error(struct check *c, bool warn, bool error) { - int i; + unsigned int i; /* Lowering level, also lower it for things this is the prereq * for */ @@ -1931,7 +1931,7 @@ static void disable_warning_error(struct check *c, bool warn, bool error) void parse_checks_option(bool warn, bool error, const char *arg) { - int i; + unsigned int i; const char *name = arg; bool enable = true; @@ -1958,7 +1958,7 @@ void parse_checks_option(bool warn, bool error, const char *arg) void process_checks(bool force, struct dt_info *dti) { - int i; + unsigned int i; int error = 0; for (i = 0; i < ARRAY_SIZE(check_table); i++) { From 72d09e2682a41589b46b8cdd4c393b8ed47ac266 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 18 Jun 2021 18:20:30 +0100 Subject: [PATCH 079/298] Makefile: add -Wsign-compare to warning options Now that all signedness comparison warnings in the source tree have been fixed, let's enable the warning option, to avoid them creeping in again. Signed-off-by: Andre Przywara Message-Id: <20210618172030.9684-6-andre.przywara@arm.com> Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ea8c659..ee77115 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ CONFIG_LOCALVERSION = ASSUME_MASK ?= 0 CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK) -WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \ +WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs -Wsign-compare \ -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS) From 69595a167f06c4482ce784e30df1ac9b16ceb5b0 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 29 Jun 2021 13:43:04 +0200 Subject: [PATCH 080/298] checks: Fix bus-range check The upper limit of the bus-range is specified by the second cell of the bus-range property. Signed-off-by: Thierry Reding Message-Id: <20210629114304.2451114-1-thierry.reding@gmail.com> Signed-off-by: David Gibson --- checks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks.c b/checks.c index e2690e9..fb3fc9c 100644 --- a/checks.c +++ b/checks.c @@ -892,7 +892,7 @@ static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struc } else { cells = (cell_t *)prop->val.val; min_bus = fdt32_to_cpu(cells[0]); - max_bus = fdt32_to_cpu(cells[0]); + max_bus = fdt32_to_cpu(cells[1]); } if ((bus_num < min_bus) || (bus_num > max_bus)) FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)", From 0869f8269161843a46c0cac0e35b4dc9324bf1a6 Mon Sep 17 00:00:00 2001 From: Georg Kotheimer Date: Sat, 31 Jul 2021 13:48:42 +0200 Subject: [PATCH 081/298] libfdt: Add ALIGNMENT error string The ALIGNMENT error was missing a string, leading to being returned. Signed-off-by: Georg Kotheimer Signed-off-by: David Gibson --- libfdt/fdt_strerror.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c index b435693..d852b77 100644 --- a/libfdt/fdt_strerror.c +++ b/libfdt/fdt_strerror.c @@ -39,6 +39,7 @@ static struct fdt_errtabent fdt_errtable[] = { FDT_ERRTABENT(FDT_ERR_BADOVERLAY), FDT_ERRTABENT(FDT_ERR_NOPHANDLES), FDT_ERRTABENT(FDT_ERR_BADFLAGS), + FDT_ERRTABENT(FDT_ERR_ALIGNMENT), }; #define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))) From 5eb5927d81ee6036f45c4e1bd89ae66ed325d721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 25 Aug 2021 16:13:50 +0400 Subject: [PATCH 082/298] fdtdump: fix -Werror=int-to-pointer-cast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With mingw64-gcc, the compiler complains with various warnings: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] Signed-off-by: Marc-André Lureau Message-Id: <20210825121350.213551-1-marcandre.lureau@redhat.com> Acked-by: Rob Herring Signed-off-by: David Gibson --- fdtdump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdtdump.c b/fdtdump.c index bdc0f94..d424869 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -21,7 +21,7 @@ #define MAX_VERSION 17U #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) -#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) +#define PALIGN(p, a) ((void *)(ALIGN((uintptr_t)(p), (a)))) #define GET_CELL(p) (p += 4, *((const fdt32_t *)(p-4))) static const char *tagname(uint32_t tag) From ff3a30c115ad7354689dc7858604356ecb7f9b1c Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 27 Jul 2021 12:30:19 -0600 Subject: [PATCH 083/298] asm: Use .asciz and .ascii instead of .string We use the .string pseudo-op both in some of our test assembly files and in our -Oasm output. We expect this to emit a \0 terminated string into the .o file. However for certain targets (e.g. HP PA-RISC) it doesn't include the \0. Use .asciz instead, which explicitly does what we want. There's also one place we can use .ascii (which explicitly emits a string *without* \0 termination) instead of multiple .byte directives. Signed-off-by: David Gibson --- dtc.h | 23 ++++++++++++++++++++- flattree.c | 6 +++--- tests/base01.asm | 38 +++++++++++++++++------------------ tests/test01.asm | 52 ++++++++++++++++++++++++------------------------ tests/trees.S | 10 ++++------ treesource.c | 23 +-------------------- 6 files changed, 75 insertions(+), 77 deletions(-) diff --git a/dtc.h b/dtc.h index cf2c6ac..0a1f549 100644 --- a/dtc.h +++ b/dtc.h @@ -116,6 +116,12 @@ enum markertype { TYPE_UINT64, TYPE_STRING, }; + +static inline bool is_type_marker(enum markertype type) +{ + return type >= TYPE_UINT8; +} + extern const char *markername(enum markertype markertype); struct marker { @@ -140,7 +146,22 @@ struct data { for_each_marker(m) \ if ((m)->type == (t)) -size_t type_marker_length(struct marker *m); +static inline struct marker *next_type_marker(struct marker *m) +{ + for_each_marker(m) + if (is_type_marker(m->type)) + break; + return m; +} + +static inline size_t type_marker_length(struct marker *m) +{ + struct marker *next = next_type_marker(m->next); + + if (next) + return next->offset - m->offset; + return 0; +} void data_free(struct data d); diff --git a/flattree.c b/flattree.c index 3d0204f..5254aeb 100644 --- a/flattree.c +++ b/flattree.c @@ -134,9 +134,9 @@ static void asm_emit_string(void *e, const char *str, int len) FILE *f = e; if (len != 0) - fprintf(f, "\t.string\t\"%.*s\"\n", len, str); + fprintf(f, "\t.asciz\t\"%.*s\"\n", len, str); else - fprintf(f, "\t.string\t\"%s\"\n", str); + fprintf(f, "\t.asciz\t\"%s\"\n", str); } static void asm_emit_align(void *e, int a) @@ -438,7 +438,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf) while (p < (strbuf.val + strbuf.len)) { len = strlen(p); - fprintf(f, "\t.string \"%s\"\n", p); + fprintf(f, "\t.asciz \"%s\"\n", p); p += len+1; } } diff --git a/tests/base01.asm b/tests/base01.asm index 266e446..63f2eca 100644 --- a/tests/base01.asm +++ b/tests/base01.asm @@ -32,7 +32,7 @@ _dt_reserve_map: dt_struct_start: _dt_struct_start: .long OF_DT_BEGIN_NODE - .string "" + .asciz "" .balign 4 .long OF_DT_PROP .long 0xa @@ -58,7 +58,7 @@ _dt_struct_start: .long 0x2 .balign 4 .long OF_DT_BEGIN_NODE - .string "memory@0" + .asciz "memory@0" .balign 4 .long OF_DT_PROP .long 0x7 @@ -77,7 +77,7 @@ _dt_struct_start: .balign 4 .long OF_DT_END_NODE .long OF_DT_BEGIN_NODE - .string "cpus" + .asciz "cpus" .balign 4 .long OF_DT_PROP .long 0x4 @@ -151,22 +151,22 @@ _dt_struct_end: .globl dt_strings_start dt_strings_start: _dt_strings_start: - .string "model" - .string "compatible" - .string "#address-cells" - .string "#size-cells" - .string "device_type" - .string "reg" - .string "d10" - .string "d23" - .string "b101" - .string "o17" - .string "hd00d" - .string "stuff" - .string "bad-d-1" - .string "bad-d-2" - .string "bad-o-1" - .string "bad-o-2" + .asciz "model" + .asciz "compatible" + .asciz "#address-cells" + .asciz "#size-cells" + .asciz "device_type" + .asciz "reg" + .asciz "d10" + .asciz "d23" + .asciz "b101" + .asciz "o17" + .asciz "hd00d" + .asciz "stuff" + .asciz "bad-d-1" + .asciz "bad-d-2" + .asciz "bad-o-1" + .asciz "bad-o-2" .globl dt_strings_end dt_strings_end: _dt_strings_end: diff --git a/tests/test01.asm b/tests/test01.asm index bbf66c7..73fa603 100644 --- a/tests/test01.asm +++ b/tests/test01.asm @@ -44,7 +44,7 @@ _dt_reserve_map: dt_struct_start: _dt_struct_start: .long OF_DT_BEGIN_NODE - .string "" + .asciz "" .balign 4 .long OF_DT_PROP .long 0xc @@ -76,7 +76,7 @@ _dt_struct_start: .long 0x2 .balign 4 .long OF_DT_BEGIN_NODE - .string "cpus" + .asciz "cpus" .balign 4 .long OF_DT_PROP .long 0x4 @@ -94,7 +94,7 @@ _dt_struct_start: .long 0x0 .balign 4 .long OF_DT_BEGIN_NODE - .string "PowerPC,970@0" + .asciz "PowerPC,970@0" .balign 4 .long OF_DT_PROP .long 0xc @@ -139,7 +139,7 @@ _dt_struct_start: .balign 4 .long OF_DT_END_NODE .long OF_DT_BEGIN_NODE - .string "PowerPC,970@1" + .asciz "PowerPC,970@1" .balign 4 .long OF_DT_PROP .long 0xc @@ -181,7 +181,7 @@ _dt_struct_start: .long OF_DT_END_NODE .long OF_DT_END_NODE .long OF_DT_BEGIN_NODE - .string "randomnode" + .asciz "randomnode" .balign 4 .long OF_DT_PROP .long 0x13 @@ -216,7 +216,7 @@ _dt_struct_start: .balign 4 .long OF_DT_END_NODE .long OF_DT_BEGIN_NODE - .string "memory@0" + .asciz "memory@0" .balign 4 .long OF_DT_PROP .long 0x7 @@ -242,7 +242,7 @@ memreg: .balign 4 .long OF_DT_END_NODE .long OF_DT_BEGIN_NODE - .string "chosen" + .asciz "chosen" .balign 4 .long OF_DT_PROP .long 0xf @@ -267,25 +267,25 @@ _dt_struct_end: .globl dt_strings_start dt_strings_start: _dt_strings_start: - .string "model" - .string "compatible" - .string "#address-cells" - .string "#size-cells" - .string "linux,phandle" - .string "name" - .string "device_type" - .string "reg" - .string "clock-frequency" - .string "timebase-frequency" - .string "linux,boot-cpu" - .string "i-cache-size" - .string "d-cache-size" - .string "string" - .string "blob" - .string "ref" - .string "mixed" - .string "bootargs" - .string "linux,platform" + .asciz "model" + .asciz "compatible" + .asciz "#address-cells" + .asciz "#size-cells" + .asciz "linux,phandle" + .asciz "name" + .asciz "device_type" + .asciz "reg" + .asciz "clock-frequency" + .asciz "timebase-frequency" + .asciz "linux,boot-cpu" + .asciz "i-cache-size" + .asciz "d-cache-size" + .asciz "string" + .asciz "blob" + .asciz "ref" + .asciz "mixed" + .asciz "bootargs" + .asciz "linux,platform" .globl dt_strings_end dt_strings_end: _dt_strings_end: diff --git a/tests/trees.S b/tests/trees.S index 95d599d..ab0871f 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -54,13 +54,13 @@ tree##_rsvmap_end: ; #define PROP_STR(tree, name, str) \ PROPHDR(tree, name, 55f - 54f) \ 54: \ - .string str ; \ + .asciz str ; \ 55: \ .balign 4 ; #define BEGIN_NODE(name) \ FDTLONG(FDT_BEGIN_NODE) ; \ - .string name ; \ + .asciz name ; \ .balign 4 ; #define END_NODE \ @@ -68,7 +68,7 @@ tree##_rsvmap_end: ; #define STRING(tree, name, str) \ tree##_##name: ; \ - .string str ; + .asciz str ; .data @@ -253,9 +253,7 @@ truncated_string_struct_end: truncated_string_strings: STRING(truncated_string, good_string, "good") truncated_string_bad_string: - .byte 'b' - .byte 'a' - .byte 'd' + .ascii "bad" /* NOTE: terminating \0 deliberately missing */ truncated_string_strings_end: truncated_string_end: diff --git a/treesource.c b/treesource.c index 061ba8c..db2ff69 100644 --- a/treesource.c +++ b/treesource.c @@ -124,27 +124,6 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) } } -static bool has_data_type_information(struct marker *m) -{ - return m->type >= TYPE_UINT8; -} - -static struct marker *next_type_marker(struct marker *m) -{ - while (m && !has_data_type_information(m)) - m = m->next; - return m; -} - -size_t type_marker_length(struct marker *m) -{ - struct marker *next = next_type_marker(m->next); - - if (next) - return next->offset - m->offset; - return 0; -} - static const char *delim_start[] = { [TYPE_UINT8] = "[", [TYPE_UINT16] = "/bits/ 16 <", @@ -230,7 +209,7 @@ static void write_propval(FILE *f, struct property *prop) size_t data_len = type_marker_length(m) ? : len - m->offset; const char *p = &prop->val.val[m->offset]; - if (has_data_type_information(m)) { + if (is_type_marker(m->type)) { emit_type = m->type; fprintf(f, " %s", delim_start[emit_type]); } else if (m->type == LABEL) From d24cc189dca6148eedf9dc9e2d45144b3851dae0 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 24 Sep 2021 21:14:34 +1000 Subject: [PATCH 084/298] asm: Use assembler macros instead of cpp macros tests/trees.S is a weird thing: a portable aseembler file, used to produce a specific binary output. Currently it uses CPP macros quite heavily to construct the dtbs we want (including some partial and broken trees). Using cpp has the side effect that we need to use ; separators between instructions (or, rather, pseudo-ops), because cpp won't expand newlines. However, it turns out that while ; is a suitable separator on most targets, it doesn't work for all of them (e.g. HP PA-RISC). Switch to using the assembler's inbuilt macros rather than CPP, so that we can use genuine newlines. Signed-off-by: David Gibson --- tests/trees.S | 361 ++++++++++++++++++++++++++------------------------ 1 file changed, 187 insertions(+), 174 deletions(-) diff --git a/tests/trees.S b/tests/trees.S index ab0871f..d69f7f1 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -1,174 +1,187 @@ #include #include "testdata.h" -#define FDTLONG(val) \ - .byte ((val) >> 24) & 0xff ; \ - .byte ((val) >> 16) & 0xff ; \ - .byte ((val) >> 8) & 0xff ; \ - .byte (val) & 0xff ; + .macro fdtlong val + .byte ((\val) >> 24) & 0xff + .byte ((\val) >> 16) & 0xff + .byte ((\val) >> 8) & 0xff + .byte (\val) & 0xff + .endm -#define TREE_HDR(tree) \ - .balign 8 ; \ - .globl tree ; \ -tree: \ - FDTLONG(FDT_MAGIC) ; \ - FDTLONG(tree##_end - tree) ; \ - FDTLONG(tree##_struct - tree) ; \ - FDTLONG(tree##_strings - tree) ; \ - FDTLONG(tree##_rsvmap - tree) ; \ - FDTLONG(0x11) ; \ - FDTLONG(0x10) ; \ - FDTLONG(0) ; \ - FDTLONG(tree##_strings_end - tree##_strings) ; \ - FDTLONG(tree##_struct_end - tree##_struct) ; + .macro treehdr tree + .balign 8 + .globl \tree +\tree : + fdtlong FDT_MAGIC + fdtlong (\tree\()_end - \tree) + fdtlong (\tree\()_struct - \tree) + fdtlong (\tree\()_strings - \tree) + fdtlong (\tree\()_rsvmap - \tree) + fdtlong 0x11 + fdtlong 0x10 + fdtlong 0 + fdtlong (\tree\()_strings_end - \tree\()_strings) + fdtlong (\tree\()_struct_end - \tree\()_struct) + .endm -#define RSVMAP_ENTRY(addrh, addrl, lenh, lenl) \ - FDTLONG(addrh) ; \ - FDTLONG(addrl) ; \ - FDTLONG(lenh) ; \ - FDTLONG(lenl) + .macro rsvmape addrh, addrl, lenh, lenl + fdtlong \addrh + fdtlong \addrl + fdtlong \lenh + fdtlong \lenl + .endm -#define EMPTY_RSVMAP(tree) \ - .balign 8 ; \ -tree##_rsvmap: ; \ - RSVMAP_ENTRY(0, 0, 0, 0) \ -tree##_rsvmap_end: ; + .macro empty_rsvmap tree + .balign 8 +\tree\()_rsvmap: + rsvmape 0, 0, 0, 0 +\tree\()_rsvmap_end: + .endm -#define PROPHDR(tree, name, len) \ - FDTLONG(FDT_PROP) ; \ - FDTLONG(len) ; \ - FDTLONG(tree##_##name - tree##_strings) ; + .macro prophdr tree, name, len + fdtlong FDT_PROP + fdtlong \len + fdtlong (\tree\()_\name - \tree\()_strings) + .endm -#define PROP_EMPTY(tree, name) \ - PROPHDR(tree, name, 0) ; + .macro propnil tree, name + prophdr \tree, \name, 0 + .endm -#define PROP_INT(tree, name, val) \ - PROPHDR(tree, name, 4) \ - FDTLONG(val) ; + .macro propu32 tree, name, val + prophdr \tree, \name, 4 + fdtlong \val + .endm -#define PROP_INT64(tree, name, valh, vall) \ - PROPHDR(tree, name, 8) \ - FDTLONG(valh) ; \ - FDTLONG(vall) ; + .macro propu64 tree, name, valh, vall + prophdr \tree, \name, 8 + fdtlong \valh + fdtlong \vall + .endm -#define PROP_STR(tree, name, str) \ - PROPHDR(tree, name, 55f - 54f) \ -54: \ - .asciz str ; \ -55: \ - .balign 4 ; + .macro propstr tree, name, str:vararg + prophdr \tree, \name, (55f - 54f) +54: + .asciz \str +55: + .balign 4 + .endm -#define BEGIN_NODE(name) \ - FDTLONG(FDT_BEGIN_NODE) ; \ - .asciz name ; \ - .balign 4 ; + .macro beginn name:vararg + fdtlong FDT_BEGIN_NODE + .asciz \name + .balign 4 + .endm -#define END_NODE \ - FDTLONG(FDT_END_NODE) ; + .macro endn + fdtlong FDT_END_NODE + .endm + + .macro string tree, name, str:vararg +\tree\()_\name : + .asciz \str + .endm -#define STRING(tree, name, str) \ -tree##_##name: ; \ - .asciz str ; .data - TREE_HDR(test_tree1) + treehdr test_tree1 .balign 8 test_tree1_rsvmap: - RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L) - RSVMAP_ENTRY(TEST_ADDR_2H, TEST_ADDR_2L, TEST_SIZE_2H, TEST_SIZE_2L) - RSVMAP_ENTRY(0, 0, 0, 0) + rsvmape TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L + rsvmape TEST_ADDR_2H, TEST_ADDR_2L, TEST_SIZE_2H, TEST_SIZE_2L + rsvmape 0, 0, 0, 0 test_tree1_rsvmap_end: test_tree1_struct: - BEGIN_NODE("") - PROP_STR(test_tree1, compatible, "test_tree1") - PROP_INT(test_tree1, prop_int, TEST_VALUE_1) - PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1H, TEST_VALUE64_1L) - PROP_STR(test_tree1, prop_str, TEST_STRING_1) - PROP_INT(test_tree1, address_cells, 1) - PROP_INT(test_tree1, size_cells, 0) + beginn "" + propstr test_tree1, compatible, "test_tree1" + propu32 test_tree1, prop_int, TEST_VALUE_1 + propu64 test_tree1, prop_int64, TEST_VALUE64_1H, TEST_VALUE64_1L + propstr test_tree1, prop_str, TEST_STRING_1 + propu32 test_tree1, address_cells, 1 + propu32 test_tree1, size_cells, 0 - BEGIN_NODE("subnode@1") - PROP_STR(test_tree1, compatible, "subnode1") - PROP_INT(test_tree1, reg, 1) - PROP_INT(test_tree1, prop_int, TEST_VALUE_1) + beginn "subnode@1" + propstr test_tree1, compatible, "subnode1" + propu32 test_tree1, reg, 1 + propu32 test_tree1, prop_int, TEST_VALUE_1 - BEGIN_NODE("subsubnode") - PROP_STR(test_tree1, compatible, "subsubnode1\0subsubnode") - PROP_STR(test_tree1, placeholder, "this is a placeholder string\0string2") - PROP_INT(test_tree1, prop_int, TEST_VALUE_1) - END_NODE + beginn "subsubnode" + propstr test_tree1, compatible, "subsubnode1\0subsubnode" + propstr test_tree1, placeholder, "this is a placeholder string\0string2" + propu32 test_tree1, prop_int, TEST_VALUE_1 + endn - BEGIN_NODE("ss1") - END_NODE + beginn "ss1" + endn - END_NODE + endn - BEGIN_NODE("subnode@2") - PROP_INT(test_tree1, reg, 2) - PROP_INT(test_tree1, linux_phandle, PHANDLE_1) - PROP_INT(test_tree1, prop_int, TEST_VALUE_2) - PROP_INT(test_tree1, address_cells, 1) - PROP_INT(test_tree1, size_cells, 0) + beginn "subnode@2" + propu32 test_tree1, reg, 2 + propu32 test_tree1, linux_phandle, PHANDLE_1 + propu32 test_tree1, prop_int, TEST_VALUE_2 + propu32 test_tree1, address_cells, 1 + propu32 test_tree1, size_cells, 0 - BEGIN_NODE("subsubnode@0") - PROP_INT(test_tree1, reg, 0) - PROP_INT(test_tree1, phandle, PHANDLE_2) - PROP_STR(test_tree1, compatible, "subsubnode2\0subsubnode") - PROP_INT(test_tree1, prop_int, TEST_VALUE_2) - END_NODE + beginn "subsubnode@0" + propu32 test_tree1, reg, 0 + propu32 test_tree1, phandle, PHANDLE_2 + propstr test_tree1, compatible, "subsubnode2\0subsubnode" + propu32 test_tree1, prop_int, TEST_VALUE_2 + endn - BEGIN_NODE("ss2") - END_NODE + beginn "ss2" + endn - END_NODE + endn - END_NODE - FDTLONG(FDT_END) + endn + fdtlong FDT_END test_tree1_struct_end: test_tree1_strings: - STRING(test_tree1, compatible, "compatible") - STRING(test_tree1, prop_int, "prop-int") - STRING(test_tree1, prop_int64, "prop-int64") - STRING(test_tree1, prop_str, "prop-str") - STRING(test_tree1, linux_phandle, "linux,phandle") - STRING(test_tree1, phandle, "phandle") - STRING(test_tree1, reg, "reg") - STRING(test_tree1, placeholder, "placeholder") - STRING(test_tree1, address_cells, "#address-cells") - STRING(test_tree1, size_cells, "#size-cells") + string test_tree1, compatible, "compatible" + string test_tree1, prop_int, "prop-int" + string test_tree1, prop_int64, "prop-int64" + string test_tree1, prop_str, "prop-str" + string test_tree1, linux_phandle, "linux,phandle" + string test_tree1, phandle, "phandle" + string test_tree1, reg, "reg" + string test_tree1, placeholder, "placeholder" + string test_tree1, address_cells, "#address-cells" + string test_tree1, size_cells, "#size-cells" test_tree1_strings_end: test_tree1_end: - TREE_HDR(truncated_property) - EMPTY_RSVMAP(truncated_property) + treehdr truncated_property + empty_rsvmap truncated_property truncated_property_struct: - BEGIN_NODE("") - PROPHDR(truncated_property, prop_truncated, 4) + beginn "" + prophdr truncated_property, prop_truncated, 4 /* Oops, no actual property data here */ truncated_property_struct_end: truncated_property_strings: - STRING(truncated_property, prop_truncated, "truncated") + string truncated_property, prop_truncated, "truncated" truncated_property_strings_end: truncated_property_end: - TREE_HDR(bad_node_char) - EMPTY_RSVMAP(bad_node_char) + treehdr bad_node_char + empty_rsvmap bad_node_char bad_node_char_struct: - BEGIN_NODE("") - BEGIN_NODE("sub$node") - END_NODE - END_NODE - FDTLONG(FDT_END) + beginn "" + beginn "sub$node" + endn + endn + fdtlong FDT_END bad_node_char_struct_end: bad_node_char_strings: @@ -176,15 +189,15 @@ bad_node_char_strings_end: bad_node_char_end: - TREE_HDR(bad_node_format) - EMPTY_RSVMAP(bad_node_format) + treehdr bad_node_format + empty_rsvmap bad_node_format bad_node_format_struct: - BEGIN_NODE("") - BEGIN_NODE("subnode@1@2") - END_NODE - END_NODE - FDTLONG(FDT_END) + beginn "" + beginn "subnode@1@2" + endn + endn + fdtlong FDT_END bad_node_format_struct_end: bad_node_format_strings: @@ -192,18 +205,18 @@ bad_node_format_strings_end: bad_node_format_end: - TREE_HDR(bad_prop_char) - EMPTY_RSVMAP(bad_prop_char) + treehdr bad_prop_char + empty_rsvmap bad_prop_char bad_prop_char_struct: - BEGIN_NODE("") - PROP_INT(bad_prop_char, prop, TEST_VALUE_1) - END_NODE - FDTLONG(FDT_END) + beginn "" + propu32 bad_prop_char, prop, TEST_VALUE_1 + endn + fdtlong FDT_END bad_prop_char_struct_end: bad_prop_char_strings: - STRING(bad_prop_char, prop, "prop$erty") + string bad_prop_char, prop, "prop$erty" bad_prop_char_strings_end: bad_prop_char_end: @@ -212,46 +225,46 @@ bad_prop_char_end: .balign 8 .globl ovf_size_strings ovf_size_strings: - FDTLONG(FDT_MAGIC) - FDTLONG(ovf_size_strings_end - ovf_size_strings) - FDTLONG(ovf_size_strings_struct - ovf_size_strings) - FDTLONG(ovf_size_strings_strings - ovf_size_strings) - FDTLONG(ovf_size_strings_rsvmap - ovf_size_strings) - FDTLONG(0x11) - FDTLONG(0x10) - FDTLONG(0) - FDTLONG(0xffffffff) - FDTLONG(ovf_size_strings_struct_end - ovf_size_strings_struct) - EMPTY_RSVMAP(ovf_size_strings) + fdtlong FDT_MAGIC + fdtlong (ovf_size_strings_end - ovf_size_strings) + fdtlong (ovf_size_strings_struct - ovf_size_strings) + fdtlong (ovf_size_strings_strings - ovf_size_strings) + fdtlong (ovf_size_strings_rsvmap - ovf_size_strings) + fdtlong 0x11 + fdtlong 0x10 + fdtlong 0 + fdtlong 0xffffffff + fdtlong (ovf_size_strings_struct_end - ovf_size_strings_struct) + empty_rsvmap ovf_size_strings ovf_size_strings_struct: - BEGIN_NODE("") - PROP_INT(ovf_size_strings, bad_string, 0) - END_NODE - FDTLONG(FDT_END) + beginn "" + propu32 ovf_size_strings, bad_string, 0 + endn + fdtlong FDT_END ovf_size_strings_struct_end: ovf_size_strings_strings: - STRING(ovf_size_strings, x, "x") + string ovf_size_strings, x, "x" ovf_size_strings_bad_string = ovf_size_strings_strings + 0x10000000 ovf_size_strings_strings_end: ovf_size_strings_end: /* truncated_string */ - TREE_HDR(truncated_string) - EMPTY_RSVMAP(truncated_string) + treehdr truncated_string + empty_rsvmap truncated_string truncated_string_struct: - BEGIN_NODE("") - PROP_EMPTY(truncated_string, good_string) - PROP_EMPTY(truncated_string, bad_string) - END_NODE - FDTLONG(FDT_END) + beginn "" + propnil truncated_string, good_string + propnil truncated_string, bad_string + endn + fdtlong FDT_END truncated_string_struct_end: truncated_string_strings: - STRING(truncated_string, good_string, "good") + string truncated_string, good_string, "good" truncated_string_bad_string: .ascii "bad" /* NOTE: terminating \0 deliberately missing */ @@ -260,12 +273,12 @@ truncated_string_end: /* truncated_memrsv */ - TREE_HDR(truncated_memrsv) + treehdr truncated_memrsv truncated_memrsv_struct: - BEGIN_NODE("") - END_NODE - FDTLONG(FDT_END) + beginn "" + endn + fdtlong FDT_END truncated_memrsv_struct_end: truncated_memrsv_strings: @@ -273,22 +286,22 @@ truncated_memrsv_strings_end: .balign 8 truncated_memrsv_rsvmap: - RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L) + rsvmape TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L truncated_memrsv_rsvmap_end: truncated_memrsv_end: /* two root nodes */ - TREE_HDR(two_roots) - EMPTY_RSVMAP(two_roots) + treehdr two_roots + empty_rsvmap two_roots two_roots_struct: - BEGIN_NODE("") - END_NODE - BEGIN_NODE("") - END_NODE - FDTLONG(FDT_END) + beginn "" + endn + beginn "" + endn + fdtlong FDT_END two_roots_struct_end: two_roots_strings: @@ -298,13 +311,13 @@ two_roots_end: /* root node with a non-empty name */ - TREE_HDR(named_root) - EMPTY_RSVMAP(named_root) + treehdr named_root + empty_rsvmap named_root named_root_struct: - BEGIN_NODE("fake") - END_NODE - FDTLONG(FDT_END) + beginn "fake" + endn + fdtlong FDT_END named_root_struct_end: named_root_strings: From e33ce1d6a8c7e54e3ad12cff33690b6da0aee1dc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 24 Sep 2021 23:39:56 +1000 Subject: [PATCH 085/298] flattree: Use '\n', not ';' to separate asm pseudo-ops The output of -Oasm is peculiar for assembler in that we want its output to be portable across targets (it consists entirely of pseudo-ops and labels, no actual instructions). It turns out that while ';' is a valid instruction/pseudo-op separator on most targets, it's not correct for all of them - e.g. HP PA-RISC. So, switch to using an actual \n instead. Signed-off-by: David Gibson --- flattree.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flattree.c b/flattree.c index 5254aeb..95e43d3 100644 --- a/flattree.c +++ b/flattree.c @@ -124,7 +124,8 @@ static void asm_emit_cell(void *e, cell_t val) { FILE *f = e; - fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n", + fprintf(f, "\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n" + "\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n", (val >> 24) & 0xff, (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff); } From 37fd700685da9001643d1b1f63ad4332e1148b04 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 27 Jul 2021 12:30:23 -0600 Subject: [PATCH 086/298] treesource: Maintain phandle label/path on output The dts output will just output phandle integer values, but often the necessary markers are present with path or label references. Improve the output and maintain phandle label or path references when present in dts output. Signed-off-by: Rob Herring Message-Id: <20210727183023.3212077-6-robh@kernel.org> Signed-off-by: David Gibson --- tests/type-preservation.dt.yaml | 3 +++ tests/type-preservation.dts | 3 +++ treesource.c | 25 +++++++++++++++++++------ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/tests/type-preservation.dt.yaml b/tests/type-preservation.dt.yaml index ee8cfde..a0cc64c 100644 --- a/tests/type-preservation.dt.yaml +++ b/tests/type-preservation.dt.yaml @@ -13,8 +13,11 @@ int64: [!u64 [0x200000000]] int64-array: [!u64 [0x100000000, 0x0]] a-string-with-nulls: ["foo\0bar", "baz"] + a-phandle: [[!phandle 0x1]] + a-phandle-with-args: [[!phandle 0x1, 0x0, 0x1], [!phandle 0x1, 0x2, 0x3]] subsubnode: compatible: ["subsubnode1", "subsubnode"] + phandle: [[0x1]] subsubsubnode: compatible: ["subsubsubnode1", [0x1234], "subsubsubnode"] ... diff --git a/tests/type-preservation.dts b/tests/type-preservation.dts index 3e380ba..921ea21 100644 --- a/tests/type-preservation.dts +++ b/tests/type-preservation.dts @@ -16,9 +16,12 @@ int64 = /bits/ 64 <0x200000000>; int64-array = /bits/ 64 <0x100000000 0x00> int64_array_label_end:; a-string-with-nulls = "foo\0bar", "baz"; + a-phandle = <&subsub1>; + a-phandle-with-args = <&subsub1 0x00 0x01>, <&subsub1 0x02 0x03>; subsub1: subsubnode { compatible = "subsubnode1", "subsubnode"; + phandle = <0x01>; subsubsub1: subsubsubnode { compatible = "subsubsubnode1", <0x1234>, valuea: valueb: "subsubsubnode"; diff --git a/treesource.c b/treesource.c index db2ff69..33fedee 100644 --- a/treesource.c +++ b/treesource.c @@ -208,26 +208,39 @@ static void write_propval(FILE *f, struct property *prop) size_t chunk_len = (m->next ? m->next->offset : len) - m->offset; size_t data_len = type_marker_length(m) ? : len - m->offset; const char *p = &prop->val.val[m->offset]; + struct marker *m_phandle; if (is_type_marker(m->type)) { emit_type = m->type; fprintf(f, " %s", delim_start[emit_type]); } else if (m->type == LABEL) fprintf(f, " %s:", m->ref); - else if (m->offset) - fputc(' ', f); - if (emit_type == TYPE_NONE) { - assert(chunk_len == 0); + if (emit_type == TYPE_NONE || chunk_len == 0) continue; - } switch(emit_type) { case TYPE_UINT16: write_propval_int(f, p, chunk_len, 2); break; case TYPE_UINT32: - write_propval_int(f, p, chunk_len, 4); + m_phandle = prop->val.markers; + for_each_marker_of_type(m_phandle, REF_PHANDLE) + if (m->offset == m_phandle->offset) + break; + + if (m_phandle) { + if (m_phandle->ref[0] == '/') + fprintf(f, "&{%s}", m_phandle->ref); + else + fprintf(f, "&%s", m_phandle->ref); + if (chunk_len > 4) { + fputc(' ', f); + write_propval_int(f, p + 4, chunk_len - 4, 4); + } + } else { + write_propval_int(f, p, chunk_len, 4); + } break; case TYPE_UINT64: write_propval_int(f, p, chunk_len, 8); From 52a16fd7282463e05ee86071463bf0499a9cedf6 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 11 Oct 2021 14:12:41 -0500 Subject: [PATCH 087/298] checks: Make interrupt_provider check dependent on interrupts_extended_is_cell If '#interrupt-cells' doesn't pass checks, no reason to run interrupt provider check. Cc: Andre Przywara Signed-off-by: Rob Herring Message-Id: <20211011191245.1009682-1-robh@kernel.org> Signed-off-by: David Gibson --- checks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks.c b/checks.c index fb3fc9c..8153793 100644 --- a/checks.c +++ b/checks.c @@ -1587,7 +1587,7 @@ static void check_interrupt_provider(struct check *c, FAIL(c, dti, node, "Missing #address-cells in interrupt provider"); } -WARNING(interrupt_provider, check_interrupt_provider, NULL); +WARNING(interrupt_provider, check_interrupt_provider, NULL, &interrupts_extended_is_cell); static void check_interrupts_property(struct check *c, struct dt_info *dti, From d8d1a9a77863a8c7031ae82a1d461aa78eb72a7b Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 11 Oct 2021 14:12:43 -0500 Subject: [PATCH 088/298] checks: Drop interrupt provider '#address-cells' check '#address-cells' is only needed when parsing 'interrupt-map' properties, so remove it from the common interrupt-provider test. Cc: Andre Przywara Reviewed-by: David Gibson Signed-off-by: Rob Herring Message-Id: <20211011191245.1009682-3-robh@kernel.org> Signed-off-by: David Gibson --- checks.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/checks.c b/checks.c index 8153793..c6eba76 100644 --- a/checks.c +++ b/checks.c @@ -1581,11 +1581,6 @@ static void check_interrupt_provider(struct check *c, if (!prop) FAIL(c, dti, node, "Missing #interrupt-cells in interrupt provider"); - - prop = get_property(node, "#address-cells"); - if (!prop) - FAIL(c, dti, node, - "Missing #address-cells in interrupt provider"); } WARNING(interrupt_provider, check_interrupt_provider, NULL, &interrupts_extended_is_cell); From 8fd24744e3618be99a939009349418fcbfa362b3 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 11 Oct 2021 14:12:44 -0500 Subject: [PATCH 089/298] checks: Ensure '#interrupt-cells' only exists in interrupt providers The interrupt provider check currently checks if an interrupt provider has #interrupt-cells, but not whether #interrupt-cells is present outside of interrupt-providers. Rework the check to cover the latter case. Cc: Andre Przywara Reviewed-by: David Gibson Signed-off-by: Rob Herring Message-Id: <20211011191245.1009682-4-robh@kernel.org> Signed-off-by: David Gibson --- checks.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/checks.c b/checks.c index c6eba76..b9fcde8 100644 --- a/checks.c +++ b/checks.c @@ -1573,14 +1573,20 @@ static void check_interrupt_provider(struct check *c, struct node *node) { struct property *prop; - - if (!node_is_interrupt_provider(node)) - return; + bool irq_provider = node_is_interrupt_provider(node); prop = get_property(node, "#interrupt-cells"); - if (!prop) + if (irq_provider && !prop) { FAIL(c, dti, node, - "Missing #interrupt-cells in interrupt provider"); + "Missing '#interrupt-cells' in interrupt provider"); + return; + } + + if (!irq_provider && prop) { + FAIL(c, dti, node, + "'#interrupt-cells' found, but node is not an interrupt provider"); + return; + } } WARNING(interrupt_provider, check_interrupt_provider, NULL, &interrupts_extended_is_cell); From 0a3a9d3449c88aabe88685ea99811bf6c02a570d Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 15 Oct 2021 16:35:26 -0500 Subject: [PATCH 090/298] checks: Add an interrupt-map check Add a check for parsing 'interrupt-map' properties. The check primarily tests parsing 'interrupt-map' properties which depends on and the parent interrupt controller (or another map) node. Note that this does not require '#address-cells' in the interrupt-map parent, but treats missing '#address-cells' as 0 which is how the Linux kernel parses it. There's numerous cases that expect this behavior. Cc: Andre Przywara Signed-off-by: Rob Herring Message-Id: <20211015213527.2237774-1-robh@kernel.org> Signed-off-by: David Gibson --- checks.c | 85 ++++++++++++++++++++++++++++++ tests/bad-interrupt-map-mask.dts | 20 +++++++ tests/bad-interrupt-map-parent.dts | 17 ++++++ tests/bad-interrupt-map.dts | 19 +++++++ tests/run_tests.sh | 3 ++ 5 files changed, 144 insertions(+) create mode 100644 tests/bad-interrupt-map-mask.dts create mode 100644 tests/bad-interrupt-map-parent.dts create mode 100644 tests/bad-interrupt-map.dts diff --git a/checks.c b/checks.c index b9fcde8..781ba11 100644 --- a/checks.c +++ b/checks.c @@ -1590,6 +1590,90 @@ static void check_interrupt_provider(struct check *c, } WARNING(interrupt_provider, check_interrupt_provider, NULL, &interrupts_extended_is_cell); +static void check_interrupt_map(struct check *c, + struct dt_info *dti, + struct node *node) +{ + struct node *root = dti->dt; + struct property *prop, *irq_map_prop; + size_t cellsize, cell, map_cells; + + irq_map_prop = get_property(node, "interrupt-map"); + if (!irq_map_prop) + return; + + if (node->addr_cells < 0) { + FAIL(c, dti, node, + "Missing '#address-cells' in interrupt-map provider"); + return; + } + cellsize = node_addr_cells(node); + cellsize += propval_cell(get_property(node, "#interrupt-cells")); + + prop = get_property(node, "interrupt-map-mask"); + if (prop && (prop->val.len != (cellsize * sizeof(cell_t)))) + FAIL_PROP(c, dti, node, prop, + "property size (%d) is invalid, expected %zu", + prop->val.len, cellsize * sizeof(cell_t)); + + if (!is_multiple_of(irq_map_prop->val.len, sizeof(cell_t))) { + FAIL_PROP(c, dti, node, irq_map_prop, + "property size (%d) is invalid, expected multiple of %zu", + irq_map_prop->val.len, sizeof(cell_t)); + return; + } + + map_cells = irq_map_prop->val.len / sizeof(cell_t); + for (cell = 0; cell < map_cells; ) { + struct node *provider_node; + struct property *cellprop; + int phandle; + size_t parent_cellsize; + + if ((cell + cellsize) >= map_cells) { + FAIL_PROP(c, dti, node, irq_map_prop, + "property size (%d) too small, expected > %zu", + irq_map_prop->val.len, (cell + cellsize) * sizeof(cell_t)); + break; + } + cell += cellsize; + + phandle = propval_cell_n(irq_map_prop, cell); + if (!phandle_is_valid(phandle)) { + /* Give up if this is an overlay with external references */ + if (!(dti->dtsflags & DTSF_PLUGIN)) + FAIL_PROP(c, dti, node, irq_map_prop, + "Cell %zu is not a phandle(%d)", + cell, phandle); + break; + } + + provider_node = get_node_by_phandle(root, phandle); + if (!provider_node) { + FAIL_PROP(c, dti, node, irq_map_prop, + "Could not get phandle(%d) node for (cell %zu)", + phandle, cell); + break; + } + + cellprop = get_property(provider_node, "#interrupt-cells"); + if (cellprop) { + parent_cellsize = propval_cell(cellprop); + } else { + FAIL(c, dti, node, "Missing property '#interrupt-cells' in node %s or bad phandle (referred from interrupt-map[%zu])", + provider_node->fullpath, cell); + break; + } + + cellprop = get_property(provider_node, "#address-cells"); + if (cellprop) + parent_cellsize += propval_cell(cellprop); + + cell += 1 + parent_cellsize; + } +} +WARNING(interrupt_map, check_interrupt_map, NULL, &phandle_references, &addr_size_cells, &interrupt_provider); + static void check_interrupts_property(struct check *c, struct dt_info *dti, struct node *node) @@ -1888,6 +1972,7 @@ static struct check *check_table[] = { &gpios_property, &interrupts_property, &interrupt_provider, + &interrupt_map, &alias_paths, diff --git a/tests/bad-interrupt-map-mask.dts b/tests/bad-interrupt-map-mask.dts new file mode 100644 index 0000000..10eaffd --- /dev/null +++ b/tests/bad-interrupt-map-mask.dts @@ -0,0 +1,20 @@ +/dts-v1/; + +/ { + interrupt-parent = <&intc>; + intc: interrupt-controller { + #interrupt-cells = <3>; + interrupt-controller; + }; + + node { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-map = <1 &intc 1 2 3>; + interrupt-map-mask = <0 0>; + + child { + interrupts = <1>; + }; + }; +}; diff --git a/tests/bad-interrupt-map-parent.dts b/tests/bad-interrupt-map-parent.dts new file mode 100644 index 0000000..fe88ce2 --- /dev/null +++ b/tests/bad-interrupt-map-parent.dts @@ -0,0 +1,17 @@ +/dts-v1/; + +/ { + interrupt-parent = <&intc>; + intc: interrupt-controller { + }; + + node { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-map = <1 &intc 1 2 3>; + + child { + interrupts = <1>; + }; + }; +}; diff --git a/tests/bad-interrupt-map.dts b/tests/bad-interrupt-map.dts new file mode 100644 index 0000000..6df8f93 --- /dev/null +++ b/tests/bad-interrupt-map.dts @@ -0,0 +1,19 @@ +/dts-v1/; + +/ { + interrupt-parent = <&intc>; + intc: interrupt-controller { + #interrupt-cells = <3>; + interrupt-controller; + }; + + node { + /* Missing #address-cells = <0>; */ + #interrupt-cells = <1>; + interrupt-map = <1 &intc 1 2 3>; + + child { + interrupts = <1>; + }; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 0e270fe..d100d5a 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -717,6 +717,9 @@ dtc_tests () { run_sh_test "$SRCDIR/dtc-checkfails.sh" -n deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/good-gpio.dts" check_tests "$SRCDIR/bad-interrupt-cells.dts" interrupts_property check_tests "$SRCDIR/bad-interrupt-controller.dts" interrupt_provider + check_tests "$SRCDIR/bad-interrupt-map.dts" interrupt_map + check_tests "$SRCDIR/bad-interrupt-map-parent.dts" interrupt_map + check_tests "$SRCDIR/bad-interrupt-map-mask.dts" interrupt_map run_sh_test "$SRCDIR/dtc-checkfails.sh" node_name_chars -- -I dtb -O dtb bad_node_char.dtb run_sh_test "$SRCDIR/dtc-checkfails.sh" node_name_format -- -I dtb -O dtb bad_node_format.dtb run_sh_test "$SRCDIR/dtc-checkfails.sh" property_name_chars -- -I dtb -O dtb bad_prop_char.dtb From 4eda2590f481db53318a2f203c85eab3dde4b340 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sun, 31 Oct 2021 14:09:31 +0100 Subject: [PATCH 091/298] CI: Cirrus: bump used FreeBSD from 12.1 to 13.0 CI freebsd_12 job currently fails to build PRs, because of: ``` ld-elf.so.1: /usr/local/bin/bison: Undefined symbol "fread_unlocked@FBSD_1.6" ``` According to FreeBSD issue tracker[1], the proper solution is to upgrade to a supported release, so do that for our CI. [1]: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=253452 Signed-off-by: Ahmad Fatoum --- .cirrus.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index c270a09..d2dc34e 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,9 +1,9 @@ env: CIRRUS_CLONE_DEPTH: 1 -freebsd_12_task: +freebsd_13_task: freebsd_instance: - image: freebsd-12-1-release-amd64 + image: freebsd-13-0-release-amd64 install_script: pkg install -y bison gmake pkgconf build_script: From 5216f3f1bbb70aef463b6cd78dbbb0f4c4c71606 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 10 Nov 2021 18:33:29 -0600 Subject: [PATCH 092/298] libfdt: Add static lib to meson build The meson build is not building the static libfdt, so add it. Signed-off-by: Rob Herring Message-Id: <20211111003329.2347536-1-robh@kernel.org> Reviewed-by: Simon Glass Tested-by: Simon Glass Signed-off-by: David Gibson --- libfdt/meson.build | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libfdt/meson.build b/libfdt/meson.build index 0307ffb..71f29b6 100644 --- a/libfdt/meson.build +++ b/libfdt/meson.build @@ -24,6 +24,11 @@ libfdt = library( install: true, ) +libfdt_a = static_library( + 'fdt', sources, + install: true, +) + libfdt_inc = include_directories('.') libfdt_dep = declare_dependency( From c691776ddb26acbd3674722caafacaf7b6e3e807 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 10 Nov 2021 19:11:32 -0600 Subject: [PATCH 093/298] pylibfdt: Use setuptools instead of distutils The use of setuptools is favored over distutils. setuptools is needed to support building Python 'wheels' and for pip support. Signed-off-by: Rob Herring Message-Id: <20211111011135.2386773-2-robh@kernel.org> Signed-off-by: David Gibson --- pylibfdt/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py index ef40f15..f065a59 100755 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -10,7 +10,7 @@ Copyright (C) 2017 Google, Inc. Written by Simon Glass """ -from distutils.core import setup, Extension +from setuptools import setup, Extension import os import re import sys From 0b106a77dbdc34ef809526febafc490b90d79a54 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 10 Nov 2021 19:11:33 -0600 Subject: [PATCH 094/298] pylibfdt: Use setuptools_scm for the version The DTC version in version_gen.h causes a warning with setuptools: setuptools/dist.py:501: UserWarning: The version specified ('1.6.1-g5454474d') \ is an invalid version, this may not work as expected with newer versions of \ setuptools, pip, and PyPI. Please see PEP 440 for more details. It also creates an unnecessary dependency on the rest of the build system(s). Switch to use setuptools_scm instead to get the version for pylibfdt. Signed-off-by: Rob Herring Message-Id: <20211111011135.2386773-3-robh@kernel.org> Signed-off-by: David Gibson --- pylibfdt/Makefile.pylibfdt | 2 +- pylibfdt/meson.build | 1 - pylibfdt/setup.py | 18 ++++-------------- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 1b5f236..015a05e 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -16,7 +16,7 @@ ifndef V SETUPFLAGS += --quiet endif -$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE) +$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) @$(VECHO) PYMOD $@ $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=$(PYLIBFDT_dir) diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build index 088f249..fad5aa1 100644 --- a/pylibfdt/meson.build +++ b/pylibfdt/meson.build @@ -5,7 +5,6 @@ custom_target( 'pylibfdt', input: 'libfdt.i', output: '_libfdt.so', - depends: version_gen_h, command: [setup_py, 'build_ext', '--build-lib=' + meson.current_build_dir()], build_by_default: true, ) diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py index f065a59..52b61b6 100755 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -15,10 +15,6 @@ import os import re import sys - -VERSION_PATTERN = '^#define DTC_VERSION "DTC ([^"]*)"$' - - def get_top_builddir(): if '--top-builddir' in sys.argv: index = sys.argv.index('--top-builddir') @@ -27,18 +23,9 @@ def get_top_builddir(): else: return os.getcwd() - srcdir = os.path.dirname(os.path.abspath(sys.argv[0])) top_builddir = get_top_builddir() - -def get_version(): - version_file = os.path.join(top_builddir, 'version_gen.h') - f = open(version_file, 'rt') - m = re.match(VERSION_PATTERN, f.readline()) - return m.group(1) - - libfdt_module = Extension( '_libfdt', sources=[os.path.join(srcdir, 'libfdt.i')], @@ -50,7 +37,10 @@ libfdt_module = Extension( setup( name='libfdt', - version=get_version(), + use_scm_version={ + "root": os.path.join(srcdir, '..'), + }, + setup_requires = ['setuptools_scm'], author='Simon Glass ', description='Python binding for libfdt', ext_modules=[libfdt_module], From 69a760747d8d9d1c5dcceebc05e868e1eaf13a2b Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 10 Nov 2021 19:11:34 -0600 Subject: [PATCH 095/298] pylibfdt: Split setup.py author name and email The 'author' field in setup.py is supposed to be just the name. The email address goes in 'author_email' field. Cc: Simon Glass Signed-off-by: Rob Herring Message-Id: <20211111011135.2386773-4-robh@kernel.org> Signed-off-by: David Gibson --- pylibfdt/setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py index 52b61b6..75ce09a 100755 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -41,7 +41,8 @@ setup( "root": os.path.join(srcdir, '..'), }, setup_requires = ['setuptools_scm'], - author='Simon Glass ', + author='Simon Glass', + author_email='sjg@chromium.org', description='Python binding for libfdt', ext_modules=[libfdt_module], package_dir={'': srcdir}, From 23b56cb7e18992650c79a04c9e4e3f2740bc1fbd Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 10 Nov 2021 19:11:35 -0600 Subject: [PATCH 096/298] pylibfdt: Move setup.py to the top level Using 'pip' and several setup.py sub-commands currently don't work with pylibfdt. The primary reason is Python packaging has opinions on the directory structure of repositories and one of those appears to be the inability to reference source files outside of setup.py's subtree. This means a sdist cannot be created with all necessary source components (i.e. libfdt headers). Moving setup.py to the top-level solves these problems. With this change. the following commands now work: Creating packages for pypi.org: ./setup.py sdist bdist_wheel Using pip for installs: pip install . pip install git+http://github.com/robherring/dtc.git@pypi-v2 Signed-off-by: Rob Herring Message-Id: <20211111011135.2386773-5-robh@kernel.org> Signed-off-by: David Gibson --- .gitignore | 4 ++++ MANIFEST.in | 9 +++++++++ pylibfdt/Makefile.pylibfdt | 3 +-- pylibfdt/meson.build | 4 ++-- pylibfdt/setup.py => setup.py | 15 ++++++++------- 5 files changed, 24 insertions(+), 11 deletions(-) create mode 100644 MANIFEST.in rename pylibfdt/setup.py => setup.py (75%) diff --git a/.gitignore b/.gitignore index 8e332d8..416fa05 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,7 @@ lex.yy.c # cscope files cscope.* ncscope.* + +.eggs/ +build/ +dist/ diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..9e6c4ac --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) + +global-exclude * +include setup.py +include pylibfdt/libfdt.i +include pylibfdt/*.py +include libfdt/libfdt.h +include libfdt/fdt.h +include libfdt/libfdt_env.h diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 015a05e..82f565e 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -9,8 +9,7 @@ PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%) PYLIBFDT_CLEANDIRS_L = build __pycache__ PYLIBFDT_CLEANDIRS = $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%) -SETUP = $(PYLIBFDT_dir)/setup.py -SETUPFLAGS = --top-builddir . +SETUP = ./setup.py ifndef V SETUPFLAGS += --quiet diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build index fad5aa1..f684cbb 100644 --- a/pylibfdt/meson.build +++ b/pylibfdt/meson.build @@ -1,5 +1,5 @@ -setup_py = find_program('setup.py') -setup_py = [setup_py.path(), '--quiet', '--top-builddir', meson.current_build_dir() / '..'] +setup_py = find_program('../setup.py') +setup_py = [setup_py.path(), '--quiet', '--top-builddir', meson.project_build_root()] custom_target( 'pylibfdt', diff --git a/pylibfdt/setup.py b/setup.py similarity index 75% rename from pylibfdt/setup.py rename to setup.py index 75ce09a..4b07be9 100755 --- a/pylibfdt/setup.py +++ b/setup.py @@ -15,36 +15,37 @@ import os import re import sys +srcdir = os.path.dirname(__file__) + def get_top_builddir(): if '--top-builddir' in sys.argv: index = sys.argv.index('--top-builddir') sys.argv.pop(index) return sys.argv.pop(index) else: - return os.getcwd() + return srcdir -srcdir = os.path.dirname(os.path.abspath(sys.argv[0])) top_builddir = get_top_builddir() libfdt_module = Extension( '_libfdt', - sources=[os.path.join(srcdir, 'libfdt.i')], - include_dirs=[os.path.join(srcdir, '../libfdt')], + sources=[os.path.join(srcdir, 'pylibfdt/libfdt.i')], + include_dirs=[os.path.join(srcdir, 'libfdt')], libraries=['fdt'], library_dirs=[os.path.join(top_builddir, 'libfdt')], - swig_opts=['-I' + os.path.join(srcdir, '../libfdt')], + swig_opts=['-I' + os.path.join(srcdir, 'libfdt')], ) setup( name='libfdt', use_scm_version={ - "root": os.path.join(srcdir, '..'), + "root": srcdir, }, setup_requires = ['setuptools_scm'], author='Simon Glass', author_email='sjg@chromium.org', description='Python binding for libfdt', ext_modules=[libfdt_module], - package_dir={'': srcdir}, + package_dir={'': os.path.join(srcdir, 'pylibfdt')}, py_modules=['libfdt'], ) From 383e148b70a47ab15f97a19bb999d54f9c3e810f Mon Sep 17 00:00:00 2001 From: Ross Burton Date: Thu, 11 Nov 2021 16:05:36 +0000 Subject: [PATCH 097/298] pylibfdt: fix with Python 3.10 Since Python 2.5 the argument parsing functions when parsing expressions such as s# (string plus length) expect the length to be an int or a ssize_t, depending on whether PY_SSIZE_T_CLEAN is defined or not. Python 3.8 deprecated the use of int, and with Python 3.10 this symbol must be defined and ssize_t used[1]. Define the magic symbol when building the extension, and cast the ints from the libfdt API to ssize_t as appropriate. [1] https://docs.python.org/3.10/whatsnew/3.10.html#id2 Signed-off-by: Ross Burton Message-Id: <20211111160536.2516573-1-ross.burton@arm.com> [dwg: Adjust for new location of setup.py] Tested-by: Rob Herring Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 4 ++-- setup.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 51ee801..075ef70 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -1044,9 +1044,9 @@ typedef uint32_t fdt32_t; $result = Py_None; else %#if PY_VERSION_HEX >= 0x03000000 - $result = Py_BuildValue("y#", $1, *arg4); + $result = Py_BuildValue("y#", $1, (Py_ssize_t)*arg4); %#else - $result = Py_BuildValue("s#", $1, *arg4); + $result = Py_BuildValue("s#", $1, (Py_ssize_t)*arg4); %#endif } diff --git a/setup.py b/setup.py index 4b07be9..0a0daf1 100755 --- a/setup.py +++ b/setup.py @@ -30,6 +30,7 @@ top_builddir = get_top_builddir() libfdt_module = Extension( '_libfdt', sources=[os.path.join(srcdir, 'pylibfdt/libfdt.i')], + define_macros=[('PY_SSIZE_T_CLEAN', None)], include_dirs=[os.path.join(srcdir, 'libfdt')], libraries=['fdt'], library_dirs=[os.path.join(top_builddir, 'libfdt')], From db72398cd4371324901e8ff54980543e0139c1b9 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 11 Nov 2021 22:16:28 -0600 Subject: [PATCH 098/298] README: Update pylibfdt install instructions Now that pip is supported for installs, update the install instructions to use it. Using pip over setup.py is generally recommended and simpler. Also, drop 'SETUP_PREFIX' as it doesn't exist anywhere. Signed-off-by: Rob Herring Message-Id: <20211112041633.741598-2-robh@kernel.org> Signed-off-by: David Gibson --- README | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/README b/README index d9bf850..5f5655d 100644 --- a/README +++ b/README @@ -48,18 +48,24 @@ If you add new features, please check code coverage: # Open 'htmlcov/index.html' in your browser -To install the library via the normal setup.py method, use: +The library can be installed with pip from a local source tree: - ./pylibfdt/setup.py install [--prefix=/path/to/install_dir] + pip install . [--user|--prefix=/path/to/install_dir] -If --prefix is not provided, the default prefix is used, typically '/usr' -or '/usr/local'. See Python's distutils documentation for details. You can -also install via the Makefile if you like, but the above is more common. +Or directly from a remote git repo: + + pip install git+git://git.kernel.org/pub/scm/utils/dtc/dtc.git@main + +The install depends on libfdt shared library being installed on the host system +first. Generally, using --user or --prefix is not necessary and pip will use the +default location for the Python installation which varies if the user is root or +not. + +You can also install everything via make if you like, but pip is recommended. To install both libfdt and pylibfdt you can use: - make install [SETUP_PREFIX=/path/to/install_dir] \ - [PREFIX=/path/to/install_dir] + make install [PREFIX=/path/to/install_dir] To disable building the python library, even if swig and Python are available, use: From 1cc41b1c969f1fa5090b166397e4bab4ab1aa449 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 11 Nov 2021 22:16:29 -0600 Subject: [PATCH 099/298] pylibfdt: Add packaging metadata PyPI expects to have various package metadata including long description, license, and classifiers. Add them. Signed-off-by: Rob Herring Message-Id: <20211112041633.741598-3-robh@kernel.org> Signed-off-by: David Gibson --- MANIFEST.in | 3 +++ setup.py | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/MANIFEST.in b/MANIFEST.in index 9e6c4ac..ff8f5d6 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,9 @@ # SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) global-exclude * +include README +include GPL +include BSD-2-Clause include setup.py include pylibfdt/libfdt.i include pylibfdt/*.py diff --git a/setup.py b/setup.py index 0a0daf1..00444e6 100755 --- a/setup.py +++ b/setup.py @@ -17,6 +17,9 @@ import sys srcdir = os.path.dirname(__file__) +with open("README", "r") as fh: + long_description = fh.read() + def get_top_builddir(): if '--top-builddir' in sys.argv: index = sys.argv.index('--top-builddir') @@ -49,4 +52,18 @@ setup( ext_modules=[libfdt_module], package_dir={'': os.path.join(srcdir, 'pylibfdt')}, py_modules=['libfdt'], + + long_description=long_description, + long_description_content_type="text/plain", + url="https://git.kernel.org/pub/scm/utils/dtc/dtc.git", + license="BSD", + license_files=["GPL", "BSD-2-Clause"], + + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: BSD License", + "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", + "Operating System :: OS Independent", + ], + ) From c19a4bafa514c2c85876f0de35782abd11bed7ec Mon Sep 17 00:00:00 2001 From: Elvira Khabirova Date: Tue, 9 Nov 2021 18:47:19 +0300 Subject: [PATCH 100/298] libfdt: fix an incorrect integer promotion UINT32_MAX is an integer of type unsigned int. UINT32_MAX + 1 overflows unless explicitly computed as unsigned long long. This led to some invalid addresses being treated as valid. Cast UINT32_MAX to uint64_t explicitly. Signed-off-by: Elvira Khabirova --- libfdt/fdt_addresses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/fdt_addresses.c b/libfdt/fdt_addresses.c index 9a82cd0..c40ba09 100644 --- a/libfdt/fdt_addresses.c +++ b/libfdt/fdt_addresses.c @@ -73,7 +73,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, /* check validity of address */ prop = data; if (addr_cells == 1) { - if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size)) + if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size)) return -FDT_ERR_BADVALUE; fdt32_st(prop, (uint32_t)addr); From 45f3d1a095dd3440578d5c6313eba555a791f3fb Mon Sep 17 00:00:00 2001 From: Vikram Garhwal Date: Wed, 17 Nov 2021 18:53:56 -0800 Subject: [PATCH 101/298] libfdt: overlay: make overlay_get_target() public This is done to get the target path for the overlay nodes which is very useful in many cases. For example, Xen hypervisor needs it when applying overlays because Xen needs to do further processing of the overlay nodes, e.g. mapping of resources(IRQs and IOMMUs) to other VMs, creation of SMMU pagetables, etc. Signed-off-by: Vikram Garhwal Message-Id: <1637204036-382159-2-git-send-email-fnu.vikram@xilinx.com> Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 29 +++++++---------------------- libfdt/libfdt.h | 18 ++++++++++++++++++ libfdt/version.lds | 1 + 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index d217e79..5c0c398 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -40,37 +40,22 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) return fdt32_to_cpu(*val); } -/** - * overlay_get_target - retrieves the offset of a fragment's target - * @fdt: Base device tree blob - * @fdto: Device tree overlay blob - * @fragment: node offset of the fragment in the overlay - * @pathp: pointer which receives the path of the target (or NULL) - * - * overlay_get_target() retrieves the target offset in the base - * device tree of a fragment, no matter how the actual targeting is - * done (through a phandle or a path) - * - * returns: - * the targeted node offset in the base device tree - * Negative error code on error - */ -static int overlay_get_target(const void *fdt, const void *fdto, - int fragment, char const **pathp) +int fdt_overlay_target_offset(const void *fdt, const void *fdto, + int fragment_offset, char const **pathp) { uint32_t phandle; const char *path = NULL; int path_len = 0, ret; /* Try first to do a phandle based lookup */ - phandle = overlay_get_target_phandle(fdto, fragment); + phandle = overlay_get_target_phandle(fdto, fragment_offset); if (phandle == (uint32_t)-1) return -FDT_ERR_BADPHANDLE; /* no phandle, try path */ if (!phandle) { /* And then a path based lookup */ - path = fdt_getprop(fdto, fragment, "target-path", &path_len); + path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len); if (path) ret = fdt_path_offset(fdt, path); else @@ -636,7 +621,7 @@ static int overlay_merge(void *fdt, void *fdto) if (overlay < 0) return overlay; - target = overlay_get_target(fdt, fdto, fragment, NULL); + target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL); if (target < 0) return target; @@ -779,7 +764,7 @@ static int overlay_symbol_update(void *fdt, void *fdto) return -FDT_ERR_BADOVERLAY; /* get the target of the fragment */ - ret = overlay_get_target(fdt, fdto, fragment, &target_path); + ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path); if (ret < 0) return ret; target = ret; @@ -801,7 +786,7 @@ static int overlay_symbol_update(void *fdt, void *fdto) if (!target_path) { /* again in case setprop_placeholder changed it */ - ret = overlay_get_target(fdt, fdto, fragment, &target_path); + ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path); if (ret < 0) return ret; target = ret; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 7f117e8..a7f432c 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -2116,6 +2116,24 @@ int fdt_del_node(void *fdt, int nodeoffset); */ int fdt_overlay_apply(void *fdt, void *fdto); +/** + * fdt_overlay_target_offset - retrieves the offset of a fragment's target + * @fdt: Base device tree blob + * @fdto: Device tree overlay blob + * @fragment_offset: node offset of the fragment in the overlay + * @pathp: pointer which receives the path of the target (or NULL) + * + * fdt_overlay_target_offset() retrieves the target offset in the base + * device tree of a fragment, no matter how the actual targeting is + * done (through a phandle or a path) + * + * returns: + * the targeted node offset in the base device tree + * Negative error code on error + */ +int fdt_overlay_target_offset(const void *fdt, const void *fdto, + int fragment_offset, char const **pathp); + /**********************************************************************/ /* Debugging / informational functions */ /**********************************************************************/ diff --git a/libfdt/version.lds b/libfdt/version.lds index 7ab85f1..cbce5d4 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -77,6 +77,7 @@ LIBFDT_1.2 { fdt_appendprop_addrrange; fdt_setprop_inplace_namelen_partial; fdt_create_with_flags; + fdt_overlay_target_offset; local: *; }; From 17739b7ef510917471409d71fb45d8eaf6a1e1fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 9 Dec 2021 07:14:20 +0100 Subject: [PATCH 102/298] Support 'r' format for printing raw bytes with fdtget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FT is sometimes used for storing raw data. That is quite common for U-Boot FIT images. Extracting such data is not trivial currently. Using type 's' (string) will replace every 0x00 (NUL) with 0x20 (space). Using type 'x' will print bytes but in xxd incompatible format. This commit adds support for 'r' (raw) format. Example usage: fdtget -t r firmware.itb /images/foo data > image.raw Support for encoding isn't added as there isn't any clean way of passing binary data as command line argument. Signed-off-by: Rafał Miłecki Message-Id: <20211209061420.29466-1-zajec5@gmail.com> Signed-off-by: David Gibson --- Documentation/manual.txt | 2 +- fdtget.c | 5 +++++ fdtput.c | 2 ++ tests/run_tests.sh | 2 ++ tests/utilfdt_test.c | 5 ++++- util.c | 4 ++-- util.h | 3 ++- 7 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Documentation/manual.txt b/Documentation/manual.txt index 97e53b9..cf4b253 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -712,7 +712,7 @@ The syntax of the fdtget command is: where options are: - s=string, i=int, u=unsigned, x=hex + s=string, i=int, u=unsigned, x=hex, r=raw Optional modifier prefix: hh or b=byte, h=2 byte, l=4 byte (default) diff --git a/fdtget.c b/fdtget.c index 54fc6a0..dd70985 100644 --- a/fdtget.c +++ b/fdtget.c @@ -97,6 +97,11 @@ static int show_data(struct display_info *disp, const char *data, int len) if (len == 0) return 0; + if (disp->type == 'r') { + fwrite(data, 1, len, stdout); + return 0; + } + is_string = (disp->type) == 's' || (!disp->type && util_is_printable_string(data, len)); if (is_string) { diff --git a/fdtput.c b/fdtput.c index 428745a..c2fecf4 100644 --- a/fdtput.c +++ b/fdtput.c @@ -433,6 +433,8 @@ int main(int argc, char *argv[]) if (utilfdt_decode_type(optarg, &disp.type, &disp.size)) usage("Invalid type string"); + if (disp.type == 'r') + usage("Unsupported raw data type"); break; case 'v': diff --git a/tests/run_tests.sh b/tests/run_tests.sh index d100d5a..11068e1 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -855,6 +855,8 @@ fdtget_tests () { run_fdtget_test 8000 -tx $dtb /cpus/PowerPC,970@1 d-cache-size run_fdtget_test "61 62 63 0" -tbx $dtb /randomnode tricky1 run_fdtget_test "a b c d de ea ad be ef" -tbx $dtb /randomnode blob + run_fdtget_test "MyBoardName\0MyBoardFamilyName\0" -tr $dtb / compatible + run_fdtget_test "\x0a\x0b\x0c\x0d\xde\xea\xad\xbe\xef" -tr $dtb /randomnode blob # Here the property size is not a multiple of 4 bytes, so it should fail run_wrap_error_test $DTGET -tlx $dtb /randomnode mixed diff --git a/tests/utilfdt_test.c b/tests/utilfdt_test.c index c621759..ba6462f 100644 --- a/tests/utilfdt_test.c +++ b/tests/utilfdt_test.c @@ -73,6 +73,9 @@ static void check_sizes(char *modifier, int expected_size) *ptr = 's'; check(fmt, 's', -1); + + *ptr = 'r'; + check(fmt, 'r', -1); } static void test_utilfdt_decode_type(void) @@ -90,7 +93,7 @@ static void test_utilfdt_decode_type(void) /* try every other character */ checkfail(""); for (ch = ' '; ch < 127; ch++) { - if (!strchr("iuxs", ch)) { + if (!strchr("iuxsr", ch)) { *fmt = ch; fmt[1] = '\0'; checkfail(fmt); diff --git a/util.c b/util.c index 40274fb..14d3868 100644 --- a/util.c +++ b/util.c @@ -353,11 +353,11 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size) } /* we should now have a type */ - if ((*fmt == '\0') || !strchr("iuxs", *fmt)) + if ((*fmt == '\0') || !strchr("iuxsr", *fmt)) return -1; /* convert qualifier (bhL) to byte size */ - if (*fmt != 's') + if (*fmt != 's' && *fmt != 'r') *size = qualifier == 'b' ? 1 : qualifier == 'h' ? 2 : qualifier == 'l' ? 4 : -1; diff --git a/util.h b/util.h index c45b2c2..7a4e910 100644 --- a/util.h +++ b/util.h @@ -143,6 +143,7 @@ int utilfdt_write_err(const char *filename, const void *blob); * i signed integer * u unsigned integer * x hex + * r raw * * TODO: Implement ll modifier (8 bytes) * TODO: Implement o type (octal) @@ -160,7 +161,7 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size); */ #define USAGE_TYPE_MSG \ - "\ts=string, i=int, u=unsigned, x=hex\n" \ + "\ts=string, i=int, u=unsigned, x=hex, r=raw\n" \ "\tOptional modifier prefix:\n" \ "\t\thh or b=byte, h=2 byte, l=4 byte (default)"; From d152126bb0293c321cae437bdf7437c393ee3619 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Fri, 24 Dec 2021 11:28:12 +0100 Subject: [PATCH 103/298] Fix Python crash on getprop deallocation Fatal Python error: none_dealloc: deallocating None Python runtime state: finalizing (tstate=0x000055c9bac70920) Current thread 0x00007fbe34e47740 (most recent call first): Aborted (core dumped) This is caused by a missing Py_INCREF on the returned Py_None, as demonstrated e.g. in https://github.com/mythosil/swig-python-incref or described at https://edcjones.tripod.com/refcount.html ("Remember to INCREF Py_None!") A PoC for triggering this crash is uploaded to https://github.com/z3ntu/pylibfdt-crash . With this patch applied to pylibfdt the crash does not happen. Signed-off-by: Luca Weiss Message-Id: <20211224102811.70695-1-luca@z3ntu.xyz> Reviewed-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 075ef70..9ccc57b 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -1040,14 +1040,16 @@ typedef uint32_t fdt32_t; /* typemap used for fdt_getprop() */ %typemap(out) (const void *) { - if (!$1) + if (!$1) { $result = Py_None; - else + Py_INCREF($result); + } else { %#if PY_VERSION_HEX >= 0x03000000 $result = Py_BuildValue("y#", $1, (Py_ssize_t)*arg4); %#else $result = Py_BuildValue("s#", $1, (Py_ssize_t)*arg4); %#endif + } } /* typemap used for fdt_setprop() */ From 83102717d7c4171aeb2d26941fa1ee2997bf4a7d Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Sat, 25 Dec 2021 14:25:55 +0100 Subject: [PATCH 104/298] pylibfdt: add Property.as_stringlist() Add a new method for decoding a string list property, useful for e.g. the "reg-names" property. Also add a test for the new method. Signed-off-by: Luca Weiss Message-Id: <20211225132558.167123-2-luca@z3ntu.xyz> Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 7 +++++++ tests/pylibfdt_tests.py | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 9ccc57b..c81b504 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -724,6 +724,13 @@ class Property(bytearray): raise ValueError('Property contains embedded nul characters') return self[:-1].decode('utf-8') + def as_stringlist(self): + """Unicode is supported by decoding from UTF-8""" + if self[-1] != 0: + raise ValueError('Property lacks nul termination') + parts = self[:-1].split(b'\x00') + return list(map(lambda x: x.decode('utf-8'), parts)) + class FdtSw(FdtRo): """Software interface to create a device tree from scratch diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 64b5bd1..7e3cc4c 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -382,6 +382,14 @@ class PyLibfdtBasicTests(unittest.TestCase): self.get_prop("prop-uint64").as_uint64()) self.assertEqual(-2, self.get_prop("prop-int64").as_int64()) + def testGetStringlistProperties(self): + """Test that we can access properties as string list""" + node = self.fdt.path_offset('/subnode@1/subsubnode') + self.assertEqual(["subsubnode1", "subsubnode"], + self.fdt.getprop(node, "compatible").as_stringlist()) + self.assertEqual(["this is a placeholder string", "string2"], + self.fdt.getprop(node, "placeholder").as_stringlist()) + def testReserveMap(self): """Test that we can access the memory reserve map""" self.assertEqual(2, self.fdt.num_mem_rsv()) From a04f69025003890be265e007238dc91041e5529b Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Sat, 25 Dec 2021 14:25:56 +0100 Subject: [PATCH 105/298] pylibfdt: add Property.as_*int*_array() Add new methods to handle decoding of int32, uint32, int64 and uint64 arrays. Also add tests for the new methods. Signed-off-by: Luca Weiss Message-Id: <20211225132558.167123-3-luca@z3ntu.xyz> Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 15 +++++++++++++++ tests/pylibfdt_tests.py | 11 +++++++++++ tests/test_props.dts | 4 ++++ 3 files changed, 30 insertions(+) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index c81b504..ac70762 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -716,6 +716,21 @@ class Property(bytearray): def as_int64(self): return self.as_cell('q') + def as_list(self, fmt): + return list(map(lambda x: x[0], struct.iter_unpack('>' + fmt, self))) + + def as_uint32_list(self): + return self.as_list('L') + + def as_int32_list(self): + return self.as_list('l') + + def as_uint64_list(self): + return self.as_list('Q') + + def as_int64_list(self): + return self.as_list('q') + def as_str(self): """Unicode is supported by decoding from UTF-8""" if self[-1] != 0: diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 7e3cc4c..5479363 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -382,6 +382,17 @@ class PyLibfdtBasicTests(unittest.TestCase): self.get_prop("prop-uint64").as_uint64()) self.assertEqual(-2, self.get_prop("prop-int64").as_int64()) + def testGetIntListProperties(self): + """Test that we can access properties as integer lists""" + self.assertEqual([128, -16, -2], + self.get_prop("prop-int32-array").as_int32_list()) + self.assertEqual([0x1, 0x98765432, 0xdeadbeef], + self.get_prop("prop-uint32-array").as_uint32_list()) + self.assertEqual([0x100000000, -2], + self.get_prop("prop-int64-array").as_int64_list()) + self.assertEqual([0x100000000, 0x1], + self.get_prop("prop-uint64-array").as_uint64_list()) + def testGetStringlistProperties(self): """Test that we can access properties as string list""" node = self.fdt.path_offset('/subnode@1/subsubnode') diff --git a/tests/test_props.dts b/tests/test_props.dts index 7e59bd1..5089023 100644 --- a/tests/test_props.dts +++ b/tests/test_props.dts @@ -8,4 +8,8 @@ prop-hex64 = /bits/ 64 <0xdeadbeef01abcdef>; prop-uint64 = /bits/ 64 <9223372036854775807>; prop-int64 = /bits/ 64 <0xfffffffffffffffe>; + prop-int32-array = <128>, <(-16)>, <0xfffffffe>; + prop-uint32-array = <0x1>, <0x98765432>, <0xdeadbeef>; + prop-int64-array = /bits/ 64 <0x100000000 0xfffffffffffffffe>; + prop-uint64-array = /bits/ 64 <0x100000000 0x1>; }; From cd5f69cbc0d4bc34a509b5f6f62234e25893b684 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Thu, 9 Dec 2021 09:58:00 +0100 Subject: [PATCH 106/298] tests: setprop_inplace: use xstrdup instead of unchecked strdup This is the only strdup instance we have, all others are xstrdup. As strdup is _POSIX_C_SOURCE >= v200809L, which we don't require and we don't check strdup error return here, switch to xstrdup instead. This aligns the test with others that call xfuncs, mainly xmalloc(). Signed-off-by: Ahmad Fatoum Signed-off-by: David Gibson --- tests/setprop_inplace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c index 7e1198d..61a0da1 100644 --- a/tests/setprop_inplace.c +++ b/tests/setprop_inplace.c @@ -58,7 +58,7 @@ int main(int argc, char *argv[]) TEST_STRING_1); verbose_printf("Old string value was \"%s\"\n", strp); - xstr = strdup(strp); + xstr = xstrdup(strp); xlen = strlen(xstr); for (i = 0; i < xlen; i++) xstr[i] = toupper(xstr[i]); From c0c2e115f82ed3bc5f9d3f9e5380f0f7e81a1c21 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Wed, 15 Dec 2021 17:30:11 +0800 Subject: [PATCH 107/298] Fix a UB when fdt_get_string return null When fdt_get_string return null, `namep` is not correctly reset. From the document of `fdt_getprop_by_offset`, the parameter `namep` will be always overwritten (that is, it will be overwritten without exception of error occurance). As for the caller (like https://github.com/topjohnwu/Magisk/blob/e097c097feb881f6097b6d1dc346f310bc92f5d6/native/jni/magiskboot/dtb.cpp#L42), the code may be like: ```cpp size_t size; const char *name; auto *value = fdt_getprop_by_offset(fdt, prop, &name, &size); ``` and if `value == nullptr`, `size` is also be overwritten correctly but `name` is not, which is quite inconsistent. This commit makes sure `name` and `size` behavior consistently (reset to reasonable value) when error occurs. Signed-off-by: LoveSy Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 17584da..9f6c551 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -481,12 +481,12 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, if (!can_assume(VALID_INPUT)) { name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff), &namelen); + *namep = name; if (!name) { if (lenp) *lenp = namelen; return NULL; } - *namep = name; } else { *namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff)); } From ca7294434309930076ff99ff4f0c817499f50f5a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 7 Nov 2021 15:43:43 -0700 Subject: [PATCH 108/298] README: Explain how to add a new API function This is not obvious so add a little note about it. Signed-off-by: Simon Glass Message-Id: <20211107224346.3181320-2-sjg@chromium.org> Signed-off-by: David Gibson --- README | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README b/README index 5f5655d..a48312a 100644 --- a/README +++ b/README @@ -77,6 +77,15 @@ More work remains to support all of libfdt, including access to numeric values. +Adding a new function to libfdt.h +--------------------------------- + +The shared library uses libfdt/version.lds to list the exported functions, so +add your new function there. Check that your function works with pylibfdt. If +it cannot be supported, put the declaration in libfdt.h behind #ifndef SWIG so +that swig ignores it. + + Tests ----- From ff5afb96d0c08133b6f709a197b8bda023531757 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 29 Dec 2021 15:08:28 +1100 Subject: [PATCH 109/298] Handle integer overflow in check_property_phandle_args() If the corresponding '#xxx-cells' value is much too large, an integer overflow can prevent the checks in check_property_phandle_args() from correctly determining that the checked property is too short for the given cells value. This leads to an infinite loops. This patch fixes the bug, and adds a testcase for it. Further information in https://github.com/dgibson/dtc/issues/64 Reported-by: Anciety Signed-off-by: David Gibson --- checks.c | 15 +++++++++------ tests/phandle-args-overflow.dts | 18 ++++++++++++++++++ tests/run_tests.sh | 3 +++ 3 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 tests/phandle-args-overflow.dts diff --git a/checks.c b/checks.c index 781ba11..9f31d26 100644 --- a/checks.c +++ b/checks.c @@ -1382,10 +1382,10 @@ struct provider { }; static void check_property_phandle_args(struct check *c, - struct dt_info *dti, - struct node *node, - struct property *prop, - const struct provider *provider) + struct dt_info *dti, + struct node *node, + struct property *prop, + const struct provider *provider) { struct node *root = dti->dt; unsigned int cell, cellsize = 0; @@ -1401,6 +1401,7 @@ static void check_property_phandle_args(struct check *c, struct node *provider_node; struct property *cellprop; cell_t phandle; + unsigned int expected; phandle = propval_cell_n(prop, cell); /* @@ -1450,10 +1451,12 @@ static void check_property_phandle_args(struct check *c, break; } - if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) { + expected = (cell + cellsize + 1) * sizeof(cell_t); + if ((expected <= cell) || prop->val.len < expected) { FAIL_PROP(c, dti, node, prop, - "property size (%d) too small for cell size %d", + "property size (%d) too small for cell size %u", prop->val.len, cellsize); + break; } } } diff --git a/tests/phandle-args-overflow.dts b/tests/phandle-args-overflow.dts new file mode 100644 index 0000000..8c8c5d7 --- /dev/null +++ b/tests/phandle-args-overflow.dts @@ -0,0 +1,18 @@ +/dts-v1/; + +/* + * https://github.com/dgibson/dtc/issues/64 + * + * Certain dtc versions had a bug where this input caused an infinite + * loop in check_property_phandle_args(). + * + */ + +/ { + clocks = <&ref &ref>; + + ref: poc { + phandle = <1>; + #clock-cells = <0xffffffff>; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 11068e1..5e4e7c4 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -513,6 +513,9 @@ libfdt_tests () { run_dtc_test -I fs -O dtb -o fs.test_tree1.test.dtb $FSBASE/test_tree1 run_test dtbs_equal_unordered -m fs.test_tree1.test.dtb test_tree1.dtb + ## https://github.com/dgibson/dtc/issues/64 + check_tests "$SRCDIR/phandle-args-overflow.dts" clocks_property + # check full tests for good in test_tree1.dtb; do run_test check_full $good From 4048aed12b81c5a0154b9af438edc99ec7d2b6a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 3 Jan 2022 11:38:55 +0400 Subject: [PATCH 110/298] setup.py: fix out of tree build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: commit 1cc41b1c9 ("pylibfdt: Add packaging metadata") Signed-off-by: Marc-André Lureau Message-Id: <20220103073855.1468799-3-marcandre.lureau@redhat.com> Signed-off-by: David Gibson --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 00444e6..029aa61 100755 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ import sys srcdir = os.path.dirname(__file__) -with open("README", "r") as fh: +with open(os.path.join(srcdir, "README"), "r") as fh: long_description = fh.read() def get_top_builddir(): From 651410e54cb9a478f2fbb16cb493a5e7808ad8fe Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sun, 25 Oct 2020 10:41:18 +0100 Subject: [PATCH 111/298] util: introduce xstrndup helper We already have xstrdup, add xstrndup as well to make it straight-forward to clone part of a string. Signed-off-by: Ahmad Fatoum --- util.c | 11 +++++++++++ util.h | 1 + 2 files changed, 12 insertions(+) diff --git a/util.c b/util.c index 14d3868..507f012 100644 --- a/util.c +++ b/util.c @@ -33,6 +33,17 @@ char *xstrdup(const char *s) return d; } +char *xstrndup(const char *s, size_t n) +{ + size_t len = strnlen(s, n) + 1; + char *d = xmalloc(len); + + memcpy(d, s, len - 1); + d[len - 1] = '\0'; + + return d; +} + int xavsprintf_append(char **strp, const char *fmt, va_list ap) { int n, size = 0; /* start with 128 bytes */ diff --git a/util.h b/util.h index 7a4e910..9d38ede 100644 --- a/util.h +++ b/util.h @@ -61,6 +61,7 @@ static inline void *xrealloc(void *p, size_t len) } extern char *xstrdup(const char *s); +extern char *xstrndup(const char *s, size_t len); extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...); extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...); From ec7986e682cf9a5078bdbad341feb807a56b21e0 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sun, 25 Oct 2020 12:39:59 +0100 Subject: [PATCH 112/298] dtc: introduce label relative path references Reference via label allows extending nodes with compile-time checking of whether the node being extended exists. This is useful to catch renamed/removed nodes after an update of the device trees to be extended. In absence of labels in the original device trees, new style path references can be used: /* upstream device tree */ / { leds: some-non-standard-led-controller-name { led-0 { default-state = "off"; }; }; }; /* downstream device tree */ &{/some-non-standard-led-controller-name/led-0} { default-state = "on"; }; This is a common theme within the barebox bootloader[0], which extends the upstream (Linux) device trees in that manner. The downside is that, especially for deep nodes, these references can get quite long and tend to break often due to upstream rework (e.g. rename to adhere to bindings). Often there is a label a level or two higher that could be used. This patch allows combining both a label and a new style path reference to get a compile-time-checked reference, which allows rewriting the previous downstream device tree snippet to: &{leds/led-0} { default-state = "on"; }; This won't be broken when /some-non-standard-led-controller-name is renamed or moved while keeping the label. And if led-0 is renamed, we will get the expected compile-time error. Overlay support is skipped for now as they require special support: The label and relative path parts need to be resolved at overlay apply-time, not at compile-time. [0]: https://www.barebox.org/doc/latest/devicetree/index.html Signed-off-by: Ahmad Fatoum --- dtc-lexer.l | 2 +- dtc-parser.y | 13 +++++++++++++ livetree.c | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 5568b4a..de60a70 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -200,7 +200,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...); return DT_LABEL_REF; } -<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */ +<*>"&{"{PATHCHAR}*\} { /* new-style path reference */ yytext[yyleng-1] = '\0'; DPRINT("Ref: %s\n", yytext+2); yylval.labelref = xstrdup(yytext+2); diff --git a/dtc-parser.y b/dtc-parser.y index a0316a3..46457d4 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -23,6 +23,12 @@ extern void yyerror(char const *s); extern struct dt_info *parser_output; extern bool treesource_error; + +static bool is_ref_relative(const char *ref) +{ + return ref[0] != '/' && strchr(&ref[1], '/'); +} + %} %union { @@ -169,6 +175,8 @@ devicetree: */ if (!($-1 & DTSF_PLUGIN)) ERROR(&@2, "Label or path %s not found", $1); + else if (is_ref_relative($1)) + ERROR(&@2, "Label-relative reference %s not supported in plugin", $1); $$ = add_orphan_node( name_node(build_node(NULL, NULL, NULL), ""), @@ -178,6 +186,9 @@ devicetree: { struct node *target = get_node_by_ref($1, $3); + if (($-1 & DTSF_PLUGIN) && is_ref_relative($3)) + ERROR(&@2, "Label-relative reference %s not supported in plugin", $3); + if (target) { add_label(&target->labels, $2); merge_nodes(target, $4); @@ -193,6 +204,8 @@ devicetree: * so $-1 is what we want (plugindecl) */ if ($-1 & DTSF_PLUGIN) { + if (is_ref_relative($2)) + ERROR(&@2, "Label-relative reference %s not supported in plugin", $2); add_orphan_node($1, $3, $2); } else { struct node *target = get_node_by_ref($1, $2); diff --git a/livetree.c b/livetree.c index cc61237..169462d 100644 --- a/livetree.c +++ b/livetree.c @@ -581,12 +581,39 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle) struct node *get_node_by_ref(struct node *tree, const char *ref) { + struct node *target = tree; + const char *label = NULL, *path = NULL; + if (streq(ref, "/")) return tree; - else if (ref[0] == '/') - return get_node_by_path(tree, ref); + + if (ref[0] == '/') + path = ref; else - return get_node_by_label(tree, ref); + label = ref; + + if (label) { + const char *slash = strchr(label, '/'); + char *buf = NULL; + + if (slash) { + buf = xstrndup(label, slash - label); + label = buf; + path = slash + 1; + } + + target = get_node_by_label(tree, label); + + free(buf); + + if (!target) + return NULL; + } + + if (path) + target = get_node_by_path(target, path); + + return target; } cell_t get_node_phandle(struct node *root, struct node *node) From 26c54f840d2340271f305c04f0d66bafac93274f Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sun, 25 Oct 2020 10:41:41 +0100 Subject: [PATCH 113/298] tests: add test cases for label-relative path references Newly added &{label/path} feature doesn't yet have any tests. Add some. Signed-off-by: Ahmad Fatoum --- tests/.gitignore | 1 + tests/Makefile.tests | 2 +- tests/path-references.c | 8 +++++- tests/path-references.dts | 9 +++++++ tests/relref_merge.c | 51 +++++++++++++++++++++++++++++++++++++++ tests/relref_merge.dts | 40 ++++++++++++++++++++++++++++++ tests/run_tests.sh | 3 +++ 7 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 tests/relref_merge.c create mode 100644 tests/relref_merge.dts diff --git a/tests/.gitignore b/tests/.gitignore index d3f1434..03bdde2 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -54,6 +54,7 @@ tmp.* /property_iterate /propname_escapes /references +/relref_merge /root_node /rw_tree1 /rw_oom diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 2b47627..2f78952 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -18,7 +18,7 @@ LIB_TESTS_L = get_mem_rsv \ open_pack rw_tree1 rw_oom set_name setprop del_property del_node \ appendprop1 appendprop2 propname_escapes \ string_escapes references path-references phandle_format \ - boot-cpuid incbin \ + boot-cpuid incbin relref_merge \ extra-terminating-null \ dtbs_equal_ordered \ dtb_reverse dtbs_equal_unordered \ diff --git a/tests/path-references.c b/tests/path-references.c index 4db61a5..b914576 100644 --- a/tests/path-references.c +++ b/tests/path-references.c @@ -53,7 +53,7 @@ int main(int argc, char *argv[]) void *fdt; const char *p; int len, multilen; - int n1, n2, n3, n4; + int n1, n2, n3, n4, n5; test_init(argc, argv); fdt = load_blob_arg(argc, argv); @@ -89,6 +89,12 @@ int main(int argc, char *argv[]) check_ref(fdt, n3, "/foobar/baz"); check_ref(fdt, n4, "/foo/baz"); + n5 = fdt_path_offset(fdt, "/bar/baz"); + if (n5 < 0) + FAIL("fdt_path_offset(/bar/baz): %s", fdt_strerror(n5)); + + check_ref(fdt, n5, "/bar/baz"); + check_rref(fdt); PASS(); diff --git a/tests/path-references.dts b/tests/path-references.dts index 1fb7d70..dd9ccfc 100644 --- a/tests/path-references.dts +++ b/tests/path-references.dts @@ -25,4 +25,13 @@ lref = &n3; }; }; + n5: bar { + baz { + }; + }; +}; + +n6: &{n5/baz} { + ref = &{n6/}; + lref = &{n5/baz}; }; diff --git a/tests/relref_merge.c b/tests/relref_merge.c new file mode 100644 index 0000000..5daab2e --- /dev/null +++ b/tests/relref_merge.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * libfdt - Flat Device Tree manipulation + * Testcase for label relative child references in dtc + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright (C) 2020 Ahmad Fatoum, Pengutronix. + */ +#include +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +static void check_exist(void *fdt, const char *path) +{ + int sn = fdt_path_offset(fdt, path); + if (sn < 0) + FAIL("%s expected but not found: %s", path, fdt_strerror(sn)); +} + +static void check_doesnt_exist(void *fdt, const char *path) +{ + int sn = fdt_path_offset(fdt, path); + if (sn >= 0) + FAIL("%s found but not expected %d", path, sn); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_exist(fdt, "/node/subnode1"); + check_exist(fdt, "/node/keep-me"); + check_doesnt_exist(fdt, "/node/remove-me"); + + check_doesnt_exist(fdt, "/node2"); + check_doesnt_exist(fdt, "/node/subnode3"); + + check_exist(fdt, "/node/subnode4"); + + check_exist(fdt, "/node/subnode1/add-me"); + + PASS(); +} diff --git a/tests/relref_merge.dts b/tests/relref_merge.dts new file mode 100644 index 0000000..d8660eb --- /dev/null +++ b/tests/relref_merge.dts @@ -0,0 +1,40 @@ +/dts-v1/; + +/ { + node_label: node { + keep-me {}; + remove-me {}; + + subnode1 { + property-inline1; + property-inline2; + property-inline3; + }; + + subnode2 { + property-inline1; + }; + + subnode3 { + property-inline1; + }; + }; + + node2_label: node2 { + property-inline1; + }; +}; +/omit-if-no-ref/ &{node_label/subnode1}; +/omit-if-no-ref/ &node2_label; +/delete-node/ &{node_label/subnode3}; + +&{node_label/} { + /delete-node/ remove-me; + + subnode4 { }; +}; + +label: &{node_label/subnode1} { + selfref = &{node_label/subnode1}; + add-me { }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 5e4e7c4..c78351d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -669,6 +669,9 @@ dtc_tests () { tree1_tests dtc_tree1_merge_path.test.dtb test_tree1.dtb run_wrap_error_test $DTC -I dts -O dtb -o /dev/null "$SRCDIR/test_label_ref.dts" + run_dtc_test -I dts -O dtb -o dtc_relref_merge.test.dtb "$SRCDIR/relref_merge.dts" + run_test relref_merge dtc_relref_merge.test.dtb + # Check prop/node delete functionality run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb "$SRCDIR/test_tree1_delete.dts" tree1_tests dtc_tree1_delete.test.dtb From c001fc01a43e7a06447c06ea3d50bd60641322b8 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 3 Feb 2022 12:04:07 -0600 Subject: [PATCH 114/298] pylibfdt: fix swig build in install A 'pip install' is silently broken unless the tree is dirty and contains pylibfdt/libfdt.py. The problem is a known issue[1] with SWIG and setuptools where the 'build_py' stage needing module.py runs before the 'build_ext' stage which generates it. The work-around is to override 'build_py' to run 'build_ext' first. [1] https://stackoverflow.com/questions/50239473/building-a-module-with-setuptools-and-swig Signed-off-by: Rob Herring Message-Id: <20220203180408.611645-2-robh@kernel.org> Signed-off-by: David Gibson --- MANIFEST.in | 1 - setup.py | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index ff8f5d6..0eee931 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -6,7 +6,6 @@ include GPL include BSD-2-Clause include setup.py include pylibfdt/libfdt.i -include pylibfdt/*.py include libfdt/libfdt.h include libfdt/fdt.h include libfdt/libfdt_env.h diff --git a/setup.py b/setup.py index 029aa61..a8e54a3 100755 --- a/setup.py +++ b/setup.py @@ -11,6 +11,8 @@ Written by Simon Glass """ from setuptools import setup, Extension +from setuptools.command.build_py import build_py as _build_py + import os import re import sys @@ -40,11 +42,17 @@ libfdt_module = Extension( swig_opts=['-I' + os.path.join(srcdir, 'libfdt')], ) +class build_py(_build_py): + def run(self): + self.run_command("build_ext") + return super().run() + setup( name='libfdt', use_scm_version={ "root": srcdir, }, + cmdclass = {'build_py' : build_py}, setup_requires = ['setuptools_scm'], author='Simon Glass', author_email='sjg@chromium.org', From ed310803ea893ed0a8bba9c4ff0d9eb0063a8bef Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Tue, 19 Apr 2022 21:45:38 +0200 Subject: [PATCH 115/298] pylibfdt: add FdtRo.get_path() Add a new Python method wrapping fdt_get_path() from the C API. Also add a test for the new method. Signed-off-by: Luca Weiss Message-Id: <20220419194537.63170-1-luca@z3ntu.xyz> Reviewed-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 28 ++++++++++++++++++++++++++++ tests/pylibfdt_tests.py | 13 +++++++++++++ 2 files changed, 41 insertions(+) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index ac70762..f9f7e7e 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -443,6 +443,29 @@ class FdtRo(object): """ return fdt_get_alias(self._fdt, name) + def get_path(self, nodeoffset, quiet=()): + """Get the full path of a node + + Args: + nodeoffset: Node offset to check + + Returns: + Full path to the node + + Raises: + FdtException if an error occurs + """ + size = 1024 + while True: + ret, path = fdt_get_path(self._fdt, nodeoffset, size) + if ret == -NOSPACE: + size = size * 2 + continue + err = check_err(ret, quiet) + if err: + return err + return path + def parent_offset(self, nodeoffset, quiet=()): """Get the offset of a node's parent @@ -1115,6 +1138,11 @@ typedef uint32_t fdt32_t; } } +%include "cstring.i" + +%cstring_output_maxsize(char *buf, int buflen); +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); + /* We have both struct fdt_property and a function fdt_property() */ %warnfilter(302) fdt_property; diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 5479363..68d6aaa 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -348,6 +348,19 @@ class PyLibfdtBasicTests(unittest.TestCase): self.assertEqual("/subnode@1/subsubnode", self.fdt3.get_alias('ss1')) self.assertEqual("/subnode@1/subsubnode/subsubsubnode", self.fdt3.get_alias('sss1')) + def testGetPath(self): + """Test for the get_path() method""" + node = self.fdt.path_offset('/subnode@1') + node2 = self.fdt.path_offset('/subnode@1/subsubnode') + self.assertEqual("/subnode@1", self.fdt.get_path(node)) + self.assertEqual("/subnode@1/subsubnode", self.fdt.get_path(node2)) + + with self.assertRaises(FdtException) as e: + self.fdt.get_path(-1) + self.assertEqual(e.exception.err, -libfdt.BADOFFSET) + + self.assertEqual(-libfdt.BADOFFSET, self.fdt.get_path(-1, quiet=(libfdt.BADOFFSET,))) + def testParentOffset(self): """Test for the parent_offset() method""" self.assertEqual(-libfdt.NOTFOUND, From 01f23ffe1679bc8009fa14b7d8d728f317d053ea Mon Sep 17 00:00:00 2001 From: Tero Tervala Date: Wed, 29 Jun 2022 19:31:14 +0300 Subject: [PATCH 116/298] Add missing relref_merge test to meson test list Will remove one "Strange test result" when running tests with meson Signed-off-by: Tero Tervala Message-Id: <20220629163114.932175-1-tero.tervala@unikie.com> Signed-off-by: David Gibson --- tests/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/meson.build b/tests/meson.build index fa06824..3776fef 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -71,6 +71,7 @@ tests = [ 'property_iterate', 'propname_escapes', 'references', + 'relref_merge', 'root_node', 'rw_oom', 'rw_tree1', From c7c7f17a83d5ec1049ddfcaf22f40fcdc53ac0c4 Mon Sep 17 00:00:00 2001 From: Tero Tervala Date: Mon, 4 Jul 2022 10:37:22 +0300 Subject: [PATCH 117/298] Fix test script to run also on dash shell /bin/sh points to dash instead of bash in some linux distros. One test would fail if dash was used, this fix will allow all tests to run properly on dash too. dash built-in printf does not support "\xNN" -hex escape format. "\NNN" -octal escape format is supported by both bash and dash printf. Replaced "$(echo "$expect")" because this actually runs /bin/echo instead of shell internal echo and in some cases causes "\NNN" escapes to be printed as the actual characters they represent instead of the escape sequence itself. Cosmetic quotes added to make printout a bit clearer. Signed-off-by: Tero Tervala Message-Id: <20220704073722.1075849-1-tero.tervala@unikie.com> Signed-off-by: David Gibson --- tests/run_tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c78351d..1b16eb8 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -195,7 +195,7 @@ asm_to_so_test () { run_fdtget_test () { expect="$1" shift - printf "fdtget-runtest.sh %s $*: " "$(echo $expect)" + printf "fdtget-runtest.sh \"%s\" $*: " "$expect" base_run_test sh "$SRCDIR/fdtget-runtest.sh" "$expect" "$@" } @@ -862,7 +862,7 @@ fdtget_tests () { run_fdtget_test "61 62 63 0" -tbx $dtb /randomnode tricky1 run_fdtget_test "a b c d de ea ad be ef" -tbx $dtb /randomnode blob run_fdtget_test "MyBoardName\0MyBoardFamilyName\0" -tr $dtb / compatible - run_fdtget_test "\x0a\x0b\x0c\x0d\xde\xea\xad\xbe\xef" -tr $dtb /randomnode blob + run_fdtget_test "\012\013\014\015\336\352\255\276\357" -tr $dtb /randomnode blob # Here the property size is not a multiple of 4 bytes, so it should fail run_wrap_error_test $DTGET -tlx $dtb /randomnode mixed From fda71da26e7fa00966a58afeb2114269b5512e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= Date: Thu, 14 Jul 2022 09:38:48 +0100 Subject: [PATCH 118/298] libfdt: Handle failed get_name() on BEGIN_NODE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Validate the return value of fdt_get_name() as an ill-formed DT, causing it to fail, could result in fdt_check_full() dereferencing NULL. fixes: a2def5479950 ("libfdt: Check that the root-node name is empty") Signed-off-by: Pierre-Clément Tosi Message-Id: <20220714083848.958492-1-ptosi@google.com> Signed-off-by: David Gibson --- libfdt/fdt_check.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/fdt_check.c b/libfdt/fdt_check.c index fa410a8..71390ee 100644 --- a/libfdt/fdt_check.c +++ b/libfdt/fdt_check.c @@ -66,7 +66,7 @@ int fdt_check_full(const void *fdt, size_t bufsize) int len; name = fdt_get_name(fdt, offset, &len); - if (*name || len) + if (!name || *name || len) return -FDT_ERR_BADSTRUCTURE; } break; From fd9b8c96c780c90dd0f1af46963bf2c52de1f0a6 Mon Sep 17 00:00:00 2001 From: Tero Tervala Date: Wed, 29 Jun 2022 19:35:31 +0300 Subject: [PATCH 119/298] Allow static building with make Set STATIC_BUILD=1 environment variable to enable static building when using makefiles. Signed-off-by: Tero Tervala Message-Id: <20220629163531.932281-1-tero.tervala@unikie.com> Signed-off-by: David Gibson --- Makefile | 13 ++++++++++--- tests/Makefile.tests | 12 +++++++----- tests/run_tests.sh | 10 +++++++--- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index ee77115..9f1223f 100644 --- a/Makefile +++ b/Makefile @@ -198,6 +198,13 @@ LIBFDT_lib = $(LIBFDT_dir)/$(LIBFDT_LIB) LIBFDT_include = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_INCLUDES)) LIBFDT_version = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_VERSION)) +ifeq ($(STATIC_BUILD),1) + CFLAGS += -static + LIBFDT_dep = $(LIBFDT_archive) +else + LIBFDT_dep = $(LIBFDT_lib) +endif + include $(LIBFDT_dir)/Makefile.libfdt .PHONY: libfdt @@ -261,11 +268,11 @@ convert-dtsv0: $(CONVERT_OBJS) fdtdump: $(FDTDUMP_OBJS) -fdtget: $(FDTGET_OBJS) $(LIBFDT_lib) +fdtget: $(FDTGET_OBJS) $(LIBFDT_dep) -fdtput: $(FDTPUT_OBJS) $(LIBFDT_lib) +fdtput: $(FDTPUT_OBJS) $(LIBFDT_dep) -fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_lib) +fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_dep) dist: git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \ diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 2f78952..2d36c5d 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -37,8 +37,10 @@ LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv \ LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%) -DL_LIB_TESTS_L = asm_tree_dump value-labels -DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%) +ifneq ($(STATIC_BUILD),1) + DL_LIB_TESTS_L = asm_tree_dump value-labels + DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%) +endif TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS) @@ -60,17 +62,17 @@ TESTS_CLEANDIRS = $(TESTS_CLEANDIRS_L:%=$(TESTS_PREFIX)%) .PHONY: tests tests: $(TESTS) $(TESTS_TREES) -$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib) +$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_dep) # Not necessary on all platforms; allow -ldl to be excluded instead of forcing # other platforms to patch it out. LIBDL = -ldl -$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib) +$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_dep) @$(VECHO) LD [libdl] $@ $(LINK.c) -o $@ $^ $(LIBDL) $(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \ - util.o $(LIBFDT_lib) + util.o $(LIBFDT_dep) $(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 1b16eb8..0cabd13 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -607,11 +607,15 @@ dtc_tests () { run_dtc_test -I dts -O asm -o oasm_$tree.test.s "$SRCDIR/$tree" asm_to_so_test oasm_$tree run_dtc_test -I dts -O dtb -o $tree.test.dtb "$SRCDIR/$tree" - run_test asm_tree_dump ./oasm_$tree.test.so oasm_$tree.test.dtb - run_wrap_test cmp oasm_$tree.test.dtb $tree.test.dtb + if [ -x ./asm_tree_dump ]; then + run_test asm_tree_dump ./oasm_$tree.test.so oasm_$tree.test.dtb + run_wrap_test cmp oasm_$tree.test.dtb $tree.test.dtb + fi done - run_test value-labels ./oasm_value-labels.dts.test.so + if [ -x ./value-labels ]; then + run_test value-labels ./oasm_value-labels.dts.test.so + fi # Check -Odts mode preserve all dtb information for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb \ From 7ad60734b1c1ac12856674fa7913fc9492dc5d28 Mon Sep 17 00:00:00 2001 From: Tero Tervala Date: Wed, 29 Jun 2022 19:35:57 +0300 Subject: [PATCH 120/298] Allow static building with meson Added "static-build" option in the meson_options.txt. Setting it to "true" allows static building. Signed-off-by: Tero Tervala Message-Id: <20220629163557.932298-1-tero.tervala@unikie.com> Signed-off-by: David Gibson --- libfdt/meson.build | 8 +++++++- meson.build | 14 ++++++++++++-- meson_options.txt | 2 ++ tests/meson.build | 9 +++++++-- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/libfdt/meson.build b/libfdt/meson.build index 71f29b6..240bdf4 100644 --- a/libfdt/meson.build +++ b/libfdt/meson.build @@ -31,9 +31,15 @@ libfdt_a = static_library( libfdt_inc = include_directories('.') +if static_build + link_with = libfdt_a +else + link_with = libfdt +endif + libfdt_dep = declare_dependency( include_directories: libfdt_inc, - link_with: libfdt, + link_with: link_with, ) install_headers( diff --git a/meson.build b/meson.build index b23ea1b..78251eb 100644 --- a/meson.build +++ b/meson.build @@ -31,8 +31,16 @@ add_project_arguments( language: 'c' ) +if get_option('static-build') + static_build = true + extra_link_args = ['-static'] +else + static_build = false + extra_link_args = [] +endif + yamltree = 'yamltree.c' -yaml = dependency('yaml-0.1', required: get_option('yaml')) +yaml = dependency('yaml-0.1', required: get_option('yaml'), static: static_build) if not yaml.found() add_project_arguments('-DNO_YAML', language: 'c') yamltree = [] @@ -85,6 +93,7 @@ if get_option('tools') ], dependencies: util_dep, install: true, + link_args: extra_link_args, ) endif @@ -105,10 +114,11 @@ if get_option('tools') ], dependencies: [util_dep, yaml], install: true, + link_args: extra_link_args, ) foreach e: ['fdtdump', 'fdtget', 'fdtput', 'fdtoverlay'] - executable(e, files(e + '.c'), dependencies: util_dep, install: true) + executable(e, files(e + '.c'), dependencies: util_dep, install: true, link_args: extra_link_args) endforeach install_data( diff --git a/meson_options.txt b/meson_options.txt index ea59c28..82621c3 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -8,3 +8,5 @@ option('valgrind', type: 'feature', value: 'auto', description: 'Valgrind support') option('python', type: 'feature', value: 'auto', description: 'Build pylibfdt Python library') +option('static-build', type: 'boolean', value: false, + description: 'Build static binaries') diff --git a/tests/meson.build b/tests/meson.build index 3776fef..4ac154a 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -96,15 +96,20 @@ tests += [ ] dl = cc.find_library('dl', required: false) -if dl.found() +if dl.found() and not static_build tests += [ 'asm_tree_dump', 'value-labels', ] endif +test_deps = [testutil_dep, util_dep, libfdt_dep] +if not static_build + test_deps += [dl] +endif + foreach t: tests - executable(t, files(t + '.c'), dependencies: [testutil_dep, util_dep, libfdt_dep, dl]) + executable(t, files(t + '.c'), dependencies: test_deps, link_args: extra_link_args) endforeach run_tests = find_program('run_tests.sh') From b33a73c62c1cd1e6062dc5416037accdc8a90b5e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 28 Jul 2022 15:51:32 +1000 Subject: [PATCH 121/298] Convert README to README.md Let's move vaguely into the twenty-first century by converting our old plain text README file to Markdown. While we're updating the formatting, make some small polish changes to the content. Signed-off-by: David Gibson --- README | 106 ----------------------------------------------- README.md | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 106 deletions(-) delete mode 100644 README create mode 100644 README.md diff --git a/README b/README deleted file mode 100644 index a48312a..0000000 --- a/README +++ /dev/null @@ -1,106 +0,0 @@ -The source tree contains the Device Tree Compiler (dtc) toolchain for -working with device tree source and binary files and also libfdt, a -utility library for reading and manipulating the binary format. - -DTC and LIBFDT are maintained by: - -David Gibson -Jon Loeliger - - -Python library --------------- - -A Python library is also available. To build this you will need to install -swig and Python development files. On Debian distributions: - - sudo apt-get install swig python3-dev - -The library provides an Fdt class which you can use like this: - -$ PYTHONPATH=../pylibfdt python3 ->>> import libfdt ->>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read()) ->>> node = fdt.path_offset('/subnode@1') ->>> print(node) -124 ->>> prop_offset = fdt.first_property_offset(node) ->>> prop = fdt.get_property_by_offset(prop_offset) ->>> print('%s=%s' % (prop.name, prop.as_str())) -compatible=subnode1 ->>> node2 = fdt.path_offset('/') ->>> print(fdt.getprop(node2, 'compatible').as_str()) -test_tree1 - -You will find tests in tests/pylibfdt_tests.py showing how to use each -method. Help is available using the Python help command, e.g.: - - $ cd pylibfdt - $ python3 -c "import libfdt; help(libfdt)" - -If you add new features, please check code coverage: - - $ sudo apt-get install python3-coverage - $ cd tests - # It's just 'coverage' on most other distributions - $ python3-coverage run pylibfdt_tests.py - $ python3-coverage html - # Open 'htmlcov/index.html' in your browser - - -The library can be installed with pip from a local source tree: - - pip install . [--user|--prefix=/path/to/install_dir] - -Or directly from a remote git repo: - - pip install git+git://git.kernel.org/pub/scm/utils/dtc/dtc.git@main - -The install depends on libfdt shared library being installed on the host system -first. Generally, using --user or --prefix is not necessary and pip will use the -default location for the Python installation which varies if the user is root or -not. - -You can also install everything via make if you like, but pip is recommended. - -To install both libfdt and pylibfdt you can use: - - make install [PREFIX=/path/to/install_dir] - -To disable building the python library, even if swig and Python are available, -use: - - make NO_PYTHON=1 - - -More work remains to support all of libfdt, including access to numeric -values. - - -Adding a new function to libfdt.h ---------------------------------- - -The shared library uses libfdt/version.lds to list the exported functions, so -add your new function there. Check that your function works with pylibfdt. If -it cannot be supported, put the declaration in libfdt.h behind #ifndef SWIG so -that swig ignores it. - - -Tests ------ - -Test files are kept in the tests/ directory. Use 'make check' to build and run -all tests. - -If you want to adjust a test file, be aware that tree_tree1.dts is compiled -and checked against a binary tree from assembler macros in trees.S. So -if you change that file you must change tree.S also. - - -Mailing list ------------- -The following list is for discussion about dtc and libfdt implementation -mailto:devicetree-compiler@vger.kernel.org - -Core device tree bindings are discussed on the devicetree-spec list: -mailto:devicetree-spec@vger.kernel.org diff --git a/README.md b/README.md new file mode 100644 index 0000000..30212bc --- /dev/null +++ b/README.md @@ -0,0 +1,120 @@ +# Device Tree Compiler and libfdt + +The source tree contains the Device Tree Compiler (dtc) toolchain for +working with device tree source and binary files and also libfdt, a +utility library for reading and manipulating the binary format. + +dtc and libfdt are maintained by: + +* [David Gibson ``](mailto:david@gibson.dropbear.id.au) +* [Jon Loeliger ``](mailto:loeliger@gmail.com) + +## Python library + +A Python library wrapping libfdt is also available. To build this you +will need to install `swig` and Python development files. On Debian +distributions: + +``` +$ sudo apt-get install swig python3-dev +``` + +The library provides an `Fdt` class which you can use like this: + +``` +$ PYTHONPATH=../pylibfdt python3 +>>> import libfdt +>>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read()) +>>> node = fdt.path_offset('/subnode@1') +>>> print(node) +124 +>>> prop_offset = fdt.first_property_offset(node) +>>> prop = fdt.get_property_by_offset(prop_offset) +>>> print('%s=%s' % (prop.name, prop.as_str())) +compatible=subnode1 +>>> node2 = fdt.path_offset('/') +>>> print(fdt.getprop(node2, 'compatible').as_str()) +test_tree1 +``` + +You will find tests in `tests/pylibfdt_tests.py` showing how to use each +method. Help is available using the Python help command, e.g.: + +``` +$ cd pylibfdt +$ python3 -c "import libfdt; help(libfdt)" +``` + +If you add new features, please check code coverage: + +``` +$ sudo apt-get install python3-coverage +$ cd tests +# It's just 'coverage' on most other distributions +$ python3-coverage run pylibfdt_tests.py +$ python3-coverage html +# Open 'htmlcov/index.html' in your browser +``` + +The library can be installed with pip from a local source tree: + +``` +$ pip install . [--user|--prefix=/path/to/install_dir] +``` + +Or directly from a remote git repo: + +``` +$ pip install git+git://git.kernel.org/pub/scm/utils/dtc/dtc.git@main +``` + +The install depends on libfdt shared library being installed on the +host system first. Generally, using `--user` or `--prefix` is not +necessary and pip will use the default location for the Python +installation which varies if the user is root or not. + +You can also install everything via make if you like, but pip is +recommended. + +To install both libfdt and pylibfdt you can use: + +``` +$ make install [PREFIX=/path/to/install_dir] +``` + +To disable building the python library, even if swig and Python are available, +use: + +``` +$ make NO_PYTHON=1 +``` + +More work remains to support all of libfdt, including access to numeric +values. + + +## Adding a new function to libfdt.h + +The shared library uses `libfdt/version.lds` to list the exported +functions, so add your new function there. Check that your function +works with pylibfdt. If it cannot be supported, put the declaration in +`libfdt.h` behind `#ifndef SWIG` so that swig ignores it. + + +## Tests + +Test files are kept in the `tests/` directory. Use `make check` to build and run +all tests. + +If you want to adjust a test file, be aware that `tree_tree1.dts` is compiled +and checked against a binary tree from assembler macros in `trees.S`. So +if you change that file you must change `tree.S` also. + + +## Mailing lists + +* The [devicetree-compiler](mailto:devicetree-compiler@vger.kernel.org) + list is for discussion about dtc and libfdt implementation. +* Core device tree bindings are discussed on the + [devicetree-spec](mailto:devicetree-spec@vger.kernel.org) list. + From 0ee1d479b23a35dbcf9a756b5c9437ac6cf12dcf Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 28 Jul 2022 16:16:08 +1000 Subject: [PATCH 122/298] Remove Jon Loeliger from maintainers list Jon hasn't been actively working on dtc maintenance for some years. Signed-off-by: David Gibson --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 30212bc..36a3912 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ utility library for reading and manipulating the binary format. dtc and libfdt are maintained by: * [David Gibson ``](mailto:david@gibson.dropbear.id.au) -* [Jon Loeliger ``](mailto:loeliger@gmail.com) ## Python library From 90b9d9de42caa136436652f63407a50c9641c00f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 28 Jul 2022 16:24:28 +1000 Subject: [PATCH 123/298] Split out information for contributors to CONTRIBUTING.md README.md covers both general information for people using and building the software, and more specific information for people contributing to either dtc or libfdt. Split out the latter information into its own file for easier reference. Signed-off-by: David Gibson --- CONTRIBUTING.md | 25 +++++++++++++++++++++++++ README.md | 19 ------------------- 2 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..51f7a82 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,25 @@ +# Contributing to dtc or libfdt + +There are two ways to submit changes for dtc or libfdt: + +* Post patches directly to the the + [devicetree-compiler](mailto:devicetree-compiler@vger.kernel.org) + mailing list. +* Submit pull requests via + [Github](https://github.com/dgibson/dtc/pulls) + +## Adding a new function to libfdt.h + +The shared library uses `libfdt/version.lds` to list the exported +functions, so add your new function there. Check that your function +works with pylibfdt. If it cannot be supported, put the declaration in +`libfdt.h` behind `#ifndef SWIG` so that swig ignores it. + +## Tests + +Test files are kept in the `tests/` directory. Use `make check` to build and run +all tests. + +If you want to adjust a test file, be aware that `tree_tree1.dts` is compiled +and checked against a binary tree from assembler macros in `trees.S`. So +if you change that file you must change `tree.S` also. diff --git a/README.md b/README.md index 36a3912..8f1a5d2 100644 --- a/README.md +++ b/README.md @@ -91,25 +91,6 @@ $ make NO_PYTHON=1 More work remains to support all of libfdt, including access to numeric values. - -## Adding a new function to libfdt.h - -The shared library uses `libfdt/version.lds` to list the exported -functions, so add your new function there. Check that your function -works with pylibfdt. If it cannot be supported, put the declaration in -`libfdt.h` behind `#ifndef SWIG` so that swig ignores it. - - -## Tests - -Test files are kept in the `tests/` directory. Use `make check` to build and run -all tests. - -If you want to adjust a test file, be aware that `tree_tree1.dts` is compiled -and checked against a binary tree from assembler macros in `trees.S`. So -if you change that file you must change `tree.S` also. - - ## Mailing lists * The [devicetree-compiler](mailto:devicetree-compiler@vger.kernel.org) From c2ccf8a77dd296e3723e285a5b556da709f09020 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 28 Jul 2022 17:44:45 +1000 Subject: [PATCH 124/298] Add description of Signed-off-by lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dtc and libfdt have been using Signed-off-by lines (as used in the Linux kernel) for some time, like a lot of open source projects. However Uwe Kleine-König pointed out we never really stated what they mean in our context. Add information on what the S-o-b line means in CONTRIBUTING.md - this is essentially a quote of the same information from the kernel documentation, with some tweaks to make sense in the new context. Suggested-by: Uwe Kleine-König Signed-off-by: David Gibson Acked-by: Uwe Kleine-König --- CONTRIBUTING.md | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 51f7a82..940dd1a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,3 +23,57 @@ all tests. If you want to adjust a test file, be aware that `tree_tree1.dts` is compiled and checked against a binary tree from assembler macros in `trees.S`. So if you change that file you must change `tree.S` also. + +## Developer's Certificate of Origin + +Like many other projects, dtc and libfdt have adopted the "Developer's +Certificate of Origin" (Signed-off-by) process created by the Linux +kernel community to improve tracking of who did what. Here's how it +works (this is a very slight modification of the description from +`Documentation/process/submitting-patches.rst` in the kernel tree): + +The sign-off is a simple line at the end of the explanation for the +patch, which certifies that you wrote it or otherwise have the right +to pass it on as an open-source patch. The rules are pretty simple: +if you can certify the below: + + Developer's Certificate of Origin 1.1 + + By making a contribution to this project, I certify that: + + (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + + (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + + (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + + (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + +then you just add a line saying:: + + Signed-off-by: Random J Developer + +using your real name (sorry, no pseudonyms or anonymous +contributions.) This will be done for you automatically if you use +`git commit -s`. Reverts should also include "Signed-off-by". `git +revert -s` does that for you. + +Any further SoBs (Signed-off-by:'s) following the author's SoB are +from people handling and transporting the patch, but were not involved +in its development. SoB chains should reflect the **real** route a +patch took as it was propagated to the maintainers, with the first SoB +entry signalling primary authorship of a single author. From f508c83fe6f0c58a59132bd3a0887aebfcd6b16f Mon Sep 17 00:00:00 2001 From: Saad Waheed Date: Fri, 29 Jul 2022 12:09:03 +0500 Subject: [PATCH 125/298] Update README in MANIFEST.in and setup.py to README.md Signed-off-by: Saad Waheed --- MANIFEST.in | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 0eee931..c1c5e67 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,7 +1,7 @@ # SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) global-exclude * -include README +include README.md include GPL include BSD-2-Clause include setup.py diff --git a/setup.py b/setup.py index a8e54a3..e82a832 100755 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ import sys srcdir = os.path.dirname(__file__) -with open(os.path.join(srcdir, "README"), "r") as fh: +with open(os.path.join(srcdir, "README.md"), "r") as fh: long_description = fh.read() def get_top_builddir(): From e64a204196c924288b8bcd741d969160cd9ac6d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= Date: Fri, 29 Jul 2022 14:10:19 +0100 Subject: [PATCH 126/298] manual.txt: Follow README.md and remove Jon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following 0ee1d479b23a ("Remove Jon Loeliger from maintainers list"), make the "Submitting Patches" section of the manual.txt consistent with the README by requesting patches to only be sent to David. Cc: Jon Loeliger Signed-off-by: Pierre-Clément Tosi Message-Id: <20220729131019.806164-1-ptosi@google.com> Signed-off-by: David Gibson --- Documentation/manual.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/manual.txt b/Documentation/manual.txt index cf4b253..2087a4d 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -43,9 +43,8 @@ The gitweb interface for the upstream repository is: 1.1) Submitting Patches -Patches should be sent to the maintainers: +Patches should be sent to the maintainer: David Gibson - Jon Loeliger and CCed to . 2) Description From 50454658f2b5c8968ccd7856d94020c893a4be46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= Date: Fri, 29 Jul 2022 14:00:19 +0100 Subject: [PATCH 127/298] libfdt: Don't mask fdt_get_name() returned error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return the error code from fdt_get_name() (contained in len when the result is NULL) instead of masking it with FDT_ERR_BADSTRUCTURE. Fixes: fda71da26e7f ("libfdt: Handle failed get_name() on BEGIN_NODE") Reported-by: Mike McTernan Signed-off-by: Pierre-Clément Tosi Message-Id: <20220729130019.804288-1-ptosi@google.com> Signed-off-by: David Gibson --- libfdt/fdt_check.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libfdt/fdt_check.c b/libfdt/fdt_check.c index 71390ee..a21ebbc 100644 --- a/libfdt/fdt_check.c +++ b/libfdt/fdt_check.c @@ -66,7 +66,10 @@ int fdt_check_full(const void *fdt, size_t bufsize) int len; name = fdt_get_name(fdt, offset, &len); - if (!name || *name || len) + if (!name) + return len; + + if (*name || len) return -FDT_ERR_BADSTRUCTURE; } break; From e37c25677dc946a025002a394172788b3169b3ce Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 31 Jul 2022 22:10:05 +1000 Subject: [PATCH 128/298] Don't generate erroneous fixups from reference to path The dtb overlay format only permits (non local) fixups to reference labels, not paths. That's because the fixup target goes into the property name in the overlay, and property names aren't permitted to include '/' characters. Stop erroneously generating such fixups, because we didn't check for this case. Signed-off-by: David Gibson --- livetree.c | 6 ++++++ tests/fixup-ref-to-path.dts | 6 ++++++ tests/run_tests.sh | 1 + 3 files changed, 13 insertions(+) create mode 100644 tests/fixup-ref-to-path.dts diff --git a/livetree.c b/livetree.c index 169462d..f46a098 100644 --- a/livetree.c +++ b/livetree.c @@ -919,6 +919,12 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn, /* m->ref can only be a REF_PHANDLE, but check anyway */ assert(m->type == REF_PHANDLE); + /* The format only permits fixups for references to label, not + * references to path */ + if (strchr(m->ref, '/')) + die("Can't generate fixup for reference to path &{%s}\n", + m->ref); + /* there shouldn't be any ':' in the arguments */ if (strchr(node->fullpath, ':') || strchr(prop->name, ':')) die("arguments should not contain ':'\n"); diff --git a/tests/fixup-ref-to-path.dts b/tests/fixup-ref-to-path.dts new file mode 100644 index 0000000..f6dcba0 --- /dev/null +++ b/tests/fixup-ref-to-path.dts @@ -0,0 +1,6 @@ +/dts-v1/; +/plugin/; + +/ { + prop = < &{/path/to/node} >; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 0cabd13..244df8a 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -271,6 +271,7 @@ libfdt_overlay_tests () { run_dtc_test -I dts -O dtb -o $tree.test.dtb "$SRCDIR/$tree.dts" run_test overlay_bad_fixup overlay_base_no_symbols.test.dtb $tree.test.dtb done + run_sh_test "$SRCDIR/dtc-fatal.sh" -I dts -O dtb -o /dev/null fixup-ref-to-path.dts } # Tests to exercise dtc's overlay generation support From c6e92108bcd9c13ebbbcab44a49fa5f39c21621e Mon Sep 17 00:00:00 2001 From: Jia Xianhua Date: Thu, 15 Sep 2022 16:47:03 +0800 Subject: [PATCH 129/298] libdtc: remove duplicate judgments There is no need to check the VALID_DTB repeatedly, and can be combined into one if statement. Signed-off-by: Jia Xianhua Signed-off-by: David Gibson --- libfdt/fdt.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 9fe7cf4..90a39e8 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -106,7 +106,6 @@ int fdt_check_header(const void *fdt) } hdrsize = fdt_header_size(fdt); if (!can_assume(VALID_DTB)) { - if ((fdt_totalsize(fdt) < hdrsize) || (fdt_totalsize(fdt) > INT_MAX)) return -FDT_ERR_TRUNCATED; @@ -115,9 +114,7 @@ int fdt_check_header(const void *fdt) if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt))) return -FDT_ERR_TRUNCATED; - } - if (!can_assume(VALID_DTB)) { /* Bounds check structure block */ if (!can_assume(LATEST) && fdt_version(fdt) < 17) { if (!check_off_(hdrsize, fdt_totalsize(fdt), From a036cc7b0c10474a4cf1cdbe0e232e637e1f2edd Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Sun, 25 Sep 2022 11:42:02 +0100 Subject: [PATCH 130/298] Makefile: limit make re-execution to avoid infinite spin make-4.4 became intentionally more eager at rebuilding outdated Makefile includes. Currently this causes `dtc` to spin infinitely in parser/dependency loop: $ make ... CHK version_gen.h BISON dtc-parser.tab.h DEP dtc-lexer.lex.c DEP dtc-parser.tab.c CHK version_gen.h BISON dtc-parser.tab.h DEP dtc-lexer.lex.c DEP dtc-parser.tab.c ... # never stops After the change build eventually fails when gets into this state: $ make ... CHK version_gen.h UPD version_gen.h DEP util.c BISON dtc-parser.tab.h DEP dtc-lexer.lex.c DEP dtc-parser.tab.c CHK version_gen.h BISON dtc-parser.tab.h DEP dtc-lexer.lex.c DEP dtc-parser.tab.c Makefile:394: *** "Make re-executed itself 10 times. Infinite recursion?". Stop. The actual recursion will be fixed separately. Signed-off-by: Sergei Trofimovich Message-Id: <20220925104203.648449-1-slyich@gmail.com> Signed-off-by: David Gibson --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 9f1223f..e7a0dcb 100644 --- a/Makefile +++ b/Makefile @@ -389,3 +389,7 @@ clean: libfdt_clean pylibfdt_clean tests_clean $(BISON) -b $(basename $(basename $@)) -d $< FORCE: + +ifeq ($(MAKE_RESTARTS),10) +$(error "Make re-executed itself $(MAKE_RESTARTS) times. Infinite recursion?") +endif From 98a07006c48dc0bc3f42b3b3ce75b7f03e87e724 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Sun, 25 Sep 2022 11:42:03 +0100 Subject: [PATCH 131/298] Makefile: fix infinite recursion by dropping non-existent `%.output` Without the change GNU `make-4.4` falls into infinite recursion of trying to generate %.output files (bison is not passed flags to generate debug output). This happens on GNU `make-4.4` only after GNU make change to more eagerly rebuild all target outputs in multiple targets: https://savannah.gnu.org/bugs/index.php?63098 The recursion here is the following: - Makefile depends on *.d files - *.d files depend on *.c files - *.c files are generated by bison - bison is triggered whenever some of it's multiple targets are missing In our case `%.output` is always missing and bison is always reran. *.d files are always regenerated on `make` run. And make is always restarted as *.d files are always regenerated. The fix removes infeasible `%.output`. Signed-off-by: Sergei Trofimovich Message-Id: <20220925104203.648449-2-slyich@gmail.com> Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e7a0dcb..d4e7551 100644 --- a/Makefile +++ b/Makefile @@ -384,7 +384,7 @@ clean: libfdt_clean pylibfdt_clean tests_clean @$(VECHO) LEX $@ $(LEX) -o$@ $< -%.tab.c %.tab.h %.output: %.y +%.tab.c %.tab.h: %.y @$(VECHO) BISON $@ $(BISON) -b $(basename $(basename $@)) -d $< From 035fb90d537540a5fbf24569df74aec667704e4d Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Tue, 11 Oct 2022 11:26:10 -0700 Subject: [PATCH 132/298] libfdt: add fdt_get_property_by_offset_w helper Add a new fdt_get_property_by_offset_w helper function. It is a wrapper on fdt_get_property_by_offset that returns a writable pointer to a property at a given offset. Signed-off-by: Tadeusz Struk Message-Id: <20221011182611.116011-1-tadeusz.struk@linaro.org> Signed-off-by: David Gibson --- libfdt/libfdt.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index a7f432c..d0a2ed2 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -660,6 +660,13 @@ int fdt_next_property_offset(const void *fdt, int offset); const struct fdt_property *fdt_get_property_by_offset(const void *fdt, int offset, int *lenp); +static inline struct fdt_property *fdt_get_property_by_offset_w(void *fdt, + int offset, + int *lenp) +{ + return (struct fdt_property *)(uintptr_t) + fdt_get_property_by_offset(fdt, offset, lenp); +} /** * fdt_get_property_namelen - find a property based on substring From 73590342fc85ca207ca1e6cbc110179873a96962 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Wed, 5 Oct 2022 16:29:30 -0700 Subject: [PATCH 133/298] libfdt: prevent integer overflow in fdt_next_tag Since fdt_next_tag() in a public API function all input parameters, including the fdt blob should not be trusted. It is possible to forge a blob with invalid property length that will cause integer overflow during offset calculation. To prevent that, validate the property length read from the blob before doing calculations. Signed-off-by: Tadeusz Struk Message-Id: <20221005232931.3016047-1-tadeusz.struk@linaro.org> Signed-off-by: David Gibson --- libfdt/fdt.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 90a39e8..20c6415 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -162,7 +162,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) { const fdt32_t *tagp, *lenp; - uint32_t tag; + uint32_t tag, len, sum; int offset = startoffset; const char *p; @@ -188,12 +188,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); if (!can_assume(VALID_DTB) && !lenp) return FDT_END; /* premature end */ + + len = fdt32_to_cpu(*lenp); + sum = len + offset; + if (!can_assume(VALID_DTB) && + (INT_MAX <= sum || sum < (uint32_t) offset)) + return FDT_END; /* premature end */ + /* skip-name offset, length and value */ - offset += sizeof(struct fdt_property) - FDT_TAGSIZE - + fdt32_to_cpu(*lenp); + offset += sizeof(struct fdt_property) - FDT_TAGSIZE + len; + if (!can_assume(LATEST) && - fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && - ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) + fdt_version(fdt) < 0x10 && len >= 8 && + ((offset - len) % 8) != 0) offset += 4; break; From 55778a03df61623ddd743b04772ab90ce128db61 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Tue, 11 Oct 2022 11:26:11 -0700 Subject: [PATCH 134/298] libfdt: tests: add get_next_tag_invalid_prop_len Add a new test get_next_tag_invalid_prop_len, which covers fdt_next_tag(), when it is passed an corrupted blob, with invalid property len values. The test runs twice, on a blob in sw and finished state. Signed-off-by: Tadeusz Struk Message-Id: <20221011182611.116011-2-tadeusz.struk@linaro.org> Signed-off-by: David Gibson --- tests/.gitignore | 1 + tests/Makefile.tests | 2 +- tests/get_next_tag_invalid_prop_len.c | 100 ++++++++++++++++++++++++++ tests/meson.build | 1 + tests/run_tests.sh | 1 + 5 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 tests/get_next_tag_invalid_prop_len.c diff --git a/tests/.gitignore b/tests/.gitignore index 03bdde2..3376ed9 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -74,3 +74,4 @@ tmp.* /truncated_memrsv /utilfdt_test /value-labels +/get_next_tag_invalid_prop_len diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 2d36c5d..2c5b4c9 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -4,7 +4,7 @@ LIB_TESTS_L = get_mem_rsv \ get_path supernode_atdepth_offset parent_offset \ node_offset_by_prop_value node_offset_by_phandle \ node_check_compatible node_offset_by_compatible \ - get_alias \ + get_alias get_next_tag_invalid_prop_len \ char_literal \ sized_cells \ notfound \ diff --git a/tests/get_next_tag_invalid_prop_len.c b/tests/get_next_tag_invalid_prop_len.c new file mode 100644 index 0000000..25d57c3 --- /dev/null +++ b/tests/get_next_tag_invalid_prop_len.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_next_tag() + */ +#include +#include +#include +#include + +#include +#include "tests.h" +#include "testdata.h" + +#define FDT_SIZE 65536 +#define CHECK_ERR(err) \ +({ if (err) \ + FAIL("%s: %d: %s", __FILE__, __LINE__, fdt_strerror(err)); \ +}) + +static void fdt_next_tag_test(bool fdt_finished) +{ + struct fdt_property *prp; + void *fdt; + int nextoff = 0, offset, err; + uint32_t tag; + + fdt = malloc(FDT_SIZE); + if (!fdt) + FAIL("Can't allocate memory"); + err = fdt_create(fdt, FDT_SIZE); + CHECK_ERR(err); + err = fdt_finish_reservemap(fdt); + CHECK_ERR(err); + /* Create a root node and add two properties */ + err = fdt_begin_node(fdt, ""); + CHECK_ERR(err); + err = fdt_property_u32(fdt, "prop-int-32", 0x1234); + CHECK_ERR(err); + err = fdt_property_u32(fdt, "prop2-int-32", 0x4321); + CHECK_ERR(err); + err = fdt_end_node(fdt); + CHECK_ERR(err); + if (fdt_finished) { + /* Call fdt_finish to set the correct fdt state. */ + err = fdt_finish(fdt); + CHECK_ERR(err); + } + + offset = fdt_first_property_offset(fdt, 0); + if (offset <= 0) + FAIL("Invalid offset %x, expected value greater than 0, finished=%d\n", + offset, fdt_finished); + + /* Normal case */ + tag = fdt_next_tag(fdt, offset, &nextoff); + if (tag != FDT_PROP) + FAIL("Invalid tag %x, expected FDT_PROP, finished=%d\n", + tag, fdt_finished); + if (nextoff <= 0) + FAIL("Invalid nextoff %d, expected value greater than 0, finished=%d", + nextoff, fdt_finished); + + /* Get a writable ptr to the first property and corrupt the length */ + prp = fdt_get_property_by_offset_w(fdt, offset, NULL); + if (!prp) + FAIL("Bad property pointer, finished=%d", fdt_finished); + + /* int overflow case */ + prp->len = cpu_to_fdt32(0xFFFFFFFA); + tag = fdt_next_tag(fdt, offset, &nextoff); + if (tag != FDT_END) + FAIL("Invalid tag %x, expected premature FDT_END, finished=%d", + tag, fdt_finished); + if (nextoff != -FDT_ERR_BADSTRUCTURE) + FAIL("Invalid nextoff, expected error -FDT_ERR_BADSTRUCTURE, finished=%d", + fdt_finished); + + /* negative offset case */ + prp->len = cpu_to_fdt32(0x7FFFFFFA); + tag = fdt_next_tag(fdt, offset, &nextoff); + if (tag != FDT_END) + FAIL("Invalid tag %x, expected premature FDT_END, finished=%d", + tag, fdt_finished); + if (nextoff != -FDT_ERR_BADSTRUCTURE) + FAIL("Invalid nextoff, expected -FDT_ERR_BADSTRUCTURE, finished=%d", + fdt_finished); + + free(fdt); +} + +int main(int argc, char *argv[]) +{ + test_init(argc, argv); + + fdt_next_tag_test(false); + fdt_next_tag_test(true); + + PASS(); +} diff --git a/tests/meson.build b/tests/meson.build index 4ac154a..29a42dd 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -47,6 +47,7 @@ tests = [ 'get_path', 'get_phandle', 'get_prop_offset', + 'get_next_tag_invalid_prop_len', 'getprop', 'incbin', 'integer-expressions', diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 244df8a..46678cb 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -513,6 +513,7 @@ libfdt_tests () { run_dtc_test -I fs -O dts -o fs.test_tree1.test.dts $FSBASE/test_tree1 run_dtc_test -I fs -O dtb -o fs.test_tree1.test.dtb $FSBASE/test_tree1 run_test dtbs_equal_unordered -m fs.test_tree1.test.dtb test_tree1.dtb + run_test get_next_tag_invalid_prop_len ## https://github.com/dgibson/dtc/issues/64 check_tests "$SRCDIR/phandle-args-overflow.dts" clocks_property From 2cd89f862cdb04d91c5d59c5b39647f7d5d5b3b8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 21 Nov 2022 14:18:44 +1100 Subject: [PATCH 135/298] dtc: Warning rather than error on possible truncation of cell values We always evaluate integer values in cell arrays as 64-bit quantities, then truncate to the size of the array cells (32-bit by default). However to detect accidental truncation of meaningful values, we give an error if the truncated portion isn't either all 0 or all 1 bits. However, this can still give counterintuitive errors. For if the user is thinking in 2's complement 32-bit arithmetic (which would be quite natural), then they'd expect the expression (-0xffffffff-2) to evaluate to -1 (0xffffffff). However in 64-bit it evaluates to 0xfffffffeffffffff which does truncate to the expected value but trips this error message. Because of this reduce the error to only a warnings, with a somewhat more helpful message. Fixes: https://github.com/dgibson/dtc/issues/74 Signed-off-by: David Gibson --- dtc-parser.y | 11 ++++++++--- tests/cell-overflow-results.dts | 7 +++++++ tests/cell-overflow.dts | 7 +++++++ tests/run_tests.sh | 5 +++++ 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 tests/cell-overflow-results.dts create mode 100644 tests/cell-overflow.dts diff --git a/dtc-parser.y b/dtc-parser.y index 46457d4..bff1337 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -404,9 +404,14 @@ arrayprefix: * within the mask to one (i.e. | in the * mask), all bits are one. */ - if (($2 > mask) && (($2 | mask) != -1ULL)) - ERROR(&@2, "Value out of range for" - " %d-bit array element", $1.bits); + if (($2 > mask) && (($2 | mask) != -1ULL)) { + char *loc = srcpos_string(&@2); + fprintf(stderr, + "WARNING: %s: Value 0x%016" PRIx64 + " truncated to 0x%0*" PRIx64 "\n", + loc, $2, $1.bits / 4, ($2 & mask)); + free(loc); + } } $$.data = data_append_integer($1.data, $2, $1.bits); diff --git a/tests/cell-overflow-results.dts b/tests/cell-overflow-results.dts new file mode 100644 index 0000000..e7f6dad --- /dev/null +++ b/tests/cell-overflow-results.dts @@ -0,0 +1,7 @@ +/dts-v1/; + +/ { + prop1 = < 0 >; + prop2 = < 0xffffffff >; + prop3 = < 0 >; +}; diff --git a/tests/cell-overflow.dts b/tests/cell-overflow.dts new file mode 100644 index 0000000..2f940e8 --- /dev/null +++ b/tests/cell-overflow.dts @@ -0,0 +1,7 @@ +/dts-v1/; + +/ { + prop1 = < (-0xffffffff - 1) >; + prop2 = < (-0xffffffff - 2) >; + prop3 = < ((-0xffffffff - 1) * 2) >; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 46678cb..91350ad 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -518,6 +518,11 @@ libfdt_tests () { ## https://github.com/dgibson/dtc/issues/64 check_tests "$SRCDIR/phandle-args-overflow.dts" clocks_property + ## https://github.com/dgibson/dtc/issues/74 + run_dtc_test -I dts -O dtb -o cell-overflow-results.test.dtb cell-overflow-results.dts + run_dtc_test -I dts -O dtb -o cell-overflow.test.dtb cell-overflow.dts + run_test dtbs_equal_ordered cell-overflow.test.dtb cell-overflow-results.test.dtb + # check full tests for good in test_tree1.dtb; do run_test check_full $good From a41509bea3e73b8dc63bf666a82275bc7d040266 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 27 Jan 2023 16:20:50 -0800 Subject: [PATCH 136/298] libfdt: Replace deprecated 0-length arrays with proper flexible arrays Replace the 0-length arrays in structures with proper flexible arrays. This will avoid warnings when building under GCC 13 with -fstrict-flex-arrays, which the Linux kernel will be doing soon: In file included from ../lib/fdt_ro.c:2: ../lib/../scripts/dtc/libfdt/fdt_ro.c: In function 'fdt_get_name': ../lib/../scripts/dtc/libfdt/fdt_ro.c:319:24: warning: 'strrchr' reading 1 or more bytes from a region of size 0 [-Wstringop-overread] 319 | leaf = strrchr(nameptr, '/'); | ^~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Kees Cook Signed-off-by: David Gibson --- libfdt/fdt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt.h b/libfdt/fdt.h index f2e6880..0c91aa7 100644 --- a/libfdt/fdt.h +++ b/libfdt/fdt.h @@ -35,14 +35,14 @@ struct fdt_reserve_entry { struct fdt_node_header { fdt32_t tag; - char name[0]; + char name[]; }; struct fdt_property { fdt32_t tag; fdt32_t len; fdt32_t nameoff; - char data[0]; + char data[]; }; #endif /* !__ASSEMBLY */ From abbd523bae6e75545ccff126a4a47218ec0defab Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 1 Feb 2023 16:44:41 -0600 Subject: [PATCH 137/298] pylibfdt: Work-around SWIG limitations with flexible arrays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit a41509bea3e7 ("libfdt: Replace deprecated 0-length arrays with proper flexible arrays") fails to build pylibfdt: ./pylibfdt/libfdt_wrap.c: In function ‘_wrap_fdt_node_header_name_set’: ./pylibfdt/libfdt_wrap.c:4350:18: error: cast specifies array type 4350 | arg1->name = (char [])(char *)memcpy(malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size)); | ^ ./pylibfdt/libfdt_wrap.c:4350:16: error: invalid use of flexible array member 4350 | arg1->name = (char [])(char *)memcpy(malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size)); | ^ ./pylibfdt/libfdt_wrap.c:4352:16: error: invalid use of flexible array member 4352 | arg1->name = 0; | ^ ./pylibfdt/libfdt_wrap.c: In function ‘_wrap_fdt_property_data_set’: ./pylibfdt/libfdt_wrap.c:4613:18: error: cast specifies array type 4613 | arg1->data = (char [])(char *)memcpy(malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size)); | ^ ./pylibfdt/libfdt_wrap.c:4613:16: error: invalid use of flexible array member 4613 | arg1->data = (char [])(char *)memcpy(malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size)); | ^ ./pylibfdt/libfdt_wrap.c:4615:16: error: invalid use of flexible array member 4615 | arg1->data = 0; | ^ Turns out this is known issue with SWIG: https://github.com/swig/swig/issues/1699 Implement the work-around to ignore the flexible array member. Fixes: a41509bea3e7 ("libfdt: Replace deprecated 0-length arrays with proper flexible arrays") Cc: Kees Cook Cc: Simon Glass Signed-off-by: Rob Herring Message-Id: <20230201224441.305757-1-robh@kernel.org> Reviewed-by: Simon Glass Tested-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index f9f7e7e..987f7b9 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -1036,6 +1036,9 @@ class NodeAdder(): %rename(fdt_property) fdt_property_func; +%immutable fdt_property::data; +%immutable fdt_node_header::name; + /* * fdt32_t is a big-endian 32-bit value defined to uint32_t in libfdt_env.h * so use the same type here. From 2022bb10879d8716d3e01468fd2fcea8ff28c803 Mon Sep 17 00:00:00 2001 From: Qun-Wei Lin Date: Thu, 12 Jan 2023 20:56:54 +0800 Subject: [PATCH 138/298] checks: Update #{size,address}-cells check for 'dma-ranges' The "dma-ranges" property value is a sequence of child-address parent-address child-size The size of each field is determined by taking the child's "#address-cells" value, the parent's "#address-cells" value, and the child's "#size-cells" value. However, in the following example, it gives a false alarm: +-----------------------------------+---------------------------------------+ | ranges.dts | dma-ranges.dts | +-----------------------------------+---------------------------------------+ | /dts-v1/; | /dts-v1/; | | | | | /{ | /{ | | #address-cells = <1>; | #address-cells = <1>; | | | | | parent { | parent { | | #address-cells = <1>; | #address-cells = <1>; | | #size-cells = <1>; | #size-cells = <1>; | | ranges = <0x0 0xe000 0x1000>; | dma-ranges = <0x0 0xe000 0x1000>; | | child { | child { | | ... | ... | | }; | }; | | }; | }; | | }; | }; | +-----------------------------------+---------------------------------------+ | no warning | Warning (avoid_unnecessary_addr_size) | +-----------------------------------+---------------------------------------+ Same as "ranges", it should not be reported in this check. Signed-off-by: Qun-Wei Lin Message-Id: <20230112125654.13390-1-qun-wei.lin@mediatek.com> Signed-off-by: David Gibson --- checks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checks.c b/checks.c index 9f31d26..69f2649 100644 --- a/checks.c +++ b/checks.c @@ -1222,7 +1222,7 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d if (!node->parent || node->addr_cells < 0 || node->size_cells < 0) return; - if (get_property(node, "ranges") || !node->children) + if (get_property(node, "ranges") || get_property(node, "dma-ranges") || !node->children) return; for_each_child(node, child) { @@ -1232,7 +1232,7 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d } if (!has_reg) - FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property"); + FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\", \"dma-ranges\" or child \"reg\" property"); } WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); From 3f29d6d85c244ad3a74f3b516075d52c0ff35ea6 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Wed, 1 Feb 2023 19:11:13 +0100 Subject: [PATCH 139/298] pylibfdt: add size_hint parameter for get_path This also enables us to test the -NOSPACE condition by adding a test setting size_hint=1 so this path is taken. Message-Id: <20230201181112.1644842-1-luca@z3ntu.xyz> Signed-off-by: Luca Weiss Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 8 ++++---- tests/pylibfdt_tests.py | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 987f7b9..2361e22 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -443,11 +443,12 @@ class FdtRo(object): """ return fdt_get_alias(self._fdt, name) - def get_path(self, nodeoffset, quiet=()): + def get_path(self, nodeoffset, size_hint=1024, quiet=()): """Get the full path of a node Args: nodeoffset: Node offset to check + size_hint: Hint for size of returned string Returns: Full path to the node @@ -455,11 +456,10 @@ class FdtRo(object): Raises: FdtException if an error occurs """ - size = 1024 while True: - ret, path = fdt_get_path(self._fdt, nodeoffset, size) + ret, path = fdt_get_path(self._fdt, nodeoffset, size_hint) if ret == -NOSPACE: - size = size * 2 + size_hint *= 2 continue err = check_err(ret, quiet) if err: diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 68d6aaa..34c2764 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -354,6 +354,7 @@ class PyLibfdtBasicTests(unittest.TestCase): node2 = self.fdt.path_offset('/subnode@1/subsubnode') self.assertEqual("/subnode@1", self.fdt.get_path(node)) self.assertEqual("/subnode@1/subsubnode", self.fdt.get_path(node2)) + self.assertEqual("/subnode@1/subsubnode", self.fdt.get_path(node2, size_hint=1)) with self.assertRaises(FdtException) as e: self.fdt.get_path(-1) From 039a99414e778332d8f9c04cbd3072e1dcc62798 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 9 Feb 2023 21:01:35 +1100 Subject: [PATCH 140/298] Bump version to v1.7.0 It's been rather too long since the last release, and quite a lot of changes have accumulated. Finally get around to rolling a release. Signed-off-by: David Gibson --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d4e7551..93938e9 100644 --- a/Makefile +++ b/Makefile @@ -10,8 +10,8 @@ # CONFIG_LOCALVERSION from some future config system. # VERSION = 1 -PATCHLEVEL = 6 -SUBLEVEL = 1 +PATCHLEVEL = 7 +SUBLEVEL = 0 EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = From 71c19f20b3ef780c17c97e3495c584532c1c6921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 22 Feb 2023 00:07:57 +0400 Subject: [PATCH 141/298] Do not redefine _GNU_SOURCE if already set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Or else, compilation will fail. Signed-off-by: Marc-André Lureau --- srcpos.c | 2 ++ tests/testutils.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/srcpos.c b/srcpos.c index 4fdb22a..87ddf8d 100644 --- a/srcpos.c +++ b/srcpos.c @@ -3,7 +3,9 @@ * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include diff --git a/tests/testutils.c b/tests/testutils.c index 10129c0..d1ddee3 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -5,7 +5,9 @@ * Copyright (C) 2006 David Gibson, IBM Corporation. */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE /* for strsignal() in glibc. FreeBSD has it either way */ +#endif #include #include From 41821821101ad8a9f83746b96b163e5bcbdbe804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 22 Feb 2023 00:08:29 +0400 Subject: [PATCH 142/298] Use #ifdef NO_VALGRIND MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using simply #if will fail when NO_VALGRIND is undefined. Signed-off-by: Marc-André Lureau --- tests/testutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testutils.c b/tests/testutils.c index d1ddee3..ca343e0 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -19,7 +19,7 @@ #include #include -#if NO_VALGRIND +#ifdef NO_VALGRIND static inline void VALGRIND_MAKE_MEM_UNDEFINED(void *p, size_t len) { } From e3cde0613bfdd59d525770bc0e15c54e58b08412 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 27 Feb 2023 19:13:13 +1100 Subject: [PATCH 143/298] Add -Wsuggest-attribute=format warning, correct warnings thus generated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add this new warning to the default build flags. It suggests adding a ((format)) attribute to xavsprintf_append(), so do that. Suggested-by: Marc-André Lureau Signed-off-by: David Gibson --- Makefile | 3 ++- meson.build | 3 ++- util.h | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 93938e9..23b4a3c 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,8 @@ ASSUME_MASK ?= 0 CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK) WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs -Wsign-compare \ - -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow + -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow \ + -Wsuggest-attribute=format CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS) BISON = bison diff --git a/meson.build b/meson.build index 78251eb..f50cf1e 100644 --- a/meson.build +++ b/meson.build @@ -14,7 +14,8 @@ add_project_arguments( '-Wstrict-prototypes', '-Wmissing-prototypes', '-Wredundant-decls', - '-Wshadow' + '-Wshadow', + '-Wsuggest-attribute=format', ]), language: 'c' ) diff --git a/util.h b/util.h index 9d38ede..1547707 100644 --- a/util.h +++ b/util.h @@ -65,7 +65,7 @@ extern char *xstrndup(const char *s, size_t len); extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...); extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...); -extern int xavsprintf_append(char **strp, const char *fmt, va_list ap); +extern int PRINTF(2, 0) xavsprintf_append(char **strp, const char *fmt, va_list ap); extern char *join_path(const char *path, const char *name); /** From 64a907f08b9bedd89833c1eee674148cff2343c6 Mon Sep 17 00:00:00 2001 From: Nikolay Letov Date: Wed, 22 Feb 2023 13:36:07 +0300 Subject: [PATCH 144/298] meson.build: bump version to 1.7.0 [This was botched in the actual 1.7.0 release :( - David Gibson] Signed-off-by: Nikolay Letov --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index f50cf1e..b2c53b9 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('dtc', 'c', - version: '1.6.0', + version: '1.7.0', license: ['GPL2+', 'BSD-2'], default_options: 'werror=true', ) From 32174a66efa4ad19fc6a2a6422e4af2ae4f055cb Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 28 Feb 2023 10:33:58 +1100 Subject: [PATCH 145/298] meson: Fix cell overflow tests when running from meson Because meson always builds out-of-tree we need to reference things in the original source tree via $SRCDIR from run_tests.sh. We forgot a couple of cases for the cell overflow tests. Fix them. Signed-off-by: David Gibson --- tests/run_tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 91350ad..f899d8c 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -519,8 +519,8 @@ libfdt_tests () { check_tests "$SRCDIR/phandle-args-overflow.dts" clocks_property ## https://github.com/dgibson/dtc/issues/74 - run_dtc_test -I dts -O dtb -o cell-overflow-results.test.dtb cell-overflow-results.dts - run_dtc_test -I dts -O dtb -o cell-overflow.test.dtb cell-overflow.dts + run_dtc_test -I dts -O dtb -o cell-overflow-results.test.dtb "$SRCDIR/cell-overflow-results.dts" + run_dtc_test -I dts -O dtb -o cell-overflow.test.dtb "$SRCDIR/cell-overflow.dts" run_test dtbs_equal_ordered cell-overflow.test.dtb cell-overflow-results.test.dtb # check full tests From 5b60f5104fccb12964632b07a49011a222522d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 28 Feb 2023 11:01:05 +0400 Subject: [PATCH 146/298] srcpos.c: fix -Wwrite-strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Signed-off-by: David Gibson --- srcpos.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/srcpos.c b/srcpos.c index 87ddf8d..8e4d18a 100644 --- a/srcpos.c +++ b/srcpos.c @@ -313,8 +313,8 @@ srcpos_string(struct srcpos *pos) static char * srcpos_string_comment(struct srcpos *pos, bool first_line, int level) { - char *pos_str, *fname, *first, *rest; - bool fresh_fname = false; + char *pos_str, *fresh_fname = NULL, *first, *rest; + const char *fname; if (!pos) { if (level > 1) { @@ -332,9 +332,9 @@ srcpos_string_comment(struct srcpos *pos, bool first_line, int level) else if (level > 1) fname = pos->file->name; else { - fname = shorten_to_initial_path(pos->file->name); - if (fname) - fresh_fname = true; + fresh_fname = shorten_to_initial_path(pos->file->name); + if (fresh_fname) + fname = fresh_fname; else fname = pos->file->name; } @@ -348,7 +348,7 @@ srcpos_string_comment(struct srcpos *pos, bool first_line, int level) first_line ? pos->first_line : pos->last_line); if (fresh_fname) - free(fname); + free(fresh_fname); if (pos->next != NULL) { rest = srcpos_string_comment(pos->next, first_line, level); From 44c9b73801c1e02e95b533a3cb498ab8c532e98b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 28 Feb 2023 11:02:18 +0400 Subject: [PATCH 147/298] tests: fix -Wwrite-strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Signed-off-by: David Gibson --- tests/path_offset.c | 4 ++-- tests/utilfdt_test.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/path_offset.c b/tests/path_offset.c index 82527d4..8e657af 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -41,7 +41,7 @@ static int check_subnode(void *fdt, int parent, const char *name) return offset; } -static void check_path_offset(void *fdt, char *path, int offset) +static void check_path_offset(void *fdt, const char *path, int offset) { int rc; @@ -56,7 +56,7 @@ static void check_path_offset(void *fdt, char *path, int offset) " %d instead of %d", path, rc, offset); } -static void check_path_offset_namelen(void *fdt, char *path, int namelen, +static void check_path_offset_namelen(void *fdt, const char *path, int namelen, int offset) { int rc; diff --git a/tests/utilfdt_test.c b/tests/utilfdt_test.c index ba6462f..f62341c 100644 --- a/tests/utilfdt_test.c +++ b/tests/utilfdt_test.c @@ -50,7 +50,7 @@ static void checkfail(const char *fmt) * \param expected_size The size (in bytes) that we expect (ignored for * strings) */ -static void check_sizes(char *modifier, int expected_size) +static void check_sizes(const char *modifier, int expected_size) { char fmt[10], *ptr; From ee5799938697db66ed93bbb0e474d389de58185d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 28 Feb 2023 11:44:31 +0400 Subject: [PATCH 148/298] checks.c: fix heap-buffer-overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ./dtc -I dts -O dtb -o aliases.dtb /home/elmarco/src/dtc/tests/aliases.dts ================================================================= ==882911==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000113 at pc 0x7f34ba0abf50 bp 0x7ffc8db22450 sp 0x7ffc8db21c00 READ of size 4 at 0x602000000113 thread T0 #0 0x7f34ba0abf4f in MemcmpInterceptorCommon(void*, int (*)(void const*, void const*, unsigned long), void const*, void const*, unsigned long) (/lib64/libasan.so.8+0xabf4f) #1 0x7f34ba0ac5e8 in memcmp (/lib64/libasan.so.8+0xac5e8) #2 0x4282dc in check_spi_bus_bridge ../checks.c:1110 #3 0x41b08d in check_nodes_props ../checks.c:140 #4 0x41b9c4 in run_check ../checks.c:180 #5 0x430a3b in process_checks ../checks.c:2056 #6 0x436a90 in main ../dtc.c:327 #7 0x7f34b964a50f in __libc_start_call_main (/lib64/libc.so.6+0x2750f) #8 0x7f34b964a5c8 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x275c8) #9 0x4025c4 in _start (/home/elmarco/src/dtc/build/dtc+0x4025c4) Signed-off-by: Marc-André Lureau Signed-off-by: David Gibson --- checks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks.c b/checks.c index 69f2649..8b1c604 100644 --- a/checks.c +++ b/checks.c @@ -1108,7 +1108,7 @@ static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct no for_each_child(node, child) { struct property *prop; for_each_property(child, prop) { - if (strprefixeq(prop->name, 4, "spi-")) { + if (strstarts(prop->name, "spi-")) { node->bus = &spi_bus; break; } From 7a1d72a788e06ed899095a892315d6cce5994a8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 28 Feb 2023 12:30:30 +0400 Subject: [PATCH 149/298] checks.c: fix check_msg() leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Signed-off-by: David Gibson --- checks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/checks.c b/checks.c index 8b1c604..fb9cf50 100644 --- a/checks.c +++ b/checks.c @@ -114,6 +114,7 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti, } fputs(str, stderr); + free(str); } #define FAIL(c, dti, node, ...) \ From 61fa22b05f693df1e4f7760ad8681b17bd8ae410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 28 Feb 2023 15:57:20 +0400 Subject: [PATCH 150/298] checks: make check.data const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: ../checks.c:47:25: error: initialization discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers] Signed-off-by: Marc-André Lureau Signed-off-by: David Gibson --- checks.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/checks.c b/checks.c index fb9cf50..21e7b62 100644 --- a/checks.c +++ b/checks.c @@ -31,7 +31,7 @@ typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node struct check { const char *name; check_fn fn; - void *data; + const void *data; bool warn, error; enum checkstatus status; bool inprogress; @@ -208,7 +208,7 @@ static void check_is_string(struct check *c, struct dt_info *dti, struct node *node) { struct property *prop; - char *propname = c->data; + const char *propname = c->data; prop = get_property(node, propname); if (!prop) @@ -227,7 +227,7 @@ static void check_is_string_list(struct check *c, struct dt_info *dti, { int rem, l; struct property *prop; - char *propname = c->data; + const char *propname = c->data; char *str; prop = get_property(node, propname); @@ -255,7 +255,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti, struct node *node) { struct property *prop; - char *propname = c->data; + const char *propname = c->data; prop = get_property(node, propname); if (!prop) @@ -1466,7 +1466,7 @@ static void check_provider_cells_property(struct check *c, struct dt_info *dti, struct node *node) { - struct provider *provider = c->data; + const struct provider *provider = c->data; struct property *prop; prop = get_property(node, provider->prop_name); From 0d56145938fe5299c7a4fe0342fe8ba80698d564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 28 Feb 2023 16:06:58 +0400 Subject: [PATCH 151/298] yamltree.c: fix -Werror=discarded-qualifiers & -Werror=cast-qual MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Signed-off-by: David Gibson --- yamltree.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/yamltree.c b/yamltree.c index 55908c8..0cb16ed 100644 --- a/yamltree.c +++ b/yamltree.c @@ -10,7 +10,7 @@ #include "dtc.h" #include "srcpos.h" -char *yaml_error_name[] = { +const char *yaml_error_name[] = { [YAML_NO_ERROR] = "no error", [YAML_MEMORY_ERROR] = "memory error", [YAML_READER_ERROR] = "reader error", @@ -33,7 +33,7 @@ static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, unsigned int seq_offset, unsigned int len, int width) { yaml_event_t event; - void *tag; + const void *tag; unsigned int off; switch(width) { @@ -47,7 +47,7 @@ static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, assert(len % width == 0); yaml_sequence_start_event_initialize(&event, NULL, - (yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE); + (const yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE); yaml_emitter_emit_or_die(emitter, &event); for (off = 0; off < len; off += width) { @@ -80,11 +80,11 @@ static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, if (is_phandle) yaml_scalar_event_initialize(&event, NULL, - (yaml_char_t*)"!phandle", (yaml_char_t *)buf, + (const yaml_char_t*)"!phandle", (const yaml_char_t *)buf, strlen(buf), 0, 0, YAML_PLAIN_SCALAR_STYLE); else yaml_scalar_event_initialize(&event, NULL, - (yaml_char_t*)YAML_INT_TAG, (yaml_char_t *)buf, + (const yaml_char_t*)YAML_INT_TAG, (const yaml_char_t *)buf, strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE); yaml_emitter_emit_or_die(emitter, &event); } @@ -105,7 +105,7 @@ static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len) assert(isascii(str[i])); yaml_scalar_event_initialize(&event, NULL, - (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str, + (const yaml_char_t *)YAML_STR_TAG, (const yaml_char_t*)str, len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); yaml_emitter_emit_or_die(emitter, &event); } @@ -119,15 +119,15 @@ static void yaml_propval(yaml_emitter_t *emitter, struct property *prop) /* Emit the property name */ yaml_scalar_event_initialize(&event, NULL, - (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)prop->name, + (const yaml_char_t *)YAML_STR_TAG, (const yaml_char_t*)prop->name, strlen(prop->name), 1, 1, YAML_PLAIN_SCALAR_STYLE); yaml_emitter_emit_or_die(emitter, &event); /* Boolean properties are easiest to deal with. Length is zero, so just emit 'true' */ if (len == 0) { yaml_scalar_event_initialize(&event, NULL, - (yaml_char_t *)YAML_BOOL_TAG, - (yaml_char_t*)"true", + (const yaml_char_t *)YAML_BOOL_TAG, + (const yaml_char_t*)"true", strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE); yaml_emitter_emit_or_die(emitter, &event); return; @@ -137,7 +137,7 @@ static void yaml_propval(yaml_emitter_t *emitter, struct property *prop) die("No markers present in property '%s' value\n", prop->name); yaml_sequence_start_event_initialize(&event, NULL, - (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE); + (const yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE); yaml_emitter_emit_or_die(emitter, &event); for_each_marker(m) { @@ -185,7 +185,7 @@ static void yaml_tree(struct node *tree, yaml_emitter_t *emitter) return; yaml_mapping_start_event_initialize(&event, NULL, - (yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE); + (const yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE); yaml_emitter_emit_or_die(emitter, &event); for_each_property(tree, prop) @@ -194,7 +194,7 @@ static void yaml_tree(struct node *tree, yaml_emitter_t *emitter) /* Loop over all the children, emitting them into the map */ for_each_child(tree, child) { yaml_scalar_event_initialize(&event, NULL, - (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)child->name, + (const yaml_char_t *)YAML_STR_TAG, (const yaml_char_t*)child->name, strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE); yaml_emitter_emit_or_die(emitter, &event); yaml_tree(child, emitter); @@ -217,7 +217,7 @@ void dt_to_yaml(FILE *f, struct dt_info *dti) yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0); yaml_emitter_emit_or_die(&emitter, &event); - yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE); + yaml_sequence_start_event_initialize(&event, NULL, (const yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE); yaml_emitter_emit_or_die(&emitter, &event); yaml_tree(dti->dt, &emitter); From 9cceabea1ee09ae0864d365b7b3cc89a01b1287c Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Tue, 28 Feb 2023 18:33:21 +0800 Subject: [PATCH 152/298] checks: correct I2C 10-bit address check Currently if there is a valid 10-bit address the following warning is always displayed due to the 7-bit check failing due to reg > 0x7f "I2C address must be less than 7-bits, got "0x800000a6". Set I2C_TEN_BIT_ADDRESS for 10 bit addresses or fix the property" Fix this issue by checking if a 10-bit address is expected, and is valid in separate if statements. Fixes: 8259d59f ("checks: Improve i2c reg property checking") Signed-off-by: Matt Ranostay Signed-off-by: David Gibson --- checks.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/checks.c b/checks.c index 21e7b62..16bc7f6 100644 --- a/checks.c +++ b/checks.c @@ -1079,10 +1079,11 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node /* Ignore I2C_OWN_SLAVE_ADDRESS */ reg &= ~I2C_OWN_SLAVE_ADDRESS; - if ((reg & I2C_TEN_BIT_ADDRESS) && ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff)) - FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"", + if (reg & I2C_TEN_BIT_ADDRESS) { + if ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff) + FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"", reg); - else if (reg > 0x7f) + } else if (reg > 0x7f) FAIL_PROP(c, dti, node, prop, "I2C address must be less than 7-bits, got \"0x%x\". Set I2C_TEN_BIT_ADDRESS for 10 bit addresses or fix the property", reg); } From 0b842c3c819971cdbe0915469759c40f6eb3db7e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 27 Feb 2023 23:11:29 +1100 Subject: [PATCH 153/298] Make build_property() xstrdup its name argument The name field of 'struct property' was really always supposed to be a malloc()ed string, that is owned by the structure. To avoid an extra strdup() for strings coming up from the lexer, build_property() and build_property_delete() expect to take such an already malloc()ed string, which means it's not correct to pass it a static string literal. That's a pretty non-obvious constraint, so a bunch of incorrect uses have crept in. Really, avoiding the extra dup from the lexer isn't a big enough benefit for this demonstrably dangerous interface. So change it to do the xstrdup() itself, removing the burden from callers. Signed-off-by: David Gibson --- dtc-parser.y | 3 +++ dtc.h | 4 ++-- fstree.c | 2 +- livetree.c | 8 ++++---- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index bff1337..9b724e5 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -284,14 +284,17 @@ propdef: DT_PROPNODENAME '=' propdata ';' { $$ = build_property($1, $3, &@$); + free($1); } | DT_PROPNODENAME ';' { $$ = build_property($1, empty_data, &@$); + free($1); } | DT_DEL_PROP DT_PROPNODENAME ';' { $$ = build_property_delete($2); + free($2); } | DT_LABEL propdef { diff --git a/dtc.h b/dtc.h index 0a1f549..0fca726 100644 --- a/dtc.h +++ b/dtc.h @@ -260,9 +260,9 @@ struct node { void add_label(struct label **labels, char *label); void delete_labels(struct label **labels); -struct property *build_property(char *name, struct data val, +struct property *build_property(const char *name, struct data val, struct srcpos *srcpos); -struct property *build_property_delete(char *name); +struct property *build_property_delete(const char *name); struct property *chain_property(struct property *first, struct property *list); struct property *reverse_properties(struct property *first); diff --git a/fstree.c b/fstree.c index 5e59594..0f9a534 100644 --- a/fstree.c +++ b/fstree.c @@ -43,7 +43,7 @@ static struct node *read_fstree(const char *dirname) "WARNING: Cannot open %s: %s\n", tmpname, strerror(errno)); } else { - prop = build_property(xstrdup(de->d_name), + prop = build_property(de->d_name, data_copy_file(pfile, st.st_size), NULL); diff --git a/livetree.c b/livetree.c index f46a098..f76ad7f 100644 --- a/livetree.c +++ b/livetree.c @@ -36,27 +36,27 @@ void delete_labels(struct label **labels) label->deleted = 1; } -struct property *build_property(char *name, struct data val, +struct property *build_property(const char *name, struct data val, struct srcpos *srcpos) { struct property *new = xmalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); - new->name = name; + new->name = xstrdup(name); new->val = val; new->srcpos = srcpos_copy(srcpos); return new; } -struct property *build_property_delete(char *name) +struct property *build_property_delete(const char *name) { struct property *new = xmalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); - new->name = name; + new->name = xstrdup(name); new->deleted = 1; return new; From 4718189c4ca83ddaa38a4990bddd1d4196b11933 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 27 Feb 2023 23:32:01 +1100 Subject: [PATCH 154/298] Delay xstrdup() of node and property names coming from a flat tree The 'name' field of 'struct node' is supposed to be an (individually) malloc()ed string. So, when taking a name from a flattened blob we need to strdup() it. Currently that happens in flat_read_string() as we take it from the flattened structure itself. That obscures what's going on because it's several steps removed from actually inserting it into node->name. It also means we need an additional strdup() and free() for the case of old dtb formats where we need to extract just the final path component from the blob for the name. While we're scanning the blob, we're doing so read-only, so it's fine to have pointers into it. Therefore simplify things a bit by delaying the xstrdup() to the point where we're actually inserting into node->name. Signed-off-by: David Gibson --- flattree.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/flattree.c b/flattree.c index 95e43d3..1bcd808 100644 --- a/flattree.c +++ b/flattree.c @@ -604,11 +604,11 @@ static void flat_realign(struct inbuf *inb, int align) die("Premature end of data parsing flat device tree\n"); } -static char *flat_read_string(struct inbuf *inb) +static const char *flat_read_string(struct inbuf *inb) { int len = 0; const char *p = inb->ptr; - char *str; + const char *str; do { if (p >= inb->limit) @@ -616,7 +616,7 @@ static char *flat_read_string(struct inbuf *inb) len++; } while ((*p++) != '\0'); - str = xstrdup(inb->ptr); + str = inb->ptr; inb->ptr += len; @@ -711,7 +711,7 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) } -static char *nodename_from_path(const char *ppath, const char *cpath) +static const char *nodename_from_path(const char *ppath, const char *cpath) { int plen; @@ -725,7 +725,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath) if (!streq(ppath, "/")) plen++; - return xstrdup(cpath + plen); + return cpath + plen; } static struct node *unflatten_tree(struct inbuf *dtbuf, @@ -733,7 +733,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, const char *parent_flatname, int flags) { struct node *node; - char *flatname; + const char *flatname; uint32_t val; node = build_node(NULL, NULL, NULL); @@ -741,9 +741,10 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, flatname = flat_read_string(dtbuf); if (flags & FTF_FULLPATH) - node->name = nodename_from_path(parent_flatname, flatname); + node->name = xstrdup(nodename_from_path(parent_flatname, + flatname)); else - node->name = flatname; + node->name = xstrdup(flatname); do { struct property *prop; @@ -785,10 +786,6 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, } } while (val != FDT_END_NODE); - if (node->name != flatname) { - free(flatname); - } - return node; } From fd68bb8c56587114fa6eeed39c36c4b347a6a5fc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 27 Feb 2023 23:18:52 +1100 Subject: [PATCH 155/298] Make name_node() xstrdup its name argument The name field of 'struct node' was really always supposed to be a malloc()ed string, that is owned by the structure. To avoid an extra strdup() for strings coming up from the lexer, name_node() expects to take uch an already malloc()ed string, which means it's not correct to pass it a static string literal. That's a pretty non-obvious constraint, so a bunch of incorrect uses have crept in. Really, avoiding the extra dup from the lexer isn't a big enough benefit for this demonstrably dangerous interface. So change it to do the xstrdup() itself, removing the burden from callers. Signed-off-by: David Gibson --- dtc-parser.y | 2 ++ dtc.h | 8 ++++---- livetree.c | 17 +++++++++-------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 9b724e5..4d5eece 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -573,10 +573,12 @@ subnode: DT_PROPNODENAME nodedef { $$ = name_node($2, $1); + free($1); } | DT_DEL_NODE DT_PROPNODENAME ';' { $$ = name_node(build_node_delete(&@$), $2); + free($2); } | DT_OMIT_NO_REF subnode { diff --git a/dtc.h b/dtc.h index 0fca726..4c4aaca 100644 --- a/dtc.h +++ b/dtc.h @@ -269,7 +269,7 @@ struct property *reverse_properties(struct property *first); struct node *build_node(struct property *proplist, struct node *children, struct srcpos *srcpos); struct node *build_node_delete(struct srcpos *srcpos); -struct node *name_node(struct node *node, char *name); +struct node *name_node(struct node *node, const char *name); struct node *omit_node_if_unused(struct node *node); struct node *reference_node(struct node *node); struct node *chain_node(struct node *first, struct node *list); @@ -336,9 +336,9 @@ struct dt_info *build_dt_info(unsigned int dtsflags, struct reserve_info *reservelist, struct node *tree, uint32_t boot_cpuid_phys); void sort_tree(struct dt_info *dti); -void generate_label_tree(struct dt_info *dti, char *name, bool allocph); -void generate_fixups_tree(struct dt_info *dti, char *name); -void generate_local_fixups_tree(struct dt_info *dti, char *name); +void generate_label_tree(struct dt_info *dti, const char *name, bool allocph); +void generate_fixups_tree(struct dt_info *dti, const char *name); +void generate_local_fixups_tree(struct dt_info *dti, const char *name); /* Checks */ diff --git a/livetree.c b/livetree.c index f76ad7f..803093f 100644 --- a/livetree.c +++ b/livetree.c @@ -116,11 +116,11 @@ struct node *build_node_delete(struct srcpos *srcpos) return new; } -struct node *name_node(struct node *node, char *name) +struct node *name_node(struct node *node, const char *name) { assert(node->name == NULL); - node->name = name; + node->name = xstrdup(name); return node; } @@ -250,6 +250,7 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) name_node(new_node, "__overlay__"); node = build_node(p, new_node, NULL); name_node(node, name); + free(name); add_child(dt, node); return dt; @@ -808,18 +809,18 @@ void sort_tree(struct dt_info *dti) } /* utility helper to avoid code duplication */ -static struct node *build_and_name_child_node(struct node *parent, char *name) +static struct node *build_and_name_child_node(struct node *parent, const char *name) { struct node *node; node = build_node(NULL, NULL, NULL); - name_node(node, xstrdup(name)); + name_node(node, name); add_child(parent, node); return node; } -static struct node *build_root_node(struct node *dt, char *name) +static struct node *build_root_node(struct node *dt, const char *name) { struct node *an; @@ -1040,7 +1041,7 @@ static void generate_local_fixups_tree_internal(struct dt_info *dti, generate_local_fixups_tree_internal(dti, lfn, c); } -void generate_label_tree(struct dt_info *dti, char *name, bool allocph) +void generate_label_tree(struct dt_info *dti, const char *name, bool allocph) { if (!any_label_tree(dti, dti->dt)) return; @@ -1048,7 +1049,7 @@ void generate_label_tree(struct dt_info *dti, char *name, bool allocph) dti->dt, allocph); } -void generate_fixups_tree(struct dt_info *dti, char *name) +void generate_fixups_tree(struct dt_info *dti, const char *name) { if (!any_fixup_tree(dti, dti->dt)) return; @@ -1056,7 +1057,7 @@ void generate_fixups_tree(struct dt_info *dti, char *name) dti->dt); } -void generate_local_fixups_tree(struct dt_info *dti, char *name) +void generate_local_fixups_tree(struct dt_info *dti, const char *name) { if (!any_local_fixup_tree(dti, dti->dt)) return; From 6f8b28f496093156ae126b434ed753094943da03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 28 Feb 2023 14:53:12 +0400 Subject: [PATCH 156/298] livetree: fix leak spotted by ASAN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ./dtc -I dts -O dtb -o overlay_base_manual_symbols.test.dtb /home/elmarco/src/dtc/tests/overlay_base_manual_symbols.dts ../data.c:109:2: runtime error: null pointer passed as argument 2, which is declared to never be null ================================================================= ==933317==ERROR: LeakSanitizer: detected memory leaks Direct leak of 24 byte(s) in 1 object(s) allocated from: #0 0x7f49a2aba6af in __interceptor_malloc (/lib64/libasan.so.8+0xba6af) #1 0x43183d in xmalloc ../util.h:45 #2 0x43482f in data_add_marker ../data.c:230 #3 0x449bb8 in get_node_phandle ../livetree.c:632 #4 0x421058 in fixup_phandle_references ../checks.c:627 #5 0x41b0ba in check_nodes_props ../checks.c:141 #6 0x41b1c8 in check_nodes_props ../checks.c:144 #7 0x41b9f1 in run_check ../checks.c:181 #8 0x430a68 in process_checks ../checks.c:2057 #9 0x436abd in main ../dtc.c:327 #10 0x7f49a30d850f in __libc_start_call_main (/lib64/libc.so.6+0x2750f) Only create data when necessary, and do not alias it. Signed-off-by: Marc-André Lureau [dwg: Small fixup for a slightly different approach to adjacent cleanups] Signed-off-by: David Gibson --- livetree.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/livetree.c b/livetree.c index 803093f..0ec47ed 100644 --- a/livetree.c +++ b/livetree.c @@ -617,10 +617,25 @@ struct node *get_node_by_ref(struct node *tree, const char *ref) return target; } +static void add_phandle_property(struct node *node, + const char *name, int format) +{ + struct data d; + + if (!(phandle_format & format)) + return; + if (get_property(node, name)) + return; + + d = data_add_marker(empty_data, TYPE_UINT32, NULL); + d = data_append_cell(d, node->phandle); + + add_property(node, build_property(name, d, NULL)); +} + cell_t get_node_phandle(struct node *root, struct node *node) { static cell_t phandle = 1; /* FIXME: ick, static local */ - struct data d = empty_data; if (phandle_is_valid(node->phandle)) return node->phandle; @@ -630,16 +645,8 @@ cell_t get_node_phandle(struct node *root, struct node *node) node->phandle = phandle; - d = data_add_marker(d, TYPE_UINT32, NULL); - d = data_append_cell(d, phandle); - - if (!get_property(node, "linux,phandle") - && (phandle_format & PHANDLE_LEGACY)) - add_property(node, build_property("linux,phandle", d, NULL)); - - if (!get_property(node, "phandle") - && (phandle_format & PHANDLE_EPAPR)) - add_property(node, build_property("phandle", d, NULL)); + add_phandle_property(node, "linux,phandle", PHANDLE_LEGACY); + add_phandle_property(node, "phandle", PHANDLE_EPAPR); /* If the node *does* have a phandle property, we must * be dealing with a self-referencing phandle, which will be From 083ab26da83bf5d14df5733e3b9954a0881f9ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 28 Feb 2023 11:31:00 +0400 Subject: [PATCH 157/298] tests: fix leaks spotted by ASAN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always allocate from open_blob_rw(), to simplify memory management. The fixes are not exhaustive. Signed-off-by: Marc-André Lureau Signed-off-by: David Gibson --- tests/appendprop2.c | 1 + tests/appendprop_addrrange.c | 2 +- tests/check_path.c | 1 + tests/del_node.c | 7 ++++--- tests/del_property.c | 8 +++++--- tests/overlay.c | 1 + tests/set_name.c | 8 +++++--- tests/setprop.c | 1 + tests/tests.h | 2 +- tests/testutils.c | 15 +++++---------- 10 files changed, 25 insertions(+), 21 deletions(-) diff --git a/tests/appendprop2.c b/tests/appendprop2.c index a0c1f6f..a96c88a 100644 --- a/tests/appendprop2.c +++ b/tests/appendprop2.c @@ -36,6 +36,7 @@ int main(int argc, char *argv[]) buf = xmalloc(SPACE); CHECK(fdt_open_into(fdt, buf, SPACE)); + free(fdt); fdt = buf; CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes))); diff --git a/tests/appendprop_addrrange.c b/tests/appendprop_addrrange.c index 538afcf..543a799 100644 --- a/tests/appendprop_addrrange.c +++ b/tests/appendprop_addrrange.c @@ -36,7 +36,7 @@ int main(int argc, char *argv[]) err = fdt_open_into(fdt, buf, 0x1000); if (err) FAIL("fdt_open_into(): %s", fdt_strerror(err)); - + free(fdt); fdt = buf; /* Set up */ diff --git a/tests/check_path.c b/tests/check_path.c index cc9757a..c3ae15d 100644 --- a/tests/check_path.c +++ b/tests/check_path.c @@ -32,6 +32,7 @@ static void *open_dt(char *path) * Resize our DTs to 4k so that we have room to operate on */ CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE)); + free(dt); return copy; } diff --git a/tests/del_node.c b/tests/del_node.c index 10846df..c450b2c 100644 --- a/tests/del_node.c +++ b/tests/del_node.c @@ -18,15 +18,16 @@ int main(int argc, char *argv[]) { - void *fdt; + void *fdt, *blob; int subnode1_offset, subnode2_offset, subsubnode2_offset; int err; int oldsize, delsize, newsize; test_init(argc, argv); - fdt = load_blob_arg(argc, argv); + blob = load_blob_arg(argc, argv); - fdt = open_blob_rw(fdt); + fdt = open_blob_rw(blob); + free(blob); oldsize = fdt_totalsize(fdt); diff --git a/tests/del_property.c b/tests/del_property.c index 37e8303..27a700b 100644 --- a/tests/del_property.c +++ b/tests/del_property.c @@ -18,16 +18,17 @@ int main(int argc, char *argv[]) { - void *fdt; + void *fdt, *blob; const uint32_t *intp; const char *strp; int err, lenerr; int oldsize, delsize, newsize; test_init(argc, argv); - fdt = load_blob_arg(argc, argv); + blob = load_blob_arg(argc, argv); - fdt = open_blob_rw(fdt); + fdt = open_blob_rw(blob); + free(blob); oldsize = fdt_totalsize(fdt); @@ -73,5 +74,6 @@ int main(int argc, char *argv[]) if (newsize >= oldsize) FAIL("Tree failed to shrink after deletions"); + free(fdt); PASS(); } diff --git a/tests/overlay.c b/tests/overlay.c index f3dd310..2d27918 100644 --- a/tests/overlay.c +++ b/tests/overlay.c @@ -186,6 +186,7 @@ static void *open_dt(char *path) * Resize our DTs to 4k so that we have room to operate on */ CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE)); + free(dt); return copy; } diff --git a/tests/set_name.c b/tests/set_name.c index 5020305..ab674e5 100644 --- a/tests/set_name.c +++ b/tests/set_name.c @@ -69,15 +69,17 @@ static void check_set_name(void *fdt, const char *path, const char *newname) int main(int argc, char *argv[]) { - void *fdt; + void *fdt, *blob; test_init(argc, argv); - fdt = load_blob_arg(argc, argv); - fdt = open_blob_rw(fdt); + blob = load_blob_arg(argc, argv); + fdt = open_blob_rw(blob); + free(blob); check_set_name(fdt, "/subnode@1", "subnode@17"); check_set_name(fdt, "/subnode@2/subsubnode@0", "fred@0"); check_set_name(fdt, "/subnode@17/subsubnode", "something@0"); + free(fdt); PASS(); } diff --git a/tests/setprop.c b/tests/setprop.c index fa3938d..c2d1365 100644 --- a/tests/setprop.c +++ b/tests/setprop.c @@ -36,6 +36,7 @@ int main(int argc, char *argv[]) if (err) FAIL("fdt_open_into(): %s", fdt_strerror(err)); + free(fdt); fdt = buf; intp = check_getprop_cell(fdt, 0, "prop-int", TEST_VALUE_1); diff --git a/tests/tests.h b/tests/tests.h index bf8f23c..7c1b6c0 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -123,7 +123,7 @@ void vg_prepare_blob(void *fdt, size_t bufsize); void *load_blob(const char *filename); void *load_blob_arg(int argc, char *argv[]); void save_blob(const char *filename, void *blob); -void *open_blob_rw(void *blob); +void *open_blob_rw(const void *blob); #include "util.h" diff --git a/tests/testutils.c b/tests/testutils.c index ca343e0..4c85111 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -340,19 +340,14 @@ void save_blob(const char *filename, void *fdt) free(tmp); } -void *open_blob_rw(void *blob) +void *open_blob_rw(const void *blob) { int err; - void *buf = blob; + void *buf; + int newsize = fdt_totalsize(blob) + 8; - err = fdt_open_into(blob, buf, fdt_totalsize(blob)); - if (err == -FDT_ERR_NOSPACE) { - /* Ran out of space converting to v17 */ - int newsize = fdt_totalsize(blob) + 8; - - buf = xmalloc(newsize); - err = fdt_open_into(blob, buf, newsize); - } + buf = xmalloc(newsize); + err = fdt_open_into(blob, buf, newsize); if (err) FAIL("fdt_open_into(): %s", fdt_strerror(err)); return buf; From 72fc810c3025f07de718f5f32a290a6cd5d1f4ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 28 Feb 2023 11:04:23 +0400 Subject: [PATCH 158/298] build-sys: add -Wwrite-strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Signed-off-by: David Gibson --- Makefile | 2 +- meson.build | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 23b4a3c..6ccee13 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ ASSUME_MASK ?= 0 CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK) WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs -Wsign-compare \ -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow \ - -Wsuggest-attribute=format + -Wsuggest-attribute=format -Wwrite-strings CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS) BISON = bison diff --git a/meson.build b/meson.build index b2c53b9..cef113f 100644 --- a/meson.build +++ b/meson.build @@ -16,6 +16,7 @@ add_project_arguments( '-Wredundant-decls', '-Wshadow', '-Wsuggest-attribute=format', + '-Wwrite-strings', ]), language: 'c' ) From 2cdf93a6d402a161edf16de6011bd5ad76382e92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 15 Mar 2023 11:08:19 +0100 Subject: [PATCH 159/298] fdtoverlay: Fix usage string to not mention "" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fdtoverlay doesn't have a -t option, so explaining the type formats and modifier prefixes doesn't make much sense. Signed-off-by: Uwe Kleine-König Message-Id: <20230315100819.13387-1-u.kleine-koenig@pengutronix.de> Signed-off-by: David Gibson --- fdtoverlay.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fdtoverlay.c b/fdtoverlay.c index 5350af6..cac6b65 100644 --- a/fdtoverlay.c +++ b/fdtoverlay.c @@ -23,9 +23,7 @@ /* Usage related data. */ static const char usage_synopsis[] = "apply a number of overlays to a base blob\n" - " fdtoverlay [ []]\n" - "\n" - USAGE_TYPE_MSG; + " fdtoverlay [ []]"; static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS; static struct option const usage_long_opts[] = { {"input", required_argument, NULL, 'i'}, From 9f8b382ed45e7a3ca114c1a371ce6b6edc4b3ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 24 Apr 2023 17:23:27 +0200 Subject: [PATCH 160/298] manual: Fix and improve documentation about -@ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Device trees with a /plugin/ tag ("overlays") generate a __fixups__ node when needed and independent of -q being given or not. The same is true for __local__fixups__. So don't mention these two nodes in the paragraph about -@. To not shorten the description too much, describe the semantic of the properties contained in the generated __symbols__ node. Signed-off-by: Uwe Kleine-König Signed-off-by: David Gibson --- Documentation/manual.txt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Documentation/manual.txt b/Documentation/manual.txt index 2087a4d..15a7837 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -122,12 +122,10 @@ Options: Relevant for dtb and asm output only. -@ - Generates a __symbols__ node at the root node of the resulting blob - for any node labels used, and for any local references using phandles - it also generates a __local_fixups__ node that tracks them. + Generates a __symbols__ node at the root node. This node contains a + property for each label. The property's name is the label name and the + value is the path of the labeled node. - When using the /plugin/ tag all unresolved label references to - be tracked in the __fixups__ node, making dynamic resolution possible. -A Generate automatically aliases for all node labels. This is similar to From 390f481521c350b99787da830ac8dc37b74d3c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 19 Apr 2023 08:41:14 +0200 Subject: [PATCH 161/298] fdtoverlay: Drop a a repeated article MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: David Gibson --- fdtoverlay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdtoverlay.c b/fdtoverlay.c index cac6b65..4eba046 100644 --- a/fdtoverlay.c +++ b/fdtoverlay.c @@ -48,7 +48,7 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len, int ret; /* - * We take a copies first, because a a failed apply can trash + * We take a copies first, because a failed apply can trash * both the base blob and the overlay */ tmpo = xmalloc(fdt_totalsize(overlay)); From 129bb4b78bc6c56ee517a044ba5c9dfc220f899c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 28 Apr 2023 18:30:34 +0200 Subject: [PATCH 162/298] doc: dt-object-internal: Fix a typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Message-Id: <20230428163034.775288-1-u.kleine-koenig@pengutronix.de> Signed-off-by: David Gibson --- Documentation/dt-object-internal.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/dt-object-internal.txt b/Documentation/dt-object-internal.txt index 51d68ab..c7357e6 100644 --- a/Documentation/dt-object-internal.txt +++ b/Documentation/dt-object-internal.txt @@ -35,7 +35,7 @@ We have a number of peripherals that after probing (using some undefined method) should result in different Device Tree configuration. We cannot boot with this static tree because due to the configuration of the -foo platform there exist multiple conficting peripherals DT fragments. +foo platform there exist multiple conflicting peripherals DT fragments. So for the bar peripheral we would have this: From df093279282ca0cff4d20ceb3bb5857117ed4cc4 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 9 Mar 2023 11:28:32 +0100 Subject: [PATCH 163/298] add fdt_path_getprop_namelen() helper Add a wrapper for fdt_getprop_namelen() allowing one to specify the node by path instead of offset. Signed-off-by: Rasmus Villemoes Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 9f6c551..cc2fd88 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -522,6 +522,18 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) return fdt32_ld_(php); } +static const void *fdt_path_getprop_namelen(const void *fdt, const char *path, + const char *propname, int propnamelen, + int *lenp) +{ + int offset = fdt_path_offset(fdt, path); + + if (offset < 0) + return NULL; + + return fdt_getprop_namelen(fdt, offset, propname, propnamelen, lenp); +} + const char *fdt_get_alias_namelen(const void *fdt, const char *name, int namelen) { From 18f5ec12a10ec84e957222074dadf4a3e4cc8d59 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 9 Mar 2023 11:32:39 +0100 Subject: [PATCH 164/298] use fdt_path_getprop_namelen() in fdt_get_alias_namelen() Simplify the code by making use of the new helper. Signed-off-by: Rasmus Villemoes Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index cc2fd88..7faa7a6 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -537,13 +537,7 @@ static const void *fdt_path_getprop_namelen(const void *fdt, const char *path, const char *fdt_get_alias_namelen(const void *fdt, const char *name, int namelen) { - int aliasoffset; - - aliasoffset = fdt_path_offset(fdt, "/aliases"); - if (aliasoffset < 0) - return NULL; - - return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); + return fdt_path_getprop_namelen(fdt, "/aliases", name, namelen, NULL); } const char *fdt_get_alias(const void *fdt, const char *name) From a6f997bc77d4c637308c053ec1632493c7ac437b Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 12 Apr 2023 15:47:44 +0200 Subject: [PATCH 165/298] add fdt_get_symbol() and fdt_get_symbol_namelen() functions The fdt_get_symbol_namelen() function will be used in a subsequent patch. Signed-off-by: Rasmus Villemoes Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 11 +++++++++++ libfdt/libfdt.h | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 7faa7a6..c4c520c 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -545,6 +545,17 @@ const char *fdt_get_alias(const void *fdt, const char *name) return fdt_get_alias_namelen(fdt, name, strlen(name)); } +const char *fdt_get_symbol_namelen(const void *fdt, + const char *name, int namelen) +{ + return fdt_path_getprop_namelen(fdt, "/__symbols__", name, namelen, NULL); +} + +const char *fdt_get_symbol(const void *fdt, const char *name) +{ + return fdt_get_symbol_namelen(fdt, name, strlen(name)); +} + int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) { int pdepth = 0, p = 0; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index d0a2ed2..67fcafb 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -869,6 +869,42 @@ const char *fdt_get_alias_namelen(const void *fdt, */ const char *fdt_get_alias(const void *fdt, const char *name); +/** + * fdt_get_symbol_namelen - get symbol based on substring + * @fdt: pointer to the device tree blob + * @name: name of the symbol to look up + * @namelen: number of characters of name to consider + * + * Identical to fdt_get_symbol(), but only examine the first @namelen + * characters of @name for matching the symbol name. + * + * Return: a pointer to the expansion of the symbol named @name, if it exists, + * NULL otherwise + */ +#ifndef SWIG /* Not available in Python */ +const char *fdt_get_symbol_namelen(const void *fdt, + const char *name, int namelen); +#endif + +/** + * fdt_get_symbol - retrieve the path referenced by a given symbol + * @fdt: pointer to the device tree blob + * @name: name of the symbol to look up + * + * fdt_get_symbol() retrieves the value of a given symbol. That is, + * the value of the property named @name in the node + * /__symbols__. Such a node exists only for a device tree blob that + * has been compiled with the -@ dtc option. Each property corresponds + * to a label appearing in the device tree source, with the name of + * the property being the label and the value being the full path of + * the node it is attached to. + * + * returns: + * a pointer to the expansion of the symbol named 'name', if it exists + * NULL, if the given symbol or the /__symbols__ node does not exist + */ +const char *fdt_get_symbol(const void *fdt, const char *name); + /** * fdt_get_path - determine the full path of a node * @fdt: pointer to the device tree blob From 60bcf1cde1a806fb17dd4c892aff9089f12a8165 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 12 Apr 2023 17:31:53 +0200 Subject: [PATCH 166/298] improve documentation for fdt_path_offset() The current documentation doesn't mention the possibility of passing a non-absolute path and having that treated as an alias. Add that information, along with an example (which will further be expanded in a subsequent patch), and clarify when -FDT_ERR_BADPATH can be returned. Signed-off-by: Rasmus Villemoes Signed-off-by: David Gibson --- libfdt/libfdt.h | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 67fcafb..34c4d55 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -524,10 +524,35 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); * level matching the given component, differentiated only by unit * address). * + * If the path is not absolute (i.e. does not begin with '/'), the + * first component is treated as an alias. That is, the property by + * that name is looked up in the /aliases node, and the value of that + * property used in place of that first component. + * + * For example, for this small fragment + * + * / { + * aliases { + * i2c2 = &foo; // RHS compiles to "/soc@0/i2c@30a40000/eeprom@52" + * }; + * soc@0 { + * foo: i2c@30a40000 { + * bar: eeprom@52 { + * }; + * }; + * }; + * }; + * + * these would be equivalent: + * + * /soc@0/i2c@30a40000/eeprom@52 + * i2c2/eeprom@52 + * * returns: * structure block offset of the node with the requested path (>=0), on * success - * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid + * -FDT_ERR_BADPATH, given path does not begin with '/' and the first + * component is not a valid alias * -FDT_ERR_NOTFOUND, if the requested node does not exist * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, From 44bb89cafd3d96b8df0f324b652c7bf804b38c05 Mon Sep 17 00:00:00 2001 From: Johannes Beisswenger Date: Fri, 14 Apr 2023 14:17:38 +0200 Subject: [PATCH 167/298] checks: Fix segmentation fault in check_graph_node Dts files which contain an 'endpoint' node as a direct child of the root node cause a segmentation fault inside check_graph_node(). This type of error can easily happen when a 'remote-endpoint' property is accidentally placed outside the corresponding endpoint and port nodes. Example with 'endpoint' node: /dts-v1/; / { endpoint {}; }; Example with remote-endpoint property: /dts-v1/; / { foo { remote-endpoint = <0xdeadbeef>; }; }; Signed-off-by: Johannes Beisswenger Signed-off-by: David Gibson --- checks.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/checks.c b/checks.c index 16bc7f6..8ed7a60 100644 --- a/checks.c +++ b/checks.c @@ -1767,6 +1767,11 @@ static void check_graph_nodes(struct check *c, struct dt_info *dti, get_property(child, "remote-endpoint"))) continue; + /* The root node cannot be a port */ + if (!node->parent) { + FAIL(c, dti, node, "root node contains endpoint node '%s', potentially misplaced remote-endpoint property", child->name); + continue; + } node->bus = &graph_port_bus; /* The parent of 'port' nodes can be either 'ports' or a device */ From f1657b2fb5be12d85ceb6a50d2db8a006dee830c Mon Sep 17 00:00:00 2001 From: Johannes Beisswenger Date: Fri, 14 Apr 2023 15:17:34 +0200 Subject: [PATCH 168/298] tests: Add test cases for bad endpoint node and remote-endpoint prop checks Signed-off-by: Johannes Beisswenger Signed-off-by: David Gibson --- tests/bad-graph-root1.dts | 7 +++++++ tests/bad-graph-root2.dts | 2 ++ tests/bad-graph-root3.dts | 14 ++++++++++++++ tests/bad-graph-root4.dts | 19 +++++++++++++++++++ tests/run_tests.sh | 4 ++++ 5 files changed, 46 insertions(+) create mode 100644 tests/bad-graph-root1.dts create mode 100644 tests/bad-graph-root2.dts create mode 100644 tests/bad-graph-root3.dts create mode 100644 tests/bad-graph-root4.dts diff --git a/tests/bad-graph-root1.dts b/tests/bad-graph-root1.dts new file mode 100644 index 0000000..06cf915 --- /dev/null +++ b/tests/bad-graph-root1.dts @@ -0,0 +1,7 @@ +/dts-v1/; + +/ { + foo { + remote-endpoint = <0xdeadbeef>; + }; +}; diff --git a/tests/bad-graph-root2.dts b/tests/bad-graph-root2.dts new file mode 100644 index 0000000..026f207 --- /dev/null +++ b/tests/bad-graph-root2.dts @@ -0,0 +1,2 @@ +/dts-v1/; +/ { endpoint {}; }; diff --git a/tests/bad-graph-root3.dts b/tests/bad-graph-root3.dts new file mode 100644 index 0000000..7360013 --- /dev/null +++ b/tests/bad-graph-root3.dts @@ -0,0 +1,14 @@ +/dts-v1/; + + / { + bar: bar { + port { + bar_con: endpoint { + remote-endpoint = <&foo_con>; + }; + }; + }; + foo_con: endpoint { + remote-endpoint = <&bar_con>; + }; +}; diff --git a/tests/bad-graph-root4.dts b/tests/bad-graph-root4.dts new file mode 100644 index 0000000..5b1a1ea --- /dev/null +++ b/tests/bad-graph-root4.dts @@ -0,0 +1,19 @@ +/dts-v1/; + + / { + + bar: bar { + port { + bar_con: endpoint { + remote-endpoint = <&foo_con>; + }; + }; + }; + foo { + remote-endpoint = <&bar_con>; // misplaced remote-endpoint property + port { + foo_con: endpoint { + }; + }; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index f899d8c..2af8c15 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -730,6 +730,10 @@ dtc_tests () { check_tests "$SRCDIR/bad-graph.dts" graph_child_address check_tests "$SRCDIR/bad-graph.dts" graph_port check_tests "$SRCDIR/bad-graph.dts" graph_endpoint + check_tests "$SRCDIR/bad-graph-root1.dts" graph_nodes + check_tests "$SRCDIR/bad-graph-root2.dts" graph_nodes + check_tests "$SRCDIR/bad-graph-root3.dts" graph_nodes + check_tests "$SRCDIR/bad-graph-root4.dts" graph_nodes run_sh_test "$SRCDIR/dtc-checkfails.sh" deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/bad-gpio.dts" run_sh_test "$SRCDIR/dtc-checkfails.sh" -n deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/good-gpio.dts" check_tests "$SRCDIR/bad-interrupt-cells.dts" interrupts_property From 0ac8b30ba5a112a616d0e9d482546e50bf7a6fdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 28 Apr 2023 11:35:50 +0200 Subject: [PATCH 169/298] yaml: Depend on libyaml >= 0.2.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit libyaml before 0.2.3 expects non-const string parameters. Supporting both variants would require either cpp magic or ignoring "discarded-qualifiers" compiler warnings. For the sake of simplicity just support libyaml 0.2.3 and newer. Note that NO_YAML can be overwritten on the make command line. Signed-off-by: Uwe Kleine-König --- Makefile | 6 +++++- meson.build | 2 +- tests/run_tests.sh | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 6ccee13..784e2f8 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,11 @@ else CFLAGS += $(shell $(PKG_CONFIG) --cflags valgrind) endif -NO_YAML := $(shell $(PKG_CONFIG) --exists yaml-0.1; echo $$?) +# libyaml before version 0.2.3 expects non-const string parameters. Supporting +# both variants would require either cpp magic or passing +# -Wno-error=discarded-qualifiers to the compiler. For the sake of simplicity +# just support libyaml >= 0.2.3. +NO_YAML := $(shell $(PKG_CONFIG) --atleast-version 0.2.3 yaml-0.1; echo $$?) ifeq ($(NO_YAML),1) CFLAGS += -DNO_YAML else diff --git a/meson.build b/meson.build index cef113f..4654803 100644 --- a/meson.build +++ b/meson.build @@ -42,7 +42,7 @@ else endif yamltree = 'yamltree.c' -yaml = dependency('yaml-0.1', required: get_option('yaml'), static: static_build) +yaml = dependency('yaml-0.1', version: '>=0.2.3', required: get_option('yaml'), static: static_build) if not yaml.found() add_project_arguments('-DNO_YAML', language: 'c') yamltree = [] diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 2af8c15..d7a6d49 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -32,7 +32,7 @@ if [ -n "$NO_YAML" ]; then no_yaml=false fi else - if pkg-config --exists yaml-0.1; then + if pkg-config --atleast-version 0.2.3 yaml-0.1; then no_yaml=false else no_yaml=true From c88038c9b8ca5515df44c1e86bdc4dfa4946f2b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 28 Apr 2023 09:18:25 +0200 Subject: [PATCH 170/298] Drop obsolete/broken CI definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (Free) Travis-ci is gone since November 2020, cirrus seems to be unreliable showing build breakages unrelated to changes. Signed-off-by: Uwe Kleine-König --- .cirrus.yml | 23 ------------------- .travis.yml | 65 ----------------------------------------------------- 2 files changed, 88 deletions(-) delete mode 100644 .cirrus.yml delete mode 100644 .travis.yml diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index d2dc34e..0000000 --- a/.cirrus.yml +++ /dev/null @@ -1,23 +0,0 @@ -env: - CIRRUS_CLONE_DEPTH: 1 - -freebsd_13_task: - freebsd_instance: - image: freebsd-13-0-release-amd64 - install_script: - pkg install -y bison gmake pkgconf - build_script: - gmake - test_script: - gmake check - -linux_gcc_task: - container: - image: gcc:latest - install_script: - - apt-get update - - apt-get -y install bison flex - build_script: - - make - test_script: - - make check diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a5163de..0000000 --- a/.travis.yml +++ /dev/null @@ -1,65 +0,0 @@ -language: c - -# Coverity Scan uploads -env: - global: - # COVERITY_SCAN_TOKEN (dgibson/dtc) - - secure: "vlHvXe618//IM9LQaKzqsrUbjs7ng0L9UCST4kJbJnFQDXvVe5JiSmJGd4ef7mm0NUv5bMRl2W3xCiu6BYAu/NvU3tMNHoLG+JgCJs0+wLJXbWOwji/NmH7olqgJG+CmpaCMXjARF6+nrTnBYHJL6cYyf4KVoV4B0I/hLUW91+s=" - -matrix: - include: - - addons: - apt: - packages: - - swig - - python-dev - - valgrind - - libyaml-0-2 - coverity_scan: - project: - name: dtc - description: Device Tree Compiler - notification_email: david@gibson.dropbear.id.au - build_command: make - branch_pattern: coverity_scan - script: - - make - - make check && make checkm - - # Check it builds properly without optional packages: - # python, valgrind, libyaml - - script: - - make - - make check - - - arch: arm64 - addons: - apt_packages: - - swig - - python-dev - - valgrind - - libyaml-0-2 - script: - - make - - make check checkm - - - arch: ppc64le - addons: - apt_packages: - - swig - - python-dev - - libyaml-0-2 - script: - - make - - make check - - - arch: s390x - addons: - apt_packages: - - swig - - python-dev - - valgrind - - libyaml-0-2 - script: - - make - - make check checkm From ab481e483061af6fa0023cfa7b7c0378dd944160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 28 Apr 2023 11:06:09 +0200 Subject: [PATCH 171/298] Add definition for a GitHub Actions CI job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The job just builds the full configuration on latest Ubuntu Signed-off-by: Uwe Kleine-König --- .github/workflows/build.yml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..6daaa8d --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,33 @@ +--- +name: Build test +'on': + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Install Dependencies + run: + sudo apt install + flex + libyaml-dev + pkg-config + python3-dev + swig + valgrind + bison + + - name: Build + run: make + + - name: Run check + run: make check From b2b9671583e9b006e69ec7a748fa168ef0c9dd52 Mon Sep 17 00:00:00 2001 From: Johannes Beisswenger Date: Wed, 10 May 2023 11:16:19 +0200 Subject: [PATCH 172/298] livetree: fix off-by-one in propval_cell_n() bounds check Signed-off-by: Johannes Beisswenger Signed-off-by: David Gibson --- livetree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/livetree.c b/livetree.c index 0ec47ed..49f7230 100644 --- a/livetree.c +++ b/livetree.c @@ -441,7 +441,7 @@ cell_t propval_cell(struct property *prop) cell_t propval_cell_n(struct property *prop, unsigned int n) { - assert(prop->val.len / sizeof(cell_t) >= n); + assert(prop->val.len / sizeof(cell_t) > n); return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n)); } From ea3b9a1d2c5af56c602fbfb1585536d5b21cb874 Mon Sep 17 00:00:00 2001 From: Johannes Beisswenger Date: Wed, 10 May 2023 11:22:07 +0200 Subject: [PATCH 173/298] checks: Fix crash in graph_child_address if 'reg' cell size != 1 If an endpoint node has a 'reg' property which consists of more than one cell (4 bytes) and given that matching '#address-cells' and '#size-cells' properties are specified on the port node an assertion is triggered in check_graph_child_address() before the relevant diagnostic checks in check_graph_reg() (called by check_graph_port() and check_graph_endpoint()) are executed. The issue is fixed by making graph_child_address depend on the graph_port and graph_endpoint checks. Additionally the assertion can also be triggered if the length of the 'reg' property is less than 4 bytes e.g. by specifying 'reg = "a";'. In that case however other warnings are produced highlighting the malformed property before dtc crashes. Example dts file triggering the issue: /dts-v1/; / { bar: bar { port { bar_con: endpoint { remote-endpoint = <&foo_con>; }; }; }; foo { port { #address-cells = <1>; #size-cells = <1>; // should always be 0 foo_con: endpoint@1 { reg = <1 2>; // causes assertion failure instead of diagnostic remote-endpoint = <&bar_con>; }; }; }; }; Signed-off-by: Johannes Beisswenger Signed-off-by: David Gibson --- checks.c | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/checks.c b/checks.c index 8ed7a60..c49ed51 100644 --- a/checks.c +++ b/checks.c @@ -1785,31 +1785,6 @@ static void check_graph_nodes(struct check *c, struct dt_info *dti, } WARNING(graph_nodes, check_graph_nodes, NULL); -static void check_graph_child_address(struct check *c, struct dt_info *dti, - struct node *node) -{ - int cnt = 0; - struct node *child; - - if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus) - return; - - for_each_child(node, child) { - struct property *prop = get_property(child, "reg"); - - /* No error if we have any non-zero unit address */ - if (prop && propval_cell(prop) != 0) - return; - - cnt++; - } - - if (cnt == 1 && node->addr_cells != -1) - FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary", - node->children->name); -} -WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes); - static void check_graph_reg(struct check *c, struct dt_info *dti, struct node *node) { @@ -1900,6 +1875,31 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti, } WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes); +static void check_graph_child_address(struct check *c, struct dt_info *dti, + struct node *node) +{ + int cnt = 0; + struct node *child; + + if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus) + return; + + for_each_child(node, child) { + struct property *prop = get_property(child, "reg"); + + /* No error if we have any non-zero unit address */ + if (prop && propval_cell(prop) != 0 ) + return; + + cnt++; + } + + if (cnt == 1 && node->addr_cells != -1) + FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary", + node->children->name); +} +WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes, &graph_port, &graph_endpoint); + static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &node_name_chars, &node_name_format, &property_name_chars, From d4888958d64bd9b3e0e2e6582af665f9b81706c9 Mon Sep 17 00:00:00 2001 From: Johannes Beisswenger Date: Wed, 10 May 2023 11:40:53 +0200 Subject: [PATCH 174/298] tests: Add additional tests for device graph checks * bad-graph-child-address.dts: additional child address test since the one in bad-graph.dts is now shadowed by its prerequisites also failing. * bad-graph-reg-cells.dts: test warnings produced by check_graph_reg(). Signed-off-by: Johannes Beisswenger Signed-off-by: David Gibson --- tests/bad-graph-child-address.dts | 22 +++++++++++++++++++ tests/bad-graph-reg-cells.dts | 36 +++++++++++++++++++++++++++++++ tests/run_tests.sh | 3 +++ 3 files changed, 61 insertions(+) create mode 100644 tests/bad-graph-child-address.dts create mode 100644 tests/bad-graph-reg-cells.dts diff --git a/tests/bad-graph-child-address.dts b/tests/bad-graph-child-address.dts new file mode 100644 index 0000000..f0ae26c --- /dev/null +++ b/tests/bad-graph-child-address.dts @@ -0,0 +1,22 @@ +/dts-v1/; + / { + bar: bar { + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + bar_con: endpoint { + remote-endpoint = <&foo_con>; + }; + }; + }; + }; + foo { + port { + foo_con: endpoint { + remote-endpoint = <&bar_con>; + }; + }; + }; +}; diff --git a/tests/bad-graph-reg-cells.dts b/tests/bad-graph-reg-cells.dts new file mode 100644 index 0000000..0533db0 --- /dev/null +++ b/tests/bad-graph-reg-cells.dts @@ -0,0 +1,36 @@ +/dts-v1/; + / { + bar: bar { + ports { + #address-cells = <1>; + #size-cells = <1>; // should always be 0 + port@1 { + reg = <1 2>; // should always contain only a single cell + bar_con: endpoint { + remote-endpoint = <&foo_con>; + }; + }; + port@2 { + reg = <2>; + bar_con2: endpoint { + remote-endpoint = <&foo_con2>; + }; + }; + }; + }; + foo { + port { + #address-cells = <1>; + #size-cells = <1>; // should always be 0 + foo_con: endpoint@1 { + reg = <1 2>; // should always contain only a single cell + remote-endpoint = <&bar_con>; + }; + foo_con2: endpoint@2 { + reg = <2>; + remote-endpoint = <&bar_con2>; + }; + }; + + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index d7a6d49..8aa1f89 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -734,6 +734,9 @@ dtc_tests () { check_tests "$SRCDIR/bad-graph-root2.dts" graph_nodes check_tests "$SRCDIR/bad-graph-root3.dts" graph_nodes check_tests "$SRCDIR/bad-graph-root4.dts" graph_nodes + check_tests "$SRCDIR/bad-graph-reg-cells.dts" graph_endpoint + check_tests "$SRCDIR/bad-graph-reg-cells.dts" graph_port + check_tests "$SRCDIR/bad-graph-child-address.dts" graph_child_address run_sh_test "$SRCDIR/dtc-checkfails.sh" deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/bad-gpio.dts" run_sh_test "$SRCDIR/dtc-checkfails.sh" -n deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/good-gpio.dts" check_tests "$SRCDIR/bad-interrupt-cells.dts" interrupts_property From 3b02a94b486f998aa22d898b427820a805d0904f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 14 May 2023 16:27:27 +1000 Subject: [PATCH 175/298] dtc: Correct invalid dts output with mixed phandles and integers The handling of "type preservation" dts output is based on the idea of "phandles with arguments" in properties, which isn't really a thing, other than a fairly common convention about how bindings are written. There's nothing preventing a binding which freely mixes phandles and other integers in an array of cells. Currently write_propval() handles this incorrectly: specifically the case of a phandle which follows a regular integer in a 32-bit cell array, but without a new '< >' delimited causing an extra TYPE_UINT32 marker to be inserted. In this case it omits the necessary space between the integer and the phandle reference, leading to output which can't be sent back into dtc and parsed. Correct this, and update tests to match. I think this is more or less correct for now, but really write_propval() is a big mess :(. Signed-off-by: David Gibson --- tests/type-preservation.dt.yaml | 1 + tests/type-preservation.dts | 1 + treesource.c | 2 ++ 3 files changed, 4 insertions(+) diff --git a/tests/type-preservation.dt.yaml b/tests/type-preservation.dt.yaml index a0cc64c..ae5efcf 100644 --- a/tests/type-preservation.dt.yaml +++ b/tests/type-preservation.dt.yaml @@ -15,6 +15,7 @@ a-string-with-nulls: ["foo\0bar", "baz"] a-phandle: [[!phandle 0x1]] a-phandle-with-args: [[!phandle 0x1, 0x0, 0x1], [!phandle 0x1, 0x2, 0x3]] + mixed-ints-and-phandles: [[0x1, !phandle 0x1, 0x2, !phandle 0x1]] subsubnode: compatible: ["subsubnode1", "subsubnode"] phandle: [[0x1]] diff --git a/tests/type-preservation.dts b/tests/type-preservation.dts index 921ea21..9802fab 100644 --- a/tests/type-preservation.dts +++ b/tests/type-preservation.dts @@ -18,6 +18,7 @@ a-string-with-nulls = "foo\0bar", "baz"; a-phandle = <&subsub1>; a-phandle-with-args = <&subsub1 0x00 0x01>, <&subsub1 0x02 0x03>; + mixed-ints-and-phandles = <0x01 &subsub1 0x02 &subsub1>; subsub1: subsubnode { compatible = "subsubnode1", "subsubnode"; diff --git a/treesource.c b/treesource.c index 33fedee..9b17b37 100644 --- a/treesource.c +++ b/treesource.c @@ -241,6 +241,8 @@ static void write_propval(FILE *f, struct property *prop) } else { write_propval_int(f, p, chunk_len, 4); } + if (data_len > chunk_len) + fputc(' ', f); break; case TYPE_UINT64: write_propval_int(f, p, chunk_len, 8); From e8364666d5acc985c434fb574e92c5206d9a8d6b Mon Sep 17 00:00:00 2001 From: Biswapriyo Nath Date: Mon, 15 May 2023 00:42:45 +0530 Subject: [PATCH 176/298] CI: Add build matrix with multiple Linux distributions set SETUPTOOLS_SCM_PRETEND_VERSION="0" variable because GitHub Actions does not copy the .git directory into the container. Without that, the build fails with the following error LookupError: setuptools-scm was unable to detect version for /__w/dtc/dtc. Signed-off-by: Biswapriyo Nath Signed-off-by: David Gibson --- .github/workflows/build.yml | 28 ++++++++++++++++------------ scripts/install-deps.sh | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 12 deletions(-) create mode 100755 scripts/install-deps.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6daaa8d..442d98b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,22 +12,26 @@ jobs: build: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + os: [ "alpine", "archlinux", "fedora", "ubuntu" ] + + container: + image: ${{ matrix.os }} + steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v3 - name: Install Dependencies - run: - sudo apt install - flex - libyaml-dev - pkg-config - python3-dev - swig - valgrind - bison + run: | + ./scripts/install-deps.sh - name: Build - run: make + run: | + SETUPTOOLS_SCM_PRETEND_VERSION="0" make - name: Run check - run: make check + run: | + SETUPTOOLS_SCM_PRETEND_VERSION="0" make check diff --git a/scripts/install-deps.sh b/scripts/install-deps.sh new file mode 100755 index 0000000..4076310 --- /dev/null +++ b/scripts/install-deps.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later + +if [ -f /etc/os-release ] +then + . /etc/os-release +else + echo "ERROR: OS name is not provided." + exit 1 +fi + +if [ "$NAME" = "Arch Linux" ] +then + pacman -Syu --needed --noconfirm bison diffutils flex gcc git libyaml \ + make pkgconf python python-setuptools-scm swig valgrind which +elif [ "$NAME" = "Alpine Linux" ] +then + apk add build-base bison coreutils flex git yaml yaml-dev python3-dev \ + py3-setuptools_scm swig valgrind +elif [ "$NAME" = "Fedora Linux" ] +then + dnf install -y bison diffutils flex gcc git libyaml libyaml-devel \ + make python3-devel python3-setuptools swig valgrind which +elif [ "$NAME" = "Ubuntu" ] +then + apt update + apt install -yq build-essential bison flex git libyaml-dev pkg-config \ + python3-dev python3-setuptools python3-setuptools-scm swig valgrind +else + echo "ERROR: OS name is not provided." + exit 1 +fi From 589d8c7653c75d789c6e47d69a4f5bb089aecd5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 23 May 2023 10:09:41 +0200 Subject: [PATCH 177/298] dtc: Add an option to generate __local_fixups__ and __fixups__ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This records detailed usage of labels in a dtb. This is needed in overlays (and enabled implicitly for these). For ordinary device trees it can be used to restore labels when compiling back to dts format. Signed-off-by: Uwe Kleine-König Message-Id: <20230523080941.419330-1-u.kleine-koenig@pengutronix.de> Signed-off-by: David Gibson --- Documentation/manual.txt | 14 ++++++++++++++ dtc.c | 8 +++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Documentation/manual.txt b/Documentation/manual.txt index 15a7837..598c6e6 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -126,6 +126,20 @@ Options: property for each label. The property's name is the label name and the value is the path of the labeled node. + -L + Possibly generates a __local_fixups__ and a __fixups__ node at the root node. + For each property that contains a phandle reference using a locally + defined phandle, the __local_fixups__ node contains a property (at path + /__local_fixups__/$a if $a is the path of the node). Its value is a list + of offsets that are phandle values. If there are no such properties, no + __local_fixups__ node is generated. + For each undefined label used in at least one reference, the __fixups__ + node contains a property. Its name is the label name, its value is a + list of locations where the label is used in a reference in the format + "path:property:offset". If there is no undefined label, no __fixups__ + nodes is generated. + Enabled by default for compiling overlays (i.e. dts files with a + /plugin/ tag). -A Generate automatically aliases for all node labels. This is similar to diff --git a/dtc.c b/dtc.c index bc786c5..d2e4e2b 100644 --- a/dtc.c +++ b/dtc.c @@ -47,7 +47,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix) /* Usage related data. */ static const char usage_synopsis[] = "dtc [options] "; -static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv"; +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@LAThv"; static struct option const usage_long_opts[] = { {"quiet", no_argument, NULL, 'q'}, {"in-format", a_argument, NULL, 'I'}, @@ -67,6 +67,7 @@ static struct option const usage_long_opts[] = { {"warning", a_argument, NULL, 'W'}, {"error", a_argument, NULL, 'E'}, {"symbols", no_argument, NULL, '@'}, + {"local-fixups", no_argument, NULL, 'L'}, {"auto-alias", no_argument, NULL, 'A'}, {"annotate", no_argument, NULL, 'T'}, {"help", no_argument, NULL, 'h'}, @@ -252,6 +253,11 @@ int main(int argc, char *argv[]) case '@': generate_symbols = 1; break; + + case 'L': + generate_fixups = 1; + break; + case 'A': auto_label_aliases = 1; break; From 71a8b8ef0adf01af4c78c739e04533a35c1dc89c Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Wed, 31 May 2023 11:41:42 -0300 Subject: [PATCH 178/298] libfdt: meson: Fix linking on macOS linker -undefined error is the equivalent of --no-undefined for the macOS linker, but -undefined would also be understood as a valid argument for GNU ld so we use the supported linker variant. Signed-off-by: Otavio Salvador Signed-off-by: David Gibson --- libfdt/meson.build | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libfdt/meson.build b/libfdt/meson.build index 240bdf4..e1bf083 100644 --- a/libfdt/meson.build +++ b/libfdt/meson.build @@ -16,10 +16,20 @@ sources = files( 'fdt_wip.c', ) +link_args = [] +if cc.has_link_argument('-Wl,--no-undefined') + link_args += '-Wl,--no-undefined' +else + # -undefined error is the equivalent of --no-undefined for the macOS linker, + # but -undefined would also be understood as a valid argument for GNU ld! + link_args += cc.get_supported_link_arguments('-Wl,-undefined,error') +endif + +link_args += version_script libfdt = library( 'fdt', sources, version: '1.6.0', - link_args: ['-Wl,--no-undefined', version_script], + link_args: link_args, link_depends: 'version.lds', install: true, ) From ccf1f62d59adc933fb348b866f351824cdd00c73 Mon Sep 17 00:00:00 2001 From: Yan-Jie Wang Date: Thu, 8 Jun 2023 14:39:05 +0800 Subject: [PATCH 179/298] libfdt: Fix a typo in libfdt.h The function mentioned in the comment, fdt_finished(), should be changed to fdt_finish(). Signed-off-by: Yan-Jie Wang Signed-off-by: David Gibson --- libfdt/libfdt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 34c4d55..2a4f32c 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1511,7 +1511,7 @@ int fdt_nop_node(void *fdt, int nodeoffset); * fdt_create_with_flags() begins the process of creating a new fdt with * the sequential write interface. * - * fdt creation process must end with fdt_finished() to produce a valid fdt. + * fdt creation process must end with fdt_finish() to produce a valid fdt. * * returns: * 0, on success From 6df5328a902cf719495ea8a07da383172e358fff Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 27 Jul 2023 13:23:28 +0200 Subject: [PATCH 180/298] Fix use of functions The value passed to the functions shall be the value of an unsigned char or EOF. It is implementation-defined if the char type is signed or unsigned. Cast to unsigned char to avoid undefined behaviour on systems where char is signed. This cast is already present in other parts of the code base. Signed-off-by: Sebastian Huber Signed-off-by: David Gibson --- checks.c | 2 +- yamltree.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/checks.c b/checks.c index c49ed51..2fb7ee5 100644 --- a/checks.c +++ b/checks.c @@ -1182,7 +1182,7 @@ static void check_unit_address_format(struct check *c, struct dt_info *dti, /* skip over 0x for next test */ unitname += 2; } - if (unitname[0] == '0' && isxdigit(unitname[1])) + if (unitname[0] == '0' && isxdigit((unsigned char)unitname[1])) FAIL(c, dti, node, "unit name should not have leading 0s"); } WARNING(unit_address_format, check_unit_address_format, NULL, diff --git a/yamltree.c b/yamltree.c index 0cb16ed..25fd25e 100644 --- a/yamltree.c +++ b/yamltree.c @@ -102,7 +102,7 @@ static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len) /* Make sure the entire string is in the lower 7-bit ascii range */ for (i = 0; i < len; i++) - assert(isascii(str[i])); + assert(isascii((unsigned char)str[i])); yaml_scalar_event_initialize(&event, NULL, (const yaml_char_t *)YAML_STR_TAG, (const yaml_char_t*)str, From f088e381f29eb09bcd9599a942eb4b77949526f5 Mon Sep 17 00:00:00 2001 From: Nicolas Escande Date: Wed, 26 Jul 2023 16:43:11 +0200 Subject: [PATCH 181/298] Makefile: allow to install libfdt without building executables When we only need the libfdt calling the target install-lib also builds the executables listed in $(BINS) because this target depends on all Instead lets make install-lib only depend on libfdt. Signed-off-by: Nicolas Escande Message-ID: <20230726144336.677135-1-nico.escande@gmail.com> Reviewed-by: Simon Glass Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 784e2f8..c0b68a2 100644 --- a/Makefile +++ b/Makefile @@ -238,7 +238,7 @@ install-bin: all $(SCRIPTS) $(INSTALL_PROGRAM) $(BIN) $(DESTDIR)$(BINDIR) $(INSTALL_SCRIPT) $(SCRIPTS) $(DESTDIR)$(BINDIR) -install-lib: all +install-lib: libfdt @$(VECHO) INSTALL-LIB $(INSTALL) -d $(DESTDIR)$(LIBDIR) $(INSTALL_LIB) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) From bdc5c8793a13abb8846d115b7923df87605d05bd Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Thu, 1 Jun 2023 10:12:50 -0300 Subject: [PATCH 182/298] meson: allow disabling tests The new meson build system support diverges from former build system where the tests were not built until required. This has caused an issue in NixOS[1] due to broken build of tests in Darwin platform, so this patch allows the control if tests should be build or not. 1. https://github.com/NixOS/nixpkgs/pull/235210 Signed-off-by: Otavio Salvador Signed-off-by: David Gibson --- meson.build | 8 ++++---- meson_options.txt | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/meson.build b/meson.build index 4654803..bf70f29 100644 --- a/meson.build +++ b/meson.build @@ -134,8 +134,8 @@ if not meson.is_cross_build() if py.found() and swig.found() subdir('pylibfdt') endif - - if get_option('tools') - subdir('tests') - endif +endif + +if get_option('tests') + subdir('tests') endif diff --git a/meson_options.txt b/meson_options.txt index 82621c3..36f391a 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -10,3 +10,5 @@ option('python', type: 'feature', value: 'auto', description: 'Build pylibfdt Python library') option('static-build', type: 'boolean', value: false, description: 'Build static binaries') +option('tests', type: 'boolean', value: true, + description: 'Build tests') From 4c68e4b16b22a8eb9c2dc39086f25c2d1375d049 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Sat, 29 Jul 2023 19:53:26 +0000 Subject: [PATCH 183/298] libfdt: fix library version to match project version Build the libfdt with the correct version number by pulling the version from the top-level project. Change as suggested from https://github.com/dgibson/dtc/pull/95#issuecomment-1546933095 Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- libfdt/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/meson.build b/libfdt/meson.build index e1bf083..2ea1448 100644 --- a/libfdt/meson.build +++ b/libfdt/meson.build @@ -28,7 +28,7 @@ endif link_args += version_script libfdt = library( 'fdt', sources, - version: '1.6.0', + version: meson.project_version(), link_args: link_args, link_depends: 'version.lds', install: true, From bf6377a98d977116f14c438ff2f20d670b6d247a Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Sat, 29 Jul 2023 19:30:47 +0000 Subject: [PATCH 184/298] meson: set minimum Meson version to 0.56.0 Set the minimum required version of Meson based on the highest version feature used, as detected by meson-setup. * 0.56.0: {'meson.project_build_root'} Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/meson.build b/meson.build index bf70f29..8f5fea5 100644 --- a/meson.build +++ b/meson.build @@ -2,6 +2,7 @@ project('dtc', 'c', version: '1.7.0', license: ['GPL2+', 'BSD-2'], default_options: 'werror=true', + meson_version: '>=0.56.0' ) cc = meson.get_compiler('c') From 761114effaf7216d8d7fc51d8810f2eb27682db8 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Tue, 1 Aug 2023 21:54:30 +0000 Subject: [PATCH 185/298] pylibtfdt: fix use of deprecated meson method Fixes the following warning > pylibfdt/meson.build:2: WARNING: Project targets '>=0.56.0' but uses feature deprecated since '0.55.0': ExternalProgram.path. use ExternalProgram.full_path() instead Do not use full_path() as suggested. setup_py is being called as a command by custom_target() which understands how to properly inherit the object returned by find_program(). Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- pylibfdt/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build index f684cbb..b3f5ebd 100644 --- a/pylibfdt/meson.build +++ b/pylibfdt/meson.build @@ -1,5 +1,5 @@ setup_py = find_program('../setup.py') -setup_py = [setup_py.path(), '--quiet', '--top-builddir', meson.project_build_root()] +setup_py = [setup_py, '--quiet', '--top-builddir', meson.project_build_root()] custom_target( 'pylibfdt', From 8d8372b13706514fada1415cb4b29a0ab0235d07 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Tue, 1 Aug 2023 21:54:30 +0000 Subject: [PATCH 186/298] tests: fix use of deprecated meson methods Fixes the following warnings > tests/meson.build:123: WARNING: Project targets '>=0.56.0' but uses feature deprecated since '0.55.0': ExternalProgram.path. use ExternalProgram.full_path() instead > tests/meson.build:124: WARNING: Project targets '>=0.56.0' but uses feature deprecated since '0.56.0': meson.source_root. use meson.project_source_root() or meson.global_source_root() instead. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- tests/meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/meson.build b/tests/meson.build index 29a42dd..fe10fa2 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -120,8 +120,8 @@ if not py.found() env += 'NO_PYTHON=1' else env += [ - 'PYTHON=' + py.path(), - 'PYTHONPATH=' + meson.source_root() / 'pylibfdt', + 'PYTHON=' + py.full_path(), + 'PYTHONPATH=' + meson.project_source_root() / 'pylibfdt', ] endif if not yaml.found() From d030a893be259795e7f3a791d84c262b6419ce20 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Tue, 1 Aug 2023 19:58:04 +0000 Subject: [PATCH 187/298] tests: generate dtbs in Meson build directory When running under Meson, check_tests() is generating dtb build files in the source directory. This is because dtb is named by appending ".test.dtb" to the full source file name. Use basename to extract just the source filename and write it to the working directory which is the build directory. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- tests/run_tests.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 8aa1f89..c4f8b9b 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -373,9 +373,10 @@ tree1_tests_rw () { check_tests () { tree="$1" shift + dtb=$(basename "$tree" .dts).test.dtb run_sh_test "$SRCDIR/dtc-checkfails.sh" "$@" -- -I dts -O dtb $tree - run_dtc_test -I dts -O dtb -o $tree.test.dtb -f $tree - run_sh_test "$SRCDIR/dtc-checkfails.sh" "$@" -- -I dtb -O dtb $tree.test.dtb + run_dtc_test -I dts -O dtb -o "$dtb" -f $tree + run_sh_test "$SRCDIR/dtc-checkfails.sh" "$@" -- -I dtb -O dtb "$dtb" } ALL_LAYOUTS="mts mst tms tsm smt stm" From 5e98b59793542df2731d5b3e5f13b23529208499 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Fri, 4 Aug 2023 02:14:21 +0000 Subject: [PATCH 188/298] editorconfig: use tab indentation for version.lds This file is indented with tabs, but editorconfig defaults all files to spaces. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- .editorconfig | 3 +++ libfdt/version.lds | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index d7e68fb..4ba0212 100644 --- a/.editorconfig +++ b/.editorconfig @@ -28,3 +28,6 @@ indent_size = 4 [meson.build] indent_style = space indent_size = 2 + +[*.lds] +indent_style = tab diff --git a/libfdt/version.lds b/libfdt/version.lds index cbce5d4..558a608 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -20,7 +20,7 @@ LIBFDT_1.2 { fdt_get_alias_namelen; fdt_get_alias; fdt_get_path; - fdt_header_size; + fdt_header_size; fdt_supernode_atdepth_offset; fdt_node_depth; fdt_parent_offset; From 38165954c13bdc0efe40593c252de418e6521fe2 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Fri, 4 Aug 2023 02:14:57 +0000 Subject: [PATCH 189/298] libfdt: add missing version symbols These symbols were not added to the version script when they were added to libfdt. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- libfdt/version.lds | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libfdt/version.lds b/libfdt/version.lds index 558a608..989cd89 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -78,6 +78,8 @@ LIBFDT_1.2 { fdt_setprop_inplace_namelen_partial; fdt_create_with_flags; fdt_overlay_target_offset; + fdt_get_symbol; + fdt_get_symbol_namelen; local: *; }; From 0f5864567745c50e481b132538969b87259891e3 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Tue, 1 Aug 2023 23:45:55 +0000 Subject: [PATCH 190/298] move release version into VERSION.txt To synchronize the release version of the Makefile and Meson build systems, pull the version info from a shared file. Meson requires that the shared library version follow the X.Y.Z numbering scheme. But the Makefile supported building shared libraries with an EXTRAVERSION appended, for example X.Y.Z-rc1. We want to keep the output of both systems the same to avoid issues, so we drop support for the Makefile EXTRAVERSION. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- Makefile | 8 ++------ VERSION.txt | 1 + meson.build | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) create mode 100644 VERSION.txt diff --git a/Makefile b/Makefile index c0b68a2..fc4a133 100644 --- a/Makefile +++ b/Makefile @@ -5,14 +5,11 @@ # # Version information will be constructed in this order: -# EXTRAVERSION might be "-rc", for example. +# DTC_VERSION release version as MAJOR.MINOR.PATCH # LOCAL_VERSION is likely from command line. # CONFIG_LOCALVERSION from some future config system. # -VERSION = 1 -PATCHLEVEL = 7 -SUBLEVEL = 0 -EXTRAVERSION = +DTC_VERSION = $(shell cat VERSION.txt) LOCAL_VERSION = CONFIG_LOCALVERSION = @@ -103,7 +100,6 @@ endif # Rules for versioning # -DTC_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) VERSION_FILE = version_gen.h CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ diff --git a/VERSION.txt b/VERSION.txt new file mode 100644 index 0000000..bd8bf88 --- /dev/null +++ b/VERSION.txt @@ -0,0 +1 @@ +1.7.0 diff --git a/meson.build b/meson.build index 8f5fea5..17cb135 100644 --- a/meson.build +++ b/meson.build @@ -1,8 +1,8 @@ project('dtc', 'c', - version: '1.7.0', + version: files('VERSION.txt'), license: ['GPL2+', 'BSD-2'], default_options: 'werror=true', - meson_version: '>=0.56.0' + meson_version: '>=0.57.0' ) cc = meson.get_compiler('c') From cd3e2304f4a9c4f725dcc548082ccc6c89d078a4 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Wed, 2 Aug 2023 18:44:28 +0000 Subject: [PATCH 191/298] pylibfdt: use fallback version in tarballs When building pylibfdt from the released tarballs[1] setup.py will fail with the following. > LookupError: setuptools-scm was unable to detect version for dtc. > Make sure you're either building from a fully intact git repository or > PyPI tarballs. Most other sources (such as GitHub's tarballs, a git > checkout without the .git folder) don't contain the necessary metadata > and will not work. seutptools_scm supports a 'fallback_version' that will use the provided string as the version when the git repo is not available. [1] https://www.kernel.org/pub/software/utils/dtc/dtc-1.7.0.tar.xz Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- setup.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup.py b/setup.py index e82a832..c3ffb2b 100755 --- a/setup.py +++ b/setup.py @@ -22,6 +22,9 @@ srcdir = os.path.dirname(__file__) with open(os.path.join(srcdir, "README.md"), "r") as fh: long_description = fh.read() +with open(os.path.join(srcdir, "VERSION.txt"), "r") as fh: + version = fh.readline().strip() + def get_top_builddir(): if '--top-builddir' in sys.argv: index = sys.argv.index('--top-builddir') @@ -51,6 +54,8 @@ setup( name='libfdt', use_scm_version={ "root": srcdir, + "fallback_version": version, + "fallback_root": srcdir, }, cmdclass = {'build_py' : build_py}, setup_requires = ['setuptools_scm'], From 35019949c4c72cfe4d9a95db7108758d2c7944a1 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Wed, 2 Aug 2023 20:50:17 +0000 Subject: [PATCH 192/298] workflows: build: remove setuptools_scm hack The SETUPTOOLS_SCM_PRETEND_VERSION was needed as ./setup.py would fail without it. As setuptools_scm will fail if there is not git repo, and the github workflow container does not include the source code git repo. A previous commit added "fallback_version" to setuptools_scm which instructs it to use the version from VERSION.txt when the git repo is missing. So this hack is no longer needed. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 442d98b..c8db026 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,8 +30,8 @@ jobs: - name: Build run: | - SETUPTOOLS_SCM_PRETEND_VERSION="0" make + make - name: Run check run: | - SETUPTOOLS_SCM_PRETEND_VERSION="0" make check + make check From a3dc9f006a783bc0267784772e21a54cb54d85cf Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Fri, 4 Aug 2023 15:48:27 +0000 Subject: [PATCH 193/298] libfdt: rename libfdt-X.Y.Z.so to libfdt.so.X.Y.Z The Meson build system requires that the generated shared library uses the libfdt.so.X.Y.Z naming scheme. But the Makefile is generating libfdt-X.Y.Z.so. We want to keep the output of both systems the same to avoid issues, so we rename the Makefile to match Meson. Additionally, Meson generates the base "libfdt.so -> libfdt.so.1" symlink which the Makefile hasn't been doing, add that as well. This shouldn't impact existing users as the linker should be looking for libfdt.so.1 which won't change and will still point to the correct file. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- .gitignore | 1 + Makefile | 1 + libfdt/Makefile.libfdt | 6 +++++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 416fa05..8fdf112 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.a *.patch *.so +*.so.* *~ *.bak *.tab.[ch] diff --git a/Makefile b/Makefile index fc4a133..10a56d4 100644 --- a/Makefile +++ b/Makefile @@ -218,6 +218,7 @@ $(LIBFDT_lib): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) $(LIBFDT_version) $(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) \ $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) ln -sf $(LIBFDT_LIB) $(LIBFDT_dir)/$(LIBFDT_soname) + ln -sf $(LIBFDT_soname) $(LIBFDT_dir)/$(LIBFDT_so) ifneq ($(DEPTARGETS),) -include $(LIBFDT_OBJS:%.o=$(LIBFDT_dir)/%.d) diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index b6d8fc0..b763b2e 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -4,15 +4,19 @@ # This is not a complete Makefile of itself. Instead, it is designed to # be easily embeddable into other systems of Makefiles. # + +LIBFDT_so = libfdt.$(SHAREDLIB_EXT) LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h LIBFDT_VERSION = version.lds LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \ fdt_addresses.c fdt_overlay.c fdt_check.c LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) -LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) +LIBFDT_LIB = libfdt.$(SHAREDLIB_EXT).$(DTC_VERSION) libfdt_clean: @$(VECHO) CLEAN "(libfdt)" rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%) + rm -f $(LIBFDT_dir)/$(LIBFDT_so) rm -f $(LIBFDT_dir)/$(LIBFDT_soname) + rm -f $(LIBFDT_dir)/$(LIBFDT_LIB) From 6c5e189fb9527c4f69f8bd80e34eb24878795c47 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Sat, 2 Sep 2023 10:19:31 -0500 Subject: [PATCH 194/298] github: add workflow for Meson builds Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- .github/workflows/build.yml | 30 +++++++++++++++++++++++++++++- scripts/install-deps.sh | 8 ++++---- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c8db026..be23b9f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ name: Build test - main jobs: - build: + build-make: runs-on: ubuntu-latest strategy: @@ -35,3 +35,31 @@ jobs: - name: Run check run: | make check + + build-meson: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + os: [ "alpine", "archlinux", "fedora", "ubuntu" ] + + container: + image: ${{ matrix.os }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install Dependencies + run: | + ./scripts/install-deps.sh + + - name: Setup + run: meson setup build + + - name: Build + run: meson compile -C build + + - name: Run check + run: meson test -C build diff --git a/scripts/install-deps.sh b/scripts/install-deps.sh index 4076310..12507de 100755 --- a/scripts/install-deps.sh +++ b/scripts/install-deps.sh @@ -12,20 +12,20 @@ fi if [ "$NAME" = "Arch Linux" ] then pacman -Syu --needed --noconfirm bison diffutils flex gcc git libyaml \ - make pkgconf python python-setuptools-scm swig valgrind which + make meson pkgconf python python-setuptools-scm swig valgrind which elif [ "$NAME" = "Alpine Linux" ] then apk add build-base bison coreutils flex git yaml yaml-dev python3-dev \ - py3-setuptools_scm swig valgrind + meson py3-setuptools_scm swig valgrind elif [ "$NAME" = "Fedora Linux" ] then dnf install -y bison diffutils flex gcc git libyaml libyaml-devel \ - make python3-devel python3-setuptools swig valgrind which + make meson python3-devel python3-setuptools swig valgrind which elif [ "$NAME" = "Ubuntu" ] then apt update apt install -yq build-essential bison flex git libyaml-dev pkg-config \ - python3-dev python3-setuptools python3-setuptools-scm swig valgrind + meson python3-dev python3-setuptools python3-setuptools-scm swig valgrind else echo "ERROR: OS name is not provided." exit 1 From ad8bf9f9aa39625d732b7db16badecc0842750e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= Date: Thu, 31 Aug 2023 13:39:18 +0100 Subject: [PATCH 195/298] libfdt: Fix fdt_appendprop_addrrange documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the documentation, the function should default to the very common property name when none is "specified". However, neither passing NULL (ends up calling strlen(NULL) and segfaults) nor "" (appends a property with an empty name) implements this behavior. Furthermore, the test case supposed to cover this default value actually passes the value to the function, somewhat defeating its own purpose: /* 2. default property name */ // ... err = fdt_appendprop_addrrange(fdt, 0, offset, "reg", addr, size); if (err) FAIL("Failed to set \"reg\": %s", fdt_strerror(err)); check_getprop_addrrange(fdt, 0, offset, "reg", 1); Finally, nothing in the implementation of the function seems to attempt to cover that use-case. As the feature can't ever have been used by clients and as the resulting reduced readability of the caller seems (IMO) to outweigh any potential benefit this API would bring, remove the erroneous documentation instead of trying to fix the function. Reported-by: Mostafa Saleh Signed-off-by: Pierre-Clément Tosi Message-ID: <20230831123918.rf54emwkzgtcb7aw@google.com> Signed-off-by: David Gibson --- libfdt/libfdt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 2a4f32c..0677fea 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -2029,7 +2029,7 @@ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, * address and size) to the value of the named property in the given * node, or creates a new property with that value if it does not * already exist. - * If "name" is not specified, a default "reg" is used. + * * Cell sizes are determined by parent's #address-cells and #size-cells. * * This function may insert data into the blob, and will therefore From d774337275666e013a5930aebace1c6f76e343b1 Mon Sep 17 00:00:00 2001 From: Charles Perry Date: Mon, 4 Sep 2023 07:31:03 -0700 Subject: [PATCH 196/298] dtc: fix missing string in usage_opts_help This fixes the output of the `dtc --help` command as the last few entries were offset by one. Signed-off-by: Charles Perry Message-ID: <20230904143104.1941715-1-charles.perry@savoirfairelinux.com> Signed-off-by: David Gibson --- dtc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dtc.c b/dtc.c index d2e4e2b..0655c2e 100644 --- a/dtc.c +++ b/dtc.c @@ -105,6 +105,7 @@ static const char * const usage_opts_help[] = { "\n\tEnable/disable warnings (prefix with \"no-\")", "\n\tEnable/disable errors (prefix with \"no-\")", "\n\tEnable generation of symbols", + "\n\tPossibly generates a __local_fixups__ and a __fixups__ node at the root node", "\n\tEnable auto-alias of labels", "\n\tAnnotate output .dts with input source file and line (-T -T for more details)", "\n\tPrint this help and exit", From 52157f13ef3d45984ab17fd79bf0d9c69b57ae66 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 12 Sep 2023 12:27:13 -0600 Subject: [PATCH 197/298] pylibfdt: Support boolean properties Boolean properties are unusual in that their presense or absence indicates the value of the property. This makes them a little painful to support using the existing getprop() support. Add new methods to deal with booleans specifically. Signed-off-by: Simon Glass Message-ID: <20230912182716.248253-1-sjg@chromium.org> Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 55 +++++++++++++++++++++++++++++++++++++++++ tests/pylibfdt_tests.py | 33 +++++++++++++++++++++++++ tests/test_props.dts | 1 + 3 files changed, 89 insertions(+) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 2361e22..0b50983 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -419,6 +419,35 @@ class FdtRo(object): return pdata return Property(prop_name, bytearray(pdata[0])) + def hasprop(self, nodeoffset, prop_name, quiet=()): + """Check if a node has a property + + This can be used to check boolean properties + + Args: + nodeoffset: Node offset containing property to check + prop_name: Name of property to check + quiet: Errors to ignore (empty to raise on all errors). Note that + NOTFOUND is added internally by this function so need not be + provided + + Returns: + True if the property exists in the node, else False. If an error + other than -NOTFOUND is returned by fdt_getprop() then the error + is return (-ve integer) + + Raises: + FdtError if any error occurs other than NOTFOUND (e.g. the + nodeoffset is invalid) + """ + pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), + quiet + (NOTFOUND,)) + if isinstance(pdata, (int)): + if pdata == -NOTFOUND: + return False + return pdata + return True + def get_phandle(self, nodeoffset): """Get the phandle of a node @@ -605,6 +634,32 @@ class Fdt(FdtRo): return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val, len(val)), quiet) + def setprop_bool(self, nodeoffset, prop_name, val, quiet=()): + """Set the boolean value of a property + + Either: + adds the property if not already present; or + deletes the property if present + + Args: + nodeoffset: Node offset containing the property to create/delete + prop_name: Name of property + val: Boolean value to write (i.e. True or False) + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + Error code, or 0 if OK + + Raises: + FdtException if no parent found or other error occurs + """ + exists = self.hasprop(nodeoffset, prop_name, quiet) + if val != exists: + if val: + return self.setprop(nodeoffset, prop_name, b'', quiet=quiet) + else: + return self.delprop(nodeoffset, prop_name, quiet=quiet) + def setprop_u32(self, nodeoffset, prop_name, val, quiet=()): """Set the value of a property diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 34c2764..a4f73ed 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -496,6 +496,39 @@ class PyLibfdtBasicTests(unittest.TestCase): self.assertEqual(TEST_STRING_3, self.fdt.getprop(node, prop).as_str()) + def testHasProp(self): + """Test that we can check if a node has a property""" + node = 0 + self.assertFalse(self.fdt2.hasprop(node, 'missing')) + self.assertTrue(self.fdt2.hasprop(node, 'prop-bool')) + + # Test a property with a non-empty value + self.assertTrue(self.fdt2.hasprop(node, 'prop-uint64')) + + def testSetPropBool(self): + """Test that we can update and create boolean properties""" + node = 0 + prop = 'prop-bool' + + # Make some space and then try setting a new boolean property + self.fdt.resize(self.fdt.totalsize() + 50) + self.fdt.hasprop(node, 'missing') + self.fdt.setprop_bool(node, 'missing', True) + self.assertTrue(self.fdt.hasprop(node, 'missing')) + + # Trying toggling an existing boolean property. Do each operation twice + # to make sure that the behaviour is correct when setting the property + # to the same value. + self.assertTrue(self.fdt2.hasprop(node, prop)) + self.fdt2.setprop_bool(node, prop, False) + self.assertFalse(self.fdt2.hasprop(node, prop)) + self.fdt2.setprop_bool(node, prop, False) + self.assertFalse(self.fdt2.hasprop(node, prop)) + self.fdt2.setprop_bool(node, prop, True) + self.assertTrue(self.fdt2.hasprop(node, prop)) + self.fdt2.setprop_bool(node, prop, True) + self.assertTrue(self.fdt2.hasprop(node, prop)) + def testSetName(self): """Test that we can update a node name""" node = self.fdt.path_offset('/subnode@1') diff --git a/tests/test_props.dts b/tests/test_props.dts index 5089023..09be197 100644 --- a/tests/test_props.dts +++ b/tests/test_props.dts @@ -12,4 +12,5 @@ prop-uint32-array = <0x1>, <0x98765432>, <0xdeadbeef>; prop-int64-array = /bits/ 64 <0x100000000 0xfffffffffffffffe>; prop-uint64-array = /bits/ 64 <0x100000000 0x1>; + prop-bool; }; From 79b9e326a162b15ca5758ee214e350f4f7c038fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= Date: Tue, 10 Oct 2023 10:27:25 +0100 Subject: [PATCH 198/298] libfdt: fdt_get_alias_namelen: Validate aliases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure that the alias found matches the device tree specification v0.4: Each property of the /aliases node defines an alias. The property name specifies the alias name. The property value specifies the full path to a node in the devicetree. This protects against a stack overflow caused by fdt_path_offset_namelen(fdt, path, namelen) calling fdt_path_offset(fdt, fdt_get_alias_namelen(fdt, path, namelen)) leading to infinite recursion on DTs with "circular" aliases. This fix was originally written by Mike McTernan for Android in [1]. [1]: https://android.googlesource.com/platform/external/dtc/+/9308e7f9772bd226fea9925b1fc4d53c127ed4d5 Signed-off-by: Pierre-Clément Tosi Acked-by: Mike McTernan Message-ID: <20231010092725.63h7c45p2fnmj577@google.com> Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 11 ++++++++++- tests/aliases.dts | 4 ++++ tests/get_alias.c | 14 +++++++++++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index c4c520c..9fe2f49 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -537,7 +537,16 @@ static const void *fdt_path_getprop_namelen(const void *fdt, const char *path, const char *fdt_get_alias_namelen(const void *fdt, const char *name, int namelen) { - return fdt_path_getprop_namelen(fdt, "/aliases", name, namelen, NULL); + int len; + const char *alias; + + alias = fdt_path_getprop_namelen(fdt, "/aliases", name, namelen, &len); + + if (!can_assume(VALID_DTB) && + !(alias && len > 0 && alias[len - 1] == '\0' && *alias == '/')) + return NULL; + + return alias; } const char *fdt_get_alias(const void *fdt, const char *name) diff --git a/tests/aliases.dts b/tests/aliases.dts index 853479a..03ed675 100644 --- a/tests/aliases.dts +++ b/tests/aliases.dts @@ -5,6 +5,10 @@ #size-cells = <0>; aliases { + empty = ""; + loop = "loop"; + nonull = [626164]; + relative = "s1/subsubnode"; s1 = &sub1; ss1 = &subsub1; sss1 = &subsubsub1; diff --git a/tests/get_alias.c b/tests/get_alias.c index fb2c38c..d2888d6 100644 --- a/tests/get_alias.c +++ b/tests/get_alias.c @@ -21,9 +21,16 @@ static void check_alias(void *fdt, const char *path, const char *alias) aliaspath = fdt_get_alias(fdt, alias); - if (path && !aliaspath) + if (!path && !aliaspath) + return; + + if (!aliaspath) FAIL("fdt_get_alias(%s) failed\n", alias); + if (!path) + FAIL("fdt_get_alias(%s) returned %s instead of NULL", + alias, aliaspath); + if (strcmp(aliaspath, path) != 0) FAIL("fdt_get_alias(%s) returned %s instead of %s\n", alias, aliaspath, path); @@ -36,9 +43,14 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); + check_alias(fdt, NULL, "empty"); + check_alias(fdt, NULL, "nonull"); + check_alias(fdt, NULL, "relative"); check_alias(fdt, "/subnode@1", "s1"); check_alias(fdt, "/subnode@1/subsubnode", "ss1"); check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "sss1"); + check_alias(fdt, NULL, "loop"); // Might trigger a stack overflow + PASS(); } From 2283dd78eff5b37a092988e04fd873b040ad27c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= Date: Tue, 10 Oct 2023 10:28:22 +0100 Subject: [PATCH 199/298] libfdt: fdt_path_offset_namelen: Reject empty path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reject empty paths and negative lengths, according to the DT spec v0.4: The convention for specifying a device path is: /node-name-1/node-name-2/node-name-N The path to the root node is /. This prevents the access to path[0] from ever being out-of-bounds. Signed-off-by: Pierre-Clément Tosi Message-ID: <20231010092822.qo2nxc3g47t26dqs@google.com> Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 3 +++ tests/path_offset.c | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 9fe2f49..b78c4e4 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -255,6 +255,9 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) FDT_RO_PROBE(fdt); + if (!can_assume(VALID_INPUT) && namelen <= 0) + return -FDT_ERR_BADPATH; + /* see if we have an alias */ if (*path != '/') { const char *q = memchr(path, '/', end - p); diff --git a/tests/path_offset.c b/tests/path_offset.c index 8e657af..ad8db83 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -48,10 +48,13 @@ static void check_path_offset(void *fdt, const char *path, int offset) verbose_printf("Checking offset of \"%s\" is %d...\n", path, offset); rc = fdt_path_offset(fdt, path); + if (rc == offset) + return; + if (rc < 0) FAIL("fdt_path_offset(\"%s\") failed: %s", path, fdt_strerror(rc)); - if (rc != offset) + else FAIL("fdt_path_offset(\"%s\") returned incorrect offset" " %d instead of %d", path, rc, offset); } @@ -102,6 +105,7 @@ int main(int argc, char *argv[]) check_path_offset(fdt, "/subnode@2/subsubnode", subsubnode2_offset2); /* Test paths with extraneous separators */ + check_path_offset(fdt, "", -FDT_ERR_BADPATH); check_path_offset(fdt, "//", 0); check_path_offset(fdt, "///", 0); check_path_offset(fdt, "//subnode@1", subnode1_offset); @@ -110,6 +114,8 @@ int main(int argc, char *argv[]) check_path_offset(fdt, "/subnode@2////subsubnode", subsubnode2_offset2); /* Test fdt_path_offset_namelen() */ + check_path_offset_namelen(fdt, "/subnode@1", -1, -FDT_ERR_BADPATH); + check_path_offset_namelen(fdt, "/subnode@1", 0, -FDT_ERR_BADPATH); check_path_offset_namelen(fdt, "/subnode@1", 1, 0); check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 10, subnode1_offset); check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 11, subnode1_offset); From 95c74d71f0904235d44892627322f60a18c9a28c Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 27 Oct 2023 09:29:01 -0500 Subject: [PATCH 200/298] treesource: Restore string list output when no type markers When the DTS output has no type markers, we have to guess the type. Prior to commit 32b9c6130762 ("Preserve datatype markers when emitting dts format"), instances of string lists would be delimited. Since then, a single string with embedded "\0"s are emitted. An embedded "\0" is valid for DTS files, but that's a rare exception and lists of strings are the overwhelming majority. Restore the prior behavior. stringlist.dts is reused for testing this, but needs a couple of tweaks in order to match the dts output. Reported-by: Geert Uytterhoeven Signed-off-by: Rob Herring Message-ID: <20231027142901.2536622-1-robh@kernel.org> Signed-off-by: David Gibson --- tests/run_tests.sh | 4 ++++ tests/stringlist.dts | 4 ++-- treesource.c | 24 ++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c4f8b9b..bb2ec95 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -634,6 +634,10 @@ dtc_tests () { done # Check -Odts preserving type information + run_dtc_test -I dts -O dtb -o stringlist.test.dtb "$SRCDIR/stringlist.dts" + run_dtc_test -I dtb -O dts -o stringlist.test.dts stringlist.test.dtb + run_wrap_test cmp "$SRCDIR/stringlist.dts" stringlist.test.dts + for tree in type-preservation.dts; do run_dtc_test -I dts -O dts -o $tree.test.dts "$SRCDIR/$tree" run_dtc_test -I dts -O dts $tree.test.dts diff --git a/tests/stringlist.dts b/tests/stringlist.dts index 1e4d314..c06fcd4 100644 --- a/tests/stringlist.dts +++ b/tests/stringlist.dts @@ -2,8 +2,8 @@ / { compatible = "test-strings"; - #address-cells = <2>; - #size-cells = <2>; + #address-cells = <0x02>; + #size-cells = <0x02>; device { compatible = "foo", "bar"; diff --git a/treesource.c b/treesource.c index 9b17b37..ae15839 100644 --- a/treesource.c +++ b/treesource.c @@ -139,6 +139,28 @@ static const char *delim_end[] = { [TYPE_STRING] = "", }; +static void add_string_markers(struct property *prop) +{ + int l, len = prop->val.len; + const char *p = prop->val.val; + + for (l = strlen(p) + 1; l < len; l += strlen(p + l) + 1) { + struct marker *m, **nextp; + + m = xmalloc(sizeof(*m)); + m->offset = l; + m->type = TYPE_STRING; + m->ref = NULL; + m->next = NULL; + + /* Find the end of the markerlist */ + nextp = &prop->val.markers; + while (*nextp) + nextp = &((*nextp)->next); + *nextp = m; + } +} + static enum markertype guess_value_type(struct property *prop) { int len = prop->val.len; @@ -164,6 +186,8 @@ static enum markertype guess_value_type(struct property *prop) if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul)) && (nnotstringlbl == 0)) { + if (nnul > 1) + add_string_markers(prop); return TYPE_STRING; } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { return TYPE_UINT32; From 0b8026ff254f391bc577a571ef397dd1266f1bbd Mon Sep 17 00:00:00 2001 From: Peter Marko Date: Sat, 16 Dec 2023 18:58:31 +0100 Subject: [PATCH 201/298] meson: allow building from shallow clones When building from shallow clone, tag is not available and version defaults to git hash. Problem is that some builds check DTC version and fail the comparison. Example is https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git Which fails to build with following error: dtc version too old (039a994), you need at least version 1.4.4 Drop --always from git describe command, see https://github.com/mesonbuild/meson/blob/1.3.0/mesonbuild/utils/universal.py#L773 This will make it more closer to build via Makefile. Signed-off-by: Peter Marko Signed-off-by: David Gibson --- meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/meson.build b/meson.build index 17cb135..bfe3347 100644 --- a/meson.build +++ b/meson.build @@ -59,6 +59,7 @@ py = py.find_installation(required: get_option('python')) swig = find_program('swig', required: get_option('python')) version_gen_h = vcs_tag( + command: ['git', 'describe', '--dirty=+'], input: 'version_gen.h.in', output: 'version_gen.h', ) From dcef5f834ea34bcb9f8d0e86db1268fde52ead77 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Tue, 23 Jan 2024 14:04:10 +0100 Subject: [PATCH 202/298] tests: use correct pkg-config when cross compiling By convention, the PKG_CONFIG environment variable is used to tell build systems which pkg-config executable should be used. This is often used when cross compiling, where it might be set to something like "aarch64-unknown-linux-gnu-pkg-config". Signed-off-by: Alyssa Ross Message-ID: <20240123130409.181128-2-hi@alyssa.is> Signed-off-by: David Gibson --- tests/run_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index bb2ec95..3225a12 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -32,7 +32,7 @@ if [ -n "$NO_YAML" ]; then no_yaml=false fi else - if pkg-config --atleast-version 0.2.3 yaml-0.1; then + if ${PKG_CONFIG:-pkg-config} --atleast-version 0.2.3 yaml-0.1; then no_yaml=false else no_yaml=true From 3fbfdd08afd2a7a25b27433f6f5678c0fe694721 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Tue, 23 Jan 2024 14:07:42 +0100 Subject: [PATCH 203/298] libfdt: fix duplicate meson target If default_library is set to static, the libfdt target (which just uses library()) is already static, so we should just use that. This fixes this Meson error: libfdt/meson.build:37:11: ERROR: Tried to create target "fdt", but a target of that name already exists. Signed-off-by: Alyssa Ross Message-ID: <20240123130742.185409-1-hi@alyssa.is> Signed-off-by: David Gibson --- libfdt/meson.build | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/libfdt/meson.build b/libfdt/meson.build index 2ea1448..9d07c5f 100644 --- a/libfdt/meson.build +++ b/libfdt/meson.build @@ -34,19 +34,21 @@ libfdt = library( install: true, ) -libfdt_a = static_library( - 'fdt', sources, - install: true, -) +link_with = libfdt + +if get_option('default_library') != 'static' + libfdt_a = static_library( + 'fdt', sources, + install: true, + ) + + if static_build + link_with = libfdt_a + endif +endif libfdt_inc = include_directories('.') -if static_build - link_with = libfdt_a -else - link_with = libfdt -endif - libfdt_dep = declare_dependency( include_directories: libfdt_inc, link_with: link_with, From a669223f7a60cff6843995b9dd4afa472c2512c6 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 8 Feb 2024 20:14:05 +0100 Subject: [PATCH 204/298] Makefile: do not hardcode the `install` program path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On systems that do not use the FHS, such as NixOS, the `install` program is not located in `/usr/bin/` as its location is dynamic. `dtc` can be easily installed on such systems by using the `install` program available in the `$PATH` with: make PREFIX=… INSTALL=install However, this becomes more difficult when `dtc` is being compiled as part of a larger toolchain, as the toolchain build scripts will not spontaneously pass such an argument on the command line. This happens for example when `dtc` is build as a part of the RTEMS build system. By not hardcoding a predefined path for `install`, as is done for other executables, `dtc` will allow the one in the `$PATH` to be used. Signed-off-by: Samuel Tardieu Message-ID: <20240208191405.1597654-1-sam@rfc1149.net> Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 10a56d4..f1f0ab3 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ SWIG = swig PKG_CONFIG ?= pkg-config PYTHON ?= python3 -INSTALL = /usr/bin/install +INSTALL = install INSTALL_PROGRAM = $(INSTALL) INSTALL_LIB = $(INSTALL) INSTALL_DATA = $(INSTALL) -m 644 From da39ee0e68b6d9293133a7c41c6cf73354dce337 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 21 Feb 2024 13:57:56 -0800 Subject: [PATCH 205/298] libfdt: rework shared/static libraries Instead of creating 2 libraries manualy, just call both_libraries and link to the appropriate one as requested. Fixes compilation when passing -Ddefault_libraries=both as the static_library name is duplicated. Signed-off-by: Rosen Penev Signed-off-by: David Gibson --- libfdt/meson.build | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/libfdt/meson.build b/libfdt/meson.build index 9d07c5f..bf8343f 100644 --- a/libfdt/meson.build +++ b/libfdt/meson.build @@ -26,7 +26,7 @@ else endif link_args += version_script -libfdt = library( +libfdt = both_libraries( 'fdt', sources, version: meson.project_version(), link_args: link_args, @@ -34,17 +34,10 @@ libfdt = library( install: true, ) -link_with = libfdt - -if get_option('default_library') != 'static' - libfdt_a = static_library( - 'fdt', sources, - install: true, - ) - - if static_build - link_with = libfdt_a - endif +if static_build + link_with = libfdt.get_static_lib() +else + link_with = libfdt.get_shared_lib() endif libfdt_inc = include_directories('.') From 24f60011fd43683d8e3916435c4c726e9baac9c9 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 23 Feb 2024 15:36:00 +1100 Subject: [PATCH 206/298] libfdt: Simplify adjustment of values for local fixups In a couple of places in fdt_overlay.c we need to adjust a phandle value in a property (either a node's phandle itself or a reference) by some delta. Currently this is done if a fairly convoluted way, open-coding loading the value and handling of a non-aligned reference, and then using fdt_setprop_inplace_partial() to replace the value. This becomes much simpler if we use fdt_getprop_w() to get a writable pointer to the value then we can just load/store it with fdt32_{ld,st}(). Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 52 +++++++++++++------------------------------- 1 file changed, 15 insertions(+), 37 deletions(-) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index 5c0c398..7ec839a 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -101,26 +101,22 @@ int fdt_overlay_target_offset(const void *fdt, const void *fdto, static int overlay_phandle_add_offset(void *fdt, int node, const char *name, uint32_t delta) { - const fdt32_t *val; - uint32_t adj_val; + fdt32_t *valp, val; int len; - val = fdt_getprop(fdt, node, name, &len); - if (!val) + valp = fdt_getprop_w(fdt, node, name, &len); + if (!valp) return len; - if (len != sizeof(*val)) + if (len != sizeof(val)) return -FDT_ERR_BADPHANDLE; - adj_val = fdt32_to_cpu(*val); - if ((adj_val + delta) < adj_val) + val = fdt32_ld(valp); + if (val + delta < val || val + delta == (uint32_t)-1) return -FDT_ERR_NOPHANDLES; - adj_val += delta; - if (adj_val == (uint32_t)-1) - return -FDT_ERR_NOPHANDLES; - - return fdt_setprop_inplace_u32(fdt, node, name, adj_val); + fdt32_st(valp, val + delta); + return 0; } /** @@ -213,8 +209,8 @@ static int overlay_update_local_node_references(void *fdto, fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { const fdt32_t *fixup_val; - const char *tree_val; const char *name; + char *tree_val; int fixup_len; int tree_len; int i; @@ -228,7 +224,7 @@ static int overlay_update_local_node_references(void *fdto, return -FDT_ERR_BADOVERLAY; fixup_len /= sizeof(uint32_t); - tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); + tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len); if (!tree_val) { if (tree_len == -FDT_ERR_NOTFOUND) return -FDT_ERR_BADOVERLAY; @@ -237,33 +233,15 @@ static int overlay_update_local_node_references(void *fdto, } for (i = 0; i < fixup_len; i++) { - fdt32_t adj_val; - uint32_t poffset; + fdt32_t *refp; - poffset = fdt32_to_cpu(fixup_val[i]); + refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i)); /* - * phandles to fixup can be unaligned. - * - * Use a memcpy for the architectures that do - * not support unaligned accesses. + * phandles to fixup can be unaligned, so use + * fdt32_{ld,st}() to read/write them. */ - memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); - - adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta); - - ret = fdt_setprop_inplace_namelen_partial(fdto, - tree_node, - name, - strlen(name), - poffset, - &adj_val, - sizeof(adj_val)); - if (ret == -FDT_ERR_NOSPACE) - return -FDT_ERR_BADOVERLAY; - - if (ret) - return ret; + fdt32_st(refp, fdt32_ld(refp) + delta); } } From 5e6cefa17e2dfdaf6323a7cd886ee6ea17b978b3 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Mon, 4 Mar 2024 16:55:23 -0800 Subject: [PATCH 207/298] fix MinGW format attribute Setting -D__USE_MINGW_ANSI_STDIO=1 is wrong and should not be used. MinGW internally uses a macro to select between gnu_printf and printf. Just use that instead of using a wrong format under clang backends. Signed-off-by: Rosen Penev Signed-off-by: David Gibson --- meson.build | 7 ------- util.h | 4 +++- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/meson.build b/meson.build index bfe3347..79151cd 100644 --- a/meson.build +++ b/meson.build @@ -22,13 +22,6 @@ add_project_arguments( language: 'c' ) -if host_machine.system() == 'windows' - add_project_arguments( - '-D__USE_MINGW_ANSI_STDIO=1', - language: 'c' - ) -endif - add_project_arguments( '-DFDT_ASSUME_MASK=' + get_option('assume-mask').to_string(), language: 'c' diff --git a/util.h b/util.h index 1547707..b448cd7 100644 --- a/util.h +++ b/util.h @@ -13,7 +13,9 @@ */ #ifdef __GNUC__ -#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +#ifdef __MINGW_PRINTF_FORMAT +#define PRINTF(i, j) __attribute__((format (__MINGW_PRINTF_FORMAT, i, j))) +#elif __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) #define PRINTF(i, j) __attribute__((format (gnu_printf, i, j))) #else #define PRINTF(i, j) __attribute__((format (printf, i, j))) From 417e3299dbd17f25e318608aa31e38c501697227 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 6 Mar 2024 14:46:22 +1100 Subject: [PATCH 208/298] github: Update to newer checkout action We're getting deprecation warnings about the v3 one. Signed-off-by: David Gibson --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index be23b9f..9f28bda 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Dependencies run: | @@ -49,7 +49,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Dependencies run: | From 92b5d4e9167846b398d810e025c10fef9120029c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 6 Mar 2024 15:06:06 +1100 Subject: [PATCH 209/298] pylibfdt: Remove some apparently deprecated options from setup.py We seem to get deprecation warnings because of these. Signed-off-by: David Gibson --- setup.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/setup.py b/setup.py index c3ffb2b..602caab 100755 --- a/setup.py +++ b/setup.py @@ -52,13 +52,7 @@ class build_py(_build_py): setup( name='libfdt', - use_scm_version={ - "root": srcdir, - "fallback_version": version, - "fallback_root": srcdir, - }, cmdclass = {'build_py' : build_py}, - setup_requires = ['setuptools_scm'], author='Simon Glass', author_email='sjg@chromium.org', description='Python binding for libfdt', From 057a7dbbb7770878401a81510120ec9930abaf6f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 6 Mar 2024 15:11:14 +1100 Subject: [PATCH 210/298] github: Display meson test logs on failure Currently the way we integrate the existing tests into meson means meson test itself doesn't show any detailed logs of the failures, those just go to the meson testlog file. As a hack to see what's failing in CI builds, display that file if the tests fail. Signed-off-by: David Gibson --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9f28bda..f841eef 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,4 +62,4 @@ jobs: run: meson compile -C build - name: Run check - run: meson test -C build + run: meson test -C build || cat build/meson-logs/testlog.txt From ae97d974586206bb3bdd442716cc98c5c52f9648 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 6 Mar 2024 15:43:52 +1100 Subject: [PATCH 211/298] github: Don't accidentally suppress test errors The last commit, displaying the meson testlog if we fail tests had the accidentaly side effect of not propagating the failure to show up properly in github's dashboard. Fix that. Signed-off-by: David Gibson --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f841eef..b414314 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,4 +62,4 @@ jobs: run: meson compile -C build - name: Run check - run: meson test -C build || cat build/meson-logs/testlog.txt + run: if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi From b0aacd0a77350a1c6c8539e669095aac9a25f5a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 6 Mar 2024 11:54:38 +0400 Subject: [PATCH 212/298] github: add windows/msys CI build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Signed-off-by: David Gibson --- .github/workflows/build.yml | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b414314..e3ea9e1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,12 @@ name: Build test branches: - main +# ensure that the workflow is only triggered once per PR, subsequent pushes to the PR will cancel +# and restart the workflow. See https://docs.github.com/en/actions/using-jobs/using-concurrency +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + jobs: build-make: runs-on: ubuntu-latest @@ -63,3 +69,45 @@ jobs: - name: Run check run: if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi + + build-windows: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + include: + - { sys: mingw32 } + - { sys: mingw64 } + - { sys: ucrt64 } + - { sys: clang64 } + name: ${{ matrix.sys }} + defaults: + run: + shell: msys2 {0} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: ${{matrix.sys}} + update: true + install: >- + git + flex + bison + pacboy: >- + toolchain:p + meson:p + ninja:p + libyaml:p + swig:p + python-setuptools-scm:p + + - name: '🚧 Build' + run: | + meson setup -Dtools=true -Dtests=false build + meson compile -C build From 1fad065080e6cae0ec1a4ad6288733cd24c103f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 25 Feb 2024 18:54:23 +0100 Subject: [PATCH 213/298] libfdt: overlay: ensure that existing phandles are not overwritten MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A phandle in an overlay is not supposed to overwrite a phandle that already exists in the base dtb as this breaks references to the respective node in the base. So add another iteration over the fdto that checks for such overwrites and fixes the fdto phandle's value to match the fdt's. A test is added that checks that newly added phandles and existing phandles work as expected. Signed-off-by: Uwe Kleine-König Message-ID: <20240225175422.156393-2-u.kleine-koenig@pengutronix.de> Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 251 ++++++++++++++++++++++++++++++ tests/overlay_base_phandle.dts | 21 +++ tests/overlay_overlay_phandle.dts | 34 ++++ tests/run_tests.sh | 28 ++++ 4 files changed, 334 insertions(+) create mode 100644 tests/overlay_base_phandle.dts create mode 100644 tests/overlay_overlay_phandle.dts diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index 7ec839a..f500f2d 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -498,6 +498,249 @@ static int overlay_fixup_phandles(void *fdt, void *fdto) return 0; } +/** + * overlay_adjust_local_conflicting_phandle: Changes a phandle value + * @fdto: Device tree overlay + * @node: The node the phandle is set for + * @fdt_phandle: The new value for the phandle + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_adjust_local_conflicting_phandle(void *fdto, int node, + uint32_t fdt_phandle) +{ + const fdt32_t *php; + int len, ret; + + php = fdt_getprop(fdto, node, "phandle", &len); + if (php && len == sizeof(*php)) { + ret = fdt_setprop_inplace_u32(fdto, node, "phandle", fdt_phandle); + if (ret) + return ret; + } + + php = fdt_getprop(fdto, node, "linux,phandle", &len); + if (php && len == sizeof(*php)) { + ret = fdt_setprop_inplace_u32(fdto, node, "linux,phandle", fdt_phandle); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_update_node_conflicting_references - Recursively replace phandle values + * @fdto: Device tree overlay blob + * @tree_node: Node to recurse into + * @fixup_node: Node offset of the matching local fixups node + * @fdt_phandle: Value to replace phandles with + * @fdto_phandle: Value to be replaced + * + * Replaces all phandles with value @fdto_phandle by @fdt_phandle. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_update_node_conflicting_references(void *fdto, int tree_node, + int fixup_node, + uint32_t fdt_phandle, + uint32_t fdto_phandle) +{ + int fixup_prop; + int fixup_child; + int ret; + + fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { + const fdt32_t *fixup_val; + const char *name; + char *tree_val; + int fixup_len; + int tree_len; + int i; + + fixup_val = fdt_getprop_by_offset(fdto, fixup_prop, + &name, &fixup_len); + if (!fixup_val) + return fixup_len; + + if (fixup_len % sizeof(uint32_t)) + return -FDT_ERR_BADOVERLAY; + fixup_len /= sizeof(uint32_t); + + tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len); + if (!tree_val) { + if (tree_len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + + return tree_len; + } + + for (i = 0; i < fixup_len; i++) { + fdt32_t *refp; + uint32_t valp; + + refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i)); + valp = fdt32_ld(refp); + + if (valp == fdto_phandle) + fdt32_st(refp, fdt_phandle); + } + } + + fdt_for_each_subnode(fixup_child, fdto, fixup_node) { + const char *fixup_child_name = fdt_get_name(fdto, fixup_child, NULL); + int tree_child; + + tree_child = fdt_subnode_offset(fdto, tree_node, fixup_child_name); + + if (tree_child == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + if (tree_child < 0) + return tree_child; + + ret = overlay_update_node_conflicting_references(fdto, tree_child, + fixup_child, + fdt_phandle, + fdto_phandle); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_update_local_conflicting_references - Recursively replace phandle values + * @fdto: Device tree overlay blob + * @fdt_phandle: Value to replace phandles with + * @fdto_phandle: Value to be replaced + * + * Replaces all phandles with value @fdto_phandle by @fdt_phandle. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_update_local_conflicting_references(void *fdto, + uint32_t fdt_phandle, + uint32_t fdto_phandle) +{ + int fixups; + + fixups = fdt_path_offset(fdto, "/__local_fixups__"); + if (fixups == -FDT_ERR_NOTFOUND) + return 0; + if (fixups < 0) + return fixups; + + return overlay_update_node_conflicting_references(fdto, 0, fixups, + fdt_phandle, + fdto_phandle); +} + +/** + * overlay_prevent_phandle_overwrite_node - Helper function for overlay_prevent_phandle_overwrite + * @fdt: Base Device tree blob + * @fdtnode: Node in fdt that is checked for an overwrite + * @fdto: Device tree overlay blob + * @fdtonode: Node in fdto matching @fdtnode + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_prevent_phandle_overwrite_node(void *fdt, int fdtnode, + void *fdto, int fdtonode) +{ + uint32_t fdt_phandle, fdto_phandle; + int fdtochild; + + fdt_phandle = fdt_get_phandle(fdt, fdtnode); + fdto_phandle = fdt_get_phandle(fdto, fdtonode); + + if (fdt_phandle && fdto_phandle) { + int ret; + + ret = overlay_adjust_local_conflicting_phandle(fdto, fdtonode, + fdt_phandle); + if (ret) + return ret; + + ret = overlay_update_local_conflicting_references(fdto, + fdt_phandle, + fdto_phandle); + if (ret) + return ret; + } + + fdt_for_each_subnode(fdtochild, fdto, fdtonode) { + const char *name = fdt_get_name(fdto, fdtochild, NULL); + int fdtchild; + int ret; + + fdtchild = fdt_subnode_offset(fdt, fdtnode, name); + if (fdtchild == -FDT_ERR_NOTFOUND) + /* + * no further overwrites possible here as this node is + * new + */ + continue; + + ret = overlay_prevent_phandle_overwrite_node(fdt, fdtchild, + fdto, fdtochild); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_prevent_phandle_overwrite - Fixes overlay phandles to not overwrite base phandles + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * Checks recursively if applying fdto overwrites phandle values in the base + * dtb. When such a phandle is found, the fdto is changed to use the fdt's + * phandle value to not break references in the base. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_prevent_phandle_overwrite(void *fdt, void *fdto) +{ + int fragment; + + fdt_for_each_subnode(fragment, fdto, 0) { + int overlay; + int target; + int ret; + + overlay = fdt_subnode_offset(fdto, fragment, "__overlay__"); + if (overlay == -FDT_ERR_NOTFOUND) + continue; + + if (overlay < 0) + return overlay; + + target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL); + if (target < 0) + return target; + + ret = overlay_prevent_phandle_overwrite_node(fdt, target, + fdto, overlay); + if (ret) + return ret; + } + + return 0; +} + /** * overlay_apply_node - Merges a node into the base device tree * @fdt: Base Device Tree blob @@ -802,18 +1045,26 @@ int fdt_overlay_apply(void *fdt, void *fdto) if (ret) goto err; + /* Increase all phandles in the fdto by delta */ ret = overlay_adjust_local_phandles(fdto, delta); if (ret) goto err; + /* Adapt the phandle values in fdto to the above increase */ ret = overlay_update_local_references(fdto, delta); if (ret) goto err; + /* Update fdto's phandles using symbols from fdt */ ret = overlay_fixup_phandles(fdt, fdto); if (ret) goto err; + /* Don't overwrite phandles in fdt */ + ret = overlay_prevent_phandle_overwrite(fdt, fdto); + if (ret) + goto err; + ret = overlay_merge(fdt, fdto); if (ret) goto err; diff --git a/tests/overlay_base_phandle.dts b/tests/overlay_base_phandle.dts new file mode 100644 index 0000000..20639a7 --- /dev/null +++ b/tests/overlay_base_phandle.dts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 Uwe Kleine-König + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +/ { + node_a: a { + value = <17>; + }; + + node_b: b { + a = <&node_a>; + }; + + node_d: d { + b = <&node_b>; + }; +}; diff --git a/tests/overlay_overlay_phandle.dts b/tests/overlay_overlay_phandle.dts new file mode 100644 index 0000000..a0fa668 --- /dev/null +++ b/tests/overlay_overlay_phandle.dts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Uwe Kleine-König + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +/plugin/; + +&{/} { + /* + * /b already has a label "node_b" in the base dts, also b is already + * referenced in the base, so both the base's b and this b have a + * phandle value. + */ + node_b2: b { + value = <42>; + d = <&node_d>; + }; + + node_c: c { + value = <23>; + b = <&node_b2>; + }; + + d { + a = <&node_a>; + c = <&node_c>; + }; +}; + +&node_a { + value = <32>; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 3225a12..f13cdb2 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -1040,6 +1040,34 @@ fdtoverlay_tests() { run_dtc_test -@ -I dts -O dtb -o $stacked_addlabeldtb $stacked_addlabel run_fdtoverlay_test baz "/foonode/barnode/baznode" "baz-property" "-ts" ${stacked_base_nolabeldtb} ${stacked_addlabel_targetdtb} ${stacked_addlabeldtb} ${stacked_bardtb} ${stacked_bazdtb} + + # verify that phandles are not overwritten + run_dtc_test -@ -I dts -O dtb -o overlay_base_phandle.test.dtb "$SRCDIR/overlay_base_phandle.dts" + run_dtc_test -@ -I dts -O dtb -o overlay_overlay_phandle.test.dtb "$SRCDIR/overlay_overlay_phandle.dts" + run_wrap_test $FDTOVERLAY -i overlay_base_phandle.test.dtb -o overlay_base_phandleO.test.dtb overlay_overlay_phandle.test.dtb + + pa=$($DTGET overlay_base_phandleO.test.dtb /a phandle) + pb=$($DTGET overlay_base_phandleO.test.dtb /b phandle) + pc=$($DTGET overlay_base_phandleO.test.dtb /c phandle) + pd=$($DTGET overlay_base_phandleO.test.dtb /d phandle) + ba=$($DTGET overlay_base_phandleO.test.dtb /b a) + bd=$($DTGET overlay_base_phandleO.test.dtb /b d) + cb=$($DTGET overlay_base_phandleO.test.dtb /c b) + da=$($DTGET overlay_base_phandleO.test.dtb /d a) + db=$($DTGET overlay_base_phandleO.test.dtb /d b) + dc=$($DTGET overlay_base_phandleO.test.dtb /d c) + + shorten_echo "check phandle to noda a wasn't overwritten: " + run_wrap_test test "$ba-$da" = "$pa-$pa" + + shorten_echo "check phandle to noda b wasn't overwritten: " + run_wrap_test test "$cb-$db" = "$pb-$pb" + + shorten_echo "check phandle to noda c wasn't overwritten: " + run_wrap_test test "$dc" = "$pc" + + shorten_echo "check phandle to noda d wasn't overwritten: " + run_wrap_test test "$bd" = "$pd" } pylibfdt_tests () { From 822123856980f84562406cc7bd1d4d6c2b8bc184 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Mon, 18 Mar 2024 18:24:19 +0000 Subject: [PATCH 214/298] pylibfdt: fix get_mem_rsv for newer Python versions The test for get_mem_rsv fails on newer versions of Python with the following error. > Traceback (most recent call last): > File "/__w/dtc/dtc/tests/pylibfdt_tests.py", line 421, in testReserveMap > self.assertEqual([ 0xdeadbeef00000000, 0x100000], > AssertionError: Lists differ: [16045690981097406464, 1048576] != [0, 16045690981097406464, 1048576] > > First differing element 0: > 16045690981097406464 > 0 > > Second list contains 1 additional elements. > First extra element 2: > 1048576 > > - [16045690981097406464, 1048576] > + [0, 16045690981097406464, 1048576] > ? +++ It appears this is because the PyTuple_GET_SIZE() function that was used to build the fdt_get_mem_rsv() return value has changed. It now is returning a non-zero value when it's passed an integer, which causes the SWIG wrapper to append the returned arguments to the return error rather then ignore them. This is valid behaviour per Python's documentation, which says it will "Return the size of the tuple p, which must be non-NULL and point to a tuple; no error checking is performed"[1]. As passing an integer is not a tuple, its return value is undefined. Fix this issue on older and newer versions by avoiding PyTuple_GET_SIZE() entirely. Always append the arguments to the list, and instead use the wrapper python function to check the first argument and then splice the last two arguments as the return value. [1] https://docs.python.org/3/c-api/tuple.html#c.PyTuple_GET_SIZE Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 0b50983..bbc91ad 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -295,7 +295,9 @@ class FdtRo(object): Returns: Number of memory reserve-map records """ - return check_err(fdt_get_mem_rsv(self._fdt, index), quiet) + val = fdt_get_mem_rsv(self._fdt, index) + check_err(val[0], quiet) + return val[1:] def subnode_offset(self, parentoffset, name, quiet=()): """Get the offset of a named subnode @@ -1188,12 +1190,7 @@ typedef uint32_t fdt32_t; %typemap(argout) uint64_t * { PyObject *val = PyLong_FromUnsignedLongLong(*arg$argnum); - if (!result) { - if (PyTuple_GET_SIZE(resultobj) == 0) - resultobj = val; - else - resultobj = SWIG_Python_AppendOutput(resultobj, val); - } + resultobj = SWIG_Python_AppendOutput(resultobj, val); } %include "cstring.i" From e81900635c95629f4bf3ee4b4dae852ba6b6d60f Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Mon, 18 Mar 2024 17:04:19 +0000 Subject: [PATCH 215/298] meson: fix pylibfdt missing dependency on libfdt The python library requires libfdt to build. This would intermittently fail depending on what order targets compiled. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- pylibfdt/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build index b3f5ebd..2179f4e 100644 --- a/pylibfdt/meson.build +++ b/pylibfdt/meson.build @@ -4,6 +4,7 @@ setup_py = [setup_py, '--quiet', '--top-builddir', meson.project_build_root()] custom_target( 'pylibfdt', input: 'libfdt.i', + depends: libfdt, output: '_libfdt.so', command: [setup_py, 'build_ext', '--build-lib=' + meson.current_build_dir()], build_by_default: true, From bb51223083a493146c34b1f0528abfbe925d620c Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Mon, 18 Mar 2024 16:25:33 +0000 Subject: [PATCH 216/298] meson: fix dependencies of tests If the tests are run without a full compile they will fail. For example with the following. > rm -rf build/ > meson setup build/ > meson test -C build/ This is because the tests rely on the devicetree tools and test executables. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- meson.build | 14 +++++++------- pylibfdt/meson.build | 2 +- tests/meson.build | 11 +++++++++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/meson.build b/meson.build index 79151cd..4bb1196 100644 --- a/meson.build +++ b/meson.build @@ -50,6 +50,7 @@ endif py = import('python') py = py.find_installation(required: get_option('python')) swig = find_program('swig', required: get_option('python')) +pylibfdt_enabled = not meson.is_cross_build() and py.found() and swig.found() ? true : false version_gen_h = vcs_tag( command: ['git', 'describe', '--dirty=+'], @@ -59,6 +60,7 @@ version_gen_h = vcs_tag( subdir('libfdt') +dtc_tools = [] if get_option('tools') flex = find_program('flex', required: true) bison = find_program('bison', required: true) @@ -82,7 +84,7 @@ if get_option('tools') ) if cc.check_header('fnmatch.h') - executable( + dtc_tools += executable( 'convert-dtsv0', [ lgen.process('convert-dtsv0-lexer.l'), @@ -94,7 +96,7 @@ if get_option('tools') ) endif - executable( + dtc_tools += executable( 'dtc', [ lgen.process('dtc-lexer.l'), @@ -115,7 +117,7 @@ if get_option('tools') ) foreach e: ['fdtdump', 'fdtget', 'fdtput', 'fdtoverlay'] - executable(e, files(e + '.c'), dependencies: util_dep, install: true, link_args: extra_link_args) + dtc_tools += executable(e, files(e + '.c'), dependencies: util_dep, install: true, link_args: extra_link_args) endforeach install_data( @@ -125,10 +127,8 @@ if get_option('tools') ) endif -if not meson.is_cross_build() - if py.found() and swig.found() - subdir('pylibfdt') - endif +if pylibfdt_enabled + subdir('pylibfdt') endif if get_option('tests') diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build index 2179f4e..978c53f 100644 --- a/pylibfdt/meson.build +++ b/pylibfdt/meson.build @@ -1,7 +1,7 @@ setup_py = find_program('../setup.py') setup_py = [setup_py, '--quiet', '--top-builddir', meson.project_build_root()] -custom_target( +pylibfdt = custom_target( 'pylibfdt', input: 'libfdt.i', depends: libfdt, diff --git a/tests/meson.build b/tests/meson.build index fe10fa2..32d0015 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -109,8 +109,9 @@ if not static_build test_deps += [dl] endif +tests_exe = [] foreach t: tests - executable(t, files(t + '.c'), dependencies: test_deps, link_args: extra_link_args) + tests_exe += executable(t, files(t + '.c'), dependencies: test_deps, link_args: extra_link_args) endforeach run_tests = find_program('run_tests.sh') @@ -128,11 +129,17 @@ if not yaml.found() env += 'NO_YAML=1' endif +run_test_deps = [ + dtc_tools, dumptrees_dtb, tests_exe +] +if pylibfdt_enabled + run_test_deps += pylibfdt +endif test( 'run-test', run_tests, workdir: meson.current_build_dir(), - depends: dumptrees_dtb, + depends: run_test_deps, env: env, timeout: 1800, # mostly for valgrind ) From 9ca7d62dbf0be2d582e00b51544032b52123054e Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Mon, 18 Mar 2024 18:56:03 +0000 Subject: [PATCH 217/298] meson: split run-tests by type Instead of running run-tests on all tests, split them down into the 9 separate run-tests test types. This provides better granularity of test results from the Meson test harness. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- tests/meson.build | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/tests/meson.build b/tests/meson.build index 32d0015..41e60f2 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -129,17 +129,32 @@ if not yaml.found() env += 'NO_YAML=1' endif +run_test_types = [ + 'libfdt', + 'utilfdt', + 'dtc', + 'dtbs_equal', + 'fdtget', + 'fdtput', + 'fdtdump', + 'fdtoverlay' +] run_test_deps = [ dtc_tools, dumptrees_dtb, tests_exe ] if pylibfdt_enabled + run_test_types += 'pylibfdt' run_test_deps += pylibfdt endif -test( - 'run-test', - run_tests, - workdir: meson.current_build_dir(), - depends: run_test_deps, - env: env, - timeout: 1800, # mostly for valgrind -) +foreach test_type : run_test_types + test( + test_type, + run_tests, + args: ['-t', test_type], + is_parallel: false, + workdir: meson.current_build_dir(), + depends: run_test_deps, + env: env, + timeout: 1800, # mostly for valgrind + ) +endforeach From 4fd3f4f0a95d04944271e9482b111de6e3bb7124 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Mon, 18 Mar 2024 17:06:37 +0000 Subject: [PATCH 218/298] github: enforce testing pylibfdt and yaml support The Ubuntu runner was not building the yaml support as it's using Ubuntu 22 (jammy) which uses libyaml 0.2.2, but the build requires libyaml 0.2.3. Switch to Ubuntu 23 which has libyaml 0.2.5. This was not detected by the runner as the Yaml feature defaults to "auto" which turns off if it fails to find the dependency. In the runner force yaml to enabled so if it fails to build it will trigger a build failure. We also force python support for the same reason. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e3ea9e1..200c9b7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ "alpine", "archlinux", "fedora", "ubuntu" ] + os: [ "alpine", "archlinux", "fedora", "ubuntu:23.10" ] container: image: ${{ matrix.os }} @@ -48,7 +48,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ "alpine", "archlinux", "fedora", "ubuntu" ] + os: [ "alpine", "archlinux", "fedora", "ubuntu:23.10" ] container: image: ${{ matrix.os }} @@ -62,7 +62,7 @@ jobs: ./scripts/install-deps.sh - name: Setup - run: meson setup build + run: meson setup -D python=enabled -D yaml=enabled build - name: Build run: meson compile -C build From 855c934e26aeadb5bab878d1b148090af2480c90 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Wed, 20 Mar 2024 21:59:56 +0000 Subject: [PATCH 219/298] tests: fix tests broken under Meson Tests running under Meson run from a different working directory then under Makefile. Some of these tests had not been fixed to work from a different directory because the tests were testing for an error condition which is indistinguishable from a missing file. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- tests/run_tests.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index f13cdb2..462f2ca 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -271,7 +271,7 @@ libfdt_overlay_tests () { run_dtc_test -I dts -O dtb -o $tree.test.dtb "$SRCDIR/$tree.dts" run_test overlay_bad_fixup overlay_base_no_symbols.test.dtb $tree.test.dtb done - run_sh_test "$SRCDIR/dtc-fatal.sh" -I dts -O dtb -o /dev/null fixup-ref-to-path.dts + run_sh_test "$SRCDIR/dtc-fatal.sh" -I dts -O dtb -o /dev/null "$SRCDIR/fixup-ref-to-path.dts" } # Tests to exercise dtc's overlay generation support @@ -497,13 +497,13 @@ libfdt_tests () { run_dtc_test -I dts -O dtb "$SRCDIR/bad-size-cells.dts" - run_wrap_error_test $DTC division-by-zero.dts - run_wrap_error_test $DTC bad-octal-literal.dts + run_wrap_error_test $DTC "$SRCDIR/division-by-zero.dts" + run_wrap_error_test $DTC "$SRCDIR/bad-octal-literal.dts" run_dtc_test -I dts -O dtb "$SRCDIR/nul-in-escape.dts" - run_wrap_error_test $DTC nul-in-line-info1.dts - run_wrap_error_test $DTC nul-in-line-info2.dts + run_wrap_error_test $DTC "$SRCDIR/nul-in-line-info1.dts" + run_wrap_error_test $DTC "$SRCDIR/nul-in-line-info2.dts" - run_wrap_error_test $DTC -I dtb -O dts -o /dev/null ovf_size_strings.dtb + run_wrap_error_test $DTC -I dtb -O dts -o /dev/null "$SRCDIR/ovf_size_strings.dtb" run_test check_header test_tree1.dtb @@ -774,7 +774,7 @@ dtc_tests () { # Check warning options run_sh_test "$SRCDIR/dtc-checkfails.sh" address_cells_is_cell interrupts_extended_is_cell -n size_cells_is_cell -- -Wno_size_cells_is_cell -I dts -O dtb "$SRCDIR/bad-ncells.dts" run_sh_test "$SRCDIR/dtc-fails.sh" -n test-warn-output.test.dtb -I dts -O dtb "$SRCDIR/bad-ncells.dts" - run_sh_test "$SRCDIR/dtc-fails.sh" test-error-output.test.dtb -I dts -O dtb bad-ncells.dts -Esize_cells_is_cell + run_sh_test "$SRCDIR/dtc-fails.sh" test-error-output.test.dtb -I dts -O dtb "$SRCDIR/bad-ncells.dts" -Esize_cells_is_cell run_sh_test "$SRCDIR/dtc-checkfails.sh" always_fail -- -Walways_fail -I dts -O dtb "$SRCDIR/test_tree1.dts" run_sh_test "$SRCDIR/dtc-checkfails.sh" -n always_fail -- -Walways_fail -Wno_always_fail -I dts -O dtb "$SRCDIR/test_tree1.dts" run_sh_test "$SRCDIR/dtc-fails.sh" test-negation-1.test.dtb -Ealways_fail -I dts -O dtb "$SRCDIR/test_tree1.dts" From e6d2942008379e750740de54152efa586dc5d7b8 Mon Sep 17 00:00:00 2001 From: Zheng Guangyuan <1628513611@qq.com> Date: Mon, 8 Apr 2024 13:02:02 +0800 Subject: [PATCH 220/298] tests: Remove two_roots and named_root from LIBTREE_TESTS_L and add all dtb filenames generated by dumptrees to TESTS_TREES_L in Makefile.tests These two binaries are not produced; two_roots.dtb and named_root.dtb are instead generated in TESTS_TREES. Redundant file entries eliminated and Ensures that all dtb filenames generated by dumptrees are now accounted for in the TEST_TREES, addressing previous omissions Signed-off-by: Zheng Guangyuan <1628513611@qq.com> Signed-off-by: David Gibson --- tests/Makefile.tests | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 2c5b4c9..05bb3b2 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -32,8 +32,7 @@ LIB_TESTS_L = get_mem_rsv \ fs_tree1 LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) -LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv \ - two_roots named_root +LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%) @@ -44,7 +43,9 @@ endif TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS) -TESTS_TREES_L = test_tree1.dtb +TESTS_TREES_L = test_tree1.dtb bad_node_char.dtb bad_node_format.dtb \ + bad_prop_char.dtb ovf_size_strings.dtb truncated_property.dtb \ + truncated_string.dtb truncated_memrsv.dtb two_roots.dtb named_root.dtb TESTS_TREES = $(TESTS_TREES_L:%=$(TESTS_PREFIX)%) TESTS_TARGETS = $(TESTS) $(TESTS_TREES) From 4dd831affd015efbb6e0a56d55ac5ef7812af97a Mon Sep 17 00:00:00 2001 From: Zheng Guangyuan <1628513611@qq.com> Date: Sun, 28 Apr 2024 13:47:07 +0800 Subject: [PATCH 221/298] libfdt: tests: Update test case for overlay_bad_fixup Changed the target DTS from overlay_base_no_symbols.test.dtb to overlay_base_manual_symbols.test.dtb. This ensures that the test case doesn't exit prematurely due to the absence of label-linked phandle in the symbols node. The update guarantees that the test case appropriately checks the validity of the fixup string linked to the label, as intended. Signed-off-by: Zheng Guangyuan <1628513611@qq.com> Signed-off-by: David Gibson --- tests/run_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 462f2ca..b14c864 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -269,7 +269,7 @@ libfdt_overlay_tests () { for test in $BAD_FIXUP_TREES; do tree="overlay_bad_fixup_$test" run_dtc_test -I dts -O dtb -o $tree.test.dtb "$SRCDIR/$tree.dts" - run_test overlay_bad_fixup overlay_base_no_symbols.test.dtb $tree.test.dtb + run_test overlay_bad_fixup overlay_base_manual_symbols.test.dtb $tree.test.dtb done run_sh_test "$SRCDIR/dtc-fatal.sh" -I dts -O dtb -o /dev/null "$SRCDIR/fixup-ref-to-path.dts" } From ae26223a056e040b2d812202283d47c6e034d063 Mon Sep 17 00:00:00 2001 From: Zheng Guangyuan <1628513611@qq.com> Date: Sun, 28 Apr 2024 13:44:57 +0800 Subject: [PATCH 222/298] libfdt: overlay: Refactor overlay_fixup_phandle Refactored overlay_fixup_phandle to optimize efficiency by moving the phandle lookup logic based on label outside the overlay_fixup_one_phandle call. This avoids redundant phandle lookups when a single label is associated with multiple modifications. Signed-off-by: Zheng Guangyuan <1628513611@qq.com> Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index f500f2d..e19506f 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -315,7 +315,7 @@ static int overlay_update_local_references(void *fdto, uint32_t delta) * @name: Name of the property holding the phandle reference in the overlay * @name_len: number of name characters to consider * @poffset: Offset within the overlay property where the phandle is stored - * @label: Label of the node referenced by the phandle + * @phandle: Phandle referencing the node * * overlay_fixup_one_phandle() resolves an overlay phandle pointing to * a node in the base device tree. @@ -332,30 +332,14 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto, int symbols_off, const char *path, uint32_t path_len, const char *name, uint32_t name_len, - int poffset, const char *label) + int poffset, uint32_t phandle) { - const char *symbol_path; - uint32_t phandle; fdt32_t phandle_prop; - int symbol_off, fixup_off; - int prop_len; + int fixup_off; if (symbols_off < 0) return symbols_off; - symbol_path = fdt_getprop(fdt, symbols_off, label, - &prop_len); - if (!symbol_path) - return prop_len; - - symbol_off = fdt_path_offset(fdt, symbol_path); - if (symbol_off < 0) - return symbol_off; - - phandle = fdt_get_phandle(fdt, symbol_off); - if (!phandle) - return -FDT_ERR_NOTFOUND; - fixup_off = fdt_path_offset_namelen(fdto, path, path_len); if (fixup_off == -FDT_ERR_NOTFOUND) return -FDT_ERR_BADOVERLAY; @@ -394,6 +378,10 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, const char *value; const char *label; int len; + const char *symbol_path; + int prop_len; + int symbol_off; + uint32_t phandle; value = fdt_getprop_by_offset(fdto, property, &label, &len); @@ -404,6 +392,18 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, return len; } + symbol_path = fdt_getprop(fdt, symbols_off, label, &prop_len); + if (!symbol_path) + return prop_len; + + symbol_off = fdt_path_offset(fdt, symbol_path); + if (symbol_off < 0) + return symbol_off; + + phandle = fdt_get_phandle(fdt, symbol_off); + if (!phandle) + return -FDT_ERR_NOTFOUND; + do { const char *path, *name, *fixup_end; const char *fixup_str = value; @@ -445,7 +445,7 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off, path, path_len, name, name_len, - poffset, label); + poffset, phandle); if (ret) return ret; } while (len > 0); From c17d76ab5e84336bd98da30e0ea716f6a779e4ce Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Fri, 31 May 2024 08:31:49 -0500 Subject: [PATCH 223/298] checks: Check the overall length of "interrupt-map" It is possible the overall length of "interrupt-map" is shorter than expected. A likely scenario is if "#address-cells" in the interrupt parent is not accounted for and there is only a single map entry. With multiple entries, one of the other tests would likely fail. Signed-off-by: Rob Herring (Arm) Message-ID: <20240531133149.1498139-1-robh@kernel.org> Signed-off-by: David Gibson --- checks.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/checks.c b/checks.c index 2fb7ee5..10fb638 100644 --- a/checks.c +++ b/checks.c @@ -1675,6 +1675,10 @@ static void check_interrupt_map(struct check *c, parent_cellsize += propval_cell(cellprop); cell += 1 + parent_cellsize; + if (cell > map_cells) + FAIL_PROP(c, dti, node, irq_map_prop, + "property size (%d) mismatch, expected %zu", + irq_map_prop->val.len, cell * sizeof(cell_t)); } } WARNING(interrupt_map, check_interrupt_map, NULL, &phandle_references, &addr_size_cells, &interrupt_provider); From b98239da2f18d2bfe0934ac705ef8d8b92277f74 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Sun, 23 Jun 2024 21:20:57 -0500 Subject: [PATCH 224/298] tests/meson.build: fix python and yaml tests not running The run-tests.sh script attempts to detect if Python and Yaml support is enabled in the build. This has caused false-negatives where it fails to find the Python library even though it was compiled into the build. Avoid this problem altogether and always set the NO_PYTHON and NO_YAML to match if the features are enabled in Meson. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- tests/meson.build | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/meson.build b/tests/meson.build index 41e60f2..9cf6e3d 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -123,10 +123,13 @@ else env += [ 'PYTHON=' + py.full_path(), 'PYTHONPATH=' + meson.project_source_root() / 'pylibfdt', + 'NO_PYTHON=0', ] endif if not yaml.found() env += 'NO_YAML=1' +else + env += 'NO_YAML=0' endif run_test_types = [ From d598fc3648ecf9f6e5a3cc024ba83b1537bee753 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Sun, 23 Jun 2024 21:17:48 -0500 Subject: [PATCH 225/298] tests/run_tests.sh: fix Meson library path being dropped Meson automatically passes in LD_LIBRARY_PATH pointing at the correct build directory for libfdt.so. So preserve LD_LIBRARY_PATH if it's already set. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- tests/run_tests.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index b14c864..c5d6a88 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -55,7 +55,11 @@ fi if [ -z "$TEST_LIBDIR" ]; then TEST_LIBDIR=../libfdt fi -export LD_LIBRARY_PATH="$TEST_LIBDIR" +if [ -n "$LD_LIBRARY_PATH" ]; then + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$TEST_LIBDIR" +else + export LD_LIBRARY_PATH="$TEST_LIBDIR" +fi export QUIET_TEST=1 STOP_ON_FAIL=0 From 9e313b14e684bf7c9a12e989c2330f7533650cda Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Sun, 23 Jun 2024 16:29:01 -0500 Subject: [PATCH 226/298] pylibfdt/meson.build: fix Python library being rebuilt during install User @sharkcz noted that when the '--quiet' flag is removed from ./setup.py, the following can be seen from the `./setup.py install` stage. Running custom install script 'dtc/g/pylibfdt/../setup.py --top-builddir \ dtc/g/redhat-linux-build install --prefix=/usr/local --root=$DESTDIR' running install ... building '_libfdt' extension swigging dtc/g/pylibfdt/../pylibfdt/libfdt.i to \ dtc/g/pylibfdt/../pylibfdt/libfdt_wrap.c swig -python -Idtc/g/pylibfdt/../libfdt -o \ dtc/g/pylibfdt/../pylibfdt/libfdt_wrap.c dtc/g/pylibfdt/../pylibfdt/libfdt.i gcc -fno-strict-overflow -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 \ -DNDEBUG -fexceptions -fexceptions -fexceptions -fPIC -DPY_SSIZE_T_CLEAN \ -Idtc/g/pylibfdt/../libfdt -I/usr/include/python3.12 -c \ dtc/g/pylibfdt/../pylibfdt/libfdt_wrap.c -o \ build/temp.linux-ppc64le-cpython-312dtc/g/pylibfdt/../pylibfdt/libfdt_wrap.o creating build/lib.linux-ppc64le-cpython-312 gcc -shared build/temp.linux-ppc64le-cpython-312dtc/g/pylibfdt/../pylibfdt/libfdt_wrap.o \ -Ldtc/g/redhat-linux-build/libfdt -L/usr/lib64 -lfdt -o \ build/lib.linux-ppc64le-cpython-312/_libfdt.cpython-312-powerpc64le-linux-gnu.so copying dtc/g/pylibfdt/../pylibfdt/libfdt.py -> build/lib.linux-ppc64le-cpython-312 Meaning the python library is getting recompiled during the `meson install` phase. This causes build issues as Meson does not set the compiler and linker flags during the install phase. The reason the library is getting rebuilt is during the normal build with "build_ext", the `--build-lib` flag gets passed which changes the default output build directory. But there is no equivalent option for the "install" command. Install instead looks in the default directory "./build" and so does not find the previously built library. Since we can't fix the "install" command, drop the --build-lib flag. This causes setup.py to compile the libraries at `/build/lib.linux-x86_64-cpython-312/`. We must also then fix run_tests.sh to find the library build directory as it's machine-dependent. Fixes: #135 Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- pylibfdt/meson.build | 2 +- tests/run_tests.sh | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build index 978c53f..6157f8d 100644 --- a/pylibfdt/meson.build +++ b/pylibfdt/meson.build @@ -6,7 +6,7 @@ pylibfdt = custom_target( input: 'libfdt.i', depends: libfdt, output: '_libfdt.so', - command: [setup_py, 'build_ext', '--build-lib=' + meson.current_build_dir()], + command: [setup_py, 'build_ext'], build_by_default: true, ) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c5d6a88..937b128 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -18,7 +18,9 @@ if [ -n "$NO_PYTHON" ]; then no_python=false fi else - if [ -f ../pylibfdt/_libfdt.so ] || [ -f ../pylibfdt/_libfdt.cpython-3*.so ]; then + if [ -f ../pylibfdt/_libfdt.so ] \ + || [ -f ../pylibfdt/_libfdt.cpython-3*.so ] \ + || [ -f ../build/lib.*/_libfdt.cpython-3*.so ]; then no_python=false else no_python=true @@ -61,6 +63,16 @@ else export LD_LIBRARY_PATH="$TEST_LIBDIR" fi +# Find the python module that distutils builds under a machine-specific path +PYLIBFDT_BUILD=$(echo ../build/lib.*) +if [ -e "$PYLIBFDT_BUILD" ]; then + if [ -n "$PYTHONPATH" ]; then + export PYTHONPATH="$PYTHONPATH:$PYLIBFDT_BUILD" + else + export PYTHONPATH="$PYLIBFDT_BUILD" + fi +fi + export QUIET_TEST=1 STOP_ON_FAIL=0 From ff4f17eb58650784ffb2e8a8fbefebce1038f80b Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Mon, 24 Jun 2024 19:19:11 -0500 Subject: [PATCH 227/298] pylibfdt/Makefile.pylibfdt: fix Python library being rebuild during install The Python module gets built during the 'make install' command even if 'make all' was run prior for build. This is the same issue as described in the previous commit "pylibfdt/meson.build: fix Python library being rebuilt during install". Remove the '--build-lib' flag so setuptools can find the build module. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- pylibfdt/Makefile.pylibfdt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 82f565e..eee1701 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -17,7 +17,7 @@ endif $(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) @$(VECHO) PYMOD $@ - $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=$(PYLIBFDT_dir) + $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext install_pylibfdt: $(PYMODULE) @$(VECHO) INSTALL-PYLIB From 7b8a30eceabe7d8828d082c1bfe2458423bbac2f Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Sun, 30 Jun 2024 11:09:05 -0500 Subject: [PATCH 228/298] pylibfdt: fix Python version In commit "pylibfdt: Remove some apparently deprecated options from setup.py" the scm version tracking was removed. But it was not replaced with the fixed version. This causes the Python modules to be installed as version '0.0.0'. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 602caab..293bb6b 100755 --- a/setup.py +++ b/setup.py @@ -52,6 +52,7 @@ class build_py(_build_py): setup( name='libfdt', + version=version, cmdclass = {'build_py' : build_py}, author='Simon Glass', author_email='sjg@chromium.org', @@ -72,5 +73,4 @@ setup( "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", "Operating System :: OS Independent", ], - ) From ab86f1e9fda819a920d4243005bf282c0d7b5f4a Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Sun, 30 Jun 2024 11:11:24 -0500 Subject: [PATCH 229/298] pylibfdt: add VERSION.txt to Python sdist The VERSION.txt file tells setup.py what library version to use, so we must include it in the source distrbution. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST.in b/MANIFEST.in index c1c5e67..904d124 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -9,3 +9,4 @@ include pylibfdt/libfdt.i include libfdt/libfdt.h include libfdt/fdt.h include libfdt/libfdt_env.h +include VERSION.txt From d54aaf93673c78669468737f1cbc1b465d6adfa0 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Sun, 30 Jun 2024 10:59:55 -0500 Subject: [PATCH 230/298] pylibfdt: clean up python build directory In commit "pylibfdt/Makefile.pylibfdt: fix Python library being rebuild during install" the build directory moved to the top level of the repo. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- .gitignore | 1 + pylibfdt/Makefile.pylibfdt | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 8fdf112..8e1e0c0 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ ncscope.* .eggs/ build/ dist/ +*.egg-info/ diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index eee1701..73c8b76 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -6,8 +6,8 @@ PYLIBFDT_srcs = $(PYLIBFDT_dir)/libfdt.i PYMODULE = $(PYLIBFDT_dir)/_libfdt.so PYLIBFDT_CLEANFILES_L = libfdt_wrap.c libfdt.py *.pyc *.so PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%) -PYLIBFDT_CLEANDIRS_L = build __pycache__ -PYLIBFDT_CLEANDIRS = $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%) +PYLIBFDT_CLEANDIRS_L = __pycache__ libfdt.egg-info +PYLIBFDT_CLEANDIRS = build $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%) SETUP = ./setup.py From 49d30894466e78cc8fbc0c09dcdccdd4de709181 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Mon, 8 Apr 2024 22:27:13 -0500 Subject: [PATCH 231/298] meson: fix installation with meson-python The meson-python backend fails to map 'dtdiff' install into Python wheels. Removing the prefix from the install_dir path allows meson-python to map dtdiff. The install_data(install_dir) documentation says "If this is a relative path, it is assumed to be relative to the prefix"[1]. So removing the prefix does not change the installation behaviour. [1] https://mesonbuild.com/Reference-manual_functions.html#install_data Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 4bb1196..310699f 100644 --- a/meson.build +++ b/meson.build @@ -122,7 +122,7 @@ if get_option('tools') install_data( 'dtdiff', - install_dir: get_option('prefix') / get_option('bindir'), + install_dir: get_option('bindir'), install_mode: 'rwxr-xr-x', ) endif From 61e88fdcec522c42320a7d97cd528edf3631ee41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 26 Jun 2024 09:55:52 +0200 Subject: [PATCH 232/298] libfdt: overlay: Fix phandle overwrite check for new subtrees MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the overlay's target is only created in a previous fragment, it doesn't exist in the unmodified base device tree. For the phandle overwrite check this can be ignored because in this case the base tree doesn't contain a phandle that could be overwritten. Adapt the corresponding check to not error out if that happens but just continue with the next fragment. This is currently triggered by arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dtso in the kernel repository which creates /panel in its first fragment and modifies it in its second. Reported-by: Rob Herring Link: https://lore.kernel.org/all/CAL_JsqL9MPycDjqQfPNAuGfC6EMrdzUivr+fuOS7YgU3biGd4A@mail.gmail.com/ Fixes: 1fad065080e6 ("libfdt: overlay: ensure that existing phandles are not overwritten") Signed-off-by: Uwe Kleine-König Message-ID: <20240626075551.2493048-2-u.kleine-koenig@baylibre.com> Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 8 +++++++- tests/overlay_overlay_bypath.dts | 4 ++++ tests/overlay_overlay_no_fixups.dts | 8 ++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index e19506f..28b667f 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -729,7 +729,13 @@ static int overlay_prevent_phandle_overwrite(void *fdt, void *fdto) return overlay; target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL); - if (target < 0) + if (target == -FDT_ERR_NOTFOUND) + /* + * The subtree doesn't exist in the base, so nothing + * will be overwritten. + */ + continue; + else if (target < 0) return target; ret = overlay_prevent_phandle_overwrite_node(fdt, target, diff --git a/tests/overlay_overlay_bypath.dts b/tests/overlay_overlay_bypath.dts index f23e7b6..dfcb7cd 100644 --- a/tests/overlay_overlay_bypath.dts +++ b/tests/overlay_overlay_bypath.dts @@ -46,3 +46,7 @@ new-sub-test-property; }; }; + +&{/new-local-node} { + another-new-property; +}; diff --git a/tests/overlay_overlay_no_fixups.dts b/tests/overlay_overlay_no_fixups.dts index e8d0f96..1dbdcdc 100644 --- a/tests/overlay_overlay_no_fixups.dts +++ b/tests/overlay_overlay_no_fixups.dts @@ -72,6 +72,14 @@ }; }; + fragment@7 { + target-path = "/new-local-node"; + + __overlay__ { + another-new-property; + }; + }; + __local_fixups__ { fragment@5 { __overlay__ { From 1df7b047fe437708c70cbd2262557d19e40022a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Hor=C3=A1k?= Date: Thu, 27 Jun 2024 17:32:37 +0200 Subject: [PATCH 233/298] pylibfdt/Makefile.pylibfdt: use project's flags to compile the extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seems the project's CFLAGS are not used when compiling the python extension's C code via the setup.py script. Some default flags are used instead. Thus pass the CFLAGS explicitly. Unfortunately the SWIG generated code is not clean and requires -Wno-error override to compile successfully, because -Werror is used in the project's flags. Signed-off-by: Dan Horák Signed-off-by: David Gibson --- pylibfdt/Makefile.pylibfdt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 73c8b76..d20659c 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -17,7 +17,7 @@ endif $(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) @$(VECHO) PYMOD $@ - $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext + CFLAGS="$(CFLAGS) -Wno-error" $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext install_pylibfdt: $(PYMODULE) @$(VECHO) INSTALL-PYLIB From 84b056a89d3c5b6cf6c5eeeafd4c4b14d6333aa9 Mon Sep 17 00:00:00 2001 From: Michael Riesch Date: Wed, 31 Jul 2024 09:01:16 +0200 Subject: [PATCH 234/298] checks: relax graph checks for overlays In device tree overlays, the following patterns occur frequently: board.dts: /dts-v1/; / { display-controller { ports { #address-cells = <1>; #size-cells = <0>; vp0: port@0 { reg = <0>; vp0_out: endpoint { }; }; vp1: port@1 { reg = <1>; }; }; }; }; overlay-endpoint.dtso: /dts-v1/; /plugin/; &{/} { hdmi-tx-connector { port { hdmi_tx_in: endpoint { remote-endpoint = <&vp0_out>; }; }; }; }; &vp0_out { remote-endpoint = <&hdmi_tx_in>; }; In this case, dtc expects that the node referenced by &vp0_out is named "endpoint", but the name cannot be inferred. Also, dtc complains about the connections between the endpoints not being bidirectional. Similarly, for a different overlay overlay-port.dtso: /dts-v1/; /plugin/; &{/} { panel { port { panel_in: endpoint { remote-endpoint = <&vp1_out>; }; }; }; }; &vp1 { vp1_out: endpoint { remote-endpoint = <&panel_in>; }; }; dtc expects that the node referenced by &vp1 is named "port", but the name cannot be inferred. Relax the corresponding checks and skip the parts that are not reasonable for device tree overlays. Signed-off-by: Michael Riesch Signed-off-by: David Gibson --- checks.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/checks.c b/checks.c index 10fb638..6e06aea 100644 --- a/checks.c +++ b/checks.c @@ -1826,10 +1826,14 @@ static void check_graph_port(struct check *c, struct dt_info *dti, if (node->bus != &graph_port_bus) return; + check_graph_reg(c, dti, node); + + /* skip checks below for overlays */ + if (dti->dtsflags & DTSF_PLUGIN) + return; + if (!strprefixeq(node->name, node->basenamelen, "port")) FAIL(c, dti, node, "graph port node name should be 'port'"); - - check_graph_reg(c, dti, node); } WARNING(graph_port, check_graph_port, NULL, &graph_nodes); @@ -1864,11 +1868,15 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti, if (!node->parent || node->parent->bus != &graph_port_bus) return; + check_graph_reg(c, dti, node); + + /* skip checks below for overlays */ + if (dti->dtsflags & DTSF_PLUGIN) + return; + if (!strprefixeq(node->name, node->basenamelen, "endpoint")) FAIL(c, dti, node, "graph endpoint node name should be 'endpoint'"); - check_graph_reg(c, dti, node); - remote_node = get_remote_endpoint(c, dti, node); if (!remote_node) return; From bcd02b523429fed05fdf3751e7074367741bbfbd Mon Sep 17 00:00:00 2001 From: Markus Heidelberg Date: Fri, 9 Aug 2024 09:05:27 +0200 Subject: [PATCH 235/298] fdtoverlay: remove wrong singular article in a comment Signed-off-by: Markus Heidelberg Signed-off-by: David Gibson --- fdtoverlay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdtoverlay.c b/fdtoverlay.c index 4eba046..699b4f6 100644 --- a/fdtoverlay.c +++ b/fdtoverlay.c @@ -48,7 +48,7 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len, int ret; /* - * We take a copies first, because a failed apply can trash + * We take copies first, because a failed apply can trash * both the base blob and the overlay */ tmpo = xmalloc(fdt_totalsize(overlay)); From 3501d373f0a24d29814d8111a13de62d88ab86bd Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 11 Aug 2024 09:02:43 -0600 Subject: [PATCH 236/298] Require Python 3 We don't need to support Python 2 anymore, so drop the comment and add the minimum required version. Use version 3.8 since I am not sure that it works on older versions and 3.7 has reached end-of-life. Signed-off-by: Simon Glass Message-ID: <20240811150248.7537-1-sjg@chromium.org> Signed-off-by: David Gibson --- setup.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 293bb6b..749bf1b 100755 --- a/setup.py +++ b/setup.py @@ -1,9 +1,6 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) -# While Python 3 is the default, it's also possible to invoke -# this setup.py script with Python 2. - """ setup.py file for SWIG libfdt Copyright (C) 2017 Google, Inc. @@ -60,6 +57,7 @@ setup( ext_modules=[libfdt_module], package_dir={'': os.path.join(srcdir, 'pylibfdt')}, py_modules=['libfdt'], + python_requires=">=3.8", long_description=long_description, long_description_content_type="text/plain", From 78b6a85c113b011cbb9294e68aa42cb89c45e4e1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 11 Aug 2024 09:02:44 -0600 Subject: [PATCH 237/298] Tidy up some pylint warnings Resolve all the pylint warnings currently in setup.py Signed-off-by: Simon Glass Message-ID: <20240811150248.7537-2-sjg@chromium.org> Signed-off-by: David Gibson --- setup.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/setup.py b/setup.py index 749bf1b..4e880e4 100755 --- a/setup.py +++ b/setup.py @@ -7,28 +7,32 @@ Copyright (C) 2017 Google, Inc. Written by Simon Glass """ +import os +import sys + from setuptools import setup, Extension from setuptools.command.build_py import build_py as _build_py -import os -import re -import sys srcdir = os.path.dirname(__file__) -with open(os.path.join(srcdir, "README.md"), "r") as fh: +with open(os.path.join(srcdir, "README.md"), "r", encoding='utf-8') as fh: long_description = fh.read() -with open(os.path.join(srcdir, "VERSION.txt"), "r") as fh: +with open(os.path.join(srcdir, "VERSION.txt"), "r", encoding='utf-8') as fh: version = fh.readline().strip() def get_top_builddir(): + """Figure out the top-level directory containing the source code + + Returns: + str: Directory to build in + """ if '--top-builddir' in sys.argv: index = sys.argv.index('--top-builddir') sys.argv.pop(index) return sys.argv.pop(index) - else: - return srcdir + return srcdir top_builddir = get_top_builddir() @@ -42,15 +46,18 @@ libfdt_module = Extension( swig_opts=['-I' + os.path.join(srcdir, 'libfdt')], ) -class build_py(_build_py): + +class BuildPy(_build_py): + """Small class to run the build_ext command""" def run(self): self.run_command("build_ext") return super().run() + setup( name='libfdt', version=version, - cmdclass = {'build_py' : build_py}, + cmdclass = {'build_py' : BuildPy}, author='Simon Glass', author_email='sjg@chromium.org', description='Python binding for libfdt', From 7e5a88984081c29097c8cfa4bb666ef9174b6ca5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 11 Aug 2024 09:02:45 -0600 Subject: [PATCH 238/298] setup: Move version and full_description into a function Do this processing in a function and return the result, to reduce the amount of code at the top level. Signed-off-by: Simon Glass Message-ID: <20240811150248.7537-3-sjg@chromium.org> Signed-off-by: David Gibson --- setup.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 4e880e4..eb0963c 100755 --- a/setup.py +++ b/setup.py @@ -16,11 +16,24 @@ from setuptools.command.build_py import build_py as _build_py srcdir = os.path.dirname(__file__) -with open(os.path.join(srcdir, "README.md"), "r", encoding='utf-8') as fh: - long_description = fh.read() +def scan_for_info(srcdir): + """Scan for the version and long_description fields + + Args: + srcdir (str): Source-directory path + + Returns: tuple + str: Full description (contents of README.md) + str: Version string + """ + with open(os.path.join(srcdir, "VERSION.txt"), "r", encoding='utf-8') as fh: + version = fh.readline().strip() + + with open(os.path.join(srcdir, "README.md"), "r", encoding='utf-8') as fh: + long_description = fh.read() + + return version, long_description -with open(os.path.join(srcdir, "VERSION.txt"), "r", encoding='utf-8') as fh: - version = fh.readline().strip() def get_top_builddir(): """Figure out the top-level directory containing the source code @@ -53,6 +66,7 @@ class BuildPy(_build_py): self.run_command("build_ext") return super().run() +version, long_description = scan_for_info(srcdir) setup( name='libfdt', From e277553b98800f4071017e04166573349aa5078c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 11 Aug 2024 09:02:46 -0600 Subject: [PATCH 239/298] setup: Collect top-level code together Move most of the top-level code together, with the classes and functions above, for easier reading. The srcdir is left where it is for now. Signed-off-by: Simon Glass Message-ID: <20240811150248.7537-4-sjg@chromium.org> Signed-off-by: David Gibson --- setup.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index eb0963c..be3cf90 100755 --- a/setup.py +++ b/setup.py @@ -47,6 +47,15 @@ def get_top_builddir(): return sys.argv.pop(index) return srcdir + +class BuildPy(_build_py): + """Small class to run the build_ext command""" + def run(self): + self.run_command("build_ext") + return super().run() + + +version, long_description = scan_for_info(srcdir) top_builddir = get_top_builddir() libfdt_module = Extension( @@ -60,14 +69,6 @@ libfdt_module = Extension( ) -class BuildPy(_build_py): - """Small class to run the build_ext command""" - def run(self): - self.run_command("build_ext") - return super().run() - -version, long_description = scan_for_info(srcdir) - setup( name='libfdt', version=version, From 3d5e376925fd15d8990c8a4ddcfff5f68150cf72 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 11 Aug 2024 09:02:47 -0600 Subject: [PATCH 240/298] setup: Move setting of srcdir down to the bottom Put this variable assignment next to the others. Pass it to get_top_builddir() instead of relying on the global variable. Signed-off-by: Simon Glass Message-ID: <20240811150248.7537-5-sjg@chromium.org> Signed-off-by: David Gibson --- setup.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index be3cf90..52844ce 100755 --- a/setup.py +++ b/setup.py @@ -14,8 +14,6 @@ from setuptools import setup, Extension from setuptools.command.build_py import build_py as _build_py -srcdir = os.path.dirname(__file__) - def scan_for_info(srcdir): """Scan for the version and long_description fields @@ -35,9 +33,12 @@ def scan_for_info(srcdir): return version, long_description -def get_top_builddir(): +def get_top_builddir(srcdir): """Figure out the top-level directory containing the source code + Args: + srcdir (str): Source-directory path + Returns: str: Directory to build in """ @@ -55,8 +56,8 @@ class BuildPy(_build_py): return super().run() +srcdir = os.path.dirname(__file__) version, long_description = scan_for_info(srcdir) -top_builddir = get_top_builddir() libfdt_module = Extension( '_libfdt', @@ -64,7 +65,7 @@ libfdt_module = Extension( define_macros=[('PY_SSIZE_T_CLEAN', None)], include_dirs=[os.path.join(srcdir, 'libfdt')], libraries=['fdt'], - library_dirs=[os.path.join(top_builddir, 'libfdt')], + library_dirs=[os.path.join(get_top_builddir(srcdir), 'libfdt')], swig_opts=['-I' + os.path.join(srcdir, 'libfdt')], ) From 99031e3a4a6e479466ae795790b44727434ca27d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sat, 17 Aug 2024 18:22:16 +1000 Subject: [PATCH 241/298] Bump version to v1.7.1 Prepare for a new release. Signed-off-by: David Gibson --- VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.txt b/VERSION.txt index bd8bf88..943f9cb 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -1.7.0 +1.7.1 From 9b5f65fb3d8dd5fd3564fdd00b21d6685b019ba8 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 3 Oct 2024 08:15:40 +0200 Subject: [PATCH 242/298] libfdt.h: typo and consistency fixes Most of these are plain typos. Exceptions: - "devicetree" is only used in that form in the grammar and in mailing list references; all other instances, in particular all in prose, use "device tree". - I don't know what "nodeequested" was supposed to be, the sentence reads just fine without it. - "inexistant" is a rare form of nonexistent. Signed-off-by: Rasmus Villemoes Signed-off-by: David Gibson --- libfdt/libfdt.h | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 0677fea..42e59fd 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -285,7 +285,7 @@ size_t fdt_header_size(const void *fdt); /** * fdt_header_size_ - internal function to get header size from a version number - * @version: devicetree version number + * @version: device tree version number * * Return: size of DTB header in bytes */ @@ -764,7 +764,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, * to within the device blob itself, not a copy of the value). If * lenp is non-NULL, the length of the property value is also * returned, in the integer pointed to by lenp. If namep is non-NULL, - * the property's namne will also be returned in the char * pointed to + * the property's name will also be returned in the char * pointed to * by namep (this will be a pointer to within the device tree's string * block, not a new copy of the name). * @@ -772,7 +772,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, * pointer to the property's value * if lenp is non-NULL, *lenp contains the length of the property * value (>=0) - * if namep is non-NULL *namep contiains a pointer to the property + * if namep is non-NULL *namep contains a pointer to the property * name. * NULL, on error * if lenp is non-NULL, *lenp contains an error code (<0): @@ -866,7 +866,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); /** * fdt_get_alias_namelen - get alias based on substring * @fdt: pointer to the device tree blob - * @name: name of the alias th look up + * @name: name of the alias to look up * @namelen: number of characters of name to consider * * Identical to fdt_get_alias(), but only examine the first @namelen @@ -883,7 +883,7 @@ const char *fdt_get_alias_namelen(const void *fdt, /** * fdt_get_alias - retrieve the path referenced by a given alias * @fdt: pointer to the device tree blob - * @name: name of the alias th look up + * @name: name of the alias to look up * * fdt_get_alias() retrieves the value of a given alias. That is, the * value of the property named @name in the node /aliases. @@ -1698,7 +1698,7 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, * @len: length of the property value * @prop_data: return pointer to property data * - * fdt_setprop_placeholer() allocates the named property in the given node. + * fdt_setprop_placeholder() allocates the named property in the given node. * If the property exists it is resized. In either case a pointer to the * property data is returned. * @@ -2059,7 +2059,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, * @nodeoffset: offset of the node whose property to nop * @name: name of the property to nop * - * fdt_del_property() will delete the given property. + * fdt_delprop() will delete the given property. * * This function will delete data from the blob, and will therefore * change the offsets of some existing nodes. @@ -2111,8 +2111,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, * change the offsets of some existing nodes. * * returns: - * structure block offset of the created nodeequested subnode (>=0), on - * success + * structure block offset of the created subnode (>=0), on success * -FDT_ERR_NOTFOUND, if the requested subnode does not exist * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE * tag @@ -2167,7 +2166,7 @@ int fdt_del_node(void *fdt, int nodeoffset); * returns: * 0, on success * -FDT_ERR_NOSPACE, there's not enough space in the base device tree - * -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or + * -FDT_ERR_NOTFOUND, the overlay points to some nonexistent nodes or * properties in the base DT * -FDT_ERR_BADPHANDLE, * -FDT_ERR_BADOVERLAY, From f9968fa06921b2ab82f9a7e39a0042d5d57511fa Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 3 Oct 2024 08:16:24 +0200 Subject: [PATCH 243/298] libfdt.h: whitespace consistency fixups In these cases, spaces are used for indentation/alignment while the surrounding lines use tab. Fix it up for consistency. Signed-off-by: Rasmus Villemoes Signed-off-by: David Gibson --- libfdt/libfdt.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 42e59fd..96782bc 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -14,7 +14,7 @@ extern "C" { #endif #define FDT_FIRST_SUPPORTED_VERSION 0x02 -#define FDT_LAST_COMPATIBLE_VERSION 0x10 +#define FDT_LAST_COMPATIBLE_VERSION 0x10 #define FDT_LAST_SUPPORTED_VERSION 0x11 /* Error codes: informative error codes */ @@ -554,7 +554,7 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); * -FDT_ERR_BADPATH, given path does not begin with '/' and the first * component is not a valid alias * -FDT_ERR_NOTFOUND, if the requested node does not exist - * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, @@ -599,7 +599,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); * structure block offset of the property (>=0), on success * -FDT_ERR_NOTFOUND, if the requested node has no properties * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, @@ -620,7 +620,7 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset); * structure block offset of the next property (>=0), on success * -FDT_ERR_NOTFOUND, if the given property is the last in its node * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag - * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, @@ -1259,8 +1259,8 @@ const char *fdt_stringlist_get(const void *fdt, int nodeoffset, * * returns: * 0 <= n < FDT_MAX_NCELLS, on success - * 2, if the node has no #address-cells property - * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * 2, if the node has no #address-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid * #address-cells property * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, @@ -1280,8 +1280,8 @@ int fdt_address_cells(const void *fdt, int nodeoffset); * * returns: * 0 <= n < FDT_MAX_NCELLS, on success - * 1, if the node has no #size-cells property - * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * 1, if the node has no #size-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid * #size-cells property * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, @@ -2121,7 +2121,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, * blob to contain the new node * -FDT_ERR_NOSPACE * -FDT_ERR_BADLAYOUT - * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, From 18aa49a9f68dfa2a00edee071a95019ed30da9f7 Mon Sep 17 00:00:00 2001 From: Colin Finck Date: Mon, 21 Oct 2024 13:34:25 +0200 Subject: [PATCH 244/298] Escape spaces in depfile with backslashes. This matches how Linux escapes spaces in paths. The same syntax is also used by other build tools that output depfiles, e.g. https://github.com/rust-lang/cargo/blob/edd36eba5e0d6e0cfcb84bd0cc651ba8bf5e7f83/src/cargo/core/compiler/output_depinfo.rs#L19 Signed-off-by: Colin Finck Signed-off-by: David Gibson --- dtc.c | 4 +++- srcpos.c | 6 ++++-- util.c | 16 ++++++++++++++++ util.h | 5 +++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/dtc.c b/dtc.c index 0655c2e..beda8d5 100644 --- a/dtc.c +++ b/dtc.c @@ -289,7 +289,9 @@ int main(int argc, char *argv[]) if (!depfile) die("Couldn't open dependency file %s: %s\n", depname, strerror(errno)); - fprintf(depfile, "%s:", outname); + + fprint_path_escaped(depfile, outname); + fputc(':', depfile); } if (inform == NULL) diff --git a/srcpos.c b/srcpos.c index 8e4d18a..5e2f7dd 100644 --- a/srcpos.c +++ b/srcpos.c @@ -160,8 +160,10 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep) strerror(errno)); } - if (depfile) - fprintf(depfile, " %s", fullname); + if (depfile) { + fputc(' ', depfile); + fprint_path_escaped(depfile, fullname); + } if (fullnamep) *fullnamep = fullname; diff --git a/util.c b/util.c index 507f012..4125923 100644 --- a/util.c +++ b/util.c @@ -23,6 +23,22 @@ #include "util.h" #include "version_gen.h" +void fprint_path_escaped(FILE *fp, const char *path) +{ + const char *p = path; + + while (*p) { + if (*p == ' ') { + fputc('\\', fp); + fputc(' ', fp); + } else { + fputc(*p, fp); + } + + p++; + } +} + char *xstrdup(const char *s) { int len = strlen(s) + 1; diff --git a/util.h b/util.h index b448cd7..800f2e2 100644 --- a/util.h +++ b/util.h @@ -42,6 +42,11 @@ static inline void NORETURN PRINTF(1, 2) die(const char *str, ...) exit(1); } +/** + * Writes path to fp, escaping spaces with a backslash. + */ +void fprint_path_escaped(FILE *fp, const char *path); + static inline void *xmalloc(size_t len) { void *new = malloc(len); From d1e2384185c5eeb8e238f7a8174ff43ea0da5d92 Mon Sep 17 00:00:00 2001 From: Markus Volk Date: Mon, 28 Oct 2024 18:26:45 +0100 Subject: [PATCH 245/298] pylibfdt/libfdt.i: Use SWIG_AppendOutput MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Swig has changed language specific AppendOutput functions. The helper macro SWIG_AppendOutput remains unchanged. Use that instead of SWIG_Python_AppendOutput, which would require an extra parameter since swig 4.3.0. | /home/flk/poky/build-hypr/tmp/work/x86_64-linux/python3-dtc-native/1.7.0/git/pylibfdt/libfdt_wrap.c: In function ‘_wrap_fdt_next_node’: | /home/flk/poky/build-hypr/tmp/work/x86_64-linux/python3-dtc-native/1.7.0/git/pylibfdt/libfdt_wrap.c:5598:17: error: too few arguments to function ‘SWIG_Python_AppendOutput’ | 5598 | resultobj = SWIG_Python_AppendOutput(resultobj, val); Signed-off-by: Markus Volk Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index bbc91ad..9f5b6a9 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -1137,7 +1137,7 @@ typedef uint32_t fdt32_t; fdt_string(fdt1, fdt32_to_cpu($1->nameoff))); buff = PyByteArray_FromStringAndSize( (const char *)($1 + 1), fdt32_to_cpu($1->len)); - resultobj = SWIG_Python_AppendOutput(resultobj, buff); + resultobj = SWIG_AppendOutput(resultobj, buff); } } @@ -1178,7 +1178,7 @@ typedef uint32_t fdt32_t; %typemap(argout) int *depth { PyObject *val = Py_BuildValue("i", *arg$argnum); - resultobj = SWIG_Python_AppendOutput(resultobj, val); + resultobj = SWIG_AppendOutput(resultobj, val); } %apply int *depth { int *depth }; @@ -1190,7 +1190,7 @@ typedef uint32_t fdt32_t; %typemap(argout) uint64_t * { PyObject *val = PyLong_FromUnsignedLongLong(*arg$argnum); - resultobj = SWIG_Python_AppendOutput(resultobj, val); + resultobj = SWIG_AppendOutput(resultobj, val); } %include "cstring.i" From 838f11e830e31cdd99e39c4134068bf36e4d9796 Mon Sep 17 00:00:00 2001 From: Amjad Alsharafi Date: Mon, 28 Oct 2024 11:57:28 +0800 Subject: [PATCH 246/298] fdtoverlay: provide better error message for missing `/__symbols__` This was added because trying to apply overlay on dtb without knowing a lot about the subject can be frustrating with strange error messages. Before this, it will tell you: `Failed to apply 'overlay.dtbo': FDT_ERR_BADOFFSET` This message is similar to what's shown in `u-boot` when trying to apply overlay Signed-off-by: Amjad Alsharafi Signed-off-by: David Gibson --- fdtoverlay.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fdtoverlay.c b/fdtoverlay.c index 699b4f6..ee1eb8f 100644 --- a/fdtoverlay.c +++ b/fdtoverlay.c @@ -46,6 +46,7 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len, char *tmp = NULL; char *tmpo; int ret; + bool has_symbols; /* * We take copies first, because a failed apply can trash @@ -62,6 +63,8 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len, fdt_strerror(ret)); goto fail; } + ret = fdt_path_offset(tmp, "/__symbols__"); + has_symbols = ret >= 0; memcpy(tmpo, overlay, fdt_totalsize(overlay)); @@ -74,6 +77,11 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len, if (ret) { fprintf(stderr, "\nFailed to apply '%s': %s\n", name, fdt_strerror(ret)); + if (!has_symbols) { + fprintf(stderr, + "base blob does not have a '/__symbols__' node, " + "make sure you have compiled the base blob with '-@' option\n"); + } goto fail; } From 48795c82bdb6cbc597853293fbb41799ccecb5c2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 6 Nov 2024 14:00:45 +1100 Subject: [PATCH 247/298] pylibfdt: Don't emit warnings from swig generate C code The swig generated code has a heap of warnings with the flags we usually use. These aren't helpful, since there's nothing we can do about them from the dtc side. So, just disable the warnings flags when compiling the Python module. Signed-off-by: David Gibson --- pylibfdt/Makefile.pylibfdt | 1 + 1 file changed, 1 insertion(+) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index d20659c..647203f 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -15,6 +15,7 @@ ifndef V SETUPFLAGS += --quiet endif +$(PYMODULE): WARNINGS = # suppress warnings from generated code $(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) @$(VECHO) PYMOD $@ CFLAGS="$(CFLAGS) -Wno-error" $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext From 2d10aa2afe35527728db30b35ec491ecb6959e5c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 6 Nov 2024 14:01:37 +1100 Subject: [PATCH 248/298] Bump version to v1.7.2 Prepare for a new release. Signed-off-by: David Gibson --- VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.txt b/VERSION.txt index 943f9cb..f8a696c 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -1.7.1 +1.7.2 From b75515af4576173850734d6aed87069cef733961 Mon Sep 17 00:00:00 2001 From: Bingwu Zhang Date: Sat, 16 Nov 2024 18:12:28 +0800 Subject: [PATCH 249/298] libfdt: Remove extra semi-colons outside functions When compiling with -Werror -Wpedantic, both GCC and Clang fails, saying that these semi-colons are redundant, so remove them. Signed-off-by: Bingwu Zhang Message-ID: <20241116101228.164707-6-xtex@envs.net> Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 2 +- libfdt/libfdt.h | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index 28b667f..f61ca7e 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -351,7 +351,7 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto, name, name_len, poffset, &phandle_prop, sizeof(phandle_prop)); -}; +} /** * overlay_fixup_phandle - Set an overlay phandle to the base one diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 96782bc..2e182ea 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -263,16 +263,16 @@ int fdt_next_subnode(const void *fdt, int offset); struct fdt_header *fdth = (struct fdt_header *)fdt; \ fdth->name = cpu_to_fdt32(val); \ } -fdt_set_hdr_(magic); -fdt_set_hdr_(totalsize); -fdt_set_hdr_(off_dt_struct); -fdt_set_hdr_(off_dt_strings); -fdt_set_hdr_(off_mem_rsvmap); -fdt_set_hdr_(version); -fdt_set_hdr_(last_comp_version); -fdt_set_hdr_(boot_cpuid_phys); -fdt_set_hdr_(size_dt_strings); -fdt_set_hdr_(size_dt_struct); +fdt_set_hdr_(magic) +fdt_set_hdr_(totalsize) +fdt_set_hdr_(off_dt_struct) +fdt_set_hdr_(off_dt_strings) +fdt_set_hdr_(off_mem_rsvmap) +fdt_set_hdr_(version) +fdt_set_hdr_(last_comp_version) +fdt_set_hdr_(boot_cpuid_phys) +fdt_set_hdr_(size_dt_strings) +fdt_set_hdr_(size_dt_struct) #undef fdt_set_hdr_ /** From d1656730abfb8ce293af278a8d1f74456c137389 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Sat, 16 Nov 2024 11:28:16 +0000 Subject: [PATCH 250/298] Add a SBOM file in CycloneDX format Improve supply chain security by including a SBOM file with substituted values. This will be used to construct a composite platform SBOM. Signed-off-by: Richard Hughes Signed-off-by: David Gibson --- libfdt/sbom.cdx.json | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 libfdt/sbom.cdx.json diff --git a/libfdt/sbom.cdx.json b/libfdt/sbom.cdx.json new file mode 100644 index 0000000..303cf54 --- /dev/null +++ b/libfdt/sbom.cdx.json @@ -0,0 +1,41 @@ +{ + "bomFormat": "CycloneDX", + "specVersion": "1.6", + "version": 1, + "components": [ + { + "type": "library", + "bom-ref": "pkg:github/dgibson/libfdt@@VCS_TAG@", + "cpe": "cpe:2.3:a:dgibson:libfdt:@VCS_TAG@:*:*:*:*:*:*:*", + "name": "libfdt", + "version": "@VCS_VERSION@", + "description": "Utility library for reading and manipulating the FDT binary format", + "authors": [ + { + "name": "@VCS_SBOM_AUTHORS@" + } + ], + "supplier": { + "name": "libfdt developers" + }, + "licenses": [ + { + "license": { + "id": "BSD-2-Clause" + } + }, + { + "license": { + "id": "GPL-2.0-or-later" + } + } + ], + "externalReferences": [ + { + "type": "vcs", + "url": "https://github.com/dgibson/dtc" + } + ] + } + ] +} From b3bbee6b1242b4bb84fcb31365b76a3a45be3b6b Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Mon, 18 Nov 2024 09:18:08 +0000 Subject: [PATCH 251/298] libfdt: Move the SBOM authors section I was mistaken, and another maintainer pointed out the author-of-this-file metadata needs to be in a different place. Apologies for the churn. Signed-off-by: Richard Hughes Signed-off-by: David Gibson --- libfdt/sbom.cdx.json | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libfdt/sbom.cdx.json b/libfdt/sbom.cdx.json index 303cf54..4d023e5 100644 --- a/libfdt/sbom.cdx.json +++ b/libfdt/sbom.cdx.json @@ -2,6 +2,13 @@ "bomFormat": "CycloneDX", "specVersion": "1.6", "version": 1, + "metadata": { + "authors": [ + { + "name": "@VCS_SBOM_AUTHORS@" + } + ] + }, "components": [ { "type": "library", @@ -10,11 +17,6 @@ "name": "libfdt", "version": "@VCS_VERSION@", "description": "Utility library for reading and manipulating the FDT binary format", - "authors": [ - { - "name": "@VCS_SBOM_AUTHORS@" - } - ], "supplier": { "name": "libfdt developers" }, From 1c745a9bd169e9e5ecd213ebb1e814754d831d21 Mon Sep 17 00:00:00 2001 From: Bingwu Zhang Date: Sat, 23 Nov 2024 17:48:14 +0800 Subject: [PATCH 252/298] libfdt: Remove fdt parameter from overlay_fixup_one_phandle When compiling with -Wall -Wextra, the unused fdt parameter becomes a warning. With -Werror, it becomes an error and fails the build. As the parameter is not used in the function, let's remove it. Signed-off-by: Bingwu Zhang Message-ID: <20241123094814.15504-2-xtex@envs.net> Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index f61ca7e..e6b9eb6 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -307,7 +307,6 @@ static int overlay_update_local_references(void *fdto, uint32_t delta) /** * overlay_fixup_one_phandle - Set an overlay phandle to the base one - * @fdt: Base Device Tree blob * @fdto: Device tree overlay blob * @symbols_off: Node offset of the symbols node in the base device tree * @path: Path to a node holding a phandle in the overlay @@ -328,8 +327,7 @@ static int overlay_update_local_references(void *fdto, uint32_t delta) * 0 on success * Negative error code on failure */ -static int overlay_fixup_one_phandle(void *fdt, void *fdto, - int symbols_off, +static int overlay_fixup_one_phandle(void *fdto, int symbols_off, const char *path, uint32_t path_len, const char *name, uint32_t name_len, int poffset, uint32_t phandle) @@ -443,7 +441,7 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, if ((*endptr != '\0') || (endptr <= (sep + 1))) return -FDT_ERR_BADOVERLAY; - ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off, + ret = overlay_fixup_one_phandle(fdto, symbols_off, path, path_len, name, name_len, poffset, phandle); if (ret) From 4292b072a23a281fe3ff6c59f0d7985e37fd8454 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Sun, 24 Nov 2024 16:01:47 -0600 Subject: [PATCH 253/298] .github/workflows: update ubuntu runner to supported version The Ubuntu runner fails with the following message > E: The repository 'http://security.ubuntu.com/ubuntu mantic-security Release' does not have a Release file. Ubuntu 23.10 is end-of-life as of July 2024 anyway. So switch to the latest Ubuntu tag, which is currently 24.04. See https://discourse.ubuntu.com/t/edubuntu-23-10-has-reached-end-of-life-eol/46325 Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 200c9b7..a030ae6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ "alpine", "archlinux", "fedora", "ubuntu:23.10" ] + os: [ "alpine", "archlinux", "fedora", "ubuntu" ] container: image: ${{ matrix.os }} @@ -48,7 +48,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ "alpine", "archlinux", "fedora", "ubuntu:23.10" ] + os: [ "alpine", "archlinux", "fedora", "ubuntu" ] container: image: ${{ matrix.os }} From 9a969f3b70b07bbf1c9df44a38d7f8d1d3a6e2a5 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Sun, 24 Nov 2024 15:48:04 -0600 Subject: [PATCH 254/298] pylibfdt/libfdt.i: fix backwards compatibility of return values When our Python functions wrap `fdt_getprop()` they return a list containing `[*data, length]`. In SWIG v4.2 and earlier SWIG would discard `*data` if it is NULL/None. Causing the return value to just be `length`. But starting in SWIG v4.3 it no longer discards `*data`. So the return value is now `[None, length]`. Handle this compatibility issue in libfdt.i by checking if the return value looks like the older 4.2 return value, and casting it to the newer style. See https://github.com/swig/swig/pull/2907 Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 9f5b6a9..bb9985c 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -114,11 +114,14 @@ def check_err_null(val, quiet=()): FdtException if val indicates an error was reported and the error is not in @quiet. """ - # Normally a list is returned which contains the data and its length. - # If we get just an integer error code, it means the function failed. + # Compatibility for SWIG v4.2 and earlier. SWIG 4.2 would drop the first + # item from the list if it was None, returning only the second item. if not isinstance(val, list): - if -val not in quiet: - raise FdtException(val) + val = [None, val] + + if val[0] is None: + if -val[1] not in quiet: + raise FdtException(val[1]) return val class FdtRo(object): @@ -395,8 +398,8 @@ class FdtRo(object): """ pdata = check_err_null( fdt_get_property_by_offset(self._fdt, prop_offset), quiet) - if isinstance(pdata, (int)): - return pdata + if pdata[0] is None: + return pdata[1] return Property(pdata[0], pdata[1]) def getprop(self, nodeoffset, prop_name, quiet=()): @@ -417,8 +420,8 @@ class FdtRo(object): """ pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), quiet) - if isinstance(pdata, (int)): - return pdata + if pdata[0] is None: + return pdata[1] return Property(prop_name, bytearray(pdata[0])) def hasprop(self, nodeoffset, prop_name, quiet=()): @@ -444,10 +447,10 @@ class FdtRo(object): """ pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), quiet + (NOTFOUND,)) - if isinstance(pdata, (int)): - if pdata == -NOTFOUND: + if pdata[0] is None: + if pdata[1] == -NOTFOUND: return False - return pdata + return pdata[1] return True def get_phandle(self, nodeoffset): From 66c7d0e6f4f3c43636c70bab9ced2e157b4acf62 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Sat, 23 Nov 2024 13:21:28 -0600 Subject: [PATCH 255/298] tests/sw_tree1.c: fix unitialized saveptr Building the dtc tests on the Conda build system results in the following error. > In function '__strtok_r_1c', 2024-11-23T19:17:20.7930512Z inlined from 'main' at ../tests/sw_tree1.c:140:17: > $BUILD_PREFIX/x86_64-conda-linux-gnu/sysroot/usr/include/bits/string2.h:1177:10: error: 'saveptr' may be used uninitialized [-Werror=maybe-uninitialized] > 1177 | while (*__s == __sep) > | ^~~~ > ../tests/sw_tree1.c: In function 'main': > ../tests/sw_tree1.c:137:39: note: 'saveptr' was declared here > 137 | char *str = argv[2], *saveptr, *tok; > | ^~~~~~~ > cc1: all warnings being treated as errors The manpage `strtok(3)` says the following. > VERSIONS > On some implementations, *saveptr is required to be NULL on the first call to strtok_r() that is being used to parse str. So set it to NULL. Signed-off-by: Brandon Maier --- tests/sw_tree1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 7069ace..7aa808c 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -134,7 +134,7 @@ int main(int argc, char *argv[]) } } if (argc == 3) { - char *str = argv[2], *saveptr, *tok; + char *str = argv[2], *saveptr = NULL, *tok; bool default_flag = false; while ((tok = strtok_r(str, ",", &saveptr)) != NULL) { From 6f183c7d9246bde8f05d2edbc31fdd497c4a8702 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 6 Nov 2024 14:01:08 +0100 Subject: [PATCH 256/298] checks: Relax avoid_unnecessary_addr_size check to allow child ranges properties Do not fail the unnecessary #address-cells/#size-cells check if any children of the node have a "ranges" property. Suggested-by: Rob Herring Link: https://lore.kernel.org/all/CAL_JsqKebRL454poAYZ9i=sCsHqGzmocLy0psQcng-79UWJB-A@mail.gmail.com/ Signed-off-by: Philipp Zabel Message-ID: <20241106130108.852323-1-p.zabel@pengutronix.de> Signed-off-by: David Gibson --- checks.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/checks.c b/checks.c index 6e06aea..9e6a7b6 100644 --- a/checks.c +++ b/checks.c @@ -1217,9 +1217,7 @@ WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL, static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *dti, struct node *node) { - struct property *prop; struct node *child; - bool has_reg = false; if (!node->parent || node->addr_cells < 0 || node->size_cells < 0) return; @@ -1228,13 +1226,18 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d return; for_each_child(node, child) { - prop = get_property(child, "reg"); - if (prop) - has_reg = true; + /* + * Even if the child devices' address space is not mapped into + * the parent bus (no 'ranges' property on node), children can + * still have registers on a local bus, or map local addresses + * to another subordinate address space. The properties on the + * child nodes then make #address-cells/#size-cells necessary: + */ + if (get_property(child, "reg") || get_property(child, "ranges")) + return; } - if (!has_reg) - FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\", \"dma-ranges\" or child \"reg\" property"); + FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\", \"dma-ranges\" or child \"reg\" or \"ranges\" property"); } WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); From 1e8c5f60e1270391a51a1c55e2c16b235428afa2 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Thu, 5 Dec 2024 19:50:02 +0530 Subject: [PATCH 257/298] Add clang-format config Add clang-format config based on Linux kernel clang-format config. Allows for consistent formatting rules for all future contributions. Signed-off-by: Ayush Singh Message-ID: <20241205-clang-format-v2-1-07d21007bdab@beagleboard.org> Signed-off-by: David Gibson --- .clang-format | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..e5d1518 --- /dev/null +++ b/.clang-format @@ -0,0 +1,135 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# clang-format configuration file. Intended for clang-format >= 11. +# +# For more information, see: +# +# Documentation/dev-tools/clang-format.rst +# https://clang.llvm.org/docs/ClangFormat.html +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# +--- +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false + +# Taken from: +# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' \ +# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \ +# | LC_ALL=C sort -u +ForEachMacros: + - 'fdt_for_each_property_offset' + - 'fdt_for_each_subnode' + - 'for_each_child' + - 'for_each_child_withdel' + - 'for_each_label' + - 'for_each_label_withdel' + - 'for_each_marker' + - 'for_each_marker_of_type' + - 'for_each_property' + - 'for_each_property_withdel' + +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentGotoLabels: false +IndentPPDirectives: None +IndentWidth: 8 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 8 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true + +# Taken from git's rules +PenaltyBreakAssignment: 10 +PenaltyBreakBeforeFirstCallParameter: 30 +PenaltyBreakComment: 10 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakString: 10 +PenaltyExcessCharacter: 100 +PenaltyReturnTypeOnItsOwnLine: 60 + +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatementsExceptForEachMacros +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp03 +TabWidth: 8 +UseTab: Always +... From 56b2b30c5bd0df9d9cf3cdbe8d934e7db9cb8ca9 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Thu, 5 Dec 2024 10:21:03 +0530 Subject: [PATCH 258/298] libfdt: add fdt_get_property_namelen_w() Similar to the non-namelen variant, it is implemented in terms of fdt_get_property_namelen() Reviewed-by: David Gibson Signed-off-by: Ayush Singh Message-ID: <20241205-setprop-namelen-v2-1-0d85a3d2e7b1@beagleboard.org> Signed-off-by: David Gibson --- libfdt/libfdt.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 2e182ea..7d0c252 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -712,6 +712,13 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt, int nodeoffset, const char *name, int namelen, int *lenp); +static inline struct fdt_property * +fdt_get_property_namelen_w(void *fdt, int nodeoffset, const char *name, + int namelen, int *lenp) +{ + return (struct fdt_property *)(uintptr_t)fdt_get_property_namelen( + fdt, nodeoffset, name, namelen, lenp); +} #endif /** From 0f69cedc08fca505c89b46eb669cc94757c74b58 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Thu, 5 Dec 2024 10:21:04 +0530 Subject: [PATCH 259/298] libfdt_internal: fdt_find_string_len_() Allow specifying string length to `fdt_find_string_`. fdt_find_string_() now internally uses this function. Reviewed-by: David Gibson Signed-off-by: Ayush Singh Message-ID: <20241205-setprop-namelen-v2-2-0d85a3d2e7b1@beagleboard.org> Signed-off-by: David Gibson --- libfdt/fdt.c | 8 ++++---- libfdt/libfdt_internal.h | 11 ++++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 20c6415..95f644c 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -312,14 +312,14 @@ int fdt_next_subnode(const void *fdt, int offset) return offset; } -const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) +const char *fdt_find_string_len_(const char *strtab, int tabsize, const char *s, + int slen) { - int len = strlen(s) + 1; - const char *last = strtab + tabsize - len; + const char *last = strtab + tabsize - (slen + 1); const char *p; for (p = strtab; p <= last; p++) - if (memcmp(p, s, len) == 0) + if (memcmp(p, s, slen) == 0 && p[slen] == '\0') return p; return NULL; } diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 16bda19..1fd35f3 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -6,6 +6,7 @@ * Copyright (C) 2006 David Gibson, IBM Corporation. */ #include +#include #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) @@ -20,7 +21,15 @@ int32_t fdt_ro_probe_(const void *fdt); int fdt_check_node_offset_(const void *fdt, int offset); int fdt_check_prop_offset_(const void *fdt, int offset); -const char *fdt_find_string_(const char *strtab, int tabsize, const char *s); + +const char *fdt_find_string_len_(const char *strtab, int tabsize, const char *s, + int s_len); +static inline const char *fdt_find_string_(const char *strtab, int tabsize, + const char *s) +{ + return fdt_find_string_len_(strtab, tabsize, s, strlen(s)); +} + int fdt_node_end_offset_(void *fdt, int nodeoffset); static inline const void *fdt_offset_ptr_(const void *fdt, int offset) From bdca8612009ec723af26beaa26e39138b948c87f Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Thu, 5 Dec 2024 10:21:05 +0530 Subject: [PATCH 260/298] libfdt: Add fdt_setprop_namelen() Allow specifying name length in setprop similar to `fdt_get_property_namelen` functions. Signed-off-by: Ayush Singh Message-ID: <20241205-setprop-namelen-v2-3-0d85a3d2e7b1@beagleboard.org> Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 41 +++++++++++++---------- libfdt/libfdt.h | 81 +++++++++++++++++++++++++++++++++++++++++++--- libfdt/version.lds | 2 ++ 3 files changed, 103 insertions(+), 21 deletions(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 3621d36..7475caf 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -124,31 +124,33 @@ static int fdt_splice_string_(void *fdt, int newlen) * allocated. Ignored if can_assume(NO_ROLLBACK) * @return offset of string in the string table (whether found or added) */ -static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) +static int fdt_find_add_string_(void *fdt, const char *s, int slen, + int *allocated) { char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); const char *p; char *new; - int len = strlen(s) + 1; int err; if (!can_assume(NO_ROLLBACK)) *allocated = 0; - p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); + p = fdt_find_string_len_(strtab, fdt_size_dt_strings(fdt), s, slen); if (p) /* found it */ return (p - strtab); new = strtab + fdt_size_dt_strings(fdt); - err = fdt_splice_string_(fdt, len); + err = fdt_splice_string_(fdt, slen + 1); if (err) return err; if (!can_assume(NO_ROLLBACK)) *allocated = 1; - memcpy(new, s, len); + memcpy(new, s, slen); + new[slen] = '\0'; + return (new - strtab); } @@ -181,13 +183,15 @@ int fdt_del_mem_rsv(void *fdt, int n) return fdt_splice_mem_rsv_(fdt, re, 1, 0); } -static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name, +static int fdt_resize_property_(void *fdt, int nodeoffset, + const char *name, int namelen, int len, struct fdt_property **prop) { int oldlen; int err; - *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); + *prop = fdt_get_property_namelen_w(fdt, nodeoffset, name, namelen, + &oldlen); if (!*prop) return oldlen; @@ -200,7 +204,7 @@ static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name, } static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, - int len, struct fdt_property **prop) + int namelen, int len, struct fdt_property **prop) { int proplen; int nextoffset; @@ -211,7 +215,7 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) return nextoffset; - namestroff = fdt_find_add_string_(fdt, name, &allocated); + namestroff = fdt_find_add_string_(fdt, name, namelen, &allocated); if (namestroff < 0) return namestroff; @@ -255,17 +259,18 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name) return 0; } -int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, - int len, void **prop_data) +int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name, + int namelen, int len, void **prop_data) { struct fdt_property *prop; int err; FDT_RW_PROBE(fdt); - err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop); + err = fdt_resize_property_(fdt, nodeoffset, name, namelen, len, &prop); if (err == -FDT_ERR_NOTFOUND) - err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); + err = fdt_add_property_(fdt, nodeoffset, name, namelen, len, + &prop); if (err) return err; @@ -273,13 +278,14 @@ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, return 0; } -int fdt_setprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len) +int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name, + int namelen, const void *val, int len) { void *prop_data; int err; - err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data); + err = fdt_setprop_placeholder_namelen(fdt, nodeoffset, name, namelen, + len, &prop_data); if (err) return err; @@ -307,7 +313,8 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name, prop->len = cpu_to_fdt32(newlen); memcpy(prop->data + oldlen, val, len); } else { - err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); + err = fdt_add_property_(fdt, nodeoffset, name, strlen(name), + len, &prop); if (err) return err; memcpy(prop->data, val, len); diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 7d0c252..127f41a 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1666,6 +1666,38 @@ int fdt_del_mem_rsv(void *fdt, int n); */ int fdt_set_name(void *fdt, int nodeoffset, const char *name); +/** + * fdt_setprop_namelen - create or change a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @namelen: length of the name + * @val: pointer to data to set the property value to + * @len: length of the property value + * + * fdt_setprop_namelen() sets the value of the named property in the given + * node to the given value and length, creating the property if it + * does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name, + int namelen, const void *val, int len); + /** * fdt_setprop - create or change a property * @fdt: pointer to the device tree blob @@ -1694,8 +1726,44 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name); * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ -int fdt_setprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len); +static inline int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + return fdt_setprop_namelen(fdt, nodeoffset, name, strlen(name), val, + len); +} + +/** + * fdt_setprop_placeholder_namelen - allocate space for a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @namelen: length of the name + * @len: length of the property value + * @prop_data: return pointer to property data + * + * fdt_setprop_placeholder_namelen() allocates the named property in the given node. + * If the property exists it is resized. In either case a pointer to the + * property data is returned. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name, + int namelen, int len, void **prop_data); /** * fdt_setprop_placeholder - allocate space for a property @@ -1725,8 +1793,13 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ -int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, - int len, void **prop_data); +static inline int fdt_setprop_placeholder(void *fdt, int nodeoffset, + const char *name, int len, + void **prop_data) +{ + return fdt_setprop_placeholder_namelen(fdt, nodeoffset, name, + strlen(name), len, prop_data); +} /** * fdt_setprop_u32 - set a property to a 32-bit integer diff --git a/libfdt/version.lds b/libfdt/version.lds index 989cd89..cbfef54 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -43,6 +43,7 @@ LIBFDT_1.2 { fdt_add_mem_rsv; fdt_del_mem_rsv; fdt_set_name; + fdt_setprop_namelen; fdt_setprop; fdt_delprop; fdt_add_subnode_namelen; @@ -71,6 +72,7 @@ LIBFDT_1.2 { fdt_find_max_phandle; fdt_generate_phandle; fdt_check_full; + fdt_setprop_placeholder_namelen; fdt_setprop_placeholder; fdt_property_placeholder; fdt_header_size_; From 755db115355b101dea144eca5c272fdfa15e900f Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Thu, 5 Dec 2024 10:21:06 +0530 Subject: [PATCH 261/298] libfdt: Add fdt_setprop_namelen_string() Macro using fdt_setprop_namelen() internally similar to `fdt_setprop_string()`. Reviewed-by: David Gibson Signed-off-by: Ayush Singh Message-ID: <20241205-setprop-namelen-v2-4-0d85a3d2e7b1@beagleboard.org> Signed-off-by: David Gibson --- libfdt/libfdt.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 127f41a..f2675b1 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1919,6 +1919,38 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, #define fdt_setprop_string(fdt, nodeoffset, name, str) \ fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) +/** + * fdt_setprop_namelen_string - set a property to a string value + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @namelen: number of characters of name to consider + * @str: string value for the property + * + * fdt_setprop_namelen_string() sets the value of the named property in the + * given node to the given string value (using the length of the + * string to determine the new length of the property), or creates a + * new property with that value if it does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_setprop_namelen_string(fdt, nodeoffset, name, namelen, str) \ + fdt_setprop_namelen((fdt), (nodeoffset), (name), (namelen), (str), \ + strlen(str) + 1) /** * fdt_setprop_empty - set a property to an empty value From 267efc7d469477927baa5c0e540d91cb51ca25bf Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 13 Dec 2024 15:14:38 +0100 Subject: [PATCH 262/298] checks: Warn about missing #address-cells for interrupt parents The device tree specification (v0.4) suggests that #address-cells is mandatory for interrupt parent nodes. If this property is missing, Linux will default to the value of 0. A number of device tree files rely on Linux' fallback and don't specify an explicit #address-cells as suggested by the specification. This can cause issues when these device trees are passed to software with a more pedantic interpretation of the DT spec. Add a warning when this case is detected so that device tree files can be fixed. Reported-by: Brad Griffis Signed-off-by: Thierry Reding Reviewed-by: Rob Herring (Arm) Message-ID: <20241213141438.3616902-1-thierry.reding@gmail.com> Signed-off-by: David Gibson --- checks.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/checks.c b/checks.c index 9e6a7b6..123f2eb 100644 --- a/checks.c +++ b/checks.c @@ -1676,6 +1676,10 @@ static void check_interrupt_map(struct check *c, cellprop = get_property(provider_node, "#address-cells"); if (cellprop) parent_cellsize += propval_cell(cellprop); + else + FAIL_PROP(c, dti, node, irq_map_prop, + "Missing property '#address-cells' in node %s, using 0 as fallback", + provider_node->fullpath); cell += 1 + parent_cellsize; if (cell > map_cells) From 18f4f305fdd7e14c8941658a29c7b85c27d41de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 11 Nov 2024 15:07:12 +0400 Subject: [PATCH 263/298] build: fix -Dtools=false build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When configuring the project, meson fails with: tests/meson.build:107:27: ERROR: Unknown variable "util_dep" Declare the util_dep dependency regardless if 'tools' are enabled, so tests can be built with it. Fixes: bdc5c8793a1 ("meson: allow disabling tests") Signed-off-by: Marc-André Lureau Signed-off-by: David Gibson --- meson.build | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/meson.build b/meson.build index 310699f..6dbf633 100644 --- a/meson.build +++ b/meson.build @@ -61,16 +61,16 @@ version_gen_h = vcs_tag( subdir('libfdt') dtc_tools = [] +util_dep = declare_dependency( + sources: ['util.c', version_gen_h], + include_directories: '.', + dependencies: libfdt_dep +) + if get_option('tools') flex = find_program('flex', required: true) bison = find_program('bison', required: true) - util_dep = declare_dependency( - sources: ['util.c', version_gen_h], - include_directories: '.', - dependencies: libfdt_dep - ) - lgen = generator( flex, output: '@PLAINNAME@.lex.c', From 175d2a564c473530397b6ff2d9f3581708b03a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 13 Jan 2025 22:29:11 +0100 Subject: [PATCH 264/298] Use build_root_node() instead of open-coding it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit build_root_node() does error checking (which is good!) but otherwise behaves exactly as the code replaced here. Signed-off-by: Uwe Kleine-König Signed-off-by: David Gibson --- livetree.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/livetree.c b/livetree.c index 49f7230..04e3f2a 100644 --- a/livetree.c +++ b/livetree.c @@ -1014,9 +1014,7 @@ static void add_local_fixup_entry(struct dt_info *dti, /* walk the path components creating nodes if they don't exist */ for (wn = lfn, i = 1; i < depth; i++, wn = nwn) { /* if no node exists, create it */ - nwn = get_subnode(wn, compp[i]); - if (!nwn) - nwn = build_and_name_child_node(wn, compp[i]); + nwn = build_root_node(wn, compp[i]); } free(compp); From 4ea851f5a44dabb5f1f8f9d4adacd1e0ae5a033d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 13 Jan 2025 22:35:41 +0100 Subject: [PATCH 265/298] Let get_subnode() not return deleted nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both current callers actually don't want deleted nodes returned by get_subnode(). So change semantics of this function to only return "live" nodes. Signed-off-by: Uwe Kleine-König Signed-off-by: David Gibson --- livetree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/livetree.c b/livetree.c index 04e3f2a..4627533 100644 --- a/livetree.c +++ b/livetree.c @@ -504,7 +504,7 @@ struct node *get_subnode(struct node *node, const char *nodename) struct node *child; for_each_child(node, child) - if (streq(child->name, nodename)) + if (streq(child->name, nodename) && !child->deleted) return child; return NULL; From 915daadbb62d68bc49c5a14a360d1c39e0131f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 13 Jan 2025 22:43:11 +0100 Subject: [PATCH 266/298] Start with empty __local_fixups__ and __fixups__ nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the meta nodes __local_fixups__ and __fixups__ are generated, and one of these (or both) already exist, the information contained there is duplicated at best and stale otherwise. So remove the nodes before starting to fill them. Signed-off-by: Uwe Kleine-König Signed-off-by: David Gibson --- livetree.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/livetree.c b/livetree.c index 4627533..93c77d9 100644 --- a/livetree.c +++ b/livetree.c @@ -1056,16 +1056,29 @@ void generate_label_tree(struct dt_info *dti, const char *name, bool allocph) void generate_fixups_tree(struct dt_info *dti, const char *name) { + struct node *n = get_subnode(dti->dt, name); + + /* Start with an empty __fixups__ node to not get duplicates */ + if (n) + n->deleted = true; + if (!any_fixup_tree(dti, dti->dt)) return; - generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), + generate_fixups_tree_internal(dti, + build_and_name_child_node(dti->dt, name), dti->dt); } void generate_local_fixups_tree(struct dt_info *dti, const char *name) { + struct node *n = get_subnode(dti->dt, name); + + /* Start with an empty __local_fixups__ node to not get duplicates */ + if (n) + n->deleted = true; if (!any_local_fixup_tree(dti, dti->dt)) return; - generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), + generate_local_fixups_tree_internal(dti, + build_and_name_child_node(dti->dt, name), dti->dt); } From ce1d8588880aecd7af264e422a16a8b33617cef7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 5 Feb 2025 13:39:43 +1100 Subject: [PATCH 267/298] tests: When building .so from -O asm output mark as non-executable stack For certain tests, we take the output from dtc -O asm and build it into a .so shared library which we then dlopen() for further tests. Because we don't mark it otherwise, it's treated as requiring an executable stack, which dlopen() refuses to open as of glibc-2.41. Of course, the library is pure data, no code, so it certainly doesn't need an executable stack. Add the -znoexecstack linker option to avoid the error. Fixes: https://github.com/dgibson/dtc/issues/163 Reported-by: Xi Ruoyao Signed-off-by: David Gibson --- tests/run_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 937b128..f0b51c0 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -201,7 +201,7 @@ run_dtc_test () { } asm_to_so () { - $CC -shared -o $1.test.so "$SRCDIR/data.S" $1.test.s + $CC -shared -Wl,-znoexecstack -o $1.test.so "$SRCDIR/data.S" $1.test.s } asm_to_so_test () { From 1ccd232709d409798aac93f45b2a2e1c43e98ec4 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 2 Mar 2025 17:28:26 -0500 Subject: [PATCH 268/298] meson: don't build test programs by default They are only used when running tests, and are included as depedencies of the test cases themselves already. Marking them to not build by default, means that 291 compile edges can be skipped when only running ``` meson setup builddir/ ninja -C builddir/ meson install -C builddir/ ``` resulting in an overall much faster build. Instead they will be compiled on-demand by `meson test`, only for users that actually run the tests. Signed-off-by: Eli Schwartz Message-ID: <20250302222839.2256985-1-eschwartz@gentoo.org> Signed-off-by: David Gibson --- tests/meson.build | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/meson.build b/tests/meson.build index 9cf6e3d..f1044b9 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -1,7 +1,9 @@ trees = static_library('trees', files('trees.S'), c_args: '-D__ASSEMBLY__', + build_by_default: false, include_directories: libfdt_inc) dumptrees = executable('dumptrees', files('dumptrees.c'), + build_by_default: false, link_with: trees, dependencies: libfdt_dep) dumptrees_dtb = custom_target( @@ -111,7 +113,7 @@ endif tests_exe = [] foreach t: tests - tests_exe += executable(t, files(t + '.c'), dependencies: test_deps, link_args: extra_link_args) + tests_exe += executable(t, files(t + '.c'), dependencies: test_deps, link_args: extra_link_args, build_by_default: false) endforeach run_tests = find_program('run_tests.sh') From dd1b3e532d228ed75d34480ee539f71b76a4fa89 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Thu, 6 Mar 2025 20:30:47 -0600 Subject: [PATCH 269/298] meson: support building libfdt without static library Some packaging systems like NixOS don't support compiling static libraries. However libfdt's meson.build uses `both_library()` which forces the build to always compile shared and static libraries. Removing `both_library()` will make packaging easier. libfdt uses `both_libraries()` to support the 'static-build' option. But we do not need the 'static-build' option as Meson can natively build static using > meson setup builddir/ -Dc_link_args='-static' --prefer-static --default-library=static So drop 'static-build' and then replace `both_libraries()` with `library()`. Signed-off-by: Brandon Maier Signed-off-by: David Gibson --- libfdt/meson.build | 10 ++-------- meson.build | 16 +++------------- meson_options.txt | 2 -- tests/meson.build | 10 ++++------ 4 files changed, 9 insertions(+), 29 deletions(-) diff --git a/libfdt/meson.build b/libfdt/meson.build index bf8343f..c2f4bd6 100644 --- a/libfdt/meson.build +++ b/libfdt/meson.build @@ -26,7 +26,7 @@ else endif link_args += version_script -libfdt = both_libraries( +libfdt = library( 'fdt', sources, version: meson.project_version(), link_args: link_args, @@ -34,17 +34,11 @@ libfdt = both_libraries( install: true, ) -if static_build - link_with = libfdt.get_static_lib() -else - link_with = libfdt.get_shared_lib() -endif - libfdt_inc = include_directories('.') libfdt_dep = declare_dependency( include_directories: libfdt_inc, - link_with: link_with, + link_with: libfdt, ) install_headers( diff --git a/meson.build b/meson.build index 6dbf633..3026f88 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project('dtc', 'c', version: files('VERSION.txt'), license: ['GPL2+', 'BSD-2'], - default_options: 'werror=true', + default_options: ['werror=true', 'default_library=both'], meson_version: '>=0.57.0' ) @@ -27,16 +27,8 @@ add_project_arguments( language: 'c' ) -if get_option('static-build') - static_build = true - extra_link_args = ['-static'] -else - static_build = false - extra_link_args = [] -endif - yamltree = 'yamltree.c' -yaml = dependency('yaml-0.1', version: '>=0.2.3', required: get_option('yaml'), static: static_build) +yaml = dependency('yaml-0.1', version: '>=0.2.3', required: get_option('yaml')) if not yaml.found() add_project_arguments('-DNO_YAML', language: 'c') yamltree = [] @@ -92,7 +84,6 @@ if get_option('tools') ], dependencies: util_dep, install: true, - link_args: extra_link_args, ) endif @@ -113,11 +104,10 @@ if get_option('tools') ], dependencies: [util_dep, yaml], install: true, - link_args: extra_link_args, ) foreach e: ['fdtdump', 'fdtget', 'fdtput', 'fdtoverlay'] - dtc_tools += executable(e, files(e + '.c'), dependencies: util_dep, install: true, link_args: extra_link_args) + dtc_tools += executable(e, files(e + '.c'), dependencies: util_dep, install: true) endforeach install_data( diff --git a/meson_options.txt b/meson_options.txt index 36f391a..62b31b3 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -8,7 +8,5 @@ option('valgrind', type: 'feature', value: 'auto', description: 'Valgrind support') option('python', type: 'feature', value: 'auto', description: 'Build pylibfdt Python library') -option('static-build', type: 'boolean', value: false, - description: 'Build static binaries') option('tests', type: 'boolean', value: true, description: 'Build tests') diff --git a/tests/meson.build b/tests/meson.build index f1044b9..52d657e 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -98,22 +98,20 @@ tests += [ 'truncated_string', ] +test_deps = [testutil_dep, util_dep, libfdt_dep] + dl = cc.find_library('dl', required: false) -if dl.found() and not static_build +if dl.found() tests += [ 'asm_tree_dump', 'value-labels', ] -endif - -test_deps = [testutil_dep, util_dep, libfdt_dep] -if not static_build test_deps += [dl] endif tests_exe = [] foreach t: tests - tests_exe += executable(t, files(t + '.c'), dependencies: test_deps, link_args: extra_link_args, build_by_default: false) + tests_exe += executable(t, files(t + '.c'), dependencies: test_deps, build_by_default: false) endforeach run_tests = find_program('run_tests.sh') From da85f91931e52c0f9661cff83fe0a5e83f6cc845 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 13 Mar 2025 20:05:27 +0100 Subject: [PATCH 270/298] Remove duplicated words in documentation and comments Let's avoid repeating single words here! Signed-off-by: Thomas Huth Message-ID: <20250313190527.1556019-1-thuth@redhat.com> Signed-off-by: David Gibson --- CONTRIBUTING.md | 2 +- Documentation/dt-object-internal.txt | 2 +- libfdt/libfdt.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 940dd1a..48c8efd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ There are two ways to submit changes for dtc or libfdt: -* Post patches directly to the the +* Post patches directly to the [devicetree-compiler](mailto:devicetree-compiler@vger.kernel.org) mailing list. * Submit pull requests via diff --git a/Documentation/dt-object-internal.txt b/Documentation/dt-object-internal.txt index c7357e6..dbbbcea 100644 --- a/Documentation/dt-object-internal.txt +++ b/Documentation/dt-object-internal.txt @@ -6,7 +6,7 @@ the hardware capabilities. This is insufficient for platforms that need to dynamically insert Device Tree fragments into the live tree. -This document explains the the Device Tree object format and +This document explains the Device Tree object format and modifications made to the Device Tree compiler, which make it possible. 1. Simplified Problem Definition diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index f2675b1..b5e7200 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1569,7 +1569,7 @@ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) * @fdt: pointer to the device tree blob * @name: name of property to add * @len: length of property value in bytes - * @valp: returns a pointer to where where the value should be placed + * @valp: returns a pointer to where the value should be placed * * returns: * 0, on success From 205fbef17b7b2f410e34ac79aa1559a8d492b66c Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 13 Mar 2025 20:16:07 +0100 Subject: [PATCH 271/298] Fix some typos Discovered with the "codespell" utility. Signed-off-by: Thomas Huth Message-ID: <20250313191607.1556384-1-thuth@redhat.com> Signed-off-by: David Gibson --- README.license | 2 +- dtc.c | 2 +- dtc.h | 2 +- flattree.c | 2 +- libfdt/libfdt_internal.h | 4 ++-- pylibfdt/libfdt.i | 2 +- tests/comments.dts | 2 +- tests/nopulate.c | 2 +- tests/run_tests.sh | 2 +- tests/testutils.c | 6 +++--- tests/utilfdt_test.c | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/README.license b/README.license index 102b004..a4edc2b 100644 --- a/README.license +++ b/README.license @@ -28,7 +28,7 @@ tools. Allowing libfdt to be used under the terms of the BSD license makes that it easier for vendors or authors of such software to do so. This does mean that libfdt code could be "stolen" - say, included in a -proprietary fimware and extended without contributing those extensions +proprietary firmware and extended without contributing those extensions back to the libfdt mainline. While I hope that doesn't happen, I believe the goal of allowing libfdt to be widely used is more important than avoiding that. libfdt is quite small, and hardly diff --git a/dtc.c b/dtc.c index beda8d5..b3445b7 100644 --- a/dtc.c +++ b/dtc.c @@ -15,7 +15,7 @@ int quiet; /* Level of quietness */ unsigned int reservenum;/* Number of memory reservation slots */ int minsize; /* Minimum blob size */ int padsize; /* Additional padding to blob */ -int alignsize; /* Additional padding to blob accroding to the alignsize */ +int alignsize; /* Additional padding to blob according to the alignsize */ int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties */ int generate_symbols; /* enable symbols & fixup support */ int generate_fixups; /* suppress generation of fixups on symbol support */ diff --git a/dtc.h b/dtc.h index 4c4aaca..9acf071 100644 --- a/dtc.h +++ b/dtc.h @@ -38,7 +38,7 @@ extern int quiet; /* Level of quietness */ extern unsigned int reservenum; /* Number of memory reservation slots */ extern int minsize; /* Minimum blob size */ extern int padsize; /* Additional padding to blob */ -extern int alignsize; /* Additional padding to blob accroding to the alignsize */ +extern int alignsize; /* Additional padding to blob according to the alignsize */ extern int phandle_format; /* Use linux,phandle or phandle properties */ extern int generate_symbols; /* generate symbols for nodes with labels */ extern int generate_fixups; /* generate fixups */ diff --git a/flattree.c b/flattree.c index 1bcd808..30e6de2 100644 --- a/flattree.c +++ b/flattree.c @@ -503,7 +503,7 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version) * Reserve map entries. * Align the reserve map to a doubleword boundary. * Each entry is an (address, size) pair of u64 values. - * Always supply a zero-sized temination entry. + * Always supply a zero-sized termination entry. */ asm_emit_align(f, 8); emit_label(f, symprefix, "reserve_map"); diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 1fd35f3..773bba8 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -56,8 +56,8 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) } /* - * Internal helpers to access tructural elements of the device tree - * blob (rather than for exaple reading integers from within property + * Internal helpers to access structural elements of the device tree + * blob (rather than for example reading integers from within property * values). We assume that we are either given a naturally aligned * address for the platform or if we are not, we are on a platform * where unaligned memory reads will be handled in a graceful manner. diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index bb9985c..1f9c047 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -162,7 +162,7 @@ class FdtRo(object): quiet: Errors to ignore (empty to raise on all errors) Returns: - Typle: + Tuple: Offset of the next node, if any, else a -ve error Depth of the returned node, if any, else undefined diff --git a/tests/comments.dts b/tests/comments.dts index 0b04b6b..d315d7f 100644 --- a/tests/comments.dts +++ b/tests/comments.dts @@ -25,7 +25,7 @@ prop7; /* yet * another - * multline + * multiline * comment */ prop8; diff --git a/tests/nopulate.c b/tests/nopulate.c index e06a0b3..06f8369 100644 --- a/tests/nopulate.c +++ b/tests/nopulate.c @@ -65,7 +65,7 @@ int main(int argc, char *argv[]) verbose_printf("Nopulated structure block has new size %d\n", newsize); - /* Replace old strcutre block with the new */ + /* Replace old structure block with the new */ fdt2 = xmalloc(fdt_totalsize(fdt) + newsize); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index f0b51c0..fecfe7c 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -805,7 +805,7 @@ dtc_tests () { run_dtc_test -I dtb -O dts -o stdin_odts_test_tree1.dtb.test.dts - < test_tree1.dtb run_wrap_test cmp stdin_odts_test_tree1.dtb.test.dts odts_test_tree1.dtb.test.dts - # Check integer expresisons + # Check integer expressions run_test integer-expressions -g integer-expressions.test.dts run_dtc_test -I dts -O dtb -o integer-expressions.test.dtb integer-expressions.test.dts run_test integer-expressions integer-expressions.test.dtb diff --git a/tests/testutils.c b/tests/testutils.c index 4c85111..54da2e4 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -131,7 +131,7 @@ void check_property(void *fdt, int nodeoffset, const char *name, " differs from stored length (%d != %d)", name, retlen, proplen); if (proplen != len) - FAIL("Size mismatch on property \"%s\": %d insead of %d", + FAIL("Size mismatch on property \"%s\": %d instead of %d", name, proplen, len); if (len && memcmp(val, prop->data, len) != 0) FAIL("Data mismatch on property \"%s\"", name); @@ -148,7 +148,7 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name, FAIL("fdt_getprop(\"%s\"): %s", name, fdt_strerror(proplen)); if (proplen != len) - FAIL("Size mismatch on property \"%s\": %d insead of %d", + FAIL("Size mismatch on property \"%s\": %d instead of %d", name, proplen, len); if (len && memcmp(val, propval, len) != 0) FAIL("Data mismatch on property \"%s\"", name); @@ -172,7 +172,7 @@ const void *check_get_prop_offset(void *fdt, int poffset, const char *exp_name, return NULL; if (proplen != exp_len) - FAIL("Size mismatch on property \"%s\": %d insead of %d", + FAIL("Size mismatch on property \"%s\": %d instead of %d", name, proplen, exp_len); if (exp_len && memcmp(exp_val, propval, exp_len)) FAIL("Data mismatch on property \"%s\"", name); diff --git a/tests/utilfdt_test.c b/tests/utilfdt_test.c index f62341c..992807d 100644 --- a/tests/utilfdt_test.c +++ b/tests/utilfdt_test.c @@ -46,7 +46,7 @@ static void checkfail(const char *fmt) * Add the given modifier to each of the valid sizes, and check that we get * correct values. * - * \param modifier Modifer string to use as a prefix + * \param modifier Modifier string to use as a prefix * \param expected_size The size (in bytes) that we expect (ignored for * strings) */ From f4c53f4ebf7809a07666bf728c823005e1f1a612 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 13 Mar 2025 20:27:18 +0100 Subject: [PATCH 272/298] Use __ASSEMBLER__ instead of __ASSEMBLY__ Both, Clang and GCC define __ASSEMBLER__ automatically when compiling .S files, so this macro is a much better fit for fdt.h - programs that want to use it from .S files don't have to manually #define __ASSEMBLY__ that way. While we're at it, also change it in testdata.h, then we don't have to define __ASSEMBLY__ in the Makefile / meson.build file anymore. Signed-off-by: Thomas Huth Message-ID: <20250313192718.1561683-1-thuth@redhat.com> Signed-off-by: David Gibson --- Makefile | 2 +- libfdt/fdt.h | 4 ++-- tests/meson.build | 2 +- tests/testdata.h | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index f1f0ab3..a00123d 100644 --- a/Makefile +++ b/Makefile @@ -360,7 +360,7 @@ clean: libfdt_clean pylibfdt_clean tests_clean %.o: %.S @$(VECHO) AS $@ - $(CC) $(CPPFLAGS) $(AFLAGS) -D__ASSEMBLY__ -o $@ -c $< + $(CC) $(CPPFLAGS) $(AFLAGS) -o $@ -c $< %.d: %.c @$(VECHO) DEP $< diff --git a/libfdt/fdt.h b/libfdt/fdt.h index 0c91aa7..a07abfc 100644 --- a/libfdt/fdt.h +++ b/libfdt/fdt.h @@ -7,7 +7,7 @@ * Copyright 2012 Kim Phillips, Freescale Semiconductor. */ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct fdt_header { fdt32_t magic; /* magic word FDT_MAGIC */ @@ -45,7 +45,7 @@ struct fdt_property { char data[]; }; -#endif /* !__ASSEMBLY */ +#endif /* !__ASSEMBLER__ */ #define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ #define FDT_TAGSIZE sizeof(fdt32_t) diff --git a/tests/meson.build b/tests/meson.build index 52d657e..37bfd47 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -1,4 +1,4 @@ -trees = static_library('trees', files('trees.S'), c_args: '-D__ASSEMBLY__', +trees = static_library('trees', files('trees.S'), build_by_default: false, include_directories: libfdt_inc) diff --git a/tests/testdata.h b/tests/testdata.h index 4f9e3ba..fcebc2c 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -1,4 +1,4 @@ -#ifdef __ASSEMBLY__ +#ifdef __ASSEMBLER__ #define ASM_CONST_LL(x) (x) #else #define ASM_CONST_LL(x) (x##ULL) @@ -46,7 +46,7 @@ #define TEST_MEMREGION_SIZE_HI 0x0fedcba900000000 #define TEST_MEMREGION_SIZE_INC 0x1000 -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ extern struct fdt_header test_tree1; extern struct fdt_header truncated_property; extern struct fdt_header bad_node_char; @@ -57,4 +57,4 @@ extern struct fdt_header truncated_string; extern struct fdt_header truncated_memrsv; extern struct fdt_header two_roots; extern struct fdt_header named_root; -#endif /* ! __ASSEMBLY */ +#endif /* ! __ASSEMBLER__ */ From 7ebfcac8520e7e1d22a7d1e98ffeb16a141b9cb4 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 30 Apr 2025 11:25:25 -0400 Subject: [PATCH 273/298] Makefile: deprecate in favor of Meson Building the python bindings is complicated and not very practical to do in a Makefile. The setuptools invocations previously used are confusing and don't work very well compared to Meson. Having two build systems that do different things is also confusing though. Since Meson can do everything that Make can do, but the reverse is not true, we deprecate the latter and warn when you use it. GNU Make can emit a $(warning) on every Makefile run, which is a bit noisy but means we don't need to have every target depend on a PHONY target (preventing built targets from being seen as up to date). Signed-off-by: Eli Schwartz Message-ID: <20250430152601.43554-2-eschwartz@gentoo.org> Signed-off-by: David Gibson --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index a00123d..6ab5f97 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,10 @@ # Device Tree Compiler # +$(warning WARNING: Building dtc using make is deprecated, in favour of using Meson (https://mesonbuild.com)) +$(warning ) +$(warning Use `meson setup builddir/ && meson compile -C builddir/` to build, `meson test -C builddir/` to test, or `meson configure` to see build options.) + # # Version information will be constructed in this order: # DTC_VERSION release version as MAJOR.MINOR.PATCH From ecb21febfdd32fa9e0cbd9517f9e92cc9c703ffb Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 30 Apr 2025 11:25:26 -0400 Subject: [PATCH 274/298] meson: port python bindings to build natively via meson and meson-python We get full build parallelism and fewer confusing ancient distutils paths. The python wheels build fully standalone, including linking libfdt as a static library. For convenience, when running pip install a meson option is passed that prevents building tools or installing headers/pkgconfig files. meson-python would otherwise include them in the wheel itself, in case they are needed, but this is essentially a bit useless so don't bother. The old setuptools-based build is now redundant and goes away. Signed-off-by: Eli Schwartz Message-ID: <20250430152601.43554-3-eschwartz@gentoo.org> Signed-off-by: David Gibson --- MANIFEST.in | 12 ----- Makefile | 49 +------------------ libfdt/meson.build | 32 +++++++------ meson.build | 3 +- meson_options.txt | 2 + pylibfdt/Makefile.pylibfdt | 30 ------------ pylibfdt/meson.build | 28 +++++++---- pyproject.toml | 33 +++++++++++++ setup.py | 97 -------------------------------------- 9 files changed, 73 insertions(+), 213 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 pylibfdt/Makefile.pylibfdt create mode 100644 pyproject.toml delete mode 100755 setup.py diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 904d124..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) - -global-exclude * -include README.md -include GPL -include BSD-2-Clause -include setup.py -include pylibfdt/libfdt.i -include libfdt/libfdt.h -include libfdt/fdt.h -include libfdt/libfdt_env.h -include VERSION.txt diff --git a/Makefile b/Makefile index 6ab5f97..b1815c3 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,6 @@ BISON = bison LEX = flex SWIG = swig PKG_CONFIG ?= pkg-config -PYTHON ?= python3 INSTALL = install INSTALL_PROGRAM = $(INSTALL) @@ -47,8 +46,6 @@ INCLUDEDIR = $(PREFIX)/include HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ sed -e 's/\(cygwin\|msys\).*/\1/') -NO_PYTHON ?= 0 - NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?) ifeq ($(NO_VALGRIND),1) CPPFLAGS += -DNO_VALGRIND @@ -158,29 +155,6 @@ SCRIPTS = dtdiff all: $(BIN) libfdt -# We need both Python and swig to build/install pylibfdt. -# This builds the given make ${target} if those deps are found. -check_python_deps = \ - if $(PKG_CONFIG) --cflags $(PYTHON) >/dev/null 2>&1; then \ - if which swig >/dev/null 2>&1; then \ - can_build=yes; \ - fi; \ - fi; \ - if [ "$${can_build}" = "yes" ]; then \ - $(MAKE) $${target}; \ - else \ - echo "\#\# Skipping pylibfdt (install python dev and swig to build)"; \ - fi ; - -.PHONY: maybe_pylibfdt -maybe_pylibfdt: FORCE - target=pylibfdt; $(check_python_deps) - -ifeq ($(NO_PYTHON),0) -all: maybe_pylibfdt -endif - - ifneq ($(DEPTARGETS),) ifneq ($(MAKECMDGOALS),libfdt) -include $(DTC_OBJS:%.o=%.d) @@ -254,14 +228,6 @@ install-includes: install: install-bin install-lib install-includes -.PHONY: maybe_install_pylibfdt -maybe_install_pylibfdt: FORCE - target=install_pylibfdt; $(check_python_deps) - -ifeq ($(NO_PYTHON),0) -install: maybe_install_pylibfdt -endif - $(VERSION_FILE): Makefile FORCE $(call filechk,version) @@ -287,16 +253,6 @@ dist: gzip -9 > ../dtc-$(dtc_version).tar.gz -# -# Rules for pylibfdt -# -PYLIBFDT_dir = pylibfdt - -include $(PYLIBFDT_dir)/Makefile.pylibfdt - -.PHONY: pylibfdt -pylibfdt: $(PYLIBFDT_dir)/_libfdt.so - # # Release signing and uploading # This is for maintainer convenience, don't try this at home. @@ -330,9 +286,6 @@ TESTS_BIN += fdtput TESTS_BIN += fdtget TESTS_BIN += fdtdump TESTS_BIN += fdtoverlay -ifeq ($(NO_PYTHON),0) -TESTS_PYLIBFDT += maybe_pylibfdt -endif ifneq ($(MAKECMDGOALS),libfdt) include tests/Makefile.tests @@ -344,7 +297,7 @@ endif STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* \ *.tab.[ch] *.lex.c *.output -clean: libfdt_clean pylibfdt_clean tests_clean +clean: libfdt_clean tests_clean @$(VECHO) CLEAN rm -f $(STD_CLEANFILES) rm -f $(VERSION_FILE) diff --git a/libfdt/meson.build b/libfdt/meson.build index c2f4bd6..9c6ef54 100644 --- a/libfdt/meson.build +++ b/libfdt/meson.build @@ -31,7 +31,7 @@ libfdt = library( version: meson.project_version(), link_args: link_args, link_depends: 'version.lds', - install: true, + install: get_option('default_library') != 'static' or not wheel_only, ) libfdt_inc = include_directories('.') @@ -41,20 +41,22 @@ libfdt_dep = declare_dependency( link_with: libfdt, ) -install_headers( - files( - 'fdt.h', - 'libfdt.h', - 'libfdt_env.h', +if not wheel_only + install_headers( + files( + 'fdt.h', + 'libfdt.h', + 'libfdt_env.h', + ) ) -) -pkgconfig = import('pkgconfig') + pkgconfig = import('pkgconfig') -pkgconfig.generate( - libraries: libfdt, - version: meson.project_version(), - filebase: 'libfdt', - name: 'libfdt', - description: 'Flat Device Tree manipulation', -) + pkgconfig.generate( + libraries: libfdt, + version: meson.project_version(), + filebase: 'libfdt', + name: 'libfdt', + description: 'Flat Device Tree manipulation', + ) +endif diff --git a/meson.build b/meson.build index 3026f88..ed4a39d 100644 --- a/meson.build +++ b/meson.build @@ -43,6 +43,7 @@ py = import('python') py = py.find_installation(required: get_option('python')) swig = find_program('swig', required: get_option('python')) pylibfdt_enabled = not meson.is_cross_build() and py.found() and swig.found() ? true : false +wheel_only = get_option('wheel-only') version_gen_h = vcs_tag( command: ['git', 'describe', '--dirty=+'], @@ -59,7 +60,7 @@ util_dep = declare_dependency( dependencies: libfdt_dep ) -if get_option('tools') +if get_option('tools') and not wheel_only flex = find_program('flex', required: true) bison = find_program('bison', required: true) diff --git a/meson_options.txt b/meson_options.txt index 62b31b3..a866b17 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -10,3 +10,5 @@ option('python', type: 'feature', value: 'auto', description: 'Build pylibfdt Python library') option('tests', type: 'boolean', value: true, description: 'Build tests') +option('wheel-only', type: 'boolean', value: false, + description: 'building from meson-python') diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt deleted file mode 100644 index 647203f..0000000 --- a/pylibfdt/Makefile.pylibfdt +++ /dev/null @@ -1,30 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) -# Makefile.pylibfdt -# - -PYLIBFDT_srcs = $(PYLIBFDT_dir)/libfdt.i -PYMODULE = $(PYLIBFDT_dir)/_libfdt.so -PYLIBFDT_CLEANFILES_L = libfdt_wrap.c libfdt.py *.pyc *.so -PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%) -PYLIBFDT_CLEANDIRS_L = __pycache__ libfdt.egg-info -PYLIBFDT_CLEANDIRS = build $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%) - -SETUP = ./setup.py - -ifndef V -SETUPFLAGS += --quiet -endif - -$(PYMODULE): WARNINGS = # suppress warnings from generated code -$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) - @$(VECHO) PYMOD $@ - CFLAGS="$(CFLAGS) -Wno-error" $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext - -install_pylibfdt: $(PYMODULE) - @$(VECHO) INSTALL-PYLIB - $(PYTHON) $(SETUP) $(SETUPFLAGS) install --prefix=$(PREFIX) - -pylibfdt_clean: - @$(VECHO) CLEAN "(pylibfdt)" - rm -f $(PYLIBFDT_CLEANFILES) - rm -rf $(PYLIBFDT_CLEANDIRS) diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build index 6157f8d..b13d802 100644 --- a/pylibfdt/meson.build +++ b/pylibfdt/meson.build @@ -1,13 +1,21 @@ -setup_py = find_program('../setup.py') -setup_py = [setup_py, '--quiet', '--top-builddir', meson.project_build_root()] - -pylibfdt = custom_target( - 'pylibfdt', +libfdt_c = custom_target( + 'swig', input: 'libfdt.i', - depends: libfdt, - output: '_libfdt.so', - command: [setup_py, 'build_ext'], - build_by_default: true, + output: ['libfdt.c', 'libfdt.py'], + install: true, + install_dir: [false, py.get_install_dir(pure: false)], + command: [swig, '-python', '-I'+meson.current_source_dir() / '../libfdt', '-o', '@OUTPUT0@', '@INPUT@'] ) -meson.add_install_script(setup_py, 'install', '--prefix=' + get_option('prefix'), '--root=$DESTDIR') +nowarn_gen = cc.get_supported_arguments( + '-Wno-cast-qual', + '-Wno-missing-prototypes', + '-Wno-redundant-decls', +) +pylibfdt = py.extension_module( + '_libfdt', + libfdt_c, + c_args: ['-DPY_SSIZE_T_CLEAN'] + nowarn_gen, + dependencies: [libfdt_dep, py.dependency()], + install: true, +) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..853d13e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,33 @@ +[build-system] +build-backend = 'mesonpy' +requires = ['meson-python'] + +[project] +name = 'libfdt' +authors = [ + {name = 'Simon Glass', email = 'sjg@chromium.org'}, +] +classifiers = [ + 'Programming Language :: Python :: 3', + 'License :: OSI Approved :: BSD License', + 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', + 'Operating System :: OS Independent', +] +description = 'Python binding for libfdt' +readme = 'README.md' +requires-python = '>=3.8' +dynamic = ['version'] + +[project.urls] +'homepage' = 'https://git.kernel.org/pub/scm/utils/dtc/dtc.git' + +# These arguments are applied only when building a redistributable binary wheel +# for uploading to PyPI. We don't want to install libraries (or headers / +# pkgconfig files / executables) that clash with system C installs, so we +# disable everything other than the python bindings themselves, and build the +# python C-API extension using static linkage to avoid juggling "libdir" / +# LD_LIBRARY_PATH / RPATH around. When building both the C library and the +# python bindings for a distro, `meson setup` will still default to shared +# libraries. +[tool.meson-python.args] +setup = ['-Ddefault_library=static', '-Dwheel-only=true'] diff --git a/setup.py b/setup.py deleted file mode 100755 index 52844ce..0000000 --- a/setup.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python3 -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) - -""" -setup.py file for SWIG libfdt -Copyright (C) 2017 Google, Inc. -Written by Simon Glass -""" - -import os -import sys - -from setuptools import setup, Extension -from setuptools.command.build_py import build_py as _build_py - - -def scan_for_info(srcdir): - """Scan for the version and long_description fields - - Args: - srcdir (str): Source-directory path - - Returns: tuple - str: Full description (contents of README.md) - str: Version string - """ - with open(os.path.join(srcdir, "VERSION.txt"), "r", encoding='utf-8') as fh: - version = fh.readline().strip() - - with open(os.path.join(srcdir, "README.md"), "r", encoding='utf-8') as fh: - long_description = fh.read() - - return version, long_description - - -def get_top_builddir(srcdir): - """Figure out the top-level directory containing the source code - - Args: - srcdir (str): Source-directory path - - Returns: - str: Directory to build in - """ - if '--top-builddir' in sys.argv: - index = sys.argv.index('--top-builddir') - sys.argv.pop(index) - return sys.argv.pop(index) - return srcdir - - -class BuildPy(_build_py): - """Small class to run the build_ext command""" - def run(self): - self.run_command("build_ext") - return super().run() - - -srcdir = os.path.dirname(__file__) -version, long_description = scan_for_info(srcdir) - -libfdt_module = Extension( - '_libfdt', - sources=[os.path.join(srcdir, 'pylibfdt/libfdt.i')], - define_macros=[('PY_SSIZE_T_CLEAN', None)], - include_dirs=[os.path.join(srcdir, 'libfdt')], - libraries=['fdt'], - library_dirs=[os.path.join(get_top_builddir(srcdir), 'libfdt')], - swig_opts=['-I' + os.path.join(srcdir, 'libfdt')], -) - - -setup( - name='libfdt', - version=version, - cmdclass = {'build_py' : BuildPy}, - author='Simon Glass', - author_email='sjg@chromium.org', - description='Python binding for libfdt', - ext_modules=[libfdt_module], - package_dir={'': os.path.join(srcdir, 'pylibfdt')}, - py_modules=['libfdt'], - python_requires=">=3.8", - - long_description=long_description, - long_description_content_type="text/plain", - url="https://git.kernel.org/pub/scm/utils/dtc/dtc.git", - license="BSD", - license_files=["GPL", "BSD-2-Clause"], - - classifiers=[ - "Programming Language :: Python :: 3", - "License :: OSI Approved :: BSD License", - "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", - "Operating System :: OS Independent", - ], -) From e0b7749c26a9ea28a480bca4a87d238e284ac68f Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Tue, 11 Mar 2025 21:05:37 +0530 Subject: [PATCH 275/298] Add alloc_marker - Add helper to allocate new marker Reviewed-by: David Gibson Signed-off-by: Ayush Singh Message-ID: <20250311-previous-value-v2-1-e4a8611e956f@beagleboard.org> Signed-off-by: David Gibson --- data.c | 20 +++++++++++++++----- dtc.h | 2 ++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/data.c b/data.c index 1473423..913796f 100644 --- a/data.c +++ b/data.c @@ -228,11 +228,7 @@ struct data data_add_marker(struct data d, enum markertype type, char *ref) { struct marker *m; - m = xmalloc(sizeof(*m)); - m->offset = d.len; - m->type = type; - m->ref = ref; - m->next = NULL; + m = alloc_marker(d.len, type, ref); return data_append_markers(d, m); } @@ -254,3 +250,17 @@ bool data_is_one_string(struct data d) return true; } + +struct marker *alloc_marker(unsigned int offset, enum markertype type, + char *ref) +{ + struct marker *m; + + m = xmalloc(sizeof(*m)); + m->offset = offset; + m->type = type; + m->ref = ref; + m->next = NULL; + + return m; +} diff --git a/dtc.h b/dtc.h index 9acf071..bd80339 100644 --- a/dtc.h +++ b/dtc.h @@ -183,6 +183,8 @@ struct data data_append_byte(struct data d, uint8_t byte); struct data data_append_zeroes(struct data d, int len); struct data data_append_align(struct data d, int align); +struct marker *alloc_marker(unsigned int offset, enum markertype type, + char *ref); struct data data_add_marker(struct data d, enum markertype type, char *ref); bool data_is_one_string(struct data d); From b841391bbd08e101b76cb6cddb26bf8faaee6203 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Thu, 5 Jun 2025 16:18:06 +0530 Subject: [PATCH 276/298] srcpos: Define srcpos_free srcpos can be chained together using srcpos_extend. However, in such cases, we need to free all the chained nodes. srcpos_free is a helper to recursively free all the linked srcpos. Signed-off-by: Ayush Singh Message-ID: <20250605-previous-value-v3-1-0983d0733a07@beagleboard.org> Signed-off-by: David Gibson --- livetree.c | 2 +- srcpos.c | 11 +++++++++++ srcpos.h | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/livetree.c b/livetree.c index 93c77d9..d51d058 100644 --- a/livetree.c +++ b/livetree.c @@ -174,7 +174,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) old_prop->val = new_prop->val; old_prop->deleted = 0; - free(old_prop->srcpos); + srcpos_free(old_prop->srcpos); old_prop->srcpos = new_prop->srcpos; free(new_prop); new_prop = NULL; diff --git a/srcpos.c b/srcpos.c index 5e2f7dd..5bb57bf 100644 --- a/srcpos.c +++ b/srcpos.c @@ -287,6 +287,17 @@ struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail) return pos; } +void srcpos_free(struct srcpos *pos) +{ + struct srcpos *p_next; + + while (pos) { + p_next = pos->next; + free(pos); + pos = p_next; + } +} + char * srcpos_string(struct srcpos *pos) { diff --git a/srcpos.h b/srcpos.h index 4318d7a..4d60b50 100644 --- a/srcpos.h +++ b/srcpos.h @@ -88,6 +88,7 @@ extern void srcpos_update(struct srcpos *pos, const char *text, int len); extern struct srcpos *srcpos_copy(struct srcpos *pos); extern struct srcpos *srcpos_extend(struct srcpos *new_srcpos, struct srcpos *old_srcpos); +extern void srcpos_free(struct srcpos *pos); extern char *srcpos_string(struct srcpos *pos); extern char *srcpos_string_first(struct srcpos *pos, int level); extern char *srcpos_string_last(struct srcpos *pos, int level); From 97011d1f4e98ecb07ff6aadb14d218a8265b4799 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 12 Jun 2025 07:38:29 +0200 Subject: [PATCH 277/298] meson: use override_find_program/override_dependency Allow projects that use dtc as a subproject to find the tools and library via find_program() and dependency(). This way, for those projects there is no different between system dtc and subproject dtc. Signed-off-by: Paolo Bonzini Message-ID: <20250612053829.1037412-1-pbonzini@redhat.com> Signed-off-by: David Gibson --- libfdt/meson.build | 1 + meson.build | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/libfdt/meson.build b/libfdt/meson.build index 9c6ef54..68d4c1d 100644 --- a/libfdt/meson.build +++ b/libfdt/meson.build @@ -40,6 +40,7 @@ libfdt_dep = declare_dependency( include_directories: libfdt_inc, link_with: libfdt, ) +meson.override_dependency('libfdt', libfdt_dep) if not wheel_only install_headers( diff --git a/meson.build b/meson.build index ed4a39d..66b44e8 100644 --- a/meson.build +++ b/meson.build @@ -118,6 +118,10 @@ if get_option('tools') and not wheel_only ) endif +foreach e: dtc_tools + meson.override_find_program(e.name(), e) +endforeach + if pylibfdt_enabled subdir('pylibfdt') endif From 84d9dd2fcbc865a35d7f04d9b465b05ef286d281 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Thu, 5 Jun 2025 16:18:07 +0530 Subject: [PATCH 278/298] dtc: Add data_insert_data function Add helper function to insert a data struct into another. Signed-off-by: Ayush Singh Message-ID: <20250605-previous-value-v3-2-0983d0733a07@beagleboard.org> Signed-off-by: David Gibson --- data.c | 27 +++++++++++++++++++++++++++ dtc.h | 1 + 2 files changed, 28 insertions(+) diff --git a/data.c b/data.c index 913796f..5b25aa0 100644 --- a/data.c +++ b/data.c @@ -251,6 +251,33 @@ bool data_is_one_string(struct data d) return true; } +struct data data_insert_data(struct data d, struct marker *m, struct data old) +{ + unsigned int offset = m->offset; + struct marker *next = m->next; + struct marker *marker; + struct data new_data; + char *ref; + + new_data = data_insert_at_marker(d, m, old.val, old.len); + + /* Copy all markers from old value */ + marker = old.markers; + for_each_marker(marker) { + ref = NULL; + + if (marker->ref) + ref = xstrdup(marker->ref); + + m->next = alloc_marker(marker->offset + offset, marker->type, + ref); + m = m->next; + } + m->next = next; + + return new_data; +} + struct marker *alloc_marker(unsigned int offset, enum markertype type, char *ref) { diff --git a/dtc.h b/dtc.h index bd80339..3a220b9 100644 --- a/dtc.h +++ b/dtc.h @@ -182,6 +182,7 @@ struct data data_append_addr(struct data d, uint64_t addr); struct data data_append_byte(struct data d, uint8_t byte); struct data data_append_zeroes(struct data d, int len); struct data data_append_align(struct data d, int align); +struct data data_insert_data(struct data d, struct marker *m, struct data old); struct marker *alloc_marker(unsigned int offset, enum markertype type, char *ref); From 53c63dd421d79dbd81e1b608c9b807a463d124a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 14 Jan 2025 11:58:28 +0100 Subject: [PATCH 279/298] dtdiff: Use input format dtb for dtbo files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The file ending .dtbo is typically used for device tree overlays. These are in the dtb input format, too. So assume this input format for *.dtbo as is already done for *.dtb. Signed-off-by: Uwe Kleine-König Signed-off-by: David Gibson --- dtdiff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dtdiff b/dtdiff index cdbf079..841b085 100644 --- a/dtdiff +++ b/dtdiff @@ -17,7 +17,7 @@ source_and_sort () { *.dts) IFORMAT=dts ;; - *.dtb) + *.dtb|*.dtbo) IFORMAT=dtb ;; esac From 7da5d106c7400fc02b0b5bee1b565b07895f5132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 1 Jul 2025 11:54:00 +0200 Subject: [PATCH 280/298] fdtput: Fix documentation about existing nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documentation claims that `-c` would "Create nodes if they don't already exist". This is true, but suggests that trying to create a node that already exists is not an error. fdtput however errors out in that case. Similar `fdtput -d` errors out when called for a non-existing node. Drop the "if they [don't] already exist" to make that clearer. Signed-off-by: Uwe Kleine-König Signed-off-by: David Gibson --- fdtput.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fdtput.c b/fdtput.c index c2fecf4..825640c 100644 --- a/fdtput.c +++ b/fdtput.c @@ -389,8 +389,8 @@ static struct option const usage_long_opts[] = { USAGE_COMMON_LONG_OPTS, }; static const char * const usage_opts_help[] = { - "Create nodes if they don't already exist", - "Delete nodes (and any subnodes) if they already exist", + "Create nodes", + "Delete nodes (and any subnodes)", "Delete properties if they already exist", "Automatically create nodes as needed for the node path", "Type of data", From 605dc044c3fef39fe5404d40f2b5569d77916339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 14 Jan 2025 11:09:29 +0100 Subject: [PATCH 281/298] New helper to add markers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The add_marker() function is used to create a new marker and add it at the right spot to the relevant marker list. Use it in the add_string_markers() helper (which gets slightly quicker by it). Signed-off-by: Uwe Kleine-König Signed-off-by: David Gibson --- treesource.c | 52 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/treesource.c b/treesource.c index ae15839..d25f01f 100644 --- a/treesource.c +++ b/treesource.c @@ -139,26 +139,48 @@ static const char *delim_end[] = { [TYPE_STRING] = "", }; +/* + * The invariants in the marker list are: + * - offsets are non-strictly monotonically increasing + * - for a single offset there is at most one type marker + * - for a single offset that has both a type marker and non-type markers, the + * type marker appears before the others. + */ +static struct marker **add_marker(struct marker **mi, + enum markertype type, unsigned int offset, char *ref) +{ + struct marker *nm; + + while (*mi && (*mi)->offset < offset) + mi = &(*mi)->next; + + if (*mi && (*mi)->offset == offset && is_type_marker((*mi)->type)) { + if (is_type_marker(type)) + return mi; + mi = &(*mi)->next; + } + + if (*mi && (*mi)->offset == offset && type == (*mi)->type) + return mi; + + nm = xmalloc(sizeof(*nm)); + nm->type = type; + nm->offset = offset; + nm->ref = ref; + nm->next = *mi; + *mi = nm; + + return &nm->next; +} + static void add_string_markers(struct property *prop) { int l, len = prop->val.len; const char *p = prop->val.val; + struct marker **mi = &prop->val.markers; - for (l = strlen(p) + 1; l < len; l += strlen(p + l) + 1) { - struct marker *m, **nextp; - - m = xmalloc(sizeof(*m)); - m->offset = l; - m->type = TYPE_STRING; - m->ref = NULL; - m->next = NULL; - - /* Find the end of the markerlist */ - nextp = &prop->val.markers; - while (*nextp) - nextp = &((*nextp)->next); - *nextp = m; - } + for (l = strlen(p) + 1; l < len; l += strlen(p + l) + 1) + mi = add_marker(mi, TYPE_STRING, l, NULL); } static enum markertype guess_value_type(struct property *prop) From 9cabae6b0351dff7eb634ebcdcabf06a276c1222 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 9 Jul 2025 15:24:52 +0100 Subject: [PATCH 282/298] checks: Fix detection of 'i2c-bus' node If an I2C controller has a 'i2c-bus' child node, then the function check_i2c_bus_bridge() does not detect this as expected and warnings such as the following are observed: Warning (i2c_bus_bridge): /example-0/i2c@7000c000: \ incorrect #address-cells for I2C bus Warning (i2c_bus_bridge): /example-0/i2c@7000c000: \ incorrect #size-cells for I2C bus These warnings occur because the '#address-cells' and '#size-cells' are not directly present under the I2C controller node but the 'i2c-bus' child node. The function check_i2c_bus_bridge() does not detect this because it is using the parent node's 'basenamelen' and not the child node's 'basenamelen' when comparing the child node name with 'i2c-bus'. The parent node's 'basenamelen' is shorter ('i2c') than 'i2c-bus' and so the strprefixeq() test fails. Fix this by using the child node 'basenamelen' when comparing the child node name. Fixes: 53a1bd546905 ("checks: add I2C bus checks") Signed-off-by: Jon Hunter Message-ID: <20250709142452.249492-1-jonathanh@nvidia.com> Signed-off-by: David Gibson --- checks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks.c b/checks.c index 123f2eb..7e3fed5 100644 --- a/checks.c +++ b/checks.c @@ -1024,7 +1024,7 @@ static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct no } else if (strprefixeq(node->name, node->basenamelen, "i2c")) { struct node *child; for_each_child(node, child) { - if (strprefixeq(child->name, node->basenamelen, "i2c-bus")) + if (strprefixeq(child->name, child->basenamelen, "i2c-bus")) return; } node->bus = &i2c_bus; From 52f07dcca47cb88aec51b85663f95f46b7e41457 Mon Sep 17 00:00:00 2001 From: Vivian Wang Date: Fri, 4 Jul 2025 18:15:20 +0800 Subject: [PATCH 283/298] dtc: Add informative error for stray identifier When a DTS is preprocessed, sometimes the user fails to include the correct header files, or make a spelling mistake on a macro name. This leads to a stray identifier in the DTS, like: property = <1 2 FOO BAR(3, 4)>; Give a more helpful error message than "syntax error" by recognizing and reporting the identifier, like this: Lexical error: :2.21-24 Unexpected 'FOO' Also, treat that identifier as literal, which often helps the parser go further and may generate more helpful error messages. Signed-off-by: Vivian Wang Signed-off-by: David Gibson --- dtc-lexer.l | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/dtc-lexer.l b/dtc-lexer.l index de60a70..15d585c 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -151,6 +151,21 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...); return DT_LABEL; } +{LABEL} { + /* Missed includes or macro definitions while + * preprocessing can lead to unexpected identifiers in + * the input. Report a slightly more informative error + * in this case */ + + lexical_error("Unexpected '%s'", yytext); + + /* Treat it as a literal which often generates further + * useful error messages */ + + yylval.integer = 0; + return DT_LITERAL; + } + ([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? { char *e; DPRINT("Integer Literal: '%s'\n", yytext); From 5b71660724d7399db52a2ce65da7dacb6e662468 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 25 Jul 2025 13:01:41 +1000 Subject: [PATCH 284/298] tests: Work around limitation in FreeBSD's printf(1) Some of our testcases check fdtget retreiving string list properties that include internal \0 characters. We use printf(1) to generate the expected value for comparison. However, on FreeBSD, printf(1)'s %b format option can't handle \0: it will terminate that argument ignoring it and everything after. Curiously, internal \0 *is* ok in the main format string. So avoid using %b and use the format string directly instead. Link: https:/https://github.com/dgibson/dtc/issues/165 Signed-off-by: David Gibson --- tests/fdtget-runtest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh index 18b7404..35fa5e1 100755 --- a/tests/fdtget-runtest.sh +++ b/tests/fdtget-runtest.sh @@ -9,7 +9,7 @@ rm -f $LOG $EXPECT trap "rm -f $LOG $EXPECT" 0 expect="$1" -printf '%b\n' "$expect" > $EXPECT +printf "$expect\n" > $EXPECT shift verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@" From a0dd7b608102bb04de414b47933f776827cf5427 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 28 Jul 2025 16:42:34 +1000 Subject: [PATCH 285/298] fdtput: Use strtol() in preference to sscanf() I find the exact semantics of scanf() always confusing, and mostly we use strtol() and similar functions instead. Switch fdtput to using strtol and similar functions instead of sscanf(). As well as being more in keeping with what we do in other places, this works around a FreeBSD bug[0], where sscanf(), but not strtol() parses "003" as having value 0. [0] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=288440 Link: https://github.com/dgibson/dtc/issues/165 Signed-off-by: David Gibson --- fdtput.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/fdtput.c b/fdtput.c index 825640c..05f2b93 100644 --- a/fdtput.c +++ b/fdtput.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -64,16 +65,12 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count, int len; /* length of this cell/string/byte */ int ival; int upto; /* the number of bytes we have written to buf */ - char fmt[3]; upto = 0; if (disp->verbose) fprintf(stderr, "Decoding value:\n"); - fmt[0] = '%'; - fmt[1] = disp->type ? disp->type : 'd'; - fmt[2] = '\0'; for (; arg_count > 0; arg++, arg_count--, upto += len) { /* assume integer unless told otherwise */ if (disp->type == 's') @@ -94,7 +91,34 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count, fprintf(stderr, "\tstring: '%s'\n", ptr); } else { fdt32_t *iptr = (fdt32_t *)ptr; - sscanf(*arg, fmt, &ival); + char *endptr; + + errno = 0; + switch (disp->type) { + case 'x': + ival = strtoul(*arg, &endptr, 16); + break; + case 'o': + ival = strtoul(*arg, &endptr, 8); + break; + case 'i': + ival = strtol(*arg, &endptr, 0); + break; + case 'u': + ival = strtoul(*arg, &endptr, 0); + break; + default: /* 0 or 'd' */ + ival = strtol(*arg, &endptr, 10); + } + + if (*endptr != '\0' || errno) { + if (disp->verbose) { + fprintf(stderr, + "Couldn't parse \"%s\" as an integer\n", + *arg); + } + return -1; + } if (len == 4) *iptr = cpu_to_fdt32(ival); else From 33e66ec845b8914ad45f559a275673a2a2881576 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 24 Jul 2025 13:26:31 +1000 Subject: [PATCH 286/298] tests: Add compatibility with uutils In some places run_tsets.sh needs to get the size of files, which it does with stat(1). However the syntax to do this is different between GNU coreutils stat(1) and BSD's stat(1). We have some logic that looks for "GNU" in the version string to figure out the correct version. This will break upcoming Ubuntu versions which are now using uutils, a Rust reimplementation of coreutils. These support the same GNU syntax, but don't have the "GNU" in the version string. Update the detection to simply try the GNU version and otherwise assume BSD. Link: https://github.com/dgibson/dtc/issues/166 Signed-off-by: David Gibson --- tests/run_tests.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index fecfe7c..2e172d7 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -43,13 +43,14 @@ fi # stat differs between platforms if [ -z "$STATSZ" ]; then - stat --version 2>/dev/null | grep -q 'GNU' - GNUSTAT=$? - if [ "$GNUSTAT" -ne 0 ]; then - # Assume BSD stat if we can't detect as GNU stat - STATSZ="stat -f %Uz" - else + # First attempt GNU style, this is supported by both the + # actual GNU coreutils version, and the Rust re-implementation + # uutils, used in recent Ubuntu versions + if stat -c %s $0; then STATSZ="stat -c %s" + else + # Otherwise assume BSD style stat + STATSZ="stat -f %Uz" fi fi From 4132ac08ba95713316e604e4bd09923c0d14ffd7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Aug 2025 11:34:18 +1000 Subject: [PATCH 287/298] libfdt: Document most remaining functions Largely an experiment using an AI assistant. Used Claude to generate documentation comments for most of the functions in libfdt.h which currently lack them. Then hand reviewed and edited. Or, as Claude describes it: Add detailed documentation comments for core libfdt functions including: - Low-level functions (fdt_offset_ptr, fdt_next_tag, fdt_check_full) - Sequential write functions (fdt_resize, fdt_add_reservemap_entry, fdt_finish_reservemap, fdt_begin_node, fdt_property, fdt_end_node, fdt_finish) - Read-write functions (fdt_create_empty_tree, fdt_open_into, fdt_pack) - Error handling (fdt_strerror) Documentation includes parameter descriptions, return value meanings, and usage notes for proper API usage. Generated-by: Claude 1.0.64 (claude-sonnet-4@20250514) Reviewed-by: David Gibson Signed-off-by: David Gibson --- libfdt/TODO | 1 - libfdt/libfdt.h | 214 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+), 1 deletion(-) diff --git a/libfdt/TODO b/libfdt/TODO index 288437e..ea2ef92 100644 --- a/libfdt/TODO +++ b/libfdt/TODO @@ -1,3 +1,2 @@ - Tree traversal functions - Graft function -- Complete libfdt.h documenting comments diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index b5e7200..7a10f66 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -116,6 +116,20 @@ extern "C" { /* Low-level functions (you probably don't need these) */ /**********************************************************************/ +/** + * fdt_offset_ptr - safely get a byte range within the device tree blob + * @fdt: Pointer to the device tree blob + * @offset: Offset within the blob to the desired byte range + * @checklen: Required length of the byte range + * + * fdt_offset_ptr() returns a pointer to the byte range of length @checklen at + * the given @offset within the device tree blob, after verifying that the byte + * range fits entirely within the blob and does not overflow. + * + * returns: + * pointer to the byte range, on success + * NULL, if the requested range does not fit within the blob + */ #ifndef SWIG /* This function is not useful in Python */ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); #endif @@ -124,6 +138,20 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); } +/** + * fdt_next_tag - get next tag in the device tree + * @fdt: Pointer to the device tree blob + * @offset: Offset within the blob to start searching + * @nextoffset: Pointer to variable to store the offset of the next tag + * + * fdt_next_tag() returns the tag type of the next tag in the device tree + * blob starting from the given @offset. If @nextoffset is non-NULL, it will + * be set to the offset immediately following the tag. + * + * returns: + * the tag type (FDT_BEGIN_NODE, FDT_END_NODE, FDT_PROP, FDT_NOP, FDT_END), + * FDT_END, if offset is out of bounds + */ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); /* @@ -334,6 +362,23 @@ int fdt_move(const void *fdt, void *buf, int bufsize); /* Read-only functions */ /**********************************************************************/ +/** + * fdt_check_full - check device tree validity + * @fdt: pointer to the device tree blob + * @bufsize: size of the buffer containing the device tree + * + * fdt_check_full() checks that the given buffer contains a valid + * flattened device tree and that the tree structure is internally + * consistent. This is a more thorough check than fdt_check_header(). + * + * returns: + * 0, on success + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ int fdt_check_full(const void *fdt, size_t bufsize); /** @@ -1540,10 +1585,90 @@ int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags); */ int fdt_create(void *buf, int bufsize); +/** + * fdt_resize - move and resize a device tree in sequential write state + * @fdt: Pointer to the device tree to resize + * @buf: Buffer where resized tree should be placed + * @bufsize: Size of the buffer at @buf + * + * fdt_resize() moves the device tree blob from @fdt to @buf and + * resizes it to fit in the new buffer size. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if @bufsize is too small + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ int fdt_resize(void *fdt, void *buf, int bufsize); + +/** + * fdt_add_reservemap_entry - add an entry to the memory reserve map + * @fdt: Pointer to the device tree blob + * @addr: Start address of the reserve map entry + * @size: Size of the reserved region + * + * fdt_add_reservemap_entry() adds a memory reserve map entry to the + * device tree blob during the sequential write process. This function + * can only be called after fdt_create() and before fdt_finish_reservemap(). + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if there is insufficient space in the blob + * -FDT_ERR_BADSTATE, if not in the correct sequential write state + */ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); + +/** + * fdt_finish_reservemap - complete the memory reserve map + * @fdt: Pointer to the device tree blob + * + * fdt_finish_reservemap() completes the memory reserve map section + * of the device tree blob during sequential write. After calling this + * function, no more reserve map entries can be added and the blob + * moves to the structure creation phase. + * + * returns: + * 0, on success + * -FDT_ERR_BADSTATE, if not in the correct sequential write state + */ int fdt_finish_reservemap(void *fdt); + +/** + * fdt_begin_node - start creation of a new node + * @fdt: Pointer to the device tree blob + * @name: Name of the node to create + * + * fdt_begin_node() starts the creation of a new node with the given + * @name during sequential write. After calling this function, properties + * can be added with fdt_property() and subnodes can be created with + * additional fdt_begin_node() calls. The node must be completed with + * fdt_end_node(). + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if there is insufficient space in the blob + * -FDT_ERR_BADSTATE, if not in the correct sequential write state + */ int fdt_begin_node(void *fdt, const char *name); + +/** + * fdt_property - add a property to the current node + * @fdt: Pointer to the device tree blob + * @name: Name of the property to add + * @val: Pointer to the property value + * @len: Length of the property value in bytes + * + * fdt_property() adds a property with the given @name and value to + * the current node during sequential write. This function can only + * be called between fdt_begin_node() and fdt_end_node(). + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if there is insufficient space in the blob + * -FDT_ERR_BADSTATE, if not currently within a node + */ int fdt_property(void *fdt, const char *name, const void *val, int len); static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) { @@ -1580,15 +1705,94 @@ int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp); #define fdt_property_string(fdt, name, str) \ fdt_property(fdt, name, str, strlen(str)+1) + +/** + * fdt_end_node - complete the current node + * @fdt: Pointer to the device tree blob + * + * fdt_end_node() completes the current node during sequential write. This + * function must be called to close each node started with + * fdt_begin_node(). After calling this function, no more properties or subnodes + * can be added to the node. + * + * returns: + * 0, on success + * -FDT_ERR_BADSTATE, if not currently within a node + */ int fdt_end_node(void *fdt); + +/** + * fdt_finish - complete device tree creation + * @fdt: Pointer to the device tree blob + * + * fdt_finish() completes the device tree creation process started with + * fdt_create(). This function finalizes the device tree blob and makes it ready + * for use. After calling this function, the blob is complete and can be used + * with libfdt read-only and read-write functions, but not with sequential write + * functions. + * + * returns: + * 0, on success + * -FDT_ERR_BADSTATE, if the sequential write process is incomplete + */ int fdt_finish(void *fdt); /**********************************************************************/ /* Read-write functions */ /**********************************************************************/ +/** + * fdt_create_empty_tree - create an empty device tree + * @buf: Buffer where the empty tree should be created + * @bufsize: Size of the buffer at @buf + * + * fdt_create_empty_tree() creates a minimal empty device tree blob + * in the given buffer. The tree contains only a root node with no + * properties or subnodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if @bufsize is too small for even an empty tree + */ int fdt_create_empty_tree(void *buf, int bufsize); + +/** + * fdt_open_into - move a device tree into a new buffer and make editable + * @fdt: Pointer to the device tree to move + * @buf: Buffer where the editable tree should be placed + * @bufsize: Size of the buffer at @buf + * + * fdt_open_into() moves and reorganizes the device tree blob from @fdt + * into @buf, converting it to a format suitable for read-write operations. + * The new buffer should allow space for modifications. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if @bufsize is too small + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ int fdt_open_into(const void *fdt, void *buf, int bufsize); + +/** + * fdt_pack - pack a device tree blob + * @fdt: Pointer to the device tree blob + * + * fdt_pack() reorganizes the device tree blob to eliminate any free space + * and pack it into the minimum possible size. This is useful after making + * modifications that might have left gaps in the blob. + * + * returns: + * 0, on success + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, standard meanings + */ int fdt_pack(void *fdt); /** @@ -2317,6 +2521,16 @@ int fdt_overlay_target_offset(const void *fdt, const void *fdto, /* Debugging / informational functions */ /**********************************************************************/ +/** + * fdt_strerror - return string description of error code + * @errval: Error code returned by a libfdt function + * + * fdt_strerror() returns a string description of the error code passed + * in @errval. + * + * returns: + * pointer to a string describing the error code + */ const char *fdt_strerror(int errval); #ifdef __cplusplus From 2ad738722b79dbfccd4ddbe7408720bac3dba3d6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Aug 2025 15:35:06 +1000 Subject: [PATCH 288/298] build: Add FreeBSD and non-GNU linker compatibility Add compatibility fixes for non-GNU compilers and linkers by testing versions before using certain flags. In particular this fixes make build problems on FreeBSD. Generated-by: Claude Code 1.0.65 (claude-sonnet-4@20250514) Reviewed-by: David Gibson Signed-off-by: David Gibson --- Makefile | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index b1815c3..83d8220 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,10 @@ ASSUME_MASK ?= 0 CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK) WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs -Wsign-compare \ -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow \ - -Wsuggest-attribute=format -Wwrite-strings + -Wwrite-strings +ifeq ($(shell $(CC) --version | grep -q gcc && echo gcc),gcc) +WARNINGS += -Wsuggest-attribute=format +endif CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS) BISON = bison @@ -65,6 +68,8 @@ else CFLAGS += $(shell $(PKG_CONFIG) --cflags yaml-0.1) endif +HAS_VERSION_SCRIPT := $(shell echo 'int main(){}' | $(CC) -Wl,--version-script=/dev/null -x c - -o /dev/null 2>/dev/null && echo y) + ifeq ($(HOSTOS),darwin) SHAREDLIB_EXT = dylib SHAREDLIB_CFLAGS = -fPIC @@ -72,11 +77,15 @@ SHAREDLIB_LDFLAGS = -fPIC -dynamiclib -Wl,-install_name -Wl, else ifeq ($(HOSTOS),$(filter $(HOSTOS),msys cygwin)) SHAREDLIB_EXT = so SHAREDLIB_CFLAGS = -SHAREDLIB_LDFLAGS = -shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname, +SHAREDLIB_LDFLAGS = -shared -Wl,-soname, else SHAREDLIB_EXT = so SHAREDLIB_CFLAGS = -fPIC -SHAREDLIB_LDFLAGS = -fPIC -shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname, +SHAREDLIB_LDFLAGS = -fPIC -shared -Wl,-soname, +endif + +ifeq ($(HAS_VERSION_SCRIPT),y) +SHAREDLIB_LDFLAGS += -Wl,--version-script=$(LIBFDT_version) endif # From e896802631374ab74547e3d8395f384839e60064 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Aug 2025 15:35:31 +1000 Subject: [PATCH 289/298] ci: Tweaks to GitHub Actions setup Remove some unnecessary package dependencies. Also include testing of the 'ci' branch (so as to test in-progress changes to the CI configuration itself). Generated-by: Claude Code 1.0.65 (claude-sonnet-4@20250514) Reviewed-by: David Gibson Signed-off-by: David Gibson --- .github/workflows/build.yml | 1 + scripts/install-deps.sh | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a030ae6..b6e0a9c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,6 +4,7 @@ name: Build test push: branches: - main + - ci pull_request: branches: - main diff --git a/scripts/install-deps.sh b/scripts/install-deps.sh index 12507de..d243504 100755 --- a/scripts/install-deps.sh +++ b/scripts/install-deps.sh @@ -12,20 +12,20 @@ fi if [ "$NAME" = "Arch Linux" ] then pacman -Syu --needed --noconfirm bison diffutils flex gcc git libyaml \ - make meson pkgconf python python-setuptools-scm swig valgrind which + make meson pkgconf python python-setuptools-scm swig elif [ "$NAME" = "Alpine Linux" ] then - apk add build-base bison coreutils flex git yaml yaml-dev python3-dev \ - meson py3-setuptools_scm swig valgrind + apk add build-base bison flex git yaml yaml-dev python3-dev \ + meson py3-setuptools_scm swig elif [ "$NAME" = "Fedora Linux" ] then dnf install -y bison diffutils flex gcc git libyaml libyaml-devel \ - make meson python3-devel python3-setuptools swig valgrind which + make meson python3-devel python3-setuptools swig elif [ "$NAME" = "Ubuntu" ] then apt update apt install -yq build-essential bison flex git libyaml-dev pkg-config \ - meson python3-dev python3-setuptools python3-setuptools-scm swig valgrind + meson python3-dev python3-setuptools python3-setuptools-scm swig else echo "ERROR: OS name is not provided." exit 1 From 04f948e83fef8d010dc043fc0208ac9d8c5f52d5 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Aug 2025 15:35:21 +1000 Subject: [PATCH 290/298] ci: Add GitLab CI configuration for Linux builds Add GitLab CI with Linux builds on Alpine, Arch, Fedora, and Ubuntu using both make and meson build systems. Generated-by: Claude Code 1.0.65 (claude-sonnet-4@20250514) Reviewed-by: David Gibson Signed-off-by: David Gibson --- .gitlab-ci.yml | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..f5b1fb1 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,65 @@ +stages: + - build + +variables: + GIT_DEPTH: 1 + +workflow: + rules: + - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main" + - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "ci" + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + +# Linux builds with make +.build-make-template: &build-make-template + stage: build + before_script: + - ./scripts/install-deps.sh + script: + - make + - make check + interruptible: true + +build-make-alpine: + <<: *build-make-template + image: alpine:latest + +build-make-archlinux: + <<: *build-make-template + image: archlinux:latest + +build-make-fedora: + <<: *build-make-template + image: fedora:latest + +build-make-ubuntu: + <<: *build-make-template + image: ubuntu:latest + +# Linux builds with meson +.build-meson-template: &build-meson-template + stage: build + before_script: + - ./scripts/install-deps.sh + script: + - meson setup -D python=enabled -D yaml=enabled build + - meson compile -C build + - if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi + interruptible: true + +build-meson-alpine: + <<: *build-meson-template + image: alpine:latest + +build-meson-archlinux: + <<: *build-meson-template + image: archlinux:latest + +build-meson-fedora: + <<: *build-meson-template + image: fedora:latest + +build-meson-ubuntu: + <<: *build-meson-template + image: ubuntu:latest + From 617f3d9b60f7c52473c52caf7c197718e80c912b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Aug 2025 15:35:46 +1000 Subject: [PATCH 291/298] ci: Add Cirrus CI configuration for FreeBSD testing Add FreeBSD test coverage with builds on FreeBSD 13.5 and 14.3 using both make and meson build systems. Generated-by: Claude Code 1.0.65 (claude-sonnet-4@20250514) Reviewed-by: David Gibson Signed-off-by: David Gibson --- .cirrus.yml | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .cirrus.yml diff --git a/.cirrus.yml b/.cirrus.yml new file mode 100644 index 0000000..825aeb7 --- /dev/null +++ b/.cirrus.yml @@ -0,0 +1,39 @@ +# FreeBSD build with multiple versions +freebsd_versions_task: + name: FreeBSD $FREEBSD_VERSION make build + freebsd_instance: + image_family: $FREEBSD_IMAGE + matrix: + - env: + FREEBSD_VERSION: "13.5" + FREEBSD_IMAGE: freebsd-13-5 + - env: + FREEBSD_VERSION: "14.3" + FREEBSD_IMAGE: freebsd-14-3 + install_script: + - pkg install -y git gmake flex bison python3 py312-setuptools swig libyaml pkgconf + build_script: + - gmake + check_script: + - gmake check + +# FreeBSD meson builds with multiple versions +freebsd_meson_versions_task: + name: FreeBSD $FREEBSD_VERSION meson build + freebsd_instance: + image_family: $FREEBSD_IMAGE + matrix: + - env: + FREEBSD_VERSION: "13.5" + FREEBSD_IMAGE: freebsd-13-5 + - env: + FREEBSD_VERSION: "14.3" + FREEBSD_IMAGE: freebsd-14-3 + install_script: + - pkg install -y git meson ninja flex bison python3 py312-setuptools swig libyaml pkgconf + setup_script: + - meson setup -D python=enabled -D yaml=enabled build + build_script: + - meson compile -C build + test_script: + - if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi From 1c6c51e51b29a1c7204cb0e2085709ae7caa57af Mon Sep 17 00:00:00 2001 From: Colin Finck Date: Wed, 6 Aug 2025 15:52:31 +0200 Subject: [PATCH 292/298] Consider drive letters when checking for absolute paths on Windows. This still requires you to specify paths with forward slashes instead of backslashes on Windows, due to many hardcoded checks for '/'. Fortunately, the Windows user APIs all support forward slashes too. Signed-off-by: Colin Finck Signed-off-by: David Gibson --- srcpos.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/srcpos.c b/srcpos.c index 5bb57bf..fef892f 100644 --- a/srcpos.c +++ b/srcpos.c @@ -88,6 +88,26 @@ static char *shorten_to_initial_path(char *fname) return NULL; } +/** + * Returns true if the given path is an absolute one. + * + * On Windows, it either needs to begin with a forward slash or with a drive + * letter (e.g. "C:"). + * On all other operating systems, it must begin with a forward slash to be + * considered an absolute path. + */ +static bool is_absolute_path(const char *path) +{ +#ifdef WIN32 + return ( + path[0] == '/' || + (((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) && path[1] == ':') + ); +#else + return (path[0] == '/'); +#endif +} + /** * Try to open a file in a given directory. * @@ -103,7 +123,7 @@ static char *try_open(const char *dirname, const char *fname, FILE **fp) { char *fullname; - if (!dirname || fname[0] == '/') + if (!dirname || is_absolute_path(fname)) fullname = xstrdup(fname); else fullname = join_path(dirname, fname); From 739403f222420a2fade2f939d001f51da473b6af Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Mon, 11 Aug 2025 08:04:16 -0500 Subject: [PATCH 293/298] libfdt: Drop including string.h from libfdt_internal.h Commit 0f69cedc08fc ("libfdt_internal: fdt_find_string_len_()") added a string.h include to libfdt_internal.h which introduces a libc dependency which cannot be overridden. Environments without libc (e.g. Linux kernel) use a custom libfdt_env.h. string.h is already indirectly included in libfdt_env.h, so it can be dropped from libfdt_internal.h. Fixes: 0f69cedc08fc ("libfdt_internal: fdt_find_string_len_()") Signed-off-by: Rob Herring (Arm) Message-ID: <20250811130416.2653959-1-robh@kernel.org> Reviewed-by: Simon Glass Signed-off-by: David Gibson --- libfdt/libfdt_internal.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 773bba8..b60b545 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -6,7 +6,6 @@ * Copyright (C) 2006 David Gibson, IBM Corporation. */ #include -#include #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) From 763c6ab4189c16cb61b5878dddcbd46d76535e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Aug 2025 12:35:45 +0200 Subject: [PATCH 294/298] livetree: Simplify append_to_property() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two if branches are quite similar. Build the property first (in case it doesn't exist) and then the common parts can be done outside the if block. Signed-off-by: Uwe Kleine-König Message-ID: Signed-off-by: David Gibson --- livetree.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/livetree.c b/livetree.c index d51d058..6127d60 100644 --- a/livetree.c +++ b/livetree.c @@ -340,20 +340,16 @@ void append_to_property(struct node *node, char *name, const void *data, int len, enum markertype type) { - struct data d; struct property *p; p = get_property(node, name); - if (p) { - d = data_add_marker(p->val, type, name); - d = data_append_data(d, data, len); - p->val = d; - } else { - d = data_add_marker(empty_data, type, name); - d = data_append_data(d, data, len); - p = build_property(name, d, NULL); + if (!p) { + p = build_property(name, empty_data, NULL); add_property(node, p); } + + p->val = data_add_marker(p->val, type, name); + p->val = data_append_data(p->val, data, len); } struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) From cba90ce82064ad1e6d25f20d8eaa940bd2fc97ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Sun, 17 Aug 2025 15:37:33 +0200 Subject: [PATCH 295/298] checks: Remove check for graph child addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dtc graph_child_address check can't distinguish between bindings where there can only be a single endpoint, and cases where there can be multiple endpoints. In cases where the bindings allow for multiple endpoints but only one is described false warnings about unnecessary #address-cells/#size-cells can be generated, but only if the endpoint described have an address of 0 (A), for single endpoints with a non-zero address (B) no warnings are generated. A) ports { #address-cells = <1>; #size-cells = <0>; port@0 { #address-cells = <1>; #size-cells = <0>; sourceA: endpoint@0 { reg = <0> }; }; }; B) ports { #address-cells = <1>; #size-cells = <0>; port@0 { #address-cells = <1>; #size-cells = <0>; sourceB: endpoint@1 { reg = <1> }; }; }; Remove the check as it is somewhat redundant now that we can use schemas to validate the full node. Signed-off-by: Niklas Söderlund Reviewed-by: Rob Herring (Arm) Message-ID: <20250817133733.3483922-1-niklas.soderlund+renesas@ragnatech.se> Signed-off-by: David Gibson --- checks.c | 27 +-------------------------- tests/run_tests.sh | 2 -- 2 files changed, 1 insertion(+), 28 deletions(-) diff --git a/checks.c b/checks.c index 7e3fed5..2072e1e 100644 --- a/checks.c +++ b/checks.c @@ -1894,31 +1894,6 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti, } WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes); -static void check_graph_child_address(struct check *c, struct dt_info *dti, - struct node *node) -{ - int cnt = 0; - struct node *child; - - if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus) - return; - - for_each_child(node, child) { - struct property *prop = get_property(child, "reg"); - - /* No error if we have any non-zero unit address */ - if (prop && propval_cell(prop) != 0 ) - return; - - cnt++; - } - - if (cnt == 1 && node->addr_cells != -1) - FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary", - node->children->name); -} -WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes, &graph_port, &graph_endpoint); - static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &node_name_chars, &node_name_format, &property_name_chars, @@ -2005,7 +1980,7 @@ static struct check *check_table[] = { &alias_paths, - &graph_nodes, &graph_child_address, &graph_port, &graph_endpoint, + &graph_nodes, &graph_port, &graph_endpoint, &always_fail, }; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 2e172d7..6c60488 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -749,7 +749,6 @@ dtc_tests () { check_tests "$SRCDIR/bad-phandle-cells.dts" interrupts_extended_property check_tests "$SRCDIR/bad-gpio.dts" gpios_property check_tests "$SRCDIR/good-gpio.dts" -n gpios_property - check_tests "$SRCDIR/bad-graph.dts" graph_child_address check_tests "$SRCDIR/bad-graph.dts" graph_port check_tests "$SRCDIR/bad-graph.dts" graph_endpoint check_tests "$SRCDIR/bad-graph-root1.dts" graph_nodes @@ -758,7 +757,6 @@ dtc_tests () { check_tests "$SRCDIR/bad-graph-root4.dts" graph_nodes check_tests "$SRCDIR/bad-graph-reg-cells.dts" graph_endpoint check_tests "$SRCDIR/bad-graph-reg-cells.dts" graph_port - check_tests "$SRCDIR/bad-graph-child-address.dts" graph_child_address run_sh_test "$SRCDIR/dtc-checkfails.sh" deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/bad-gpio.dts" run_sh_test "$SRCDIR/dtc-checkfails.sh" -n deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/good-gpio.dts" check_tests "$SRCDIR/bad-interrupt-cells.dts" interrupts_property From e1284ee5dc20f94097bc6424ede9c3e433dba77d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Aug 2025 12:35:46 +0200 Subject: [PATCH 296/298] livetree: Add only new data to fixup nodes instead of complete regeneration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removing the complete __fixups__ and __local_fixups__ tree might delete data that should better be retained. See the added test for a situation that was broken before. Note that without removing /__fixups__ and /__local_fixups__ in generate_fixups_tree() and generate_local_fixups_tree() respectively calling build_and_name_child_node() isn't safe as the nodes might already exist and then a duplicate would be added. So build_root_node() has to be used which copes correctly here. Fixes: 915daadbb62d ("Start with empty __local_fixups__ and __fixups__ nodes") Closes: https://github.com/dgibson/dtc/issues/170 Signed-off-by: Uwe Kleine-König Message-ID: [dwg: Use -1 instead of 1 as an error return] Signed-off-by: David Gibson --- livetree.c | 127 +++++++++++++++++++++++++++++----------- tests/retain-fixups.dts | 29 +++++++++ tests/run_tests.sh | 5 ++ 3 files changed, 128 insertions(+), 33 deletions(-) create mode 100644 tests/retain-fixups.dts diff --git a/livetree.c b/livetree.c index 6127d60..f328824 100644 --- a/livetree.c +++ b/livetree.c @@ -352,6 +352,63 @@ void append_to_property(struct node *node, p->val = data_append_data(p->val, data, len); } +static int append_unique_str_to_property(struct node *node, + char *name, const char *data, int len) +{ + struct property *p; + + p = get_property(node, name); + if (p) { + const char *s; + + if (p->val.len && p->val.val[p->val.len - 1] != '\0') + /* The current content doesn't look like a string */ + return -1; + + for (s = p->val.val; s < p->val.val + p->val.len; s = strchr(s, '\0') + 1) { + if (strcmp(data, s) == 0) + /* data already contained in node.name */ + return 0; + } + } else { + p = build_property(name, empty_data, NULL); + add_property(node, p); + } + + p->val = data_add_marker(p->val, TYPE_STRING, name); + p->val = data_append_data(p->val, data, len); + + return 0; +} + +static int append_unique_u32_to_property(struct node *node, char *name, fdt32_t value) +{ + struct property *p; + + p = get_property(node, name); + if (p) { + const fdt32_t *v, *val_end = (const fdt32_t *)p->val.val + p->val.len / 4; + + if (p->val.len % 4 != 0) + /* The current content doesn't look like a u32 array */ + return -1; + + for (v = (const void *)p->val.val; v < val_end; v++) { + if (*v == value) + /* value already contained */ + return 0; + } + } else { + p = build_property(name, empty_data, NULL); + add_property(node, p); + } + + p->val = data_add_marker(p->val, TYPE_UINT32, name); + p->val = data_append_data(p->val, &value, 4); + + return 0; +} + struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) { struct reserve_info *new = xmalloc(sizeof(*new)); @@ -914,11 +971,12 @@ static bool any_fixup_tree(struct dt_info *dti, struct node *node) return false; } -static void add_fixup_entry(struct dt_info *dti, struct node *fn, - struct node *node, struct property *prop, - struct marker *m) +static int add_fixup_entry(struct dt_info *dti, struct node *fn, + struct node *node, struct property *prop, + struct marker *m) { char *entry; + int ret; /* m->ref can only be a REF_PHANDLE, but check anyway */ assert(m->type == REF_PHANDLE); @@ -935,32 +993,39 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn, xasprintf(&entry, "%s:%s:%u", node->fullpath, prop->name, m->offset); - append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING); + ret = append_unique_str_to_property(fn, m->ref, entry, strlen(entry) + 1); free(entry); + + return ret; } -static void generate_fixups_tree_internal(struct dt_info *dti, - struct node *fn, - struct node *node) +static int generate_fixups_tree_internal(struct dt_info *dti, + struct node *fn, + struct node *node) { struct node *dt = dti->dt; struct node *c; struct property *prop; struct marker *m; struct node *refnode; + int ret = 0; for_each_property(node, prop) { m = prop->val.markers; for_each_marker_of_type(m, REF_PHANDLE) { refnode = get_node_by_ref(dt, m->ref); if (!refnode) - add_fixup_entry(dti, fn, node, prop, m); + if (add_fixup_entry(dti, fn, node, prop, m)) + ret = -1; } } for_each_child(node, c) - generate_fixups_tree_internal(dti, fn, c); + if (generate_fixups_tree_internal(dti, fn, c)) + ret = -1; + + return ret; } static bool any_local_fixup_tree(struct dt_info *dti, struct node *node) @@ -985,7 +1050,7 @@ static bool any_local_fixup_tree(struct dt_info *dti, struct node *node) return false; } -static void add_local_fixup_entry(struct dt_info *dti, +static int add_local_fixup_entry(struct dt_info *dti, struct node *lfn, struct node *node, struct property *prop, struct marker *m, struct node *refnode) @@ -1016,30 +1081,35 @@ static void add_local_fixup_entry(struct dt_info *dti, free(compp); value_32 = cpu_to_fdt32(m->offset); - append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32); + return append_unique_u32_to_property(wn, prop->name, value_32); } -static void generate_local_fixups_tree_internal(struct dt_info *dti, - struct node *lfn, - struct node *node) +static int generate_local_fixups_tree_internal(struct dt_info *dti, + struct node *lfn, + struct node *node) { struct node *dt = dti->dt; struct node *c; struct property *prop; struct marker *m; struct node *refnode; + int ret = 0; for_each_property(node, prop) { m = prop->val.markers; for_each_marker_of_type(m, REF_PHANDLE) { refnode = get_node_by_ref(dt, m->ref); if (refnode) - add_local_fixup_entry(dti, lfn, node, prop, m, refnode); + if (add_local_fixup_entry(dti, lfn, node, prop, m, refnode)) + ret = -1; } } for_each_child(node, c) - generate_local_fixups_tree_internal(dti, lfn, c); + if (generate_local_fixups_tree_internal(dti, lfn, c)) + ret = -1; + + return ret; } void generate_label_tree(struct dt_info *dti, const char *name, bool allocph) @@ -1052,29 +1122,20 @@ void generate_label_tree(struct dt_info *dti, const char *name, bool allocph) void generate_fixups_tree(struct dt_info *dti, const char *name) { - struct node *n = get_subnode(dti->dt, name); - - /* Start with an empty __fixups__ node to not get duplicates */ - if (n) - n->deleted = true; - if (!any_fixup_tree(dti, dti->dt)) return; - generate_fixups_tree_internal(dti, - build_and_name_child_node(dti->dt, name), - dti->dt); + if (generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt)) + fprintf(stderr, + "Warning: Preexisting data in %s malformed, some content could not be added.\n", + name); } void generate_local_fixups_tree(struct dt_info *dti, const char *name) { - struct node *n = get_subnode(dti->dt, name); - - /* Start with an empty __local_fixups__ node to not get duplicates */ - if (n) - n->deleted = true; if (!any_local_fixup_tree(dti, dti->dt)) return; - generate_local_fixups_tree_internal(dti, - build_and_name_child_node(dti->dt, name), - dti->dt); + if (generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt)) + fprintf(stderr, + "Warning: Preexisting data in %s malformed, some content could not be added.\n", + name); } diff --git a/tests/retain-fixups.dts b/tests/retain-fixups.dts new file mode 100644 index 0000000..ec09db8 --- /dev/null +++ b/tests/retain-fixups.dts @@ -0,0 +1,29 @@ +/dts-v1/; +/plugin/; + +/ { + fixup-node { + property = <0xffffffff>; + property-with-fixup = <0xffffffff>; + property-with-label = <&somenode>; + property-with-label-and-fixup = <&somenode>; + }; + + label: local-fixup-node { + property = <0xffffffff>; + property-with-local-fixup = <0xffffffff>; + property-with-local-label = <&label>; + property-with-local-label-and-fixup = <&label>; + }; + + __fixups__ { + somenode = "/fixup-node:property-with-fixup:0", "/fixup-node:property-with-label-and-fixup:0"; + }; + + __local_fixups__ { + local-fixup-node { + property-with-local-fixup = <0x00>; + property-with-local-label-and-fixup = <0x00>; + }; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 6c60488..f07092b 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -667,6 +667,11 @@ dtc_tests () { run_test dtbs_equal_ordered $tree.test.dtb $tree.test.dts.test.dtb done + # Check preservation of __fixups__ and __local_fixups__ + run_dtc_test -I dts -O dtb -o retain-fixups.test.dtb "$SRCDIR/retain-fixups.dts" + run_fdtget_test "/fixup-node:property-with-fixup:0 /fixup-node:property-with-label-and-fixup:0 /fixup-node:property-with-label:0" retain-fixups.test.dtb /__fixups__ somenode + run_fdtget_test "property-with-local-fixup\nproperty-with-local-label-and-fixup\nproperty-with-local-label" -p retain-fixups.test.dtb /__local_fixups__/local-fixup-node + # Check -Oyaml output if ! $no_yaml; then for tree in type-preservation; do From 9197f1ccd95c9475006677aa97bf39727c1e8aa5 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Fri, 22 Aug 2025 12:10:38 -0500 Subject: [PATCH 297/298] checks: Do not check overlays for alias paths The path given as an alias inside an overlay can be a path to a node in the base DT. The path check searches only the overlay as that is the only tree available leading to false check failures. Skip this check when checking an overlay. Signed-off-by: Andrew Davis Message-ID: <20250822171038.190122-1-afd@ti.com> Signed-off-by: David Gibson --- checks.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/checks.c b/checks.c index 2072e1e..5d09216 100644 --- a/checks.c +++ b/checks.c @@ -718,11 +718,14 @@ static void check_alias_paths(struct check *c, struct dt_info *dti, continue; } - if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) { + /* This check does not work for overlays with external paths */ + if (!(dti->dtsflags & DTSF_PLUGIN) && + (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val))) { FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)", prop->val.val); continue; } + if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name)) FAIL(c, dti, node, "aliases property name must include only lowercase and '-'"); } From 7f3184a6c550bb8fb59e93c9901d75dced889dcf Mon Sep 17 00:00:00 2001 From: Adam Lackorzynski Date: Mon, 29 Sep 2025 15:51:25 +0200 Subject: [PATCH 298/298] libfdt: Remove old MacOS strnlen workaround The check for the MacOS X version (10.7) is problematic, because it fails unless _DARWIN_C_SOURCE is defined if also _POSIX_C_SOURCE or _XOPEN_SOURCE is defined, as then the Darwin version defines are not defined. We cannot force _DARWIN_C_SOURCE reliably in the header either, because we cannot be sure that the libfdt_env.h has not already been included by another source before. The check is also only for very old versions of Mac OS X. In the interest of not replacing strnlen arbitrarily for sources using libfdt and considering that the last version of OS X 10.6 was released in 2011 I propose to remove the workaround for that system. We noticed as compiling fdt_strnlen in C++ environments fails (missing cast for memchr). Signed-off-by: Adam Lackorzynski Signed-off-by: David Gibson --- libfdt/libfdt_env.h | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h index 73b6d40..5580b48 100644 --- a/libfdt/libfdt_env.h +++ b/libfdt/libfdt_env.h @@ -66,31 +66,4 @@ static inline fdt64_t cpu_to_fdt64(uint64_t x) #undef CPU_TO_FDT16 #undef EXTRACT_BYTE -#ifdef __APPLE__ -#include - -/* strnlen() is not available on Mac OS < 10.7 */ -# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \ - MAC_OS_X_VERSION_10_7) - -#define strnlen fdt_strnlen - -/* - * fdt_strnlen: returns the length of a string or max_count - which ever is - * smallest. - * Input 1 string: the string whose size is to be determined - * Input 2 max_count: the maximum value returned by this function - * Output: length of the string or max_count (the smallest of the two) - */ -static inline size_t fdt_strnlen(const char *string, size_t max_count) -{ - const char *p = memchr(string, 0, max_count); - return p ? p - string : max_count; -} - -#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < - MAC_OS_X_VERSION_10_7) */ - -#endif /* __APPLE__ */ - #endif /* LIBFDT_ENV_H */