From 7a9f663ac7ef1218ffe3aaab66f1bf66d54eaf0a Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Wed, 15 Mar 2006 18:59:24 -0700 Subject: [PATCH 0001/1198] The problem is that asm_emit_cell() was swapping its asm output when it shouldn't be (because the assembler will do the necessary swapping). The cell values (asm_emit_cell()) are different from the data values (asm_emit_data()) because the cell values are generated within the program and don't get swapped like the data values read from the dts file. They should be left as they are so that the assembler will swap them, if necessary. For example, when the property length field was 4, the asm output contained ".long 0x4000000" and sent the kernel prom.c dt parsing code into the weeds. Pointed out by Mark Greer. --- flattree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flattree.c b/flattree.c index 474f1c1..73dd409 100644 --- a/flattree.c +++ b/flattree.c @@ -121,7 +121,7 @@ static void asm_emit_cell(void *e, cell_t val) { FILE *f = e; - fprintf(f, "\t.long\t0x%x\n", be32_to_cpu(val)); + fprintf(f, "\t.long\t0x%x\n", val); } static void asm_emit_string(void *e, char *str, int len) From f7374f60eb086979006f0b029f21824bd13d20ca Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Wed, 19 Apr 2006 11:34:22 -0500 Subject: [PATCH 0002/1198] Don't generate the mem-reserve entry for the blob itself, even for ASM output. It was inconsistent with the binary output form, and kernel folks decided to have the early kernel perform the reservation itself. --- flattree.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/flattree.c b/flattree.c index 73dd409..19d886e 100644 --- a/flattree.c +++ b/flattree.c @@ -365,8 +365,6 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version) /* * Reserve map entries. - * Since the blob is relocatable, the address of the map is not - * determinable here, so no entry is made for the DT itself. * Each entry is an (address, size) pair of u64 values. * Always supply a zero-sized temination entry. */ @@ -446,15 +444,10 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version) * Reserve map entries. * Align the reserve map to a doubleword boundary. * Each entry is an (address, size) pair of u64 values. - * Since the ASM file variant can relocate and compute the address - * and size of the the device tree itself, and an entry for it. * Always supply a zero-sized temination entry. */ asm_emit_align(f, 8); emit_label(f, symprefix, "reserve_map"); - fprintf(f, "\t.quad\t0, _%s_blob_start\n", symprefix); - fprintf(f, "\t.quad\t0, _%s_blob_end - _%s_blob_start\n", - symprefix, symprefix); fprintf(f, "/* Memory reserve map from source file */\n"); for (re = bi->reservelist; re; re = re->next) { From 05ae3d8eebdad2b8da6e02eeca3baa3cc54fe5f3 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Wed, 19 Apr 2006 11:58:45 -0500 Subject: [PATCH 0003/1198] Use .long on high and low halfs of u64s to avoid .quad as it appears .quad isn't available in some assemblers. --- flattree.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/flattree.c b/flattree.c index 19d886e..439fbbb 100644 --- a/flattree.c +++ b/flattree.c @@ -450,13 +450,21 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version) emit_label(f, symprefix, "reserve_map"); fprintf(f, "/* Memory reserve map from source file */\n"); + + /* + * Use .long on high and low halfs of u64s to avoid .quad + * as it appears .quad isn't available in some assemblers. + */ for (re = bi->reservelist; re; re = re->next) { - fprintf(f, "\t.quad\t0x%016llx\n\t.quad\t0x%016llx\n", - (unsigned long long)re->re.address, - (unsigned long long)re->re.size); + fprintf(f, "\t.long\t0x%08x\n\t.long\t0x%08x\n", + (unsigned int)(re->re.address >> 32), + (unsigned int)(re->re.address & 0xffffffff)); + fprintf(f, "\t.long\t0x%08x\n\t.long\t0x%08x\n", + (unsigned int)(re->re.size >> 32), + (unsigned int)(re->re.size & 0xffffffff)); } - fprintf(f, "\t.quad\t0\n\t.quad\t0\n"); + fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); emit_label(f, symprefix, "struct_start"); flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi); From 38e8f8fd88dae07ef8ada9d6baa41b06a4d9ac9f Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Wed, 31 May 2006 08:31:51 +1000 Subject: [PATCH 0004/1198] dtc: add setting of physical boot cpu dtc always sets the physical boot CPU to 0xfeedbeef. Add a -b option to set this. Also add warnings when using the wrong property with the wrong blob version. Signed-off-by: Michael Neuling --- dtc.c | 14 ++++++++++---- dtc.h | 8 +++++--- flattree.c | 16 ++++++++++------ livetree.c | 17 ++++++++++++----- 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/dtc.c b/dtc.c index f26b1ec..646b814 100644 --- a/dtc.c +++ b/dtc.c @@ -95,6 +95,8 @@ static void usage(void) fprintf(stderr, "\t\tBlob version to produce, defaults to 3 (relevant for dtb\n\t\tand asm output only)\n"); fprintf(stderr, "\t-R \n"); fprintf(stderr, "\t\tMake space for reserve map entries (relevant for \n\t\tdtb and asm output only)\n"); + fprintf(stderr, "\t-b \n"); + fprintf(stderr, "\t\tSet the physical boot cpu\n"); fprintf(stderr, "\t-f\n"); fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n"); exit(2); @@ -113,8 +115,9 @@ int main(int argc, char *argv[]) FILE *outf = NULL; int outversion = 3; int reservenum = 1; + int boot_cpuid_phys = 0xfeedbeef; - while ((opt = getopt(argc, argv, "I:O:o:V:R:f")) != EOF) { + while ((opt = getopt(argc, argv, "I:O:o:V:R:fb:")) != EOF) { switch (opt) { case 'I': inform = optarg; @@ -134,6 +137,9 @@ int main(int argc, char *argv[]) case 'f': force = 1; break; + case 'b': + boot_cpuid_phys = strtol(optarg, NULL, 0); + break; default: usage(); } @@ -167,7 +173,7 @@ int main(int argc, char *argv[]) if (! bi || ! bi->dt) die("Couldn't read input tree\n"); - if (! check_device_tree(bi->dt)) { + if (! check_device_tree(bi->dt, outversion, boot_cpuid_phys)) { fprintf(stderr, "Input tree has errors\n"); if (! force) exit(1); @@ -185,9 +191,9 @@ int main(int argc, char *argv[]) if (streq(outform, "dts")) { dt_to_source(outf, bi); } else if (streq(outform, "dtb")) { - dt_to_blob(outf, bi, outversion); + dt_to_blob(outf, bi, outversion, boot_cpuid_phys); } else if (streq(outform, "asm")) { - dt_to_asm(outf, bi, outversion); + dt_to_asm(outf, bi, outversion, boot_cpuid_phys); } else if (streq(outform, "null")) { /* do nothing */ } else { diff --git a/dtc.h b/dtc.h index 3d32b61..42e9de0 100644 --- a/dtc.h +++ b/dtc.h @@ -178,7 +178,7 @@ struct node *chain_node(struct node *first, struct node *list); void add_property(struct node *node, struct property *prop); void add_child(struct node *parent, struct node *child); -int check_device_tree(struct node *dt); +int check_device_tree(struct node *dt, int outversion, int boot_cpuid_phys); /* Boot info (tree plus memreserve information */ @@ -207,8 +207,10 @@ struct boot_info *build_boot_info(struct reserve_info *reservelist, /* Flattened trees */ -void dt_to_blob(FILE *f, struct boot_info *bi, int version); -void dt_to_asm(FILE *f, struct boot_info *bi, int version); +void dt_to_blob(FILE *f, struct boot_info *bi, int version, + int boot_cpuid_phys); +void dt_to_asm(FILE *f, struct boot_info *bi, int version, + int boot_cpuid_phys); struct boot_info *dt_from_blob(FILE *f); diff --git a/flattree.c b/flattree.c index 439fbbb..56c1b38 100644 --- a/flattree.c +++ b/flattree.c @@ -301,7 +301,8 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist, } static void make_bph(struct boot_param_header *bph, struct version_info *vi, - int reservesize, int dtsize, int strsize) + int reservesize, int dtsize, int strsize, + int boot_cpuid_phys) { int reserve_off; @@ -324,12 +325,13 @@ static void make_bph(struct boot_param_header *bph, + dtsize + strsize); if (vi->flags & FTF_BOOTCPUID) - bph->boot_cpuid_phys = 0xfeedbeef; + bph->boot_cpuid_phys = cpu_to_be32(boot_cpuid_phys); if (vi->flags & FTF_STRTABSIZE) bph->size_dt_strings = cpu_to_be32(strsize); } -void dt_to_blob(FILE *f, struct boot_info *bi, int version) +void dt_to_blob(FILE *f, struct boot_info *bi, int version, + int boot_cpuid_phys) { struct version_info *vi = NULL; int i; @@ -355,7 +357,8 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version) reservebuf = flatten_reserve_list(bi->reservelist, vi); /* Make header */ - make_bph(&bph, vi, reservebuf.len, dtbuf.len, strbuf.len); + make_bph(&bph, vi, reservebuf.len, dtbuf.len, strbuf.len, + boot_cpuid_phys); fwrite(&bph, vi->hdr_size, 1, f); @@ -395,7 +398,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf) } } -void dt_to_asm(FILE *f, struct boot_info *bi, int version) +void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) { struct version_info *vi = NULL; int i; @@ -434,7 +437,8 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version) vi->last_comp_version); if (vi->flags & FTF_BOOTCPUID) - fprintf(f, "\t.long\t0xdeadbeef\t/*boot_cpuid_phys*/\n"); + fprintf(f, "\t.long\t%i\t/*boot_cpuid_phys*/\n", + boot_cpuid_phys); if (vi->flags & FTF_STRTABSIZE) fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n", diff --git a/livetree.c b/livetree.c index ef54174..f64de01 100644 --- a/livetree.c +++ b/livetree.c @@ -456,7 +456,7 @@ static int check_root(struct node *root) return ok; } -static int check_cpus(struct node *root) +static int check_cpus(struct node *root, int outversion, int boot_cpuid_phys) { struct node *cpus, *cpu; struct property *prop; @@ -518,8 +518,15 @@ static int check_cpus(struct node *root) } } - if (! bootcpu) - WARNMSG("No cpu has \"linux,boot-cpu\" property\n"); + if (outversion < 2) { + if (! bootcpu) + WARNMSG("No cpu has \"linux,boot-cpu\" property\n"); + } else { + if (bootcpu) + WARNMSG("\"linux,boot-cpu\" property is deprecated in blob version 2 or higher\n"); + if (boot_cpuid_phys == 0xfeedbeef) + WARNMSG("physical boot CPU not set. Use -b option to set\n"); + } return ok; } @@ -697,7 +704,7 @@ static void fixup_phandles(struct node *root, struct node *node) fixup_phandles(root, child); } -int check_device_tree(struct node *dt) +int check_device_tree(struct node *dt, int outversion, int boot_cpuid_phys) { int ok = 1; @@ -713,7 +720,7 @@ int check_device_tree(struct node *dt) return 0; ok = ok && check_root(dt); - ok = ok && check_cpus(dt); + ok = ok && check_cpus(dt, outversion, boot_cpuid_phys); ok = ok && check_memory(dt); ok = ok && check_chosen(dt); if (! ok) From 780c742b1459977d4490bb0021524750b715e449 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 24 Jun 2006 15:42:51 -0500 Subject: [PATCH 0005/1198] Remove dead code. Signed-off-by: Jon Loeliger --- data.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/data.c b/data.c index 911b271..d3b55f9 100644 --- a/data.c +++ b/data.c @@ -20,24 +20,6 @@ #include "dtc.h" -#if 0 -static struct data data_init_buf(char *buf, int len) -{ - struct data d; - - d.asize = 0; - d.len = len; - d.val = buf; - - return d; -} - -struct data data_ref_string(char *str) -{ - return data_init_buf(str, strlen(str)+1); -} -#endif - void fixup_free(struct fixup *f) { free(f->ref); From 6cf2bcd1e09394e8f824d71cf42d9d049faceb0e Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 24 Jun 2006 15:52:48 -0500 Subject: [PATCH 0006/1198] Add copyright. Fix 80-column line. Signed-off-by: Jon Loeliger --- libdt.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/libdt.c b/libdt.c index d8b46f0..d187ca9 100644 --- a/libdt.c +++ b/libdt.c @@ -1,3 +1,23 @@ +/* + * (C) Copyright David Gibson , IBM Corporation. 2005. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + #include #include @@ -134,7 +154,8 @@ void *flat_dt_get_node(void *blob, char *path) return node; } -void flat_dt_traverse(void *blob, int (*fn)(void *blob, void *node, void *priv), +void flat_dt_traverse(void *blob, + int (*fn)(void *blob, void *node, void *priv), void *private) { struct boot_param_header *bph = blob; From 332c53642557a018ca9c729a4cd284c6e34b7f72 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Fri, 7 Jul 2006 23:28:10 +1000 Subject: [PATCH 0007/1198] dtc: fix endian issue when reading blobs The reserve mem regions are screwy if you read a blob on x86. I'm guessing there may be a few more of these lurking in the code. Signed-off-by: Michael Neuling --- flattree.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flattree.c b/flattree.c index 56c1b38..f2dc4dc 100644 --- a/flattree.c +++ b/flattree.c @@ -619,6 +619,8 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) p = inb->ptr; while (1) { flat_read_chunk(inb, &re, sizeof(re)); + re.address = be64_to_cpu(re.address); + re.size = be64_to_cpu(re.size); if (re.size == 0) break; From f016882f91d393d1010988eab304c383b8b753bb Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Mon, 30 Oct 2006 10:48:59 -0600 Subject: [PATCH 0008/1198] Change default output blob version from 3 to 16 Signed-off-by: Kim Phillips Signed-off-by: Jon Loeliger --- dtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dtc.c b/dtc.c index 646b814..fe4637c 100644 --- a/dtc.c +++ b/dtc.c @@ -92,7 +92,7 @@ static void usage(void) fprintf(stderr, "\t\t\tdtb - device tree blob\n"); fprintf(stderr, "\t\t\tasm - assembler source\n"); fprintf(stderr, "\t-V \n"); - fprintf(stderr, "\t\tBlob version to produce, defaults to 3 (relevant for dtb\n\t\tand asm output only)\n"); + fprintf(stderr, "\t\tBlob version to produce, defaults to 16 (relevant for dtb\n\t\tand asm output only)\n"); fprintf(stderr, "\t-R \n"); fprintf(stderr, "\t\tMake space for reserve map entries (relevant for \n\t\tdtb and asm output only)\n"); fprintf(stderr, "\t-b \n"); @@ -113,7 +113,7 @@ int main(int argc, char *argv[]) int opt; FILE *inf = NULL; FILE *outf = NULL; - int outversion = 3; + int outversion = 0x10; int reservenum = 1; int boot_cpuid_phys = 0xfeedbeef; From 3da0f9a10dfa9b615d06c350c7b9fe29f360a6e0 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 27 Nov 2006 16:21:28 +1100 Subject: [PATCH 0009/1198] libfdt - library for manipulating device trees in flattened format Initial revision, read-only and "in-place" (no memmove() required) write operations only. --- .gitignore | 5 + Makefile | 88 +++++++++++++++ fdt.c | 94 ++++++++++++++++ fdt.h | 58 ++++++++++ fdt_ro.c | 243 ++++++++++++++++++++++++++++++++++++++++ fdt_wip.c | 108 ++++++++++++++++++ libfdt.h | 107 ++++++++++++++++++ libfdt_env.h | 19 ++++ libfdt_internal.h | 39 +++++++ tests/.gitignore | 0 tests/Makefile | 50 +++++++++ tests/getprop.c | 41 +++++++ tests/nop_node.c | 96 ++++++++++++++++ tests/nop_property.c | 70 ++++++++++++ tests/notfound.c | 75 +++++++++++++ tests/path_offset.c | 97 ++++++++++++++++ tests/property_offset.c | 40 +++++++ tests/root_node.c | 51 +++++++++ tests/run_tests.sh | 55 +++++++++ tests/setprop_inplace.c | 69 ++++++++++++ tests/subnode_offset.c | 82 ++++++++++++++ tests/testdata.h | 8 ++ tests/tests.h | 126 +++++++++++++++++++++ tests/testutils.c | 163 +++++++++++++++++++++++++++ tests/trees.S | 84 ++++++++++++++ 25 files changed, 1868 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 fdt.c create mode 100644 fdt.h create mode 100644 fdt_ro.c create mode 100644 fdt_wip.c create mode 100644 libfdt.h create mode 100644 libfdt_env.h create mode 100644 libfdt_internal.h create mode 100644 tests/.gitignore create mode 100644 tests/Makefile create mode 100644 tests/getprop.c create mode 100644 tests/nop_node.c create mode 100644 tests/nop_property.c create mode 100644 tests/notfound.c create mode 100644 tests/path_offset.c create mode 100644 tests/property_offset.c create mode 100644 tests/root_node.c create mode 100755 tests/run_tests.sh create mode 100644 tests/setprop_inplace.c create mode 100644 tests/subnode_offset.c create mode 100644 tests/testdata.h create mode 100644 tests/tests.h create mode 100644 tests/testutils.c create mode 100644 tests/trees.S diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4b147f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.d +*.o +*.a +*.so +*~ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5f6f947 --- /dev/null +++ b/Makefile @@ -0,0 +1,88 @@ +PREFIX = /usr/local +TARGETLIBS = libfdt.a +LIBOBJS = fdt.o fdt_ro.o fdt_wip.o #fdt_sw.o + +SOURCE = $(shell find . -maxdepth 1 ! -name version.h -a -name '*.[h]') +SOURCE += *.c Makefile +NODEPTARGETS= + +CPPFLAGS = -I. +CFLAGS = -Wall -g + +LIBDIR = $(PREFIX)/$(LIB32) + +EXTRA_DIST = \ + README \ + HOWTO \ + LGPL-2.1 + +ifdef V +VECHO = : +else +VECHO = echo " " +ARFLAGS = rc +.SILENT: +endif + +DEPFILES = $(LIBOBJS:%.o=%.d) + +all: libs tests + +.PHONY: tests libs + +libs: $(TARGETLIBS) + +tests: tests/all + +tests/%: libs + $(MAKE) -C tests $* + +check: all + cd tests; ./run_tests.sh + +checkv: all + cd tests; ./run_tests.sh -v + +func: all + cd tests; ./run_tests.sh -t func + +funcv: all + cd tests; ./run_tests.sh -t func -v + +stress: all + cd tests; ./run_tests.sh -t stress + +stressv: all + cd tests; ./run_tests.sh -t stress -v + +%.o: %.c + @$(VECHO) CC $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< + +libfdt.a: $(LIBOBJS) + @$(VECHO) AR $@ + $(AR) $(ARFLAGS) $@ $^ + +%.i: %.c + @$(VECHO) CPP $@ + $(CC) $(CPPFLAGS) -E $< > $@ + +%.s: %.c + @$(VECHO) CC -S $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -S $< + +clean: + @$(VECHO) CLEAN + rm -f *~ *.o *.so *.a *.d *.i *.s core a.out $(VERSION) + $(MAKE) -C tests clean + +%.d: %.c + @$(CC) $(CPPFLAGS) -MM -MT "$*.o $@" $< > $@ + +# Workaround: Don't build dependencies for certain targets +# When the include below is executed, make will use the %.d target above to +# generate missing files. For certain targets (clean, version.h, etc) we don't +# need or want these dependency files, so don't include them in this case. +ifeq (,$(findstring <$(MAKECMDGOALS)>,$(NODEPTARGETS))) +-include $(DEPFILES) +endif diff --git a/fdt.c b/fdt.c new file mode 100644 index 0000000..0de7f68 --- /dev/null +++ b/fdt.c @@ -0,0 +1,94 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int len) +{ + void *p; + + p = (void *)fdt + fdt32_to_cpu(fdt->off_dt_struct) + offset; + + if (p + len < p) + return NULL; + return p; +} + +char *fdt_string(const struct fdt_header *fdt, int stroffset) +{ + return (char *)fdt + fdt32_to_cpu(fdt->off_dt_strings) + stroffset; +} + +int fdt_string_cmp(const struct fdt_header *fdt, int stroffset, const char *s2) +{ + const char *s1 = fdt_string(fdt, stroffset); + int len = strlen(s2) + 1; + + if (! s1) + return 0; + + if ((stroffset + len < stroffset) + || (stroffset + len > fdt32_to_cpu(fdt->size_dt_strings))) + return -2; + + return strcmp(s1, s2); +} + +uint32_t _fdt_next_tag(const struct fdt_header *fdt, int offset, int *nextoffset) +{ + const uint32_t *tagp, *lenp; + uint32_t tag; + const char *p; + + if (offset % FDT_TAGSIZE) + return -1; + + tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); + if (! tagp) + return FDT_END; /* premature end */ + tag = fdt32_to_cpu(*tagp); + offset += FDT_TAGSIZE; + + switch (tag) { + case FDT_BEGIN_NODE: + /* skip name */ + do { + p = fdt_offset_ptr(fdt, offset++, 1); + } while (p && (*p != '\0')); + if (! p) + return FDT_END; + break; + case FDT_PROP: + lenp = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, sizeof(*lenp)); + if (! lenp) + return FDT_END; + /* skip name offset, length and value */ + offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp); + break; + } + + if (nextoffset) + *nextoffset = ALIGN(offset, FDT_TAGSIZE); + + return tag; +} diff --git a/fdt.h b/fdt.h new file mode 100644 index 0000000..10b5544 --- /dev/null +++ b/fdt.h @@ -0,0 +1,58 @@ +#ifndef _FDT_H +#define _FDT_H + +#ifndef __ASSEMBLY__ + +#include + +struct fdt_header { + uint32_t magic; /* magic word FDT_MAGIC */ + uint32_t totalsize; /* total size of DT block */ + uint32_t off_dt_struct; /* offset to structure */ + uint32_t off_dt_strings; /* offset to strings */ + uint32_t off_mem_rsvmap; /* offset to memory reserve map */ + uint32_t version; /* format version */ + uint32_t last_comp_version; /* last compatible version */ + + /* version 2 fields below */ + uint32_t boot_cpuid_phys; /* Which physical CPU id we're + booting on */ + /* version 3 fields below */ + uint32_t size_dt_strings; /* size of the strings block */ +}; + +struct fdt_reserve_entry { + uint64_t address; + uint64_t size; +}; + +struct fdt_node_header { + uint32_t tag; + char name[0]; +}; + +struct fdt_property { + uint32_t tag; + uint32_t nameoff; + uint32_t len; + char data[0]; +}; + +#endif /* !__ASSEMBLY */ + +#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ +#define FDT_TAGSIZE sizeof(uint32_t) + +#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ +#define FDT_END_NODE 0x2 /* End node */ +#define FDT_PROP 0x3 /* Property: name off, + size, content */ +#define FDT_NOP 0x4 /* nop */ +#define FDT_END 0x9 + +#define FDT_V1_SIZE (7*sizeof(uint32_t)) +#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(uint32_t)) +#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(uint32_t)) + + +#endif /* _FDT_H */ diff --git a/fdt_ro.c b/fdt_ro.c new file mode 100644 index 0000000..c2a0e72 --- /dev/null +++ b/fdt_ro.c @@ -0,0 +1,243 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int check_header(const struct fdt_header *fdt) +{ + if (fdt32_to_cpu(fdt->magic) != FDT_MAGIC) + return FDT_ERR_BADMAGIC; + if (fdt32_to_cpu(fdt->version) < FDT_FIRST_SUPPORTED_VERSION) + return FDT_ERR_BADVERSION; + if (fdt32_to_cpu(fdt->last_comp_version) > FDT_LAST_SUPPORTED_VERSION) + return FDT_ERR_BADVERSION; + return 0; +} + +#define OFFSET_CHECK_HEADER(fdt) \ + { \ + int err; \ + if ((err = check_header(fdt)) != 0) \ + return OFFSET_ERROR(err); \ + } + +static int offset_streq(const struct fdt_header *fdt, int offset, + const char *s, int len) +{ + const char *p = fdt_offset_ptr(fdt, offset, len+1); + + if (! p) + /* short match */ + return 0; + + if (memcmp(p, s, len) != 0) + return 0; + + if (p[len] != '\0') + return 0; + + return 1; +} + +int fdt_property_offset(const struct fdt_header *fdt, int nodeoffset, + const char *name) +{ + int level = 0; + uint32_t tag; + struct fdt_property *prop; + int namestroff; + int offset, nextoffset; + + OFFSET_CHECK_HEADER(fdt); + + if (nodeoffset % FDT_TAGSIZE) + return OFFSET_ERROR(FDT_ERR_BADOFFSET); + + tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); + if (tag != FDT_BEGIN_NODE) + return OFFSET_ERROR(FDT_ERR_BADOFFSET); + + do { + offset = nextoffset; + if (offset % FDT_TAGSIZE) + return OFFSET_ERROR(FDT_ERR_INTERNAL); + + tag = _fdt_next_tag(fdt, offset, &nextoffset); + switch (tag) { + case FDT_END: + return OFFSET_ERROR(FDT_ERR_TRUNCATED); + + case FDT_BEGIN_NODE: + level++; + break; + + case FDT_END_NODE: + level--; + break; + + case FDT_PROP: + if (level != 0) + continue; + + prop = fdt_offset_ptr_typed(fdt, offset, prop); + if (! prop) + return OFFSET_ERROR(FDT_ERR_BADSTRUCTURE); + namestroff = fdt32_to_cpu(prop->nameoff); + if (fdt_string_cmp(fdt, namestroff, name) == 0) + /* Found it! */ + return offset; + break; + + case FDT_NOP: + break; + + default: + return OFFSET_ERROR(FDT_ERR_BADSTRUCTURE); + } + } while (level >= 0); + + return OFFSET_ERROR(FDT_ERR_NOTFOUND); +} + +int fdt_subnode_offset_namelen(const struct fdt_header *fdt, int parentoffset, + const char *name, int namelen) +{ + int level = 0; + uint32_t tag; + int offset, nextoffset; + + OFFSET_CHECK_HEADER(fdt); + + tag = _fdt_next_tag(fdt, parentoffset, &nextoffset); + if (tag != FDT_BEGIN_NODE) + return OFFSET_ERROR(FDT_ERR_BADOFFSET); + + do { + offset = nextoffset; + tag = _fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_END: + return OFFSET_ERROR(FDT_ERR_TRUNCATED); + + case FDT_BEGIN_NODE: + level++; + if (level != 1) + continue; + if (offset_streq(fdt, offset+FDT_TAGSIZE, name, namelen)) + /* Found it! */ + return offset; + break; + + case FDT_END_NODE: + level--; + break; + + case FDT_PROP: + case FDT_NOP: + break; + + default: + return OFFSET_ERROR(FDT_ERR_BADSTRUCTURE); + } + } while (level >= 0); + + return OFFSET_ERROR(FDT_ERR_NOTFOUND); +} + +int fdt_subnode_offset(const struct fdt_header *fdt, int parentoffset, + const char *name) +{ + return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); +} + +int fdt_path_offset(const struct fdt_header *fdt, const char *path) +{ + const char *end = path + strlen(path); + const char *p = path; + int offset = 0; + + OFFSET_CHECK_HEADER(fdt); + + if (*path != '/') + return OFFSET_ERROR(FDT_ERR_BADPATH); + + while (*p) { + const char *q; + + while (*p == '/') + p++; + if (! *p) + return OFFSET_ERROR(FDT_ERR_BADPATH); + q = strchr(p, '/'); + if (! q) + q = end; + + offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); + if (fdt_offset_error(offset)) + return offset; + + p = q; + } + + return offset; +} + +struct fdt_property *_fdt_getprop(const struct fdt_header *fdt, int nodeoffset, + const char *name, int *lenp) +{ + int propoffset; + struct fdt_property *prop; + int err; + int len; + + propoffset = fdt_property_offset(fdt, nodeoffset, name); + if ((err = fdt_offset_error(propoffset))) + return PTR_ERROR(err); + + prop = fdt_offset_ptr(fdt, propoffset, sizeof(prop)); + if (! prop) + return PTR_ERROR(FDT_ERR_BADSTRUCTURE); + len = fdt32_to_cpu(prop->len); + prop = fdt_offset_ptr(fdt, propoffset, sizeof(prop) + len); + if (! prop) + return PTR_ERROR(FDT_ERR_BADSTRUCTURE); + + if (lenp) + *lenp = len; + + return prop; +} + +void *fdt_getprop(const struct fdt_header *fdt, int nodeoffset, + const char *name, int *lenp) +{ + const struct fdt_property *prop; + int err; + + prop = _fdt_getprop(fdt, nodeoffset, name, lenp); + if ((err = fdt_ptr_error(prop))) + return PTR_ERROR(err); + + return prop->data; +} diff --git a/fdt_wip.c b/fdt_wip.c new file mode 100644 index 0000000..c8d07b3 --- /dev/null +++ b/fdt_wip.c @@ -0,0 +1,108 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +int fdt_setprop_inplace(struct fdt_header *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + void *propval; + int proplen; + int err; + + propval = fdt_getprop(fdt, nodeoffset, name, &proplen); + if ((err = fdt_ptr_error(propval))) + return err; + + if (proplen != len) + return FDT_ERR_SIZE_MISMATCH; + + memcpy(propval, val, len); + return 0; +} + +static void nop_region(void *start, int len) +{ + uint32_t *p; + + for (p = start; (void *)p < (start + len); p++) + *p = FDT_NOP; +} + +int fdt_nop_property(struct fdt_header *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len; + int err; + + prop = _fdt_getprop(fdt, nodeoffset, name, &len); + if ((err = fdt_ptr_error(prop))) + return err; + + nop_region(prop, len + sizeof(*prop)); + + return 0; +} + +int fdt_nop_node(struct fdt_header *fdt, int nodeoffset) +{ + int level = 0; + int err = 0; + uint32_t tag; + int offset, nextoffset; + + tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); + if (tag != FDT_BEGIN_NODE) + return FDT_ERR_BADOFFSET; + + do { + offset = nextoffset; + tag = _fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_END: + level = -1; + err = FDT_ERR_TRUNCATED; + break; + + case FDT_BEGIN_NODE: + level++; + break; + + case FDT_END_NODE: + level--; + break; + + case FDT_PROP: + case FDT_NOP: + break; + + default: + return FDT_ERR_BADSTRUCTURE; + } + } while (level >= 0); + + nop_region(fdt_offset_ptr(fdt, nodeoffset, 0), nextoffset - nodeoffset); + + return err; +} diff --git a/libfdt.h b/libfdt.h new file mode 100644 index 0000000..7f279a6 --- /dev/null +++ b/libfdt.h @@ -0,0 +1,107 @@ +#ifndef _LIBFDT_H +#define _LIBFDT_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#define FDT_FIRST_SUPPORTED_VERSION 0x10 +#define FDT_LAST_SUPPORTED_VERSION 0x10 + +/* Errors */ +#define FDT_ERR_OK 0 +#define FDT_ERR_BADMAGIC 1 +#define FDT_ERR_BADVERSION 2 +#define FDT_ERR_BADPOINTER 3 +#define FDT_ERR_BADHEADER 4 +#define FDT_ERR_BADSTRUCTURE 5 +#define FDT_ERR_BADOFFSET 6 +#define FDT_ERR_NOTFOUND 7 +#define FDT_ERR_BADPATH 8 +#define FDT_ERR_TRUNCATED 9 +#define FDT_ERR_NOSPACE 10 +#define FDT_ERR_BADSTATE 11 +#define FDT_ERR_SIZE_MISMATCH 12 +#define FDT_ERR_INTERNAL 13 + +#define FDT_ERR_MAX 13 + +/* Offset handling functions */ +void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int checklen); + +#define fdt_offset_ptr_typed(fdt, offset, var) \ + ((typeof(var))(fdt_offset_ptr((fdt), (offset), sizeof(*(var))))) + +#define fdt_offset_error(offset) \ + ( (offset) < 0 ? -(offset) : 0 ) + +#define fdt_ptr_error(ptr) \ + ( (((long)(ptr) < 0) && ((long)(ptr) >= -FDT_ERR_MAX)) ? -(long)(ptr) : 0 ) + +char *fdt_string(const struct fdt_header *fdt, int stroffset); +int fdt_string_cmp(const struct fdt_header *fdt, int stroffset, const char *s2); + +/* Read-only functions */ +int fdt_property_offset(const struct fdt_header *fdt, int nodeoffset, + const char *name); +int fdt_subnode_offset_namelen(const struct fdt_header *fdt, int parentoffset, + const char *name, int namelen); +int fdt_subnode_offset(const struct fdt_header *fdt, int parentoffset, + const char *name); + +int fdt_path_offset(const struct fdt_header *fdt, const char *path); + +void *fdt_getprop(const struct fdt_header *fdt, int nodeoffset, + const char *name, int *lenp); + +/* Write-in-place functions */ +int fdt_setprop_inplace(struct fdt_header *fdt, int nodeoffset, const char *name, + const void *val, int len); + +#define fdt_setprop_inplace_typed(fdt, nodeoffset, name, val) \ + ({ \ + typeof(val) x = val; \ + fdt_setprop_inplace(fdt, nodeoffset, name, &x, sizeof(x)); \ + }) + +int fdt_nop_property(struct fdt_header *fdt, int nodeoffset, const char *name); +int fdt_nop_node(struct fdt_header *fdt, int nodeoffset); + +#if 0 +/* Sequential-write functions */ +struct fdt_header *fdt_create(void *buf, int bufsize); +int fdt_add_reservemap_entry(struct fdt_header *fdt, uint64_t addr, uint64_t size); +int fdt_begin_structure(struct fdt_header *fdt); +int fdt_begin_node(struct fdt_header *fdt, const char *name); +int fdt_property(struct fdt_header *fdt, const char *name, const void *val, int len); +int fdt_end_node(struct fdt_header *fdt); +int fdt_finish_structure(struct fdt_header *fdt); + +/* Read-write functions */ +struct fdt_header *fdt_open(struct fdt_header *fdt, int bufsize); +int fdt_add_subnode(struct fdt_header *fdtx, void *node, const char *name); +int fdt_set_property(struct fdt_header *fdtx, void *node, const char *name, + const void *val, int len); +int fdt_del_property(struct fdt_header *fdtx, void *node, const char *name); + +/* Misc functions */ +struct fdt_header *fdt_move(struct fdt_header *fdt, void *buf, int bufsize); +#endif + +#endif /* _LIBFDT_H */ diff --git a/libfdt_env.h b/libfdt_env.h new file mode 100644 index 0000000..a9b196f --- /dev/null +++ b/libfdt_env.h @@ -0,0 +1,19 @@ +#include +#include +#include +#include +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +#define fdt32_to_cpu(x) (x) +#define cpu_to_fdt32(x) (x) +#define fdt64_to_cpu(x) (x) +#define cpu_to_fdt64(x) (x) +#else +#define fdt32_to_cpu(x) (bswap_32((x))) +#define cpu_to_fdt32(x) (bswap_32((x))) +#define fdt64_to_cpu(x) (bswap_64((x))) +#define cpu_to_fdt64(x) (bswap_64((x))) +#endif + +#include "libfdt.h" diff --git a/libfdt_internal.h b/libfdt_internal.h new file mode 100644 index 0000000..1f9ba0c --- /dev/null +++ b/libfdt_internal.h @@ -0,0 +1,39 @@ +#ifndef _LIBFDT_INTERNAL_H +#define _LIBFDT_INTERNAL_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include + +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#define PALIGN(p, a) ((void *)ALIGN((unsigned long)(p), (a))) + +#define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) +#define streq(p, q) (strcmp((p), (q)) == 0) + +uint32_t _fdt_next_tag(const struct fdt_header *fdt, int startoffset, int *nextoffset); +struct fdt_property *_fdt_getprop(const struct fdt_header *fdt, int nodeoffset, + const char *name, int *lenp); + + +#define OFFSET_ERROR(code) -(code) +#define PTR_ERROR(code) (void *)(-(code)) + +#define SW_OFFSET(fdt) ((fdt)->version) + +#endif /* _LIBFDT_INTERNAL_H */ diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..7a517c7 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,50 @@ +PREFIX = /usr/local + +LIB_TESTS = +LIBTREE_TESTS = root_node property_offset subnode_offset path_offset getprop \ + notfound \ + setprop_inplace nop_property nop_node +TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) + +CFLAGS = -Wall -g +CPPFLAGS = -I.. +LDFLAGS = -L.. + +LIBFDT = ../libfdt.a + +ifdef V +VECHO = : +else +VECHO = echo " " +.SILENT: +endif + +DEPFILES = $(TESTS:%=%.d) testutils.d + +all: $(TESTS) + +%.o: %.c + @$(VECHO) CC $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< + +%.o: %.S + @$(VECHO) AS $@ + $(CC) -D__ASSEMBLY__ $(CPPFLAGS) -o $@ -c $< + +$(LIB_TESTS): %: %.o testutils.o $(LIBFDT) + @$(VECHO) LD "(testcase)" $@ + $(CC) $(LDFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +$(LIBTREE_TESTS): %: %.o testutils.o trees.o $(LIBFDT) + @$(VECHO) LD "(testcase + trees)" $@ + $(CC) $(LDFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +clean: + @$(VECHO) CLEAN "(tests)" + rm -f *~ *.o *.so *.a *.d *.s core a.out + rm -f $(TESTS) + +%.d: %.c + @$(CC) $(CPPFLAGS) -MM -MT "$*.o $@" $< > $@ + +-include $(DEPFILES) diff --git a/tests/getprop.c b/tests/getprop.c new file mode 100644 index 0000000..cfdd2ce --- /dev/null +++ b/tests/getprop.c @@ -0,0 +1,41 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_getprop() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt = &_test_tree1; + + test_init(argc, argv); + + check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); + check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1); + + PASS(); +} diff --git a/tests/nop_node.c b/tests/nop_node.c new file mode 100644 index 0000000..86d5d63 --- /dev/null +++ b/tests/nop_node.c @@ -0,0 +1,96 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_nop_node() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt = &_test_tree1; + int subnode1_offset, subnode2_offset, subsubnode2_offset; + int err; + + test_init(argc, argv); + + subnode1_offset = fdt_path_offset(fdt, "/subnode1"); + if ((err = fdt_offset_error(subnode1_offset))) + FAIL("Couldn't find \"/subnode1\": %s", fdt_strerror(err)); + check_getprop_typed(fdt, subnode1_offset, "prop-int", TEST_VALUE_1); + + subnode2_offset = fdt_path_offset(fdt, "/subnode2"); + if ((err = fdt_offset_error(subnode2_offset))) + FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(err)); + check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); + + subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + if ((err = fdt_offset_error(subsubnode2_offset))) + FAIL("Couldn't find \"/subnode2/subsubnode\": %s", + fdt_strerror(err)); + check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); + + err = fdt_nop_node(fdt, subnode1_offset); + if (err) + FAIL("fdt_nop_node(subnode1): %s", fdt_strerror(err)); + + subnode1_offset = fdt_path_offset(fdt, "/subnode1"); + if ((err = fdt_offset_error(subnode1_offset)) != FDT_ERR_NOTFOUND) + FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"", + fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + + subnode2_offset = fdt_path_offset(fdt, "/subnode2"); + if ((err = fdt_offset_error(subnode2_offset))) + FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(err)); + check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); + + subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + if ((err = fdt_offset_error(subsubnode2_offset))) + FAIL("Couldn't find \"/subnode2/subsubnode\": %s", + fdt_strerror(err)); + check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); + + err = fdt_nop_node(fdt, subnode2_offset); + if (err) + FAIL("fdt_nop_node(subnode2): %s", fdt_strerror(err)); + + subnode1_offset = fdt_path_offset(fdt, "/subnode1"); + if ((err = fdt_offset_error(subnode1_offset)) != FDT_ERR_NOTFOUND) + FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"", + fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + + subnode2_offset = fdt_path_offset(fdt, "/subnode2"); + if ((err = fdt_offset_error(subnode2_offset)) != FDT_ERR_NOTFOUND) + FAIL("fdt_path_offset(subnode2) returned \"%s\" instead of \"%s\"", + fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + + subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + if ((err = fdt_offset_error(subsubnode2_offset)) != FDT_ERR_NOTFOUND) + FAIL("fdt_path_offset(subsubnode2) returned \"%s\" instead of \"%s\"", + fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + + PASS(); +} diff --git a/tests/nop_property.c b/tests/nop_property.c new file mode 100644 index 0000000..af488d2 --- /dev/null +++ b/tests/nop_property.c @@ -0,0 +1,70 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_nop_property() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt = &_test_tree1; + uint32_t *intp; + char *strp; + int err; + + test_init(argc, argv); + + intp = check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); + verbose_printf("int value was 0x%08x\n", *intp); + + err = fdt_nop_property(fdt, 0, "prop-int"); + if (err) + FAIL("Failed to nop \"prop-int\": %s", fdt_strerror(err)); + + intp = fdt_getprop(fdt, 0, "prop-int", NULL); + err = fdt_ptr_error(intp); + if (! err) + FAIL("prop-int still present after nopping"); + if (err != FDT_ERR_NOTFOUND) + FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); + + strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, + TEST_STRING_1); + verbose_printf("string value was \"%s\"\n", strp); + err = fdt_nop_property(fdt, 0, "prop-str"); + err = fdt_ptr_error(intp); + if (! err) + FAIL("prop-str still present after nopping"); + if (err != FDT_ERR_NOTFOUND) + FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); + + strp = fdt_getprop(fdt, 0, "prop-str", NULL); + if (fdt_ptr_error(intp) != FDT_ERR_NOTFOUND) + FAIL("prop-str still present after nopping"); + + PASS(); +} diff --git a/tests/notfound.c b/tests/notfound.c new file mode 100644 index 0000000..106830e --- /dev/null +++ b/tests/notfound.c @@ -0,0 +1,75 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for behaviour on searching for a non-existent node + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void check_error(const char *s, int err) +{ + if (err != FDT_ERR_NOTFOUND) + FAIL("%s return error %s instead of FDT_ERR_NOTFOUND", s, + fdt_strerror(err)); +} + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt = &_test_tree1; + int offset; + int subnode1_offset; + void *val; + int err; + + test_init(argc, argv); + + offset = fdt_property_offset(fdt, 0, "nonexistant-property"); + check_error("fdt_property_offset(\"nonexistant-property\")", + fdt_offset_error(offset)); + + val = fdt_getprop(fdt, 0, "nonexistant-property", NULL); + check_error("fdt_getprop(\"nonexistant-property\"", + fdt_ptr_error(val)); + + subnode1_offset = fdt_subnode_offset(fdt, 0, "subnode1"); + if ((err = fdt_offset_error(subnode1_offset))) + FAIL("Couldn't find subnode1: %s", fdt_strerror(err)); + + val = fdt_getprop(fdt, subnode1_offset, "prop-str", NULL); + check_error("fdt_getprop(\"prop-str\")", fdt_ptr_error(val)); + + offset = fdt_subnode_offset(fdt, 0, "nonexistant-subnode"); + check_error("fdt_subnode_offset(\"nonexistant-subnode\")", + fdt_offset_error(offset)); + + offset = fdt_subnode_offset(fdt, 0, "subsubnode"); + check_error("fdt_subnode_offset(\"subsubnode\")", + fdt_offset_error(offset)); + + offset = fdt_path_offset(fdt, "/nonexistant-subnode"); + check_error("fdt_path_offset(\"/nonexistant-subnode\")", + fdt_offset_error(offset)); + + PASS(); +} diff --git a/tests/path_offset.c b/tests/path_offset.c new file mode 100644 index 0000000..fd7b76b --- /dev/null +++ b/tests/path_offset.c @@ -0,0 +1,97 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_path_offset() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int check_subnode(struct fdt_header *fdt, int parent, const char *name) +{ + int offset; + int err; + struct fdt_node_header *nh; + uint32_t tag; + + verbose_printf("Checking subnode \"%s\" of %d...", name, parent); + offset = fdt_subnode_offset(fdt, parent, name); + verbose_printf("offset %d...", offset); + if ((err = fdt_offset_error(offset))) + FAIL("fdt_subnode_offset(\"%s\"): %s", name, fdt_strerror(err)); + nh = fdt_offset_ptr_typed(fdt, offset, nh); + verbose_printf("pointer %p\n", nh); + if (! nh) + FAIL("NULL retrieving subnode \"%s\"", name); + + tag = fdt32_to_cpu(nh->tag); + + if (tag != FDT_BEGIN_NODE) + FAIL("Incorrect tag 0x%08x on property \"%s\"", tag, name); + if (!streq(nh->name, name)) + FAIL("Subnode name mismatch \"%s\" instead of \"%s\"", + nh->name, name); + + return offset; +} + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt = &_test_tree1; + int subnode1_offset, subnode2_offset; + int subnode1_offset_p, subnode2_offset_p; + int subsubnode1_offset, subsubnode2_offset; + int subsubnode1_offset_p, subsubnode2_offset_p; + + test_init(argc, argv); + + subnode1_offset = check_subnode(fdt, 0, "subnode1"); + subnode2_offset = check_subnode(fdt, 0, "subnode2"); + + subnode1_offset_p = fdt_path_offset(fdt, "/subnode1"); + subnode2_offset_p = fdt_path_offset(fdt, "/subnode2"); + + if (subnode1_offset != subnode1_offset_p) + FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)", + subnode1_offset, subnode1_offset_p); + + if (subnode2_offset != subnode2_offset_p) + FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)", + subnode2_offset, subnode2_offset_p); + + subsubnode1_offset = check_subnode(fdt, subnode1_offset, "subsubnode"); + subsubnode2_offset = check_subnode(fdt, subnode2_offset, "subsubnode"); + + subsubnode1_offset_p = fdt_path_offset(fdt, "/subnode1/subsubnode"); + subsubnode2_offset_p = fdt_path_offset(fdt, "/subnode2/subsubnode"); + + if (subsubnode1_offset != subsubnode1_offset_p) + FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)", + subsubnode1_offset, subsubnode1_offset_p); + + if (subsubnode2_offset != subsubnode2_offset_p) + FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)", + subsubnode2_offset, subsubnode2_offset_p); + + PASS(); +} diff --git a/tests/property_offset.c b/tests/property_offset.c new file mode 100644 index 0000000..a106159 --- /dev/null +++ b/tests/property_offset.c @@ -0,0 +1,40 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_property_offset() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt = &_test_tree1; + + test_init(argc, argv); + + check_property_typed(fdt, 0, "prop-int", TEST_VALUE_1); + check_property(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1); + + PASS(); +} diff --git a/tests/root_node.c b/tests/root_node.c new file mode 100644 index 0000000..906359b --- /dev/null +++ b/tests/root_node.c @@ -0,0 +1,51 @@ +/* + * libfdt - Flat Device Tree manipulation + * Basic testcase for read-only access + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt = &_test_tree1; + struct fdt_node_header *nh; + + test_init(argc, argv); + + nh = fdt_offset_ptr_typed(fdt, 0, nh); + + if (! nh) + FAIL("NULL retrieving root node"); + + if (nh->tag != FDT_BEGIN_NODE) + FAIL("Wrong tag on root node"); + + if (strlen(nh->name) != 0) + FAIL("Wrong name for root node, \"%s\" instead of empty", + nh->name); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh new file mode 100755 index 0000000..11cc691 --- /dev/null +++ b/tests/run_tests.sh @@ -0,0 +1,55 @@ +#! /bin/bash + +export QUIET_TEST=1 + +ENV=/usr/bin/env + +run_test () { + echo -n "$@: " + PATH=".:$PATH" $ENV "$@" +} + +functional_tests () { + # Read-only tests + run_test root_node + run_test property_offset + run_test subnode_offset + run_test path_offset + run_test getprop + run_test notfound + + # Write-in-place tests + run_test setprop_inplace + run_test nop_property + run_test nop_node +} + +stress_tests () { + ITERATIONS=10 # Number of iterations for looping tests +} + +while getopts "vdt:" ARG ; do + case $ARG in + "v") + unset QUIET_TEST + ;; + "t") + TESTSETS=$OPTARG + ;; + esac +done + +if [ -z "$TESTSETS" ]; then + TESTSETS="func stress" +fi + +for set in $TESTSETS; do + case $set in + "func") + functional_tests + ;; + "stress") + stress_tests + ;; + esac +done diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c new file mode 100644 index 0000000..ce19bcc --- /dev/null +++ b/tests/setprop_inplace.c @@ -0,0 +1,69 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_setprop_inplace() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt = &_test_tree1; + uint32_t *intp; + char *strp, *xstr; + int xlen, i; + int err; + + test_init(argc, argv); + + intp = check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); + + verbose_printf("Old int value was 0x%08x\n", *intp); + err = fdt_setprop_inplace_typed(fdt, 0, "prop-int", ~TEST_VALUE_1); + if (err) + FAIL("Failed to set \"prop-int\" to 0x08%x: %s", + ~TEST_VALUE_1, fdt_strerror(err)); + intp = check_getprop_typed(fdt, 0, "prop-int", ~TEST_VALUE_1); + verbose_printf("New int value is 0x%08x\n", *intp); + + strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, + TEST_STRING_1); + + verbose_printf("Old string value was \"%s\"\n", strp); + xstr = strdup(strp); + xlen = strlen(xstr); + for (i = 0; i < xlen; i++) + xstr[i] = toupper(xstr[i]); + err = fdt_setprop_inplace(fdt, 0, "prop-str", xstr, xlen+1); + if (err) + FAIL("Failed to set \"prop-str\" to \"%s\": %s", + xstr, fdt_strerror(err)); + + strp = check_getprop(fdt, 0, "prop-str", xlen+1, xstr); + verbose_printf("New string value is \"%s\"\n", strp); + + PASS(); +} diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c new file mode 100644 index 0000000..d64257a --- /dev/null +++ b/tests/subnode_offset.c @@ -0,0 +1,82 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_subnode_offset() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int check_subnode(struct fdt_header *fdt, int parent, const char *name) +{ + int offset; + int err; + struct fdt_node_header *nh; + uint32_t tag; + + verbose_printf("Checking subnode \"%s\" of %d...", name, parent); + offset = fdt_subnode_offset(fdt, parent, name); + verbose_printf("offset %d...", offset); + if ((err = fdt_offset_error(offset))) + FAIL("fdt_subnode_offset(\"%s\"): %s", name, fdt_strerror(err)); + nh = fdt_offset_ptr_typed(fdt, offset, nh); + verbose_printf("pointer %p\n", nh); + if (! nh) + FAIL("NULL retrieving subnode \"%s\"", name); + + tag = fdt32_to_cpu(nh->tag); + + if (tag != FDT_BEGIN_NODE) + FAIL("Incorrect tag 0x%08x on property \"%s\"", tag, name); + if (!streq(nh->name, name)) + FAIL("Subnode name mismatch \"%s\" instead of \"%s\"", + nh->name, name); + + return offset; +} + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt = &_test_tree1; + int subnode1_offset, subnode2_offset; + int subsubnode1_offset, subsubnode2_offset; + + test_init(argc, argv); + + subnode1_offset = check_subnode(fdt, 0, "subnode1"); + subnode2_offset = check_subnode(fdt, 0, "subnode2"); + + if (subnode1_offset == subnode2_offset) + FAIL("Different subnodes have same offset"); + + check_property_typed(fdt, subnode1_offset, "prop-int", TEST_VALUE_1); + check_property_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); + + subsubnode1_offset = check_subnode(fdt, subnode1_offset, "subsubnode"); + subsubnode2_offset = check_subnode(fdt, subnode2_offset, "subsubnode"); + + check_property_typed(fdt, subsubnode1_offset, "prop-int", TEST_VALUE_1); + check_property_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); + + PASS(); +} diff --git a/tests/testdata.h b/tests/testdata.h new file mode 100644 index 0000000..318b95f --- /dev/null +++ b/tests/testdata.h @@ -0,0 +1,8 @@ +#define TEST_VALUE_1 0xdeadbeef +#define TEST_VALUE_2 0xabcd1234 + +#define TEST_STRING_1 "hello world" + +#ifndef __ASSEMBLY__ +extern struct fdt_header _test_tree1; +#endif /* ! __ASSEMBLY */ diff --git a/tests/tests.h b/tests/tests.h new file mode 100644 index 0000000..9ad07c8 --- /dev/null +++ b/tests/tests.h @@ -0,0 +1,126 @@ +#ifndef _TESTS_H +#define _TESTS_H +/* + * libfdt - Flat Device Tree manipulation + * Testcase definitions + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define DEBUG + +/* Test return codes */ +#define RC_PASS 0 +#define RC_CONFIG 1 +#define RC_FAIL 2 +#define RC_BUG 99 + +extern int verbose_test; +extern char *test_name; +void test_init(int argc, char *argv[]); + +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#define PALIGN(p, a) ((void *)ALIGN((unsigned long)(p), (a))) + +#define streq(s1, s2) (strcmp((s1),(s2)) == 0) + +#if __BYTE_ORDER == __BIG_ENDIAN +#define fdt32_to_cpu(x) (x) +#define cpu_to_fdt32(x) (x) +#define fdt64_to_cpu(x) (x) +#define cpu_to_fdt64(x) (x) +#else +#define fdt32_to_cpu(x) (bswap_32((x))) +#define cpu_to_fdt32(x) (bswap_32((x))) +#define fdt64_to_cpu(x) (bswap_64((x))) +#define cpu_to_fdt64(x) (bswap_64((x))) +#endif + +/* Each test case must define this function */ +void cleanup(void); + +#define verbose_printf(...) \ + if (verbose_test) { \ + printf(__VA_ARGS__); \ + fflush(stdout); \ + } +#define ERR "ERR: " +#define ERROR(fmt, args...) fprintf(stderr, ERR fmt, ## args) + + +#define PASS() \ + do { \ + cleanup(); \ + printf("PASS\n"); \ + exit(RC_PASS); \ + } while (0) + +#define PASS_INCONCLUSIVE() \ + do { \ + cleanup(); \ + printf("PASS (inconclusive)\n"); \ + exit(RC_PASS); \ + } while (0) + +#define IRRELEVANT() \ + do { \ + cleanup(); \ + printf("PASS (irrelevant)\n"); \ + exit(RC_PASS); \ + } while (0) + +/* Look out, gcc extension below... */ +#define FAIL(fmt, ...) \ + do { \ + cleanup(); \ + printf("FAIL\t" fmt "\n", ##__VA_ARGS__); \ + exit(RC_FAIL); \ + } while (0) + +#define CONFIG(fmt, ...) \ + do { \ + cleanup(); \ + printf("Bad configuration: " fmt "\n", ##__VA_ARGS__); \ + exit(RC_CONFIG); \ + } while (0) + +#define TEST_BUG(fmt, ...) \ + do { \ + cleanup(); \ + printf("BUG in testsuite: " fmt "\n", ##__VA_ARGS__); \ + exit(RC_BUG); \ + } while (0) + +const char *fdt_strerror(int errval); +void check_property(struct fdt_header *fdt, int nodeoffset, const char *name, + int len, const void *val); +#define check_property_typed(fdt, nodeoffset, name, val) \ + ({ \ + typeof(val) x = val; \ + check_property(fdt, nodeoffset, name, sizeof(x), &x); \ + }) + + +void *check_getprop(struct fdt_header *fdt, int nodeoffset, const char *name, + int len, const void *val); +#define check_getprop_typed(fdt, nodeoffset, name, val) \ + ({ \ + typeof(val) x = val; \ + check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \ + }) + + +#endif /* _TESTS_H */ diff --git a/tests/testutils.c b/tests/testutils.c new file mode 100644 index 0000000..30acb35 --- /dev/null +++ b/tests/testutils.c @@ -0,0 +1,163 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase common utility functions + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define _GNU_SOURCE /* for strsignal() */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "tests.h" + +int verbose_test = 1; +char *test_name; + +void __attribute__((weak)) cleanup(void) +{ +} + +static void sigint_handler(int signum, siginfo_t *si, void *uc) +{ + cleanup(); + fprintf(stderr, "%s: %s (pid=%d)\n", test_name, + strsignal(signum), getpid()); + exit(RC_BUG); +} + +void test_init(int argc, char *argv[]) +{ + int err; + struct sigaction sa_int = { + .sa_sigaction = sigint_handler, + }; + + test_name = argv[0]; + + err = sigaction(SIGINT, &sa_int, NULL); + if (err) + FAIL("Can't install SIGINT handler"); + + if (getenv("QUIET_TEST")) + verbose_test = 0; + + verbose_printf("Starting testcase \"%s\", pid %d\n", + test_name, getpid()); +} + + +struct errtabent { + const char *str; +}; + +#define ERRTABENT(val) \ + [(val)] = { .str = #val, } + +static struct errtabent errtable[] = { + ERRTABENT(FDT_ERR_OK), + ERRTABENT(FDT_ERR_BADMAGIC), + ERRTABENT(FDT_ERR_BADVERSION), + ERRTABENT(FDT_ERR_BADPOINTER), + ERRTABENT(FDT_ERR_BADHEADER), + ERRTABENT(FDT_ERR_BADSTRUCTURE), + ERRTABENT(FDT_ERR_BADOFFSET), + ERRTABENT(FDT_ERR_NOTFOUND), + ERRTABENT(FDT_ERR_BADPATH), + ERRTABENT(FDT_ERR_TRUNCATED), + ERRTABENT(FDT_ERR_NOSPACE), + ERRTABENT(FDT_ERR_BADSTATE), + ERRTABENT(FDT_ERR_SIZE_MISMATCH), + ERRTABENT(FDT_ERR_INTERNAL), +}; + +#define ERRTABSIZE (sizeof(errtable) / sizeof(errtable[0])) + +const char *fdt_strerror(int errval) +{ + if ((errval >= 0) && (errval < ERRTABSIZE)) + return errtable[errval].str; + else + return "Unknown FDT error code"; +} + +void check_property(struct fdt_header *fdt, int nodeoffset, const char *name, + int len, const void *val) +{ + int offset; + const struct fdt_property *prop; + uint32_t tag, nameoff, proplen; + const char *propname; + int err; + + verbose_printf("Checking property \"%s\"...", name); + offset = fdt_property_offset(fdt, nodeoffset, name); + verbose_printf("offset %d...", offset); + if ((err = fdt_offset_error(offset))) + FAIL("fdt_property_offset(\"%s\"): %s", name, + fdt_strerror(err)); + + prop = fdt_offset_ptr_typed(fdt, offset, prop); + verbose_printf("pointer %p\n", prop); + if (! prop) + FAIL("NULL retreiving \"%s\" pointer", name); + + tag = fdt32_to_cpu(prop->tag); + nameoff = fdt32_to_cpu(prop->nameoff); + proplen = fdt32_to_cpu(prop->len); + + if (tag != FDT_PROP) + FAIL("Incorrect tag 0x%08x on property \"%s\"", tag, name); + + propname = fdt_string(fdt, nameoff); + if (!propname || !streq(propname, name)) + FAIL("Property name mismatch \"%s\" instead of \"%s\"", + propname, name); + if (proplen != len) + FAIL("Size mismatch on property \"%s\": %d insead of %d", + name, proplen, len); + if (memcmp(val, prop->data, len) != 0) + FAIL("Data mismatch on property \"%s\"", name); + +} + +void *check_getprop(struct fdt_header *fdt, int nodeoffset, const char *name, + int len, const void *val) +{ + void *propval; + int proplen; + int err; + + propval = fdt_getprop(fdt, nodeoffset, name, &proplen); + if ((err = fdt_ptr_error(propval))) + FAIL("fdt_getprop(\"%s\"): %s", name, fdt_strerror(err)); + + if (proplen != len) + FAIL("Size mismatch on property \"%s\": %d insead of %d", + name, proplen, len); + if (memcmp(val, propval, len) != 0) + FAIL("Data mismatch on property \"%s\"", name); + + return propval; +} diff --git a/tests/trees.S b/tests/trees.S new file mode 100644 index 0000000..095f781 --- /dev/null +++ b/tests/trees.S @@ -0,0 +1,84 @@ +#include +#include "testdata.h" + +#define TREE_HDR(tree) \ + .globl _##tree ; \ +_##tree: \ +tree: \ + .long FDT_MAGIC ; \ + .long tree##_end - tree ; \ + .long tree##_struct - tree ; \ + .long tree##_strings - tree ; \ + .long tree##_rsvmap - tree ; \ + .long 0x10 ; \ + .long 0x10 ; \ + .long 0 ; \ + .long tree##_end - tree##_strings ; + +#define RSVMAP_ENTRY(addr, len) \ + .quad addr ; \ + .quad len ; + +#define PROPHDR(tree, name, len) \ + .long FDT_PROP ; \ + .long tree##_##name - tree##_strings ; \ + .long len ; + +#define PROP_INT(tree, name, val) \ + PROPHDR(tree, name, 4) \ + .long val + +#define PROP_STR(tree, name, str) \ + PROPHDR(tree, name, 55f - 54f) \ +54: \ + .string str ; \ +55: \ + .balign 4 + +#define BEGIN_NODE(name) \ + .long FDT_BEGIN_NODE ; \ + .string name ; \ + .balign 4 + +#define END_NODE \ + .long FDT_END_NODE ; + +#define STRING(tree, name, str) \ +tree##_##name: \ + .string str + + .data + + TREE_HDR(test_tree1) + +test_tree1_rsvmap: + RSVMAP_ENTRY(0, 0) + +test_tree1_struct: + BEGIN_NODE("") + PROP_INT(test_tree1, prop_int, TEST_VALUE_1) + PROP_STR(test_tree1, prop_str, TEST_STRING_1) + + BEGIN_NODE("subnode1") + PROP_INT(test_tree1, prop_int, TEST_VALUE_1) + + BEGIN_NODE("subsubnode") + PROP_INT(test_tree1, prop_int, TEST_VALUE_1) + END_NODE + END_NODE + + BEGIN_NODE("subnode2") + PROP_INT(test_tree1, prop_int, TEST_VALUE_2) + + BEGIN_NODE("subsubnode") + PROP_INT(test_tree1, prop_int, TEST_VALUE_2) + END_NODE + END_NODE + + END_NODE + .long FDT_END + +test_tree1_strings: + STRING(test_tree1, prop_int, "prop-int") + STRING(test_tree1, prop_str, "prop-str") +test_tree1_end: From 4e6221c171377324cc3e80a9c2260b9788335d87 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 28 Nov 2006 17:20:01 +1100 Subject: [PATCH 0010/1198] Have tests read example tree from a generated file, rather than link it in. This makes the tests more flexible to re-use for testing the output from the write tests. --- tests/Makefile | 28 ++++++++++++++---------- tests/dumptrees.c | 47 +++++++++++++++++++++++++++++++++++++++++ tests/getprop.c | 3 ++- tests/nop_node.c | 3 ++- tests/nop_property.c | 3 ++- tests/notfound.c | 3 ++- tests/path_offset.c | 3 ++- tests/property_offset.c | 3 ++- tests/root_node.c | 5 +++-- tests/run_tests.sh | 26 ++++++++++++++--------- tests/setprop_inplace.c | 3 ++- tests/subnode_offset.c | 3 ++- tests/tests.h | 19 ++++++++++++++++- tests/testutils.c | 41 +++++++++++++++++++++++++++++++++++ 14 files changed, 158 insertions(+), 32 deletions(-) create mode 100644 tests/dumptrees.c diff --git a/tests/Makefile b/tests/Makefile index 7a517c7..db27d07 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,10 +1,12 @@ PREFIX = /usr/local -LIB_TESTS = -LIBTREE_TESTS = root_node property_offset subnode_offset path_offset getprop \ +LIB_TESTS = root_node property_offset subnode_offset path_offset getprop \ notfound \ setprop_inplace nop_property nop_node -TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) +TESTS = $(LIB_TESTS) +UTILS = dumptrees + +TREES = test_tree1.dtb CFLAGS = -Wall -g CPPFLAGS = -I.. @@ -21,7 +23,7 @@ endif DEPFILES = $(TESTS:%=%.d) testutils.d -all: $(TESTS) +all: $(TESTS) $(TREES) %.o: %.c @$(VECHO) CC $@ @@ -31,18 +33,22 @@ all: $(TESTS) @$(VECHO) AS $@ $(CC) -D__ASSEMBLY__ $(CPPFLAGS) -o $@ -c $< -$(LIB_TESTS): %: %.o testutils.o $(LIBFDT) - @$(VECHO) LD "(testcase)" $@ - $(CC) $(LDFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) +$(TREES): trees.o dumptrees + @$(VECHO) DUMPTREES + ./dumptrees >/dev/null -$(LIBTREE_TESTS): %: %.o testutils.o trees.o $(LIBFDT) - @$(VECHO) LD "(testcase + trees)" $@ - $(CC) $(LDFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) +%: %.o + @$(VECHO) LD $@ + $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +dumptrees: trees.o + +$(LIB_TESTS): %: testutils.o $(LIBFDT) clean: @$(VECHO) CLEAN "(tests)" rm -f *~ *.o *.so *.a *.d *.s core a.out - rm -f $(TESTS) + rm -f $(TESTS) $(UTILS) *.dtb %.d: %.c @$(CC) $(CPPFLAGS) -MM -MT "$*.o $@" $< > $@ diff --git a/tests/dumptrees.c b/tests/dumptrees.c new file mode 100644 index 0000000..d7e110d --- /dev/null +++ b/tests/dumptrees.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +struct { + struct fdt_header *fdt; + const char *filename; +} trees[] = { +#define TREE(name) { &_##name, #name ".dtb" } + TREE(test_tree1), +}; + +#define NUM_TREES (sizeof(trees) / sizeof(trees[0])) + +int main(int argc, char *argv[]) +{ + int i; + + for (i = 0; i < NUM_TREES; i++) { + struct fdt_header *fdt = trees[i].fdt; + const char *filename = trees[i].filename; + int size; + int fd; + int ret; + + size = fdt32_to_cpu(fdt->totalsize); + + printf("Tree \"%s\", %d bytes\n", filename, size); + + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd < 0) + perror("open()"); + + ret = write(fd, fdt, size); + if (ret != size) + perror("write()"); + + close(fd); + } + exit(0); +} diff --git a/tests/getprop.c b/tests/getprop.c index cfdd2ce..962b912 100644 --- a/tests/getprop.c +++ b/tests/getprop.c @@ -30,9 +30,10 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt = &_test_tree1; + struct fdt_header *fdt; test_init(argc, argv); + fdt = load_blob_arg(argc, argv); check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1); diff --git a/tests/nop_node.c b/tests/nop_node.c index 86d5d63..df421c0 100644 --- a/tests/nop_node.c +++ b/tests/nop_node.c @@ -31,11 +31,12 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt = &_test_tree1; + struct fdt_header *fdt; int subnode1_offset, subnode2_offset, subsubnode2_offset; int err; test_init(argc, argv); + fdt = load_blob_arg(argc, argv); subnode1_offset = fdt_path_offset(fdt, "/subnode1"); if ((err = fdt_offset_error(subnode1_offset))) diff --git a/tests/nop_property.c b/tests/nop_property.c index af488d2..a8bed5b 100644 --- a/tests/nop_property.c +++ b/tests/nop_property.c @@ -31,12 +31,13 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt = &_test_tree1; + struct fdt_header *fdt; uint32_t *intp; char *strp; int err; test_init(argc, argv); + fdt = load_blob_arg(argc, argv); intp = check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); verbose_printf("int value was 0x%08x\n", *intp); diff --git a/tests/notfound.c b/tests/notfound.c index 106830e..1dd8bc7 100644 --- a/tests/notfound.c +++ b/tests/notfound.c @@ -36,13 +36,14 @@ void check_error(const char *s, int err) int main(int argc, char *argv[]) { - struct fdt_header *fdt = &_test_tree1; + struct fdt_header *fdt; int offset; int subnode1_offset; void *val; int err; test_init(argc, argv); + fdt = load_blob_arg(argc, argv); offset = fdt_property_offset(fdt, 0, "nonexistant-property"); check_error("fdt_property_offset(\"nonexistant-property\")", diff --git a/tests/path_offset.c b/tests/path_offset.c index fd7b76b..32222be 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -57,13 +57,14 @@ int check_subnode(struct fdt_header *fdt, int parent, const char *name) int main(int argc, char *argv[]) { - struct fdt_header *fdt = &_test_tree1; + struct fdt_header *fdt; int subnode1_offset, subnode2_offset; int subnode1_offset_p, subnode2_offset_p; int subsubnode1_offset, subsubnode2_offset; int subsubnode1_offset_p, subsubnode2_offset_p; test_init(argc, argv); + fdt = load_blob_arg(argc, argv); subnode1_offset = check_subnode(fdt, 0, "subnode1"); subnode2_offset = check_subnode(fdt, 0, "subnode2"); diff --git a/tests/property_offset.c b/tests/property_offset.c index a106159..1745258 100644 --- a/tests/property_offset.c +++ b/tests/property_offset.c @@ -29,9 +29,10 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt = &_test_tree1; + struct fdt_header *fdt; test_init(argc, argv); + fdt = load_blob_arg(argc, argv); check_property_typed(fdt, 0, "prop-int", TEST_VALUE_1); check_property(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1); diff --git a/tests/root_node.c b/tests/root_node.c index 906359b..ecd1cb1 100644 --- a/tests/root_node.c +++ b/tests/root_node.c @@ -30,11 +30,12 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt = &_test_tree1; + struct fdt_header *fdt; struct fdt_node_header *nh; test_init(argc, argv); - + fdt = load_blob_arg(argc, argv); + nh = fdt_offset_ptr_typed(fdt, 0, nh); if (! nh) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 11cc691..0ffdc93 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -9,19 +9,25 @@ run_test () { PATH=".:$PATH" $ENV "$@" } -functional_tests () { +tree1_tests () { + TREE=$1 + # Read-only tests - run_test root_node - run_test property_offset - run_test subnode_offset - run_test path_offset - run_test getprop - run_test notfound + run_test root_node $TREE + run_test property_offset $TREE + run_test subnode_offset $TREE + run_test path_offset $TREE + run_test getprop $TREE + run_test notfound $TREE # Write-in-place tests - run_test setprop_inplace - run_test nop_property - run_test nop_node + run_test setprop_inplace $TREE + run_test nop_property $TREE + run_test nop_node $TREE +} + +functional_tests () { + tree1_tests test_tree1.dtb } stress_tests () { diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c index ce19bcc..61de789 100644 --- a/tests/setprop_inplace.c +++ b/tests/setprop_inplace.c @@ -31,13 +31,14 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt = &_test_tree1; + struct fdt_header *fdt; uint32_t *intp; char *strp, *xstr; int xlen, i; int err; test_init(argc, argv); + fdt = load_blob_arg(argc, argv); intp = check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c index d64257a..0552b05 100644 --- a/tests/subnode_offset.c +++ b/tests/subnode_offset.c @@ -57,11 +57,12 @@ int check_subnode(struct fdt_header *fdt, int parent, const char *name) int main(int argc, char *argv[]) { - struct fdt_header *fdt = &_test_tree1; + struct fdt_header *fdt; int subnode1_offset, subnode2_offset; int subsubnode1_offset, subsubnode2_offset; test_init(argc, argv); + fdt = load_blob_arg(argc, argv); subnode1_offset = check_subnode(fdt, 0, "subnode1"); subnode2_offset = check_subnode(fdt, 0, "subnode2"); diff --git a/tests/tests.h b/tests/tests.h index 9ad07c8..b5fd475 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -104,6 +104,22 @@ void cleanup(void); exit(RC_BUG); \ } while (0) +static inline void *xmalloc(size_t size) +{ + void *p = malloc(size); + if (! p) + FAIL("malloc() failure"); + return p; +} + +static inline void *xrealloc(void *p, size_t size) +{ + p = realloc(p, size); + if (! p) + FAIL("realloc() failure"); + return p; +} + const char *fdt_strerror(int errval); void check_property(struct fdt_header *fdt, int nodeoffset, const char *name, int len, const void *val); @@ -121,6 +137,7 @@ void *check_getprop(struct fdt_header *fdt, int nodeoffset, const char *name, typeof(val) x = val; \ check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \ }) - +//void *load_blob(const char *filename); +void *load_blob_arg(int argc, char *argv[]); #endif /* _TESTS_H */ diff --git a/tests/testutils.c b/tests/testutils.c index 30acb35..af8c2ad 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -161,3 +162,43 @@ void *check_getprop(struct fdt_header *fdt, int nodeoffset, const char *name, return propval; } + +#define CHUNKSIZE 128 + +void *load_blob(const char *filename) +{ + int fd; + int offset = 0; + int bufsize = 1024; + char *p = NULL; + int ret; + + fd = open(filename, O_RDONLY); + if (fd < 0) + CONFIG("Couldn't open blob from \"%s\": %s", filename, + strerror(errno)); + + p = xmalloc(bufsize); + do { + if (offset == bufsize) { + bufsize *= 2; + p = xrealloc(p, bufsize); + } + + ret = read(fd, &p[offset], bufsize - offset); + if (ret < 0) + CONFIG("Couldn't read from \"%s\": %s", filename, + strerror(errno)); + + offset += ret; + } while (ret != 0); + + return p; +} + +void *load_blob_arg(int argc, char *argv[]) +{ + if (argc != 2) + CONFIG("Usage: %s ", argv[0]); + return load_blob(argv[1]); +} From 156649d4f656f47017fabb2596495ffce124bba5 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 29 Nov 2006 13:34:22 +1100 Subject: [PATCH 0011/1198] Fix building of dumptrees Without this rather odd constrained pattern rule, make attempts to build dumptrees using the default %: %.c rule instead of the defined %: %.o and %.o: %.c rules. --- tests/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index db27d07..2b165dc 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -33,18 +33,18 @@ all: $(TESTS) $(TREES) @$(VECHO) AS $@ $(CC) -D__ASSEMBLY__ $(CPPFLAGS) -o $@ -c $< -$(TREES): trees.o dumptrees - @$(VECHO) DUMPTREES - ./dumptrees >/dev/null - %: %.o @$(VECHO) LD $@ $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) -dumptrees: trees.o - $(LIB_TESTS): %: testutils.o $(LIBFDT) +dumptrees: %: trees.o + +$(TREES): dumptrees + @$(VECHO) DUMPTREES + ./dumptrees >/dev/null + clean: @$(VECHO) CLEAN "(tests)" rm -f *~ *.o *.so *.a *.d *.s core a.out From 3aa4cfd66bf75b67a2ddaed8454d0483762e69ba Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 29 Nov 2006 16:34:30 +1100 Subject: [PATCH 0012/1198] Simplify string table access functions The range sanity checking on the fdt_string_cmp() function causes problems for the sequential write code (or at least for using RO functions on an incomplete SW tree). Plus they didn't really fit with the philosphy for the RO code of working as widely as possible on weirdly constructed trees. --- fdt.c | 20 -------------------- fdt_ro.c | 7 ++++++- libfdt.h | 5 ++--- 3 files changed, 8 insertions(+), 24 deletions(-) diff --git a/fdt.c b/fdt.c index 0de7f68..03f1a0d 100644 --- a/fdt.c +++ b/fdt.c @@ -34,26 +34,6 @@ void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int len) return p; } -char *fdt_string(const struct fdt_header *fdt, int stroffset) -{ - return (char *)fdt + fdt32_to_cpu(fdt->off_dt_strings) + stroffset; -} - -int fdt_string_cmp(const struct fdt_header *fdt, int stroffset, const char *s2) -{ - const char *s1 = fdt_string(fdt, stroffset); - int len = strlen(s2) + 1; - - if (! s1) - return 0; - - if ((stroffset + len < stroffset) - || (stroffset + len > fdt32_to_cpu(fdt->size_dt_strings))) - return -2; - - return strcmp(s1, s2); -} - uint32_t _fdt_next_tag(const struct fdt_header *fdt, int offset, int *nextoffset) { const uint32_t *tagp, *lenp; diff --git a/fdt_ro.c b/fdt_ro.c index c2a0e72..bfd8163 100644 --- a/fdt_ro.c +++ b/fdt_ro.c @@ -59,6 +59,11 @@ static int offset_streq(const struct fdt_header *fdt, int offset, return 1; } +char *fdt_string(const struct fdt_header *fdt, int stroffset) +{ + return (char *)fdt + fdt32_to_cpu(fdt->off_dt_strings) + stroffset; +} + int fdt_property_offset(const struct fdt_header *fdt, int nodeoffset, const char *name) { @@ -103,7 +108,7 @@ int fdt_property_offset(const struct fdt_header *fdt, int nodeoffset, if (! prop) return OFFSET_ERROR(FDT_ERR_BADSTRUCTURE); namestroff = fdt32_to_cpu(prop->nameoff); - if (fdt_string_cmp(fdt, namestroff, name) == 0) + if (streq(fdt_string(fdt, namestroff), name)) /* Found it! */ return offset; break; diff --git a/libfdt.h b/libfdt.h index 7f279a6..605aa89 100644 --- a/libfdt.h +++ b/libfdt.h @@ -54,10 +54,9 @@ void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int checklen); #define fdt_ptr_error(ptr) \ ( (((long)(ptr) < 0) && ((long)(ptr) >= -FDT_ERR_MAX)) ? -(long)(ptr) : 0 ) -char *fdt_string(const struct fdt_header *fdt, int stroffset); -int fdt_string_cmp(const struct fdt_header *fdt, int stroffset, const char *s2); - /* Read-only functions */ +char *fdt_string(const struct fdt_header *fdt, int stroffset); + int fdt_property_offset(const struct fdt_header *fdt, int nodeoffset, const char *name); int fdt_subnode_offset_namelen(const struct fdt_header *fdt, int parentoffset, From 063693a9e42aea7beb7c6f49ecd8a8dc5ed1c387 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 29 Nov 2006 16:45:46 +1100 Subject: [PATCH 0013/1198] libfdt: Sequential write support This patch adds code to libfdt to create flat trees from scratch, writing sequentially. --- Makefile | 2 +- fdt_ro.c | 22 ++++- fdt_sw.c | 236 +++++++++++++++++++++++++++++++++++++++++++++ libfdt.h | 13 ++- libfdt_internal.h | 3 +- tests/Makefile | 3 +- tests/run_tests.sh | 8 ++ tests/sw_tree1.c | 83 ++++++++++++++++ tests/tests.h | 1 + tests/testutils.c | 26 +++++ 10 files changed, 386 insertions(+), 11 deletions(-) create mode 100644 fdt_sw.c create mode 100644 tests/sw_tree1.c diff --git a/Makefile b/Makefile index 5f6f947..0445192 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ PREFIX = /usr/local TARGETLIBS = libfdt.a -LIBOBJS = fdt.o fdt_ro.o fdt_wip.o #fdt_sw.o +LIBOBJS = fdt.o fdt_ro.o fdt_wip.o fdt_sw.o SOURCE = $(shell find . -maxdepth 1 ! -name version.h -a -name '*.[h]') SOURCE += *.c Makefile diff --git a/fdt_ro.c b/fdt_ro.c index bfd8163..43a79e5 100644 --- a/fdt_ro.c +++ b/fdt_ro.c @@ -25,12 +25,24 @@ static int check_header(const struct fdt_header *fdt) { - if (fdt32_to_cpu(fdt->magic) != FDT_MAGIC) + uint32_t magic = fdt32_to_cpu(fdt->magic); + uint32_t version = fdt32_to_cpu(fdt->version); + uint32_t last_comp_version = fdt32_to_cpu(fdt->last_comp_version); + + if (magic == FDT_MAGIC) { + /* Complete tree */ + if (version < FDT_FIRST_SUPPORTED_VERSION) + return FDT_ERR_BADVERSION; + if (last_comp_version > FDT_LAST_SUPPORTED_VERSION) + return FDT_ERR_BADVERSION; + } else if (magic == SW_MAGIC) { + /* Unfinished sequential-write blob */ + if (SW_SIZE_DT_STRUCT(fdt) == 0) + return FDT_ERR_BADSTATE; + } else { return FDT_ERR_BADMAGIC; - if (fdt32_to_cpu(fdt->version) < FDT_FIRST_SUPPORTED_VERSION) - return FDT_ERR_BADVERSION; - if (fdt32_to_cpu(fdt->last_comp_version) > FDT_LAST_SUPPORTED_VERSION) - return FDT_ERR_BADVERSION; + } + return 0; } diff --git a/fdt_sw.c b/fdt_sw.c new file mode 100644 index 0000000..84a38d8 --- /dev/null +++ b/fdt_sw.c @@ -0,0 +1,236 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int check_header_sw(struct fdt_header *fdt) +{ + if (fdt32_to_cpu(fdt->magic) != SW_MAGIC) + return FDT_ERR_BADMAGIC; + return 0; +} + +static void *grab_space(struct fdt_header *fdt, int len) +{ + int off_dt_struct = fdt32_to_cpu(fdt->off_dt_struct); + int offset = fdt32_to_cpu(SW_SIZE_DT_STRUCT(fdt)); + int spaceleft; + + spaceleft = fdt32_to_cpu(fdt->totalsize) - off_dt_struct + - fdt32_to_cpu(fdt->size_dt_strings); + + if ((offset + len < offset) || (offset + len > spaceleft)) + return NULL; + + SW_SIZE_DT_STRUCT(fdt) = cpu_to_fdt32(offset + len); + return fdt_offset_ptr(fdt, offset, len); +} + +struct fdt_header *fdt_create(void *buf, int bufsize) +{ + struct fdt_header *fdt = buf; + + if (bufsize < sizeof(struct fdt_header)) + return NULL; + + memset(buf, 0, bufsize); + + fdt->magic = cpu_to_fdt32(SW_MAGIC); + fdt->totalsize = cpu_to_fdt32(bufsize); + + fdt->off_mem_rsvmap = cpu_to_fdt32(ALIGN(sizeof(*fdt), + sizeof(struct fdt_reserve_entry))); + fdt->off_dt_struct = fdt->off_mem_rsvmap; + fdt->off_dt_strings = fdt32_to_cpu(bufsize); + + return fdt; +} + +int fdt_add_reservemap_entry(struct fdt_header *fdt, uint64_t addr, uint64_t size) +{ + struct fdt_reserve_entry *re; + int err = check_header_sw(fdt); + int offset; + + if (err) + return err; + if (SW_SIZE_DT_STRUCT(fdt)) + return FDT_ERR_BADSTATE; + + offset = fdt32_to_cpu(fdt->off_dt_struct); + if ((offset + sizeof(*re)) > fdt32_to_cpu(fdt->totalsize)) + return FDT_ERR_NOSPACE; + + re = (struct fdt_reserve_entry *)((void *)fdt + offset); + re->address = cpu_to_fdt64(addr); + re->size = cpu_to_fdt64(size); + + fdt->off_dt_struct = cpu_to_fdt32(offset + sizeof(*re)); + + return 0; +} + +int fdt_finish_reservemap(struct fdt_header *fdt) +{ + return fdt_add_reservemap_entry(fdt, 0, 0); +} + +int fdt_begin_node(struct fdt_header *fdt, const char *name) +{ + struct fdt_node_header *nh; + int err = check_header_sw(fdt); + int namelen = strlen(name) + 1; + + if (err) + return err; + + nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE)); + if (! nh) + return FDT_ERR_NOSPACE; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memcpy(nh->name, name, namelen); + return 0; +} + +int fdt_end_node(struct fdt_header *fdt) +{ + uint32_t *en; + int err = check_header_sw(fdt); + + if (err) + return err; + + en = grab_space(fdt, FDT_TAGSIZE); + if (! en) + return FDT_ERR_NOSPACE; + + *en = cpu_to_fdt32(FDT_END_NODE); + return 0; +} + +static int find_add_string(struct fdt_header *fdt, const char *s) +{ + int totalsize = fdt32_to_cpu(fdt->totalsize); + char *strtab = (char *)fdt + totalsize; + int strtabsize = fdt32_to_cpu(fdt->size_dt_strings); + int len = strlen(s) + 1; + int struct_top, offset; + + /* We treat string offsets as negative from the end of our buffer */ + /* then fix them up in fdt_finish() */ + offset = -strtabsize; + while ((offset < 0) && (memcmp(strtab + offset, s, len) != 0)) + offset++; + + if (offset < 0) + /* Found it */ + return offset; + + /* Add it */ + offset = -strtabsize - len; + struct_top = fdt32_to_cpu(fdt->off_dt_struct) + + fdt32_to_cpu(SW_SIZE_DT_STRUCT(fdt)); + if (totalsize + offset < struct_top) + return 0; /* no more room :( */ + + memcpy(strtab + offset, s, len); + fdt->size_dt_strings = cpu_to_fdt32(strtabsize + len); + return offset; +} + +int fdt_property(struct fdt_header *fdt, const char *name, const void *val, int len) +{ + struct fdt_property *prop; + int err = check_header_sw(fdt); + int nameoff; + + if (err) + return err; + + nameoff = find_add_string(fdt, name); + if (nameoff == 0) + return FDT_ERR_NOSPACE; + + prop = grab_space(fdt, sizeof(*prop) + ALIGN(len, FDT_TAGSIZE)); + if (! prop) + return FDT_ERR_NOSPACE; + + prop->tag = cpu_to_fdt32(FDT_PROP); + prop->nameoff = cpu_to_fdt32(nameoff); + prop->len = cpu_to_fdt32(len); + memcpy(prop->data, val, len); + return 0; +} + +int fdt_finish(struct fdt_header *fdt) +{ + int err = check_header_sw(fdt); + char *p = (char *)fdt; + uint32_t *end; + int oldstroffset, newstroffset, strsize; + uint32_t tag; + int offset, nextoffset; + + if (err) + return err; + + /* Add terminator */ + end = grab_space(fdt, sizeof(*end)); + if (! end) + return FDT_ERR_NOSPACE; + *end = cpu_to_fdt32(FDT_END); + + /* Relocate the string table */ + strsize = fdt32_to_cpu(fdt->size_dt_strings); + oldstroffset = fdt32_to_cpu(fdt->totalsize) - strsize; + newstroffset = fdt32_to_cpu(fdt->off_dt_struct) + + fdt32_to_cpu(SW_SIZE_DT_STRUCT(fdt)); + memmove(p + newstroffset, p + oldstroffset, strsize); + fdt->off_dt_strings = fdt32_to_cpu(newstroffset); + + /* Walk the structure, correcting string offsets */ + offset = 0; + while ((tag = _fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { + if (tag == FDT_PROP) { + struct fdt_property *prop = fdt_offset_ptr(fdt, offset, + sizeof(*prop)); + int nameoff; + + if (! prop) + return FDT_ERR_BADSTRUCTURE; + + nameoff = fdt32_to_cpu(prop->nameoff); + nameoff += strsize; + prop->nameoff = cpu_to_fdt32(nameoff); + } + offset = nextoffset; + } + + /* Finally, adjust the header */ + fdt->totalsize = cpu_to_fdt32(newstroffset + strsize); + fdt->version = cpu_to_fdt32(FDT_LAST_SUPPORTED_VERSION); + fdt->last_comp_version= cpu_to_fdt32(FDT_FIRST_SUPPORTED_VERSION); + fdt->magic = cpu_to_fdt32(FDT_MAGIC); + return 0; +} diff --git a/libfdt.h b/libfdt.h index 605aa89..b58ae0f 100644 --- a/libfdt.h +++ b/libfdt.h @@ -82,16 +82,23 @@ int fdt_setprop_inplace(struct fdt_header *fdt, int nodeoffset, const char *name int fdt_nop_property(struct fdt_header *fdt, int nodeoffset, const char *name); int fdt_nop_node(struct fdt_header *fdt, int nodeoffset); -#if 0 /* Sequential-write functions */ struct fdt_header *fdt_create(void *buf, int bufsize); int fdt_add_reservemap_entry(struct fdt_header *fdt, uint64_t addr, uint64_t size); -int fdt_begin_structure(struct fdt_header *fdt); +int fdt_finish_reservemap(struct fdt_header *fdt); int fdt_begin_node(struct fdt_header *fdt, const char *name); int fdt_property(struct fdt_header *fdt, const char *name, const void *val, int len); +#define fdt_property_typed(fdt, name, val) \ + ({ \ + typeof(val) x = (val); \ + fdt_property((fdt), (name), &x, sizeof(x)); \ + }) +#define fdt_property_string(fdt, name, str) \ + fdt_property(fdt, name, str, strlen(str)+1) int fdt_end_node(struct fdt_header *fdt); -int fdt_finish_structure(struct fdt_header *fdt); +int fdt_finish(struct fdt_header *fdt); +#if 0 /* Read-write functions */ struct fdt_header *fdt_open(struct fdt_header *fdt, int bufsize); int fdt_add_subnode(struct fdt_header *fdtx, void *node, const char *name); diff --git a/libfdt_internal.h b/libfdt_internal.h index 1f9ba0c..0bc2786 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -34,6 +34,7 @@ struct fdt_property *_fdt_getprop(const struct fdt_header *fdt, int nodeoffset, #define OFFSET_ERROR(code) -(code) #define PTR_ERROR(code) (void *)(-(code)) -#define SW_OFFSET(fdt) ((fdt)->version) +#define SW_MAGIC (~FDT_MAGIC) +#define SW_SIZE_DT_STRUCT(fdt) ((fdt)->version) #endif /* _LIBFDT_INTERNAL_H */ diff --git a/tests/Makefile b/tests/Makefile index 2b165dc..b6dc852 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -2,7 +2,8 @@ PREFIX = /usr/local LIB_TESTS = root_node property_offset subnode_offset path_offset getprop \ notfound \ - setprop_inplace nop_property nop_node + setprop_inplace nop_property nop_node \ + sw_tree1 TESTS = $(LIB_TESTS) UTILS = dumptrees diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 0ffdc93..338e47a 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -27,7 +27,15 @@ tree1_tests () { } functional_tests () { + # Make sure we don't have stale blobs lying around + rm -f *.test.dtb + tree1_tests test_tree1.dtb + + # Sequential write tests + run_test sw_tree1 + tree1_tests sw_tree1.test.dtb + tree1_tests unfinished_tree1.test.dtb } stress_tests () { diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c new file mode 100644 index 0000000..6f72006 --- /dev/null +++ b/tests/sw_tree1.c @@ -0,0 +1,83 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_nop_node() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +#define SPACE 65536 + +#define CHECK(code) \ + { \ + err = (code); \ + if (err) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } + +int main(int argc, char *argv[]) +{ + void *buf; + struct fdt_header *fdt; + int err; + + test_init(argc, argv); + + buf = xmalloc(SPACE); + fdt = fdt_create(buf, SPACE); + + CHECK(fdt_finish_reservemap(fdt)); + CHECK(fdt_begin_node(fdt, "")); + CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); + CHECK(fdt_property_string(fdt, "prop-str", TEST_STRING_1)); + + CHECK(fdt_begin_node(fdt, "subnode1")); + CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); + CHECK(fdt_begin_node(fdt, "subsubnode")); + CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); + CHECK(fdt_end_node(fdt)); + CHECK(fdt_end_node(fdt)); + + CHECK(fdt_begin_node(fdt, "subnode2")); + CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_2)); + CHECK(fdt_begin_node(fdt, "subsubnode")); + CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_2)); + CHECK(fdt_end_node(fdt)); + CHECK(fdt_end_node(fdt)); + + CHECK(fdt_end_node(fdt)); + + save_blob("unfinished_tree1.test.dtb", fdt); + + CHECK(fdt_finish(fdt)); + + verbose_printf("Completed tree, totalsize = %d\n", + fdt32_to_cpu(fdt->totalsize)); + + save_blob("sw_tree1.test.dtb", fdt); + + PASS(); +} diff --git a/tests/tests.h b/tests/tests.h index b5fd475..64ab64f 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -139,5 +139,6 @@ void *check_getprop(struct fdt_header *fdt, int nodeoffset, const char *name, }) //void *load_blob(const char *filename); void *load_blob_arg(int argc, char *argv[]); +void save_blob(const char *filename, struct fdt_header *fdt); #endif /* _TESTS_H */ diff --git a/tests/testutils.c b/tests/testutils.c index af8c2ad..4997a8e 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -202,3 +202,29 @@ void *load_blob_arg(int argc, char *argv[]) CONFIG("Usage: %s ", argv[0]); return load_blob(argv[1]); } + +void save_blob(const char *filename, struct fdt_header *fdt) +{ + int fd; + int totalsize; + int offset; + void *p; + int ret; + + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd < 0) + CONFIG("Couldn't open \"%s\" to write blob: %s", filename, + strerror(errno)); + + totalsize = fdt32_to_cpu(fdt->totalsize); + offset = 0; + p = fdt; + + while (offset < totalsize) { + ret = write(fd, p + offset, totalsize - offset); + if (ret < 0) + CONFIG("Couldn't write to \"%s\": %s", filename, + strerror(errno)); + offset += ret; + } +} From 65380f164ccd65218f5dd43dc81d162b900450ed Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 29 Nov 2006 16:49:27 +1100 Subject: [PATCH 0014/1198] Add a copy of the GPL Since the file preamples say it's there, we really should include it. --- GPL | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 GPL diff --git a/GPL b/GPL new file mode 100644 index 0000000..b7b5f53 --- /dev/null +++ b/GPL @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. From 41722c230c05b4a6ae0eec6c7537a73cb149a65e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Dec 2006 13:10:07 +1100 Subject: [PATCH 0015/1198] libfdt: Fix logic in nop_property testcase This patch fixes some completely bogus error checking logic from the nop_property testcase (resulted from a cut-and-paste error). Signed-off-by: David Gibson --- tests/nop_property.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/nop_property.c b/tests/nop_property.c index a8bed5b..94c8e74 100644 --- a/tests/nop_property.c +++ b/tests/nop_property.c @@ -57,15 +57,15 @@ int main(int argc, char *argv[]) TEST_STRING_1); verbose_printf("string value was \"%s\"\n", strp); err = fdt_nop_property(fdt, 0, "prop-str"); - err = fdt_ptr_error(intp); + if (err) + FAIL("Failed to nop \"prop-str\": %s", fdt_strerror(err)); + + strp = fdt_getprop(fdt, 0, "prop-str", NULL); + err = fdt_ptr_error(strp); if (! err) FAIL("prop-str still present after nopping"); if (err != FDT_ERR_NOTFOUND) FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); - strp = fdt_getprop(fdt, 0, "prop-str", NULL); - if (fdt_ptr_error(intp) != FDT_ERR_NOTFOUND) - FAIL("prop-str still present after nopping"); - PASS(); } From ede25deae69872417579a46a4476bbf1620657e2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Dec 2006 15:02:10 +1100 Subject: [PATCH 0016/1198] libfdt: Export accessors for header fields This patch adds exported accessor macros for the various flat device tree header fields to libfdt.h. This necessitates moving some of the byte-swapping functions. Signed-off-by: David Gibson --- fdt.c | 2 +- fdt_ro.c | 16 ++++++---------- fdt_sw.c | 41 ++++++++++++++++++----------------------- libfdt.h | 12 +++++++++++- libfdt_env.h | 5 ++++- libfdt_internal.h | 2 +- tests/dumptrees.c | 2 +- tests/tests.h | 12 ------------ 8 files changed, 42 insertions(+), 50 deletions(-) diff --git a/fdt.c b/fdt.c index 03f1a0d..b24a3fe 100644 --- a/fdt.c +++ b/fdt.c @@ -27,7 +27,7 @@ void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int len) { void *p; - p = (void *)fdt + fdt32_to_cpu(fdt->off_dt_struct) + offset; + p = (void *)fdt + fdt_off_dt_struct(fdt) + offset; if (p + len < p) return NULL; diff --git a/fdt_ro.c b/fdt_ro.c index 43a79e5..db5281c 100644 --- a/fdt_ro.c +++ b/fdt_ro.c @@ -25,19 +25,15 @@ static int check_header(const struct fdt_header *fdt) { - uint32_t magic = fdt32_to_cpu(fdt->magic); - uint32_t version = fdt32_to_cpu(fdt->version); - uint32_t last_comp_version = fdt32_to_cpu(fdt->last_comp_version); - - if (magic == FDT_MAGIC) { + if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ - if (version < FDT_FIRST_SUPPORTED_VERSION) + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) return FDT_ERR_BADVERSION; - if (last_comp_version > FDT_LAST_SUPPORTED_VERSION) + if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) return FDT_ERR_BADVERSION; - } else if (magic == SW_MAGIC) { + } else if (fdt_magic(fdt) == SW_MAGIC) { /* Unfinished sequential-write blob */ - if (SW_SIZE_DT_STRUCT(fdt) == 0) + if (sw_size_dt_struct(fdt) == 0) return FDT_ERR_BADSTATE; } else { return FDT_ERR_BADMAGIC; @@ -73,7 +69,7 @@ static int offset_streq(const struct fdt_header *fdt, int offset, char *fdt_string(const struct fdt_header *fdt, int stroffset) { - return (char *)fdt + fdt32_to_cpu(fdt->off_dt_strings) + stroffset; + return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset; } int fdt_property_offset(const struct fdt_header *fdt, int nodeoffset, diff --git a/fdt_sw.c b/fdt_sw.c index 84a38d8..b2545b9 100644 --- a/fdt_sw.c +++ b/fdt_sw.c @@ -25,24 +25,23 @@ static int check_header_sw(struct fdt_header *fdt) { - if (fdt32_to_cpu(fdt->magic) != SW_MAGIC) + if (fdt_magic(fdt) != SW_MAGIC) return FDT_ERR_BADMAGIC; return 0; } static void *grab_space(struct fdt_header *fdt, int len) { - int off_dt_struct = fdt32_to_cpu(fdt->off_dt_struct); - int offset = fdt32_to_cpu(SW_SIZE_DT_STRUCT(fdt)); + int offset = sw_size_dt_struct(fdt); int spaceleft; - spaceleft = fdt32_to_cpu(fdt->totalsize) - off_dt_struct - - fdt32_to_cpu(fdt->size_dt_strings); + spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) + - fdt_size_dt_strings(fdt); if ((offset + len < offset) || (offset + len > spaceleft)) return NULL; - SW_SIZE_DT_STRUCT(fdt) = cpu_to_fdt32(offset + len); + fdt->version = cpu_to_fdt32(offset + len); return fdt_offset_ptr(fdt, offset, len); } @@ -74,11 +73,11 @@ int fdt_add_reservemap_entry(struct fdt_header *fdt, uint64_t addr, uint64_t siz if (err) return err; - if (SW_SIZE_DT_STRUCT(fdt)) + if (sw_size_dt_struct(fdt)) return FDT_ERR_BADSTATE; - offset = fdt32_to_cpu(fdt->off_dt_struct); - if ((offset + sizeof(*re)) > fdt32_to_cpu(fdt->totalsize)) + offset = fdt_off_dt_struct(fdt); + if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) return FDT_ERR_NOSPACE; re = (struct fdt_reserve_entry *)((void *)fdt + offset); @@ -131,9 +130,8 @@ int fdt_end_node(struct fdt_header *fdt) static int find_add_string(struct fdt_header *fdt, const char *s) { - int totalsize = fdt32_to_cpu(fdt->totalsize); - char *strtab = (char *)fdt + totalsize; - int strtabsize = fdt32_to_cpu(fdt->size_dt_strings); + char *strtab = (char *)fdt + fdt_totalsize(fdt); + int strtabsize = fdt_size_dt_strings(fdt); int len = strlen(s) + 1; int struct_top, offset; @@ -149,9 +147,8 @@ static int find_add_string(struct fdt_header *fdt, const char *s) /* Add it */ offset = -strtabsize - len; - struct_top = fdt32_to_cpu(fdt->off_dt_struct) - + fdt32_to_cpu(SW_SIZE_DT_STRUCT(fdt)); - if (totalsize + offset < struct_top) + struct_top = fdt_off_dt_struct(fdt) + sw_size_dt_struct(fdt); + if (fdt_totalsize(fdt) + offset < struct_top) return 0; /* no more room :( */ memcpy(strtab + offset, s, len); @@ -188,7 +185,7 @@ int fdt_finish(struct fdt_header *fdt) int err = check_header_sw(fdt); char *p = (char *)fdt; uint32_t *end; - int oldstroffset, newstroffset, strsize; + int oldstroffset, newstroffset; uint32_t tag; int offset, nextoffset; @@ -202,11 +199,9 @@ int fdt_finish(struct fdt_header *fdt) *end = cpu_to_fdt32(FDT_END); /* Relocate the string table */ - strsize = fdt32_to_cpu(fdt->size_dt_strings); - oldstroffset = fdt32_to_cpu(fdt->totalsize) - strsize; - newstroffset = fdt32_to_cpu(fdt->off_dt_struct) - + fdt32_to_cpu(SW_SIZE_DT_STRUCT(fdt)); - memmove(p + newstroffset, p + oldstroffset, strsize); + oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); + newstroffset = fdt_off_dt_struct(fdt) + sw_size_dt_struct(fdt); + memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); fdt->off_dt_strings = fdt32_to_cpu(newstroffset); /* Walk the structure, correcting string offsets */ @@ -221,14 +216,14 @@ int fdt_finish(struct fdt_header *fdt) return FDT_ERR_BADSTRUCTURE; nameoff = fdt32_to_cpu(prop->nameoff); - nameoff += strsize; + nameoff += fdt_size_dt_strings(fdt); prop->nameoff = cpu_to_fdt32(nameoff); } offset = nextoffset; } /* Finally, adjust the header */ - fdt->totalsize = cpu_to_fdt32(newstroffset + strsize); + fdt->totalsize = cpu_to_fdt32(newstroffset + fdt_size_dt_strings(fdt)); fdt->version = cpu_to_fdt32(FDT_LAST_SUPPORTED_VERSION); fdt->last_comp_version= cpu_to_fdt32(FDT_FIRST_SUPPORTED_VERSION); fdt->magic = cpu_to_fdt32(FDT_MAGIC); diff --git a/libfdt.h b/libfdt.h index b58ae0f..d4f98dc 100644 --- a/libfdt.h +++ b/libfdt.h @@ -20,6 +20,7 @@ */ #include +#include #define FDT_FIRST_SUPPORTED_VERSION 0x10 #define FDT_LAST_SUPPORTED_VERSION 0x10 @@ -42,7 +43,16 @@ #define FDT_ERR_MAX 13 -/* Offset handling functions */ +#define fdt_magic(fdt) (fdt32_to_cpu(fdt)->magic) +#define fdt_totalsize(fdt) (fdt32_to_cpu(fdt)->totalsize) +#define fdt_off_dt_struct(fdt) (fdt32_to_cpu(fdt)->off_dt_struct) +#define fdt_off_dt_strings(fdt) (fdt32_to_cpu(fdt)->off_dt_strings) +#define fdt_off_mem_rsvmap(fdt) (fdt32_to_cpu(fdt)->off_mem_rsvmap) +#define fdt_version(fdt) (fdt32_to_cpu(fdt)->version) +#define fdt_last_comp_version(fdt) (fdt32_to_cpu(fdt)->last_comp_version) +#define fdt_boot_cpuid_phys(fdt) (fdt32_to_cpu(fdt)->boot_cpuid_phys) +#define fdt_size_dt_strings(fdt) (fdt32_to_cpu(fdt)->size_dt_strings) + void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int checklen); #define fdt_offset_ptr_typed(fdt, offset, var) \ diff --git a/libfdt_env.h b/libfdt_env.h index a9b196f..59f2536 100644 --- a/libfdt_env.h +++ b/libfdt_env.h @@ -1,3 +1,6 @@ +#ifndef _LIBFDT_ENV_H +#define _LIBFDT_ENV_H + #include #include #include @@ -16,4 +19,4 @@ #define cpu_to_fdt64(x) (bswap_64((x))) #endif -#include "libfdt.h" +#endif /* _LIBFDT_ENV_H */ diff --git a/libfdt_internal.h b/libfdt_internal.h index 0bc2786..06fa1cc 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -35,6 +35,6 @@ struct fdt_property *_fdt_getprop(const struct fdt_header *fdt, int nodeoffset, #define PTR_ERROR(code) (void *)(-(code)) #define SW_MAGIC (~FDT_MAGIC) -#define SW_SIZE_DT_STRUCT(fdt) ((fdt)->version) +#define sw_size_dt_struct(fdt) (fdt32_to_cpu(((fdt)->version))) #endif /* _LIBFDT_INTERNAL_H */ diff --git a/tests/dumptrees.c b/tests/dumptrees.c index d7e110d..f0a9b2c 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -4,8 +4,8 @@ #include #include +#include -#include "tests.h" #include "testdata.h" struct { diff --git a/tests/tests.h b/tests/tests.h index 64ab64f..732e6a4 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -37,18 +37,6 @@ void test_init(int argc, char *argv[]); #define streq(s1, s2) (strcmp((s1),(s2)) == 0) -#if __BYTE_ORDER == __BIG_ENDIAN -#define fdt32_to_cpu(x) (x) -#define cpu_to_fdt32(x) (x) -#define fdt64_to_cpu(x) (x) -#define cpu_to_fdt64(x) (x) -#else -#define fdt32_to_cpu(x) (bswap_32((x))) -#define cpu_to_fdt32(x) (bswap_32((x))) -#define fdt64_to_cpu(x) (bswap_64((x))) -#define cpu_to_fdt64(x) (bswap_64((x))) -#endif - /* Each test case must define this function */ void cleanup(void); From 423697628aa15f578a3fe8e499cdbb7ca64d075e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Dec 2006 15:07:19 +1100 Subject: [PATCH 0017/1198] libfdt: Implement fdt_move() Implement the fdt_move() function for copying/moving device trees to a new buffer, or within an existing buffer. --- fdt.c | 33 ++++++++++++++++++++ fdt_ro.c | 21 +------------ libfdt.h | 5 ++- libfdt_internal.h | 1 + tests/Makefile | 3 +- tests/move_and_save.c | 71 +++++++++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 9 ++++++ 7 files changed, 119 insertions(+), 24 deletions(-) create mode 100644 tests/move_and_save.c diff --git a/fdt.c b/fdt.c index b24a3fe..0c1a5f0 100644 --- a/fdt.c +++ b/fdt.c @@ -23,6 +23,25 @@ #include "libfdt_internal.h" +int _fdt_check_header(const struct fdt_header *fdt) +{ + if (fdt_magic(fdt) == FDT_MAGIC) { + /* Complete tree */ + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + return FDT_ERR_BADVERSION; + if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) + return FDT_ERR_BADVERSION; + } else if (fdt_magic(fdt) == SW_MAGIC) { + /* Unfinished sequential-write blob */ + if (sw_size_dt_struct(fdt) == 0) + return FDT_ERR_BADSTATE; + } else { + return FDT_ERR_BADMAGIC; + } + + return 0; +} + void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int len) { void *p; @@ -72,3 +91,17 @@ uint32_t _fdt_next_tag(const struct fdt_header *fdt, int offset, int *nextoffset return tag; } + +struct fdt_header *fdt_move(const struct fdt_header *fdt, void *buf, int bufsize) +{ + int err = _fdt_check_header(fdt); + + if (err) + return PTR_ERROR(err); + + if (fdt_totalsize(fdt) > bufsize) + return PTR_ERROR(FDT_ERR_NOSPACE); + + memmove(buf, fdt, fdt_totalsize(fdt)); + return (struct fdt_header *)buf; +} diff --git a/fdt_ro.c b/fdt_ro.c index db5281c..bbc380a 100644 --- a/fdt_ro.c +++ b/fdt_ro.c @@ -23,29 +23,10 @@ #include "libfdt_internal.h" -static int check_header(const struct fdt_header *fdt) -{ - if (fdt_magic(fdt) == FDT_MAGIC) { - /* Complete tree */ - if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) - return FDT_ERR_BADVERSION; - if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) - return FDT_ERR_BADVERSION; - } else if (fdt_magic(fdt) == SW_MAGIC) { - /* Unfinished sequential-write blob */ - if (sw_size_dt_struct(fdt) == 0) - return FDT_ERR_BADSTATE; - } else { - return FDT_ERR_BADMAGIC; - } - - return 0; -} - #define OFFSET_CHECK_HEADER(fdt) \ { \ int err; \ - if ((err = check_header(fdt)) != 0) \ + if ((err = _fdt_check_header(fdt)) != 0) \ return OFFSET_ERROR(err); \ } diff --git a/libfdt.h b/libfdt.h index d4f98dc..c0ee2b7 100644 --- a/libfdt.h +++ b/libfdt.h @@ -64,6 +64,8 @@ void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int checklen); #define fdt_ptr_error(ptr) \ ( (((long)(ptr) < 0) && ((long)(ptr) >= -FDT_ERR_MAX)) ? -(long)(ptr) : 0 ) +struct fdt_header *fdt_move(const struct fdt_header *fdt, void *buf, int bufsize); + /* Read-only functions */ char *fdt_string(const struct fdt_header *fdt, int stroffset); @@ -115,9 +117,6 @@ int fdt_add_subnode(struct fdt_header *fdtx, void *node, const char *name); int fdt_set_property(struct fdt_header *fdtx, void *node, const char *name, const void *val, int len); int fdt_del_property(struct fdt_header *fdtx, void *node, const char *name); - -/* Misc functions */ -struct fdt_header *fdt_move(struct fdt_header *fdt, void *buf, int bufsize); #endif #endif /* _LIBFDT_H */ diff --git a/libfdt_internal.h b/libfdt_internal.h index 06fa1cc..91361c2 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -26,6 +26,7 @@ #define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) #define streq(p, q) (strcmp((p), (q)) == 0) +int _fdt_check_header(const struct fdt_header *fdt); uint32_t _fdt_next_tag(const struct fdt_header *fdt, int startoffset, int *nextoffset); struct fdt_property *_fdt_getprop(const struct fdt_header *fdt, int nodeoffset, const char *name, int *lenp); diff --git a/tests/Makefile b/tests/Makefile index b6dc852..b430a68 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -3,7 +3,8 @@ PREFIX = /usr/local LIB_TESTS = root_node property_offset subnode_offset path_offset getprop \ notfound \ setprop_inplace nop_property nop_node \ - sw_tree1 + sw_tree1 \ + move_and_save TESTS = $(LIB_TESTS) UTILS = dumptrees diff --git a/tests/move_and_save.c b/tests/move_and_save.c new file mode 100644 index 0000000..526f615 --- /dev/null +++ b/tests/move_and_save.c @@ -0,0 +1,71 @@ +/* + * libfdt - Flat Device Tree manipulation + * Basic testcase for read-only access + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt, *fdt1, *fdt2, *fdt3; + void *buf; + int shuntsize; + int bufsize; + int err; + const char *inname; + char outname[PATH_MAX]; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + inname = argv[1]; + + shuntsize = ALIGN(fdt_totalsize(fdt) / 2, sizeof(uint64_t)); + bufsize = fdt_totalsize(fdt) + shuntsize; + buf = xmalloc(bufsize); + + fdt1 = fdt_move(fdt, buf, bufsize); + if ((err = fdt_ptr_error(fdt1))) + FAIL("Failed to move tree into new buffer: %s", + fdt_strerror(err)); + sprintf(outname, "moved.%s", inname); + save_blob(outname, fdt1); + + fdt2 = fdt_move(fdt1, buf + shuntsize, bufsize-shuntsize); + if ((err = fdt_ptr_error(fdt2))) + FAIL("Failed to shunt tree %d bytes: %s", + shuntsize, fdt_strerror(err)); + sprintf(outname, "shunted.%s", inname); + save_blob(outname, fdt2); + + fdt3 = fdt_move(fdt2, buf, bufsize); + if ((err = fdt_ptr_error(fdt3))) + FAIL("Failed to deshunt tree %d bytes: %s", + shuntsize, fdt_strerror(err)); + sprintf(outname, "deshunted.%s", inname); + save_blob(outname, fdt3); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 338e47a..fba7413 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -36,6 +36,15 @@ functional_tests () { run_test sw_tree1 tree1_tests sw_tree1.test.dtb tree1_tests unfinished_tree1.test.dtb + + # fdt_move tests + for tree in test_tree1.dtb sw_tree1.test.dtb unfinished_tree1.test.dtb; do + rm -f moved.$tree shunted.$tree deshunted.$tree + run_test move_and_save $tree + tree1_tests moved.$tree + tree1_tests shunted.$tree + tree1_tests deshunted.$tree + done } stress_tests () { From aeddfe2c34c88c386749334746e4016431d10952 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Dec 2006 15:11:58 +1100 Subject: [PATCH 0018/1198] libfdt: Factor out string search function This patch pulls out the logic for finding a string in the string table into _fdt_find_string(), from fdt_sw.c's find_add_string(). This function will be useful for random-access read-write functions. In the process clean up the search logic a little. --- fdt.c | 12 ++++++++++++ fdt_sw.c | 13 ++++--------- libfdt_internal.h | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/fdt.c b/fdt.c index 0c1a5f0..d3844fc 100644 --- a/fdt.c +++ b/fdt.c @@ -92,6 +92,18 @@ uint32_t _fdt_next_tag(const struct fdt_header *fdt, int offset, int *nextoffset return tag; } +const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) +{ + int len = strlen(s) + 1; + const char *last = strtab + tabsize - len; + const char *p; + + for (p = strtab; p <= last; p++) + if (memeq(p, s, len)) + return p; + return NULL; +} + struct fdt_header *fdt_move(const struct fdt_header *fdt, void *buf, int bufsize) { int err = _fdt_check_header(fdt); diff --git a/fdt_sw.c b/fdt_sw.c index b2545b9..89abacb 100644 --- a/fdt_sw.c +++ b/fdt_sw.c @@ -131,19 +131,14 @@ int fdt_end_node(struct fdt_header *fdt) static int find_add_string(struct fdt_header *fdt, const char *s) { char *strtab = (char *)fdt + fdt_totalsize(fdt); + const char *p; int strtabsize = fdt_size_dt_strings(fdt); int len = strlen(s) + 1; int struct_top, offset; - /* We treat string offsets as negative from the end of our buffer */ - /* then fix them up in fdt_finish() */ - offset = -strtabsize; - while ((offset < 0) && (memcmp(strtab + offset, s, len) != 0)) - offset++; - - if (offset < 0) - /* Found it */ - return offset; + p = _fdt_find_string(strtab - strtabsize, strtabsize, s); + if (p) + return p - strtab; /* Add it */ offset = -strtabsize - len; diff --git a/libfdt_internal.h b/libfdt_internal.h index 91361c2..96f5fa8 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -30,7 +30,7 @@ int _fdt_check_header(const struct fdt_header *fdt); uint32_t _fdt_next_tag(const struct fdt_header *fdt, int startoffset, int *nextoffset); struct fdt_property *_fdt_getprop(const struct fdt_header *fdt, int nodeoffset, const char *name, int *lenp); - +const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); #define OFFSET_ERROR(code) -(code) #define PTR_ERROR(code) (void *)(-(code)) From fe92f6bb75668d4ff1e5bf08b2ac432ba68fb5b3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Dec 2006 16:25:39 +1100 Subject: [PATCH 0019/1198] libfdt: Introduce flat tree format v17 v17 of the blob format adds a field for the size of the structure block, but is backwards compatible with v16. This patch introduces definitions for the new field, and uses it to improve the bounds checking in the read-only code. It also cleans up the sequential write code using it: we no longer need to borrow the version field as a write pointer. --- fdt.c | 7 ++++++- fdt.h | 6 +++++- fdt_sw.c | 14 +++++++------- libfdt.h | 3 ++- libfdt_internal.h | 1 - tests/trees.S | 5 +++-- 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/fdt.c b/fdt.c index d3844fc..4271dfd 100644 --- a/fdt.c +++ b/fdt.c @@ -33,7 +33,7 @@ int _fdt_check_header(const struct fdt_header *fdt) return FDT_ERR_BADVERSION; } else if (fdt_magic(fdt) == SW_MAGIC) { /* Unfinished sequential-write blob */ - if (sw_size_dt_struct(fdt) == 0) + if (fdt_size_dt_struct(fdt) == 0) return FDT_ERR_BADSTATE; } else { return FDT_ERR_BADMAGIC; @@ -46,6 +46,11 @@ void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int len) { void *p; + if (fdt_version(fdt) >= 0x11) + if (((offset + len) < offset) + || ((offset + len) > fdt_size_dt_struct(fdt))) + return NULL; + p = (void *)fdt + fdt_off_dt_struct(fdt) + offset; if (p + len < p) diff --git a/fdt.h b/fdt.h index 10b5544..fff533e 100644 --- a/fdt.h +++ b/fdt.h @@ -19,6 +19,9 @@ struct fdt_header { booting on */ /* version 3 fields below */ uint32_t size_dt_strings; /* size of the strings block */ + + /* version 17 fields below */ + uint32_t size_dt_struct; /* size of the structure block */ }; struct fdt_reserve_entry { @@ -53,6 +56,7 @@ struct fdt_property { #define FDT_V1_SIZE (7*sizeof(uint32_t)) #define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(uint32_t)) #define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(uint32_t)) - +#define FDT_V16_SIZE FDT_V3_SIZE +#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(uint32_t)) #endif /* _FDT_H */ diff --git a/fdt_sw.c b/fdt_sw.c index 89abacb..1a6b2cf 100644 --- a/fdt_sw.c +++ b/fdt_sw.c @@ -32,7 +32,7 @@ static int check_header_sw(struct fdt_header *fdt) static void *grab_space(struct fdt_header *fdt, int len) { - int offset = sw_size_dt_struct(fdt); + int offset = fdt_size_dt_struct(fdt); int spaceleft; spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) @@ -41,7 +41,7 @@ static void *grab_space(struct fdt_header *fdt, int len) if ((offset + len < offset) || (offset + len > spaceleft)) return NULL; - fdt->version = cpu_to_fdt32(offset + len); + fdt->size_dt_struct = cpu_to_fdt32(offset + len); return fdt_offset_ptr(fdt, offset, len); } @@ -55,6 +55,8 @@ struct fdt_header *fdt_create(void *buf, int bufsize) memset(buf, 0, bufsize); fdt->magic = cpu_to_fdt32(SW_MAGIC); + fdt->version = cpu_to_fdt32(FDT_LAST_SUPPORTED_VERSION); + fdt->last_comp_version= cpu_to_fdt32(FDT_FIRST_SUPPORTED_VERSION); fdt->totalsize = cpu_to_fdt32(bufsize); fdt->off_mem_rsvmap = cpu_to_fdt32(ALIGN(sizeof(*fdt), @@ -73,7 +75,7 @@ int fdt_add_reservemap_entry(struct fdt_header *fdt, uint64_t addr, uint64_t siz if (err) return err; - if (sw_size_dt_struct(fdt)) + if (fdt_size_dt_struct(fdt)) return FDT_ERR_BADSTATE; offset = fdt_off_dt_struct(fdt); @@ -142,7 +144,7 @@ static int find_add_string(struct fdt_header *fdt, const char *s) /* Add it */ offset = -strtabsize - len; - struct_top = fdt_off_dt_struct(fdt) + sw_size_dt_struct(fdt); + struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); if (fdt_totalsize(fdt) + offset < struct_top) return 0; /* no more room :( */ @@ -195,7 +197,7 @@ int fdt_finish(struct fdt_header *fdt) /* Relocate the string table */ oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); - newstroffset = fdt_off_dt_struct(fdt) + sw_size_dt_struct(fdt); + newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); fdt->off_dt_strings = fdt32_to_cpu(newstroffset); @@ -219,8 +221,6 @@ int fdt_finish(struct fdt_header *fdt) /* Finally, adjust the header */ fdt->totalsize = cpu_to_fdt32(newstroffset + fdt_size_dt_strings(fdt)); - fdt->version = cpu_to_fdt32(FDT_LAST_SUPPORTED_VERSION); - fdt->last_comp_version= cpu_to_fdt32(FDT_FIRST_SUPPORTED_VERSION); fdt->magic = cpu_to_fdt32(FDT_MAGIC); return 0; } diff --git a/libfdt.h b/libfdt.h index c0ee2b7..a3da19c 100644 --- a/libfdt.h +++ b/libfdt.h @@ -23,7 +23,7 @@ #include #define FDT_FIRST_SUPPORTED_VERSION 0x10 -#define FDT_LAST_SUPPORTED_VERSION 0x10 +#define FDT_LAST_SUPPORTED_VERSION 0x11 /* Errors */ #define FDT_ERR_OK 0 @@ -52,6 +52,7 @@ #define fdt_last_comp_version(fdt) (fdt32_to_cpu(fdt)->last_comp_version) #define fdt_boot_cpuid_phys(fdt) (fdt32_to_cpu(fdt)->boot_cpuid_phys) #define fdt_size_dt_strings(fdt) (fdt32_to_cpu(fdt)->size_dt_strings) +#define fdt_size_dt_struct(fdt) (fdt32_to_cpu(fdt)->size_dt_struct) void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int checklen); diff --git a/libfdt_internal.h b/libfdt_internal.h index 96f5fa8..67ef91d 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -36,6 +36,5 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); #define PTR_ERROR(code) (void *)(-(code)) #define SW_MAGIC (~FDT_MAGIC) -#define sw_size_dt_struct(fdt) (fdt32_to_cpu(((fdt)->version))) #endif /* _LIBFDT_INTERNAL_H */ diff --git a/tests/trees.S b/tests/trees.S index 095f781..7fa4e65 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -10,10 +10,11 @@ tree: \ .long tree##_struct - tree ; \ .long tree##_strings - tree ; \ .long tree##_rsvmap - tree ; \ - .long 0x10 ; \ + .long 0x11 ; \ .long 0x10 ; \ .long 0 ; \ - .long tree##_end - tree##_strings ; + .long tree##_end - tree##_strings ; \ + .long tree##_strings - tree##_struct ; #define RSVMAP_ENTRY(addr, len) \ .quad addr ; \ From 7ba551f96629a5273370329658a6e6b3a87068aa Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Dec 2006 16:59:43 +1100 Subject: [PATCH 0020/1198] libfdt: Read-write support This patch adds support for random access, read-write support on flat trees. --- Makefile | 2 +- fdt_rw.c | 310 +++++++++++++++++++++++++++++++++++++++++++ fdt_wip.c | 25 ++-- libfdt.h | 28 ++-- libfdt_internal.h | 8 ++ tests/Makefile | 3 +- tests/del_node.c | 114 ++++++++++++++++ tests/del_property.c | 88 ++++++++++++ tests/open_pack.c | 68 ++++++++++ tests/run_tests.sh | 13 ++ tests/rw_tree1.c | 98 ++++++++++++++ tests/setprop.c | 75 +++++++++++ tests/tests.h | 2 + 13 files changed, 815 insertions(+), 19 deletions(-) create mode 100644 fdt_rw.c create mode 100644 tests/del_node.c create mode 100644 tests/del_property.c create mode 100644 tests/open_pack.c create mode 100644 tests/rw_tree1.c create mode 100644 tests/setprop.c diff --git a/Makefile b/Makefile index 0445192..d464a82 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ PREFIX = /usr/local TARGETLIBS = libfdt.a -LIBOBJS = fdt.o fdt_ro.o fdt_wip.o fdt_sw.o +LIBOBJS = fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o SOURCE = $(shell find . -maxdepth 1 ! -name version.h -a -name '*.[h]') SOURCE += *.c Makefile diff --git a/fdt_rw.c b/fdt_rw.c new file mode 100644 index 0000000..45f1fa4 --- /dev/null +++ b/fdt_rw.c @@ -0,0 +1,310 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int rw_check_header(struct fdt_header *fdt) +{ + int err; + + if ((err = _fdt_check_header(fdt))) + return err; + if (fdt_version(fdt) < 0x11) + return FDT_ERR_BADVERSION; + if (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(*fdt), 8)) + return FDT_ERR_BADLAYOUT; + if (fdt_off_dt_struct(fdt) < + (fdt_off_mem_rsvmap(fdt) + sizeof(struct fdt_reserve_entry))) + return FDT_ERR_BADLAYOUT; + if (fdt_off_dt_strings(fdt) < + (fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt))) + return FDT_ERR_BADLAYOUT; + if (fdt_totalsize(fdt) < + (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))) + return FDT_ERR_BADLAYOUT; + return 0; +} + +#define RW_OFFSET_CHECK_HEADER(fdt) \ + { \ + int err; \ + if ((err = rw_check_header(fdt)) != 0) \ + return OFFSET_ERROR(err); \ + } + +static inline int _blob_data_size(struct fdt_header *fdt) +{ + return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); +} + +static int _blob_splice(struct fdt_header *fdt, void *p, int oldlen, int newlen) +{ + void *blob = fdt; + void *end = blob + _blob_data_size(fdt); + + if (((p + oldlen) < p) || ((p + oldlen) > end)) + return FDT_ERR_BADOFFSET; + if ((end - oldlen + newlen) > (blob + fdt_totalsize(fdt))) + return FDT_ERR_NOSPACE; + memmove(p + newlen, p + oldlen, end - p - oldlen); + return 0; +} + +static int _blob_splice_struct(struct fdt_header *fdt, void *p, + int oldlen, int newlen) +{ + int delta = newlen - oldlen; + int err; + + if ((err = _blob_splice(fdt, p, oldlen, newlen))) + return err; + + fdt->size_dt_struct = cpu_to_fdt32(fdt_size_dt_struct(fdt) + delta); + fdt->off_dt_strings = cpu_to_fdt32(fdt_off_dt_strings(fdt) + delta); + return 0; +} + +static int _blob_splice_string(struct fdt_header *fdt, int newlen) +{ + void *blob = fdt; + void *p = blob + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); + int err; + + if ((err = _blob_splice(fdt, p, 0, newlen))) + return err; + + fdt->size_dt_strings = cpu_to_fdt32(fdt_size_dt_strings(fdt) + newlen); + return 0; +} + +static int _find_add_string(struct fdt_header *fdt, const char *s) +{ + char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); + const char *p; + char *new; + int len = strlen(s) + 1; + int err; + + p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); + if (p) + /* found it */ + return (p - strtab); + + new = strtab + fdt_size_dt_strings(fdt); + err = _blob_splice_string(fdt, len); + if (err) + return -err; + + memcpy(new, s, len); + return (new - strtab); +} + +static struct fdt_property *_resize_property(struct fdt_header *fdt, int nodeoffset, + const char *name, int len) +{ + struct fdt_property *prop; + int oldlen; + int err; + + prop = _fdt_getprop(fdt, nodeoffset, name, &oldlen); + if ((err = fdt_ptr_error(prop))) + return PTR_ERROR(err); + + if ((err = _blob_splice_struct(fdt, prop->data, + ALIGN(oldlen, FDT_TAGSIZE), + ALIGN(len, FDT_TAGSIZE)))) + return PTR_ERROR(err); + + prop->len = cpu_to_fdt32(len); + return prop; +} + +static struct fdt_property *_add_property(struct fdt_header *fdt, int nodeoffset, + const char *name, int len) +{ + uint32_t tag; + struct fdt_property *prop; + int proplen; + int nextoffset; + int namestroff; + int err; + + tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); + if (tag != FDT_BEGIN_NODE) + return PTR_ERROR(FDT_ERR_BADOFFSET); + + namestroff = _find_add_string(fdt, name); + if (namestroff < 0) + return PTR_ERROR(-namestroff); + + prop = fdt_offset_ptr(fdt, nextoffset, 0); + if ((err = fdt_ptr_error(prop))) + return PTR_ERROR(err); + + proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE); + + err = _blob_splice_struct(fdt, prop, 0, proplen); + if (err) + return PTR_ERROR(err); + + prop->tag = cpu_to_fdt32(FDT_PROP); + prop->nameoff = cpu_to_fdt32(namestroff); + prop->len = cpu_to_fdt32(len); + return prop; +} + +int fdt_setprop(struct fdt_header *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + struct fdt_property *prop; + int err; + + if ((err = rw_check_header(fdt))) + return err; + + prop = _resize_property(fdt, nodeoffset, name, len); + err = fdt_ptr_error(prop); + if (err == FDT_ERR_NOTFOUND) { + prop = _add_property(fdt, nodeoffset, name, len); + err = fdt_ptr_error(prop); + } + if (err) + return err; + + memcpy(prop->data, val, len); + return 0; +} + +int fdt_delprop(struct fdt_header *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len, proplen; + int err; + + RW_OFFSET_CHECK_HEADER(fdt); + + prop = _fdt_getprop(fdt, nodeoffset, name, &len); + if ((err = fdt_ptr_error(prop))) + return err; + + proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE); + return _blob_splice_struct(fdt, prop, proplen, 0); +} + +int fdt_add_subnode_namelen(struct fdt_header *fdt, int parentoffset, + const char *name, int namelen) +{ + struct fdt_node_header *nh; + int offset, nextoffset; + int nodelen; + int err; + uint32_t tag; + uint32_t *endtag; + + RW_OFFSET_CHECK_HEADER(fdt); + + offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); + if ((err = fdt_offset_error(offset)) == 0) + return OFFSET_ERROR(FDT_ERR_EXISTS); + else if (err != FDT_ERR_NOTFOUND) + return OFFSET_ERROR(err); + + /* Try to place the new node after the parent's properties */ + _fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ + do { + offset = nextoffset; + tag = _fdt_next_tag(fdt, offset, &nextoffset); + } while (tag == FDT_PROP); + + nh = fdt_offset_ptr(fdt, offset, 0); + if ((err = fdt_ptr_error(nh))) + return OFFSET_ERROR(err); + + nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE; + err = _blob_splice_struct(fdt, nh, 0, nodelen); + if (err) + return OFFSET_ERROR(err); + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memset(nh->name, 0, ALIGN(namelen+1, FDT_TAGSIZE)); + memcpy(nh->name, name, namelen); + endtag = (uint32_t *)((void *)nh + nodelen - FDT_TAGSIZE); + *endtag = cpu_to_fdt32(FDT_END_NODE); + + return offset; +} + +int fdt_add_subnode(struct fdt_header *fdt, int parentoffset, const char *name) +{ + return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); +} + +int fdt_del_node(struct fdt_header *fdt, int nodeoffset) +{ + struct fdt_node_header *nh; + int endoffset; + int err; + + endoffset = _fdt_node_end_offset(fdt, nodeoffset); + if ((err = fdt_offset_error(endoffset))) + return err; + + nh = fdt_offset_ptr(fdt, nodeoffset, 0); + if ((err = fdt_ptr_error(nh))) + return err; + + return _blob_splice_struct(fdt, nh, endoffset - nodeoffset, 0); +} + +struct fdt_header *fdt_open_into(struct fdt_header *fdt, void *buf, int bufsize) +{ + int err; + + fdt = fdt_move(fdt, buf, bufsize); + if ((err = fdt_ptr_error(fdt))) + return PTR_ERROR(err); + + fdt->totalsize = cpu_to_fdt32(bufsize); + + /* FIXME: re-order if necessary */ + + err = rw_check_header(fdt); + if (err) + return PTR_ERROR(err); + + return fdt; +} + +struct fdt_header *fdt_pack(struct fdt_header *fdt) +{ + int err; + + err = rw_check_header(fdt); + if (err) + return PTR_ERROR(err); + + /* FIXME: pack components */ + + fdt->totalsize = cpu_to_fdt32(_blob_data_size(fdt)); + return fdt; +} diff --git a/fdt_wip.c b/fdt_wip.c index c8d07b3..8d68a96 100644 --- a/fdt_wip.c +++ b/fdt_wip.c @@ -64,26 +64,22 @@ int fdt_nop_property(struct fdt_header *fdt, int nodeoffset, const char *name) return 0; } -int fdt_nop_node(struct fdt_header *fdt, int nodeoffset) +int _fdt_node_end_offset(struct fdt_header *fdt, int nodeoffset) { int level = 0; - int err = 0; uint32_t tag; int offset, nextoffset; tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); if (tag != FDT_BEGIN_NODE) return FDT_ERR_BADOFFSET; - do { offset = nextoffset; tag = _fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_END: - level = -1; - err = FDT_ERR_TRUNCATED; - break; + return offset; case FDT_BEGIN_NODE: level++; @@ -102,7 +98,18 @@ int fdt_nop_node(struct fdt_header *fdt, int nodeoffset) } } while (level >= 0); - nop_region(fdt_offset_ptr(fdt, nodeoffset, 0), nextoffset - nodeoffset); - - return err; + return nextoffset; +} + +int fdt_nop_node(struct fdt_header *fdt, int nodeoffset) +{ + int endoffset; + int err; + + endoffset = _fdt_node_end_offset(fdt, nodeoffset); + if ((err = fdt_offset_error(endoffset))) + return err; + + nop_region(fdt_offset_ptr(fdt, nodeoffset, 0), endoffset - nodeoffset); + return 0; } diff --git a/libfdt.h b/libfdt.h index a3da19c..3872eea 100644 --- a/libfdt.h +++ b/libfdt.h @@ -40,8 +40,10 @@ #define FDT_ERR_BADSTATE 11 #define FDT_ERR_SIZE_MISMATCH 12 #define FDT_ERR_INTERNAL 13 +#define FDT_ERR_BADLAYOUT 14 +#define FDT_ERR_EXISTS 15 -#define FDT_ERR_MAX 13 +#define FDT_ERR_MAX 14 #define fdt_magic(fdt) (fdt32_to_cpu(fdt)->magic) #define fdt_totalsize(fdt) (fdt32_to_cpu(fdt)->totalsize) @@ -111,13 +113,23 @@ int fdt_property(struct fdt_header *fdt, const char *name, const void *val, int int fdt_end_node(struct fdt_header *fdt); int fdt_finish(struct fdt_header *fdt); -#if 0 /* Read-write functions */ -struct fdt_header *fdt_open(struct fdt_header *fdt, int bufsize); -int fdt_add_subnode(struct fdt_header *fdtx, void *node, const char *name); -int fdt_set_property(struct fdt_header *fdtx, void *node, const char *name, - const void *val, int len); -int fdt_del_property(struct fdt_header *fdtx, void *node, const char *name); -#endif +struct fdt_header *fdt_open_into(struct fdt_header *fdt, void *buf, int bufsize); +struct fdt_header *fdt_pack(struct fdt_header *fdt); + +int fdt_setprop(struct fdt_header *fdt, int nodeoffset, const char *name, + const void *val, int len); +#define fdt_setprop_typed(fdt, nodeoffset, name, val) \ + ({ \ + typeof(val) x = (val); \ + fdt_setprop((fdt), (nodeoffset), (name), &x, sizeof(x)); \ + }) +#define fdt_setprop_string(fdt, nodeoffset, name, str) \ + fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) +int fdt_delprop(struct fdt_header *fdt, int nodeoffset, const char *name); +int fdt_add_subnode_namelen(struct fdt_header *fdt, int parentoffset, + const char *name, int namelen); +int fdt_add_subnode(struct fdt_header *fdt, int parentoffset, const char *name); +int fdt_del_node(struct fdt_header *fdt, int nodeoffset); #endif /* _LIBFDT_H */ diff --git a/libfdt_internal.h b/libfdt_internal.h index 67ef91d..0d3e0a5 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -26,11 +26,19 @@ #define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) #define streq(p, q) (strcmp((p), (q)) == 0) +static inline int _ptr_offset(struct fdt_header *fdt, void *p) +{ + void *blob = fdt; + + return (p - blob) - fdt_off_dt_struct(fdt); +} + int _fdt_check_header(const struct fdt_header *fdt); uint32_t _fdt_next_tag(const struct fdt_header *fdt, int startoffset, int *nextoffset); struct fdt_property *_fdt_getprop(const struct fdt_header *fdt, int nodeoffset, const char *name, int *lenp); const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); +int _fdt_node_end_offset(struct fdt_header *fdt, int nodeoffset); #define OFFSET_ERROR(code) -(code) #define PTR_ERROR(code) (void *)(-(code)) diff --git a/tests/Makefile b/tests/Makefile index b430a68..c9271a7 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -4,7 +4,8 @@ LIB_TESTS = root_node property_offset subnode_offset path_offset getprop \ notfound \ setprop_inplace nop_property nop_node \ sw_tree1 \ - move_and_save + move_and_save \ + open_pack rw_tree1 setprop del_property del_node TESTS = $(LIB_TESTS) UTILS = dumptrees diff --git a/tests/del_node.c b/tests/del_node.c new file mode 100644 index 0000000..71d6831 --- /dev/null +++ b/tests/del_node.c @@ -0,0 +1,114 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_nop_node() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt; + int subnode1_offset, subnode2_offset, subsubnode2_offset; + int err; + int oldsize, delsize, newsize; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + oldsize = fdt_totalsize(fdt); + + subnode1_offset = fdt_path_offset(fdt, "/subnode1"); + if ((err = fdt_offset_error(subnode1_offset))) + FAIL("Couldn't find \"/subnode1\": %s", fdt_strerror(err)); + check_getprop_typed(fdt, subnode1_offset, "prop-int", TEST_VALUE_1); + + subnode2_offset = fdt_path_offset(fdt, "/subnode2"); + if ((err = fdt_offset_error(subnode2_offset))) + FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(err)); + check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); + + subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + if ((err = fdt_offset_error(subsubnode2_offset))) + FAIL("Couldn't find \"/subnode2/subsubnode\": %s", + fdt_strerror(err)); + check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); + + err = fdt_del_node(fdt, subnode1_offset); + if (err) + FAIL("fdt_del_node(subnode1): %s", fdt_strerror(err)); + + subnode1_offset = fdt_path_offset(fdt, "/subnode1"); + if ((err = fdt_offset_error(subnode1_offset)) != FDT_ERR_NOTFOUND) + FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"", + fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + + subnode2_offset = fdt_path_offset(fdt, "/subnode2"); + if ((err = fdt_offset_error(subnode2_offset))) + FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(err)); + check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); + + subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + if ((err = fdt_offset_error(subsubnode2_offset))) + FAIL("Couldn't find \"/subnode2/subsubnode\": %s", + fdt_strerror(err)); + check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); + + err = fdt_del_node(fdt, subnode2_offset); + if (err) + FAIL("fdt_del_node(subnode2): %s", fdt_strerror(err)); + + subnode1_offset = fdt_path_offset(fdt, "/subnode1"); + if ((err = fdt_offset_error(subnode1_offset)) != FDT_ERR_NOTFOUND) + FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"", + fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + + subnode2_offset = fdt_path_offset(fdt, "/subnode2"); + if ((err = fdt_offset_error(subnode2_offset)) != FDT_ERR_NOTFOUND) + FAIL("fdt_path_offset(subnode2) returned \"%s\" instead of \"%s\"", + fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + + subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + if ((err = fdt_offset_error(subsubnode2_offset)) != FDT_ERR_NOTFOUND) + FAIL("fdt_path_offset(subsubnode2) returned \"%s\" instead of \"%s\"", + fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + + delsize = fdt_totalsize(fdt); + + fdt = fdt_pack(fdt); + if ((err = fdt_ptr_error(fdt))) + FAIL("fdt_pack(): %s", fdt_strerror(err)); + + newsize = fdt_totalsize(fdt); + + verbose_printf("oldsize = %d, delsize = %d, newsize = %d\n", + oldsize, delsize, newsize); + + if (newsize >= oldsize) + FAIL("Tree failed to shrink after deletions"); + + PASS(); +} diff --git a/tests/del_property.c b/tests/del_property.c new file mode 100644 index 0000000..94bf47a --- /dev/null +++ b/tests/del_property.c @@ -0,0 +1,88 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_delprop() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt; + uint32_t *intp; + char *strp; + int err; + int oldsize, delsize, newsize; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + oldsize = fdt_totalsize(fdt); + + intp = check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); + verbose_printf("int value was 0x%08x\n", *intp); + + err = fdt_delprop(fdt, 0, "prop-int"); + if (err) + FAIL("Failed to delete \"prop-int\": %s", fdt_strerror(err)); + + intp = fdt_getprop(fdt, 0, "prop-int", NULL); + err = fdt_ptr_error(intp); + if (! err) + FAIL("prop-int still present after deletion"); + if (err != FDT_ERR_NOTFOUND) + FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); + + strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, + TEST_STRING_1); + verbose_printf("string value was \"%s\"\n", strp); + err = fdt_delprop(fdt, 0, "prop-str"); + if (err) + FAIL("Failed to delete \"prop-str\": %s", fdt_strerror(err)); + + strp = fdt_getprop(fdt, 0, "prop-str", NULL); + err = fdt_ptr_error(strp); + if (! err) + FAIL("prop-str still present after deletion"); + if (err != FDT_ERR_NOTFOUND) + FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); + + delsize = fdt_totalsize(fdt); + + fdt = fdt_pack(fdt); + if ((err = fdt_ptr_error(fdt))) + FAIL("fdt_pack(): %s\n", fdt_strerror(err)); + + newsize = fdt_totalsize(fdt); + + verbose_printf("oldsize = %d, delsize = %d, newsize = %d\n", + oldsize, delsize, newsize); + + if (newsize >= oldsize) + FAIL("Tree failed to shrink after deletions"); + + PASS(); +} diff --git a/tests/open_pack.c b/tests/open_pack.c new file mode 100644 index 0000000..c651694 --- /dev/null +++ b/tests/open_pack.c @@ -0,0 +1,68 @@ +/* + * libfdt - Flat Device Tree manipulation + * Basic testcase for read-only access + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt, *fdt1, *fdt2; + void *buf; + int oldsize, bufsize, packsize; + int err; + const char *inname; + char outname[PATH_MAX]; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + inname = argv[1]; + + oldsize = fdt_totalsize(fdt); + + bufsize = oldsize * 2; + + buf = xmalloc(bufsize); + + fdt1 = fdt_open_into(fdt, buf, bufsize); + if ((err = fdt_ptr_error(fdt1))) + FAIL("fdt_open_into(): %s", fdt_strerror(err)); + sprintf(outname, "opened.%s", inname); + save_blob(outname, fdt1); + + fdt2 = fdt_pack(fdt1); + if ((err = fdt_ptr_error(fdt2))) + FAIL("fdt_pack(): %s", fdt_strerror(err)); + sprintf(outname, "repacked.%s", inname); + save_blob(outname, fdt2); + + packsize = fdt_totalsize(fdt2); + + verbose_printf("oldsize = %d, bufsize = %d, packsize = %d\n", + oldsize, bufsize, packsize); + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index fba7413..1e2da40 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -45,6 +45,19 @@ functional_tests () { tree1_tests shunted.$tree tree1_tests deshunted.$tree done + + # Read-write tests + for tree in test_tree1.dtb sw_tree1.test.dtb; do + rm -f opened.$tree repacked.$tree + run_test open_pack $tree + tree1_tests opened.$tree + tree1_tests repacked.$tree + done + run_test setprop test_tree1.dtb + run_test del_property test_tree1.dtb + run_test del_node test_tree1.dtb + run_test rw_tree1 + tree1_tests rw_tree1.test.dtb } stress_tests () { diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c new file mode 100644 index 0000000..8c5582a --- /dev/null +++ b/tests/rw_tree1.c @@ -0,0 +1,98 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_nop_node() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +#define SPACE 65536 + +#define CHECK(code) \ + { \ + err = (code); \ + if (err) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } + +#define PTR_CHECK(ptr, code) \ + { \ + err = fdt_ptr_error((ptr) = (code)); \ + if (err) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } + +#define OFF_CHECK(off, code) \ + { \ + err = fdt_offset_error((off) = (code)); \ + if (err) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } + +int main(int argc, char *argv[]) +{ + void *buf; + struct fdt_header *fdt; + int err; + int offset; + + test_init(argc, argv); + + buf = xmalloc(SPACE); + + /* First create empty tree with SW */ + fdt = fdt_create(buf, SPACE); + + CHECK(fdt_finish_reservemap(fdt)); + CHECK(fdt_begin_node(fdt, "")); + CHECK(fdt_end_node(fdt)); + CHECK(fdt_finish(fdt)); + + verbose_printf("Built empty tree, totalsize = %d\n", + fdt32_to_cpu(fdt->totalsize)); + + PTR_CHECK(fdt, fdt_open_into(fdt, buf, SPACE)); + + CHECK(fdt_setprop_typed(fdt, 0, "prop-int", TEST_VALUE_1)); + CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1)); + + OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode1")); + CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_1)); + OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode")); + CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_1)); + + OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode2")); + CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_2)); + OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode")); + + CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_2)); + + PTR_CHECK(fdt, fdt_pack(fdt)); + + save_blob("rw_tree1.test.dtb", fdt); + + PASS(); +} diff --git a/tests/setprop.c b/tests/setprop.c new file mode 100644 index 0000000..3df854d --- /dev/null +++ b/tests/setprop.c @@ -0,0 +1,75 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_setprop() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +#define SPACE 65536 +#define NEW_STRING "here is quite a long test string, blah blah blah" + +int main(int argc, char *argv[]) +{ + struct fdt_header *fdt; + void *buf; + uint32_t *intp; + char *strp; + int err; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + buf = xmalloc(SPACE); + + fdt = fdt_open_into(fdt, buf, SPACE); + if ((err = fdt_ptr_error(fdt))) + FAIL("fdt_open_into(): %s", fdt_strerror(err)); + + intp = check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); + + verbose_printf("Old int value was 0x%08x\n", *intp); + err = fdt_setprop_string(fdt, 0, "prop-int", NEW_STRING); + if (err) + FAIL("Failed to set \"prop-int\" to \"%s\": %s", + NEW_STRING, fdt_strerror(err)); + + strp = check_getprop_string(fdt, 0, "prop-int", NEW_STRING); + verbose_printf("New value is \"%s\"\n", strp); + + strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, + TEST_STRING_1); + + verbose_printf("Old string value was \"%s\"\n", strp); + err = fdt_setprop(fdt, 0, "prop-str", NULL, 0); + if (err) + FAIL("Failed to empty \"prop-str\": %s", + fdt_strerror(err)); + + check_getprop(fdt, 0, "prop-str", 0, NULL); + + PASS(); +} diff --git a/tests/tests.h b/tests/tests.h index 732e6a4..a673b61 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -125,6 +125,8 @@ void *check_getprop(struct fdt_header *fdt, int nodeoffset, const char *name, typeof(val) x = val; \ check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \ }) +#define check_getprop_string(fdt, nodeoffset, name, s) \ + check_getprop((fdt), (nodeoffset), (name), strlen(s)+1, (s)) //void *load_blob(const char *filename); void *load_blob_arg(int argc, char *argv[]); void save_blob(const char *filename, struct fdt_header *fdt); From 81bdd52c0757332984f84b690abcb7ed79c45e19 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 4 Dec 2006 11:17:32 +1100 Subject: [PATCH 0021/1198] libfdt: Add dtb files to .gitignore Ignores .dtb files in the tests subdirectory. --- tests/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/.gitignore b/tests/.gitignore index e69de29..b60ed20 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -0,0 +1 @@ +*.dtb From e25487db34c3abc9310c5be4cbb16f8999cc70a9 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 4 Dec 2006 12:52:45 +1100 Subject: [PATCH 0022/1198] libfdt: Fix libfdt for little endian hosts This patch fixes a number of embarrasing oversights which meant libfdt did not work correctly on little endian machines. With this patch the testsuite now passes on x86. Device trees are always created big-endian. --- fdt_wip.c | 2 +- libfdt.h | 20 +++++++++--------- tests/root_node.c | 2 +- tests/trees.S | 53 +++++++++++++++++++++++++++++++---------------- 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/fdt_wip.c b/fdt_wip.c index 8d68a96..6e617ba 100644 --- a/fdt_wip.c +++ b/fdt_wip.c @@ -46,7 +46,7 @@ static void nop_region(void *start, int len) uint32_t *p; for (p = start; (void *)p < (start + len); p++) - *p = FDT_NOP; + *p = cpu_to_fdt32(FDT_NOP); } int fdt_nop_property(struct fdt_header *fdt, int nodeoffset, const char *name) diff --git a/libfdt.h b/libfdt.h index 3872eea..8216655 100644 --- a/libfdt.h +++ b/libfdt.h @@ -45,16 +45,16 @@ #define FDT_ERR_MAX 14 -#define fdt_magic(fdt) (fdt32_to_cpu(fdt)->magic) -#define fdt_totalsize(fdt) (fdt32_to_cpu(fdt)->totalsize) -#define fdt_off_dt_struct(fdt) (fdt32_to_cpu(fdt)->off_dt_struct) -#define fdt_off_dt_strings(fdt) (fdt32_to_cpu(fdt)->off_dt_strings) -#define fdt_off_mem_rsvmap(fdt) (fdt32_to_cpu(fdt)->off_mem_rsvmap) -#define fdt_version(fdt) (fdt32_to_cpu(fdt)->version) -#define fdt_last_comp_version(fdt) (fdt32_to_cpu(fdt)->last_comp_version) -#define fdt_boot_cpuid_phys(fdt) (fdt32_to_cpu(fdt)->boot_cpuid_phys) -#define fdt_size_dt_strings(fdt) (fdt32_to_cpu(fdt)->size_dt_strings) -#define fdt_size_dt_struct(fdt) (fdt32_to_cpu(fdt)->size_dt_struct) +#define fdt_magic(fdt) (fdt32_to_cpu(fdt->magic)) +#define fdt_totalsize(fdt) (fdt32_to_cpu(fdt->totalsize)) +#define fdt_off_dt_struct(fdt) (fdt32_to_cpu(fdt->off_dt_struct)) +#define fdt_off_dt_strings(fdt) (fdt32_to_cpu(fdt->off_dt_strings)) +#define fdt_off_mem_rsvmap(fdt) (fdt32_to_cpu(fdt->off_mem_rsvmap)) +#define fdt_version(fdt) (fdt32_to_cpu(fdt->version)) +#define fdt_last_comp_version(fdt) (fdt32_to_cpu(fdt->last_comp_version)) +#define fdt_boot_cpuid_phys(fdt) (fdt32_to_cpu(fdt->boot_cpuid_phys)) +#define fdt_size_dt_strings(fdt) (fdt32_to_cpu(fdt->size_dt_strings)) +#define fdt_size_dt_struct(fdt) (fdt32_to_cpu(fdt->size_dt_struct)) void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int checklen); diff --git a/tests/root_node.c b/tests/root_node.c index ecd1cb1..d331bdf 100644 --- a/tests/root_node.c +++ b/tests/root_node.c @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) if (! nh) FAIL("NULL retrieving root node"); - if (nh->tag != FDT_BEGIN_NODE) + if (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE) FAIL("Wrong tag on root node"); if (strlen(nh->name) != 0) diff --git a/tests/trees.S b/tests/trees.S index 7fa4e65..ca8e145 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -1,32 +1,49 @@ #include #include "testdata.h" +#define FDTLONG(val) \ + .byte ((val) >> 24) & 0xff ; \ + .byte ((val) >> 16) & 0xff ; \ + .byte ((val) >> 8) & 0xff ; \ + .byte (val) & 0xff + +#define FDTQUAD(val) \ + .byte ((val) >> 56) & 0xff ; \ + .byte ((val) >> 48) & 0xff ; \ + .byte ((val) >> 40) & 0xff ; \ + .byte ((val) >> 32) & 0xff ; \ + .byte ((val) >> 24) & 0xff ; \ + .byte ((val) >> 16) & 0xff ; \ + .byte ((val) >> 8) & 0xff ; \ + .byte (val) & 0xff + #define TREE_HDR(tree) \ .globl _##tree ; \ _##tree: \ tree: \ - .long FDT_MAGIC ; \ - .long tree##_end - tree ; \ - .long tree##_struct - tree ; \ - .long tree##_strings - tree ; \ - .long tree##_rsvmap - tree ; \ - .long 0x11 ; \ - .long 0x10 ; \ - .long 0 ; \ - .long tree##_end - tree##_strings ; \ - .long tree##_strings - tree##_struct ; + 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##_end - tree##_strings) ; \ + FDTLONG(tree##_strings - tree##_struct) ; #define RSVMAP_ENTRY(addr, len) \ - .quad addr ; \ - .quad len ; + FDTQUAD(addr) ; \ + FDTQUAD(len) ; #define PROPHDR(tree, name, len) \ - .long FDT_PROP ; \ - .long tree##_##name - tree##_strings ; \ - .long len ; + FDTLONG(FDT_PROP) ; \ + FDTLONG(tree##_##name - tree##_strings) ; \ + FDTLONG(len) ; #define PROP_INT(tree, name, val) \ PROPHDR(tree, name, 4) \ + /* For ease of testing the property values go in native-endian */ \ .long val #define PROP_STR(tree, name, str) \ @@ -37,12 +54,12 @@ tree: \ .balign 4 #define BEGIN_NODE(name) \ - .long FDT_BEGIN_NODE ; \ + FDTLONG(FDT_BEGIN_NODE) ; \ .string name ; \ .balign 4 #define END_NODE \ - .long FDT_END_NODE ; + FDTLONG(FDT_END_NODE) ; #define STRING(tree, name, str) \ tree##_##name: \ @@ -77,7 +94,7 @@ test_tree1_struct: END_NODE END_NODE - .long FDT_END + FDTLONG(FDT_END) test_tree1_strings: STRING(test_tree1, prop_int, "prop-int") From 1a765f51a41f51c7c194b6872a6d46f9dd5413f8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 7 Dec 2006 15:24:26 +1100 Subject: [PATCH 0023/1198] libfdt: Fixups for 64-bit machines The error encoding for pointers is incorrect on machines where sizeof(int) != sizeof(void *), which includes most 64-bit platforms (in particular, AMD64 and powerpc64). This patch fixes it. --- libfdt_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt_internal.h b/libfdt_internal.h index 0d3e0a5..7dfa8df 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -41,7 +41,7 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); int _fdt_node_end_offset(struct fdt_header *fdt, int nodeoffset); #define OFFSET_ERROR(code) -(code) -#define PTR_ERROR(code) (void *)(-(code)) +#define PTR_ERROR(code) (void *)(-(long)(code)) #define SW_MAGIC (~FDT_MAGIC) From 95393db96f4a14de21ff32e12bfe905d53d1566f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 11 Dec 2006 11:02:59 +1100 Subject: [PATCH 0024/1198] dtc: Remove verbose message from get_node_phandle() get_node_phandle() had a leftover debugging printf(), which could muddy dtc's output when checking trees. This patch removes it. --- livetree.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/livetree.c b/livetree.c index f64de01..72d194a 100644 --- a/livetree.c +++ b/livetree.c @@ -647,9 +647,6 @@ static cell_t get_node_phandle(struct node *root, struct node *node) { static cell_t phandle = 1; /* FIXME: ick, static local */ - fprintf(stderr, "get_node_phandle(%s) phandle=%x\n", - node->fullpath, node->phandle); - if ((node->phandle != 0) && (node->phandle != -1)) return node->phandle; From 94993f4fc47704666f4d5906d58780e01070f767 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 11 Dec 2006 16:15:34 +1100 Subject: [PATCH 0025/1198] libfdt: Abolish fdt_property_offset() fdt_property_offset() is the only function in the library returning a direct offset to a property, and no function takes such an offset (they only take offsets to nodes, not properties). Furthermore the only client uses for this function I can think of involve immediately translating the offset into a pointer, effectively duplicating the internal function _fdt_getprop() This function abolishes fdt_property_offset(), replacing it with fdt_get_property(), a renamed and now externally visible version of _fdt_getprop(). --- fdt_ro.c | 150 +++++++++---------- fdt_rw.c | 4 +- fdt_wip.c | 2 +- libfdt.h | 5 +- libfdt_internal.h | 2 - tests/Makefile | 2 +- tests/{property_offset.c => find_property.c} | 0 tests/notfound.c | 7 +- tests/run_tests.sh | 2 +- tests/testutils.c | 10 +- 10 files changed, 84 insertions(+), 100 deletions(-) rename tests/{property_offset.c => find_property.c} (100%) diff --git a/fdt_ro.c b/fdt_ro.c index bbc380a..bd58227 100644 --- a/fdt_ro.c +++ b/fdt_ro.c @@ -30,6 +30,13 @@ return OFFSET_ERROR(err); \ } +#define PTR_CHECK_HEADER(fdt) \ + { \ + int err; \ + if ((err = _fdt_check_header(fdt)) != 0) \ + return PTR_ERROR(err); \ + } + static int offset_streq(const struct fdt_header *fdt, int offset, const char *s, int len) { @@ -53,66 +60,6 @@ char *fdt_string(const struct fdt_header *fdt, int stroffset) return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset; } -int fdt_property_offset(const struct fdt_header *fdt, int nodeoffset, - const char *name) -{ - int level = 0; - uint32_t tag; - struct fdt_property *prop; - int namestroff; - int offset, nextoffset; - - OFFSET_CHECK_HEADER(fdt); - - if (nodeoffset % FDT_TAGSIZE) - return OFFSET_ERROR(FDT_ERR_BADOFFSET); - - tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); - if (tag != FDT_BEGIN_NODE) - return OFFSET_ERROR(FDT_ERR_BADOFFSET); - - do { - offset = nextoffset; - if (offset % FDT_TAGSIZE) - return OFFSET_ERROR(FDT_ERR_INTERNAL); - - tag = _fdt_next_tag(fdt, offset, &nextoffset); - switch (tag) { - case FDT_END: - return OFFSET_ERROR(FDT_ERR_TRUNCATED); - - case FDT_BEGIN_NODE: - level++; - break; - - case FDT_END_NODE: - level--; - break; - - case FDT_PROP: - if (level != 0) - continue; - - prop = fdt_offset_ptr_typed(fdt, offset, prop); - if (! prop) - return OFFSET_ERROR(FDT_ERR_BADSTRUCTURE); - namestroff = fdt32_to_cpu(prop->nameoff); - if (streq(fdt_string(fdt, namestroff), name)) - /* Found it! */ - return offset; - break; - - case FDT_NOP: - break; - - default: - return OFFSET_ERROR(FDT_ERR_BADSTRUCTURE); - } - } while (level >= 0); - - return OFFSET_ERROR(FDT_ERR_NOTFOUND); -} - int fdt_subnode_offset_namelen(const struct fdt_header *fdt, int parentoffset, const char *name, int namelen) { @@ -197,30 +144,75 @@ int fdt_path_offset(const struct fdt_header *fdt, const char *path) return offset; } -struct fdt_property *_fdt_getprop(const struct fdt_header *fdt, int nodeoffset, - const char *name, int *lenp) +struct fdt_property *fdt_get_property(const struct fdt_header *fdt, + int nodeoffset, + const char *name, int *lenp) { - int propoffset; + int level = 0; + uint32_t tag; struct fdt_property *prop; - int err; - int len; + int namestroff; + int offset, nextoffset; - propoffset = fdt_property_offset(fdt, nodeoffset, name); - if ((err = fdt_offset_error(propoffset))) - return PTR_ERROR(err); + PTR_CHECK_HEADER(fdt); - prop = fdt_offset_ptr(fdt, propoffset, sizeof(prop)); - if (! prop) - return PTR_ERROR(FDT_ERR_BADSTRUCTURE); - len = fdt32_to_cpu(prop->len); - prop = fdt_offset_ptr(fdt, propoffset, sizeof(prop) + len); - if (! prop) - return PTR_ERROR(FDT_ERR_BADSTRUCTURE); + if (nodeoffset % FDT_TAGSIZE) + return PTR_ERROR(FDT_ERR_BADOFFSET); - if (lenp) - *lenp = len; + tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); + if (tag != FDT_BEGIN_NODE) + return PTR_ERROR(FDT_ERR_BADOFFSET); - return prop; + do { + offset = nextoffset; + if (offset % FDT_TAGSIZE) + return PTR_ERROR(FDT_ERR_INTERNAL); + + tag = _fdt_next_tag(fdt, offset, &nextoffset); + switch (tag) { + case FDT_END: + return PTR_ERROR(FDT_ERR_TRUNCATED); + + case FDT_BEGIN_NODE: + level++; + break; + + case FDT_END_NODE: + level--; + break; + + case FDT_PROP: + if (level != 0) + continue; + + prop = fdt_offset_ptr_typed(fdt, offset, prop); + if (! prop) + return PTR_ERROR(FDT_ERR_BADSTRUCTURE); + namestroff = fdt32_to_cpu(prop->nameoff); + if (streq(fdt_string(fdt, namestroff), name)) { + /* Found it! */ + int len = fdt32_to_cpu(prop->len); + prop = fdt_offset_ptr(fdt, offset, + sizeof(prop)+len); + if (! prop) + return PTR_ERROR(FDT_ERR_BADSTRUCTURE); + + if (lenp) + *lenp = len; + + return prop; + } + break; + + case FDT_NOP: + break; + + default: + return PTR_ERROR(FDT_ERR_BADSTRUCTURE); + } + } while (level >= 0); + + return PTR_ERROR(FDT_ERR_NOTFOUND); } void *fdt_getprop(const struct fdt_header *fdt, int nodeoffset, @@ -229,7 +221,7 @@ void *fdt_getprop(const struct fdt_header *fdt, int nodeoffset, const struct fdt_property *prop; int err; - prop = _fdt_getprop(fdt, nodeoffset, name, lenp); + prop = fdt_get_property(fdt, nodeoffset, name, lenp); if ((err = fdt_ptr_error(prop))) return PTR_ERROR(err); diff --git a/fdt_rw.c b/fdt_rw.c index 45f1fa4..5cdb8c1 100644 --- a/fdt_rw.c +++ b/fdt_rw.c @@ -126,7 +126,7 @@ static struct fdt_property *_resize_property(struct fdt_header *fdt, int nodeoff int oldlen; int err; - prop = _fdt_getprop(fdt, nodeoffset, name, &oldlen); + prop = fdt_get_property(fdt, nodeoffset, name, &oldlen); if ((err = fdt_ptr_error(prop))) return PTR_ERROR(err); @@ -203,7 +203,7 @@ int fdt_delprop(struct fdt_header *fdt, int nodeoffset, const char *name) RW_OFFSET_CHECK_HEADER(fdt); - prop = _fdt_getprop(fdt, nodeoffset, name, &len); + prop = fdt_get_property(fdt, nodeoffset, name, &len); if ((err = fdt_ptr_error(prop))) return err; diff --git a/fdt_wip.c b/fdt_wip.c index 6e617ba..fa0df78 100644 --- a/fdt_wip.c +++ b/fdt_wip.c @@ -55,7 +55,7 @@ int fdt_nop_property(struct fdt_header *fdt, int nodeoffset, const char *name) int len; int err; - prop = _fdt_getprop(fdt, nodeoffset, name, &len); + prop = fdt_get_property(fdt, nodeoffset, name, &len); if ((err = fdt_ptr_error(prop))) return err; diff --git a/libfdt.h b/libfdt.h index 8216655..cee2b3c 100644 --- a/libfdt.h +++ b/libfdt.h @@ -72,8 +72,6 @@ struct fdt_header *fdt_move(const struct fdt_header *fdt, void *buf, int bufsize /* Read-only functions */ char *fdt_string(const struct fdt_header *fdt, int stroffset); -int fdt_property_offset(const struct fdt_header *fdt, int nodeoffset, - const char *name); int fdt_subnode_offset_namelen(const struct fdt_header *fdt, int parentoffset, const char *name, int namelen); int fdt_subnode_offset(const struct fdt_header *fdt, int parentoffset, @@ -81,6 +79,9 @@ int fdt_subnode_offset(const struct fdt_header *fdt, int parentoffset, int fdt_path_offset(const struct fdt_header *fdt, const char *path); +struct fdt_property *fdt_get_property(const struct fdt_header *fdt, + int nodeoffset, + const char *name, int *lenp); void *fdt_getprop(const struct fdt_header *fdt, int nodeoffset, const char *name, int *lenp); diff --git a/libfdt_internal.h b/libfdt_internal.h index 7dfa8df..b3da790 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -35,8 +35,6 @@ static inline int _ptr_offset(struct fdt_header *fdt, void *p) int _fdt_check_header(const struct fdt_header *fdt); uint32_t _fdt_next_tag(const struct fdt_header *fdt, int startoffset, int *nextoffset); -struct fdt_property *_fdt_getprop(const struct fdt_header *fdt, int nodeoffset, - const char *name, int *lenp); const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); int _fdt_node_end_offset(struct fdt_header *fdt, int nodeoffset); diff --git a/tests/Makefile b/tests/Makefile index c9271a7..b0c4571 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,6 +1,6 @@ PREFIX = /usr/local -LIB_TESTS = root_node property_offset subnode_offset path_offset getprop \ +LIB_TESTS = root_node find_property subnode_offset path_offset getprop \ notfound \ setprop_inplace nop_property nop_node \ sw_tree1 \ diff --git a/tests/property_offset.c b/tests/find_property.c similarity index 100% rename from tests/property_offset.c rename to tests/find_property.c diff --git a/tests/notfound.c b/tests/notfound.c index 1dd8bc7..9cdc29c 100644 --- a/tests/notfound.c +++ b/tests/notfound.c @@ -36,6 +36,7 @@ void check_error(const char *s, int err) int main(int argc, char *argv[]) { + struct fdt_property *prop; struct fdt_header *fdt; int offset; int subnode1_offset; @@ -45,9 +46,9 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); - offset = fdt_property_offset(fdt, 0, "nonexistant-property"); - check_error("fdt_property_offset(\"nonexistant-property\")", - fdt_offset_error(offset)); + prop = fdt_get_property(fdt, 0, "nonexistant-property", NULL); + check_error("fdt_get_property(\"nonexistant-property\")", + fdt_ptr_error(prop)); val = fdt_getprop(fdt, 0, "nonexistant-property", NULL); check_error("fdt_getprop(\"nonexistant-property\"", diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 1e2da40..c9c9879 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -14,7 +14,7 @@ tree1_tests () { # Read-only tests run_test root_node $TREE - run_test property_offset $TREE + run_test find_property $TREE run_test subnode_offset $TREE run_test path_offset $TREE run_test getprop $TREE diff --git a/tests/testutils.c b/tests/testutils.c index 4997a8e..994cdae 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -106,20 +106,12 @@ const char *fdt_strerror(int errval) void check_property(struct fdt_header *fdt, int nodeoffset, const char *name, int len, const void *val) { - int offset; const struct fdt_property *prop; uint32_t tag, nameoff, proplen; const char *propname; - int err; verbose_printf("Checking property \"%s\"...", name); - offset = fdt_property_offset(fdt, nodeoffset, name); - verbose_printf("offset %d...", offset); - if ((err = fdt_offset_error(offset))) - FAIL("fdt_property_offset(\"%s\"): %s", name, - fdt_strerror(err)); - - prop = fdt_offset_ptr_typed(fdt, offset, prop); + prop = fdt_get_property(fdt, nodeoffset, name, NULL); verbose_printf("pointer %p\n", prop); if (! prop) FAIL("NULL retreiving \"%s\" pointer", name); From 6ae4de5c81eac62a0c658ef302c850da3f107092 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 12 Dec 2006 12:48:15 +1100 Subject: [PATCH 0026/1198] libfdt: Remove unused _ptr_offset() function The (internal use) function _ptr_offset() is never used. Delete it. --- libfdt_internal.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libfdt_internal.h b/libfdt_internal.h index b3da790..8ea1ed0 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -26,13 +26,6 @@ #define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) #define streq(p, q) (strcmp((p), (q)) == 0) -static inline int _ptr_offset(struct fdt_header *fdt, void *p) -{ - void *blob = fdt; - - return (p - blob) - fdt_off_dt_struct(fdt); -} - int _fdt_check_header(const struct fdt_header *fdt); uint32_t _fdt_next_tag(const struct fdt_header *fdt, int startoffset, int *nextoffset); const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); From 9825f823eb5c9fc6b01e40f1b84108f5574235f2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 14 Dec 2006 15:29:25 +1100 Subject: [PATCH 0027/1198] libfdt: Fix bounds-checking bug in fdt_get_property() The libfdt functions are supposed to behave tolerably well when practical, even if given a corrupted device tree as input. A silly mistake in fdt_get_property() means we're bounds checking against the size of a pointer instead of the size of a property header, meaning we can get bogus behaviour in a corrupted device tree where the structure block ends in what's supposed to be the middle of a property. This patch corrects the problem (fdt_get_property() will now return BADSTRUCTURE in this case), and also adds a testcase to catch the bug. --- fdt_ro.c | 2 +- tests/Makefile | 5 +++- tests/run_tests.sh | 3 +++ tests/testdata.h | 1 + tests/trees.S | 14 +++++++++++ tests/truncated_property.c | 49 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 tests/truncated_property.c diff --git a/fdt_ro.c b/fdt_ro.c index bd58227..1b2383c 100644 --- a/fdt_ro.c +++ b/fdt_ro.c @@ -193,7 +193,7 @@ struct fdt_property *fdt_get_property(const struct fdt_header *fdt, /* Found it! */ int len = fdt32_to_cpu(prop->len); prop = fdt_offset_ptr(fdt, offset, - sizeof(prop)+len); + sizeof(*prop)+len); if (! prop) return PTR_ERROR(FDT_ERR_BADSTRUCTURE); diff --git a/tests/Makefile b/tests/Makefile index b0c4571..533c98e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -6,7 +6,8 @@ LIB_TESTS = root_node find_property subnode_offset path_offset getprop \ sw_tree1 \ move_and_save \ open_pack rw_tree1 setprop del_property del_node -TESTS = $(LIB_TESTS) +LIBTREE_TESTS = truncated_property +TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) UTILS = dumptrees TREES = test_tree1.dtb @@ -42,6 +43,8 @@ all: $(TESTS) $(TREES) $(LIB_TESTS): %: testutils.o $(LIBFDT) +$(LIBTREE_TESTS): %: testutils.o trees.o $(LIBFDT) + dumptrees: %: trees.o $(TREES): dumptrees diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c9c9879..f4a5a54 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -58,6 +58,9 @@ functional_tests () { run_test del_node test_tree1.dtb run_test rw_tree1 tree1_tests rw_tree1.test.dtb + + # Tests for behaviour on various sorts of corrupted trees + run_test truncated_property } stress_tests () { diff --git a/tests/testdata.h b/tests/testdata.h index 318b95f..822c69a 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -5,4 +5,5 @@ #ifndef __ASSEMBLY__ extern struct fdt_header _test_tree1; +extern struct fdt_header _truncated_property; #endif /* ! __ASSEMBLY */ diff --git a/tests/trees.S b/tests/trees.S index ca8e145..397c151 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -18,6 +18,7 @@ .byte (val) & 0xff #define TREE_HDR(tree) \ + .balign 4 ; \ .globl _##tree ; \ _##tree: \ tree: \ @@ -100,3 +101,16 @@ test_tree1_strings: STRING(test_tree1, prop_int, "prop-int") STRING(test_tree1, prop_str, "prop-str") test_tree1_end: + + TREE_HDR(truncated_property) +truncated_property_rsvmap: + RSVMAP_ENTRY(0, 0) + +truncated_property_struct: + BEGIN_NODE("") + PROPHDR(truncated_property, prop_truncated, 4) + /* Oops, no actual property data here */ + +truncated_property_strings: + STRING(truncated_property, prop_truncated, "truncated") +truncated_property_end: diff --git a/tests/truncated_property.c b/tests/truncated_property.c new file mode 100644 index 0000000..e678b96 --- /dev/null +++ b/tests/truncated_property.c @@ -0,0 +1,49 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for misbehaviour on a truncated property + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + void *fdt = &_truncated_property; + void *prop; + int err; + int len; + + test_init(argc, argv); + + prop = fdt_getprop(fdt, 0, "truncated", &len); + err = fdt_ptr_error(prop); + if (! err) + FAIL("fdt_getprop() succeeded on truncated property"); + if (err != FDT_ERR_BADSTRUCTURE) + FAIL("fdt_getprop() failed with \"%s\" instead of \"%s\"", + fdt_strerror(err), fdt_strerror(FDT_ERR_BADSTRUCTURE)); + + PASS(); +} From 568b569e8961641587cfda8ec23e64cafe45f6d7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 12 Dec 2006 15:46:14 +1100 Subject: [PATCH 0028/1198] libfdt: Fixup usage of fdt_offset_ptr() in fdt_rw.c Several places in fdt_rw.c incorrectly use fdt_offset_ptr(), using it as if it returned an encoded error code on errors, instead of returning NULL on error as it actually does. In fact, however, in these instances the extra checks in fdt_offset_ptr() are useless anyway, so we introduce a new (internal use) _fdt_offset_ptr() and use that without checking. (cherry picked from 3dffb1808dea6aee6158c92e17faa6ced9b183f2 commit) --- fdt.c | 2 +- fdt_rw.c | 19 +++++-------------- libfdt_internal.h | 5 +++++ 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/fdt.c b/fdt.c index 4271dfd..3b900a8 100644 --- a/fdt.c +++ b/fdt.c @@ -51,7 +51,7 @@ void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int len) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; - p = (void *)fdt + fdt_off_dt_struct(fdt) + offset; + p = _fdt_offset_ptr(fdt, offset); if (p + len < p) return NULL; diff --git a/fdt_rw.c b/fdt_rw.c index 5cdb8c1..8049205 100644 --- a/fdt_rw.c +++ b/fdt_rw.c @@ -157,10 +157,7 @@ static struct fdt_property *_add_property(struct fdt_header *fdt, int nodeoffset if (namestroff < 0) return PTR_ERROR(-namestroff); - prop = fdt_offset_ptr(fdt, nextoffset, 0); - if ((err = fdt_ptr_error(prop))) - return PTR_ERROR(err); - + prop = _fdt_offset_ptr(fdt, nextoffset); proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE); err = _blob_splice_struct(fdt, prop, 0, proplen); @@ -236,11 +233,9 @@ int fdt_add_subnode_namelen(struct fdt_header *fdt, int parentoffset, tag = _fdt_next_tag(fdt, offset, &nextoffset); } while (tag == FDT_PROP); - nh = fdt_offset_ptr(fdt, offset, 0); - if ((err = fdt_ptr_error(nh))) - return OFFSET_ERROR(err); - + nh = _fdt_offset_ptr(fdt, offset); nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE; + err = _blob_splice_struct(fdt, nh, 0, nodelen); if (err) return OFFSET_ERROR(err); @@ -261,7 +256,6 @@ int fdt_add_subnode(struct fdt_header *fdt, int parentoffset, const char *name) int fdt_del_node(struct fdt_header *fdt, int nodeoffset) { - struct fdt_node_header *nh; int endoffset; int err; @@ -269,11 +263,8 @@ int fdt_del_node(struct fdt_header *fdt, int nodeoffset) if ((err = fdt_offset_error(endoffset))) return err; - nh = fdt_offset_ptr(fdt, nodeoffset, 0); - if ((err = fdt_ptr_error(nh))) - return err; - - return _blob_splice_struct(fdt, nh, endoffset - nodeoffset, 0); + return _blob_splice_struct(fdt, _fdt_offset_ptr(fdt, nodeoffset), + endoffset - nodeoffset, 0); } struct fdt_header *fdt_open_into(struct fdt_header *fdt, void *buf, int bufsize) diff --git a/libfdt_internal.h b/libfdt_internal.h index 8ea1ed0..d8c7551 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -31,6 +31,11 @@ uint32_t _fdt_next_tag(const struct fdt_header *fdt, int startoffset, int *nexto const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); int _fdt_node_end_offset(struct fdt_header *fdt, int nodeoffset); +static inline void *_fdt_offset_ptr(const struct fdt_header *fdt, int offset) +{ + return (void *)fdt + fdt_off_dt_struct(fdt) + offset; +} + #define OFFSET_ERROR(code) -(code) #define PTR_ERROR(code) (void *)(-(long)(code)) From 73d60926a05814b8864c86c435e272b386513b0e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 15 Dec 2006 15:12:47 +1100 Subject: [PATCH 0029/1198] libfdt: Use void * to refer to device tree blobs At present, the blob containing a device tree is passed to the various fdt_*() functions as a (struct fdt_header *) i.e. a pointer to the header structure at the beginning of the blob. This patch changes all the functions so that they instead take a (void *) pointing to the blob. Under some circumstances can avoid the need for the caller to cast a blob pointer into a (struct fdt_header *) before passing it to the fdt_*() functions. Using a (void *) also reduce the temptation for users of the library to directly dereference toe (struct fdt_header *) to access header fields. Instead they must use the fdt_get_header() or fdt_set_header() macros, or the fdt_magic(), fdt_totalsize() etc. wrappers around them which are safer, since they will always handle endian conversion. With this change, the whole-tree moving, or manipulating functions: fdt_move(), fdt_open_into() and fdt_pack() no longer need to return a pointer to the "new" tree. The given (void *) buffer pointer they take can instead be used directly by the caller as the new tree. Those functions are thus changed to instead return an error code (which in turn reduces the number of functions using the ugly encoding of error values into pointers). Signed-off-by: David Gibson --- fdt.c | 14 ++++---- fdt_ro.c | 14 ++++---- fdt_rw.c | 67 ++++++++++++++++++----------------- fdt_sw.c | 54 ++++++++++++++--------------- fdt_wip.c | 8 ++--- libfdt.h | 77 +++++++++++++++++++++-------------------- libfdt_internal.h | 6 ++-- tests/del_node.c | 6 ++-- tests/del_property.c | 6 ++-- tests/dumptrees.c | 9 ++--- tests/find_property.c | 2 +- tests/getprop.c | 2 +- tests/move_and_save.c | 17 +++++---- tests/nop_node.c | 2 +- tests/nop_property.c | 2 +- tests/notfound.c | 2 +- tests/open_pack.c | 15 ++++---- tests/path_offset.c | 4 +-- tests/root_node.c | 2 +- tests/rw_tree1.c | 20 ++++------- tests/setprop.c | 8 +++-- tests/setprop_inplace.c | 2 +- tests/subnode_offset.c | 2 +- tests/sw_tree1.c | 9 +++-- tests/tests.h | 6 ++-- tests/testutils.c | 8 ++--- 26 files changed, 182 insertions(+), 182 deletions(-) diff --git a/fdt.c b/fdt.c index 3b900a8..bc3ec22 100644 --- a/fdt.c +++ b/fdt.c @@ -23,7 +23,7 @@ #include "libfdt_internal.h" -int _fdt_check_header(const struct fdt_header *fdt) +int _fdt_check_header(const void *fdt) { if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ @@ -42,7 +42,7 @@ int _fdt_check_header(const struct fdt_header *fdt) return 0; } -void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int len) +void *fdt_offset_ptr(const void *fdt, int offset, int len) { void *p; @@ -58,7 +58,7 @@ void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int len) return p; } -uint32_t _fdt_next_tag(const struct fdt_header *fdt, int offset, int *nextoffset) +uint32_t _fdt_next_tag(const void *fdt, int offset, int *nextoffset) { const uint32_t *tagp, *lenp; uint32_t tag; @@ -109,16 +109,16 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) return NULL; } -struct fdt_header *fdt_move(const struct fdt_header *fdt, void *buf, int bufsize) +int fdt_move(const void *fdt, void *buf, int bufsize) { int err = _fdt_check_header(fdt); if (err) - return PTR_ERROR(err); + return err; if (fdt_totalsize(fdt) > bufsize) - return PTR_ERROR(FDT_ERR_NOSPACE); + return FDT_ERR_NOSPACE; memmove(buf, fdt, fdt_totalsize(fdt)); - return (struct fdt_header *)buf; + return FDT_ERR_OK; } diff --git a/fdt_ro.c b/fdt_ro.c index 1b2383c..b58029a 100644 --- a/fdt_ro.c +++ b/fdt_ro.c @@ -37,7 +37,7 @@ return PTR_ERROR(err); \ } -static int offset_streq(const struct fdt_header *fdt, int offset, +static int offset_streq(const void *fdt, int offset, const char *s, int len) { const char *p = fdt_offset_ptr(fdt, offset, len+1); @@ -55,12 +55,12 @@ static int offset_streq(const struct fdt_header *fdt, int offset, return 1; } -char *fdt_string(const struct fdt_header *fdt, int stroffset) +char *fdt_string(const void *fdt, int stroffset) { return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset; } -int fdt_subnode_offset_namelen(const struct fdt_header *fdt, int parentoffset, +int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, const char *name, int namelen) { int level = 0; @@ -106,13 +106,13 @@ int fdt_subnode_offset_namelen(const struct fdt_header *fdt, int parentoffset, return OFFSET_ERROR(FDT_ERR_NOTFOUND); } -int fdt_subnode_offset(const struct fdt_header *fdt, int parentoffset, +int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name) { return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); } -int fdt_path_offset(const struct fdt_header *fdt, const char *path) +int fdt_path_offset(const void *fdt, const char *path) { const char *end = path + strlen(path); const char *p = path; @@ -144,7 +144,7 @@ int fdt_path_offset(const struct fdt_header *fdt, const char *path) return offset; } -struct fdt_property *fdt_get_property(const struct fdt_header *fdt, +struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, const char *name, int *lenp) { @@ -215,7 +215,7 @@ struct fdt_property *fdt_get_property(const struct fdt_header *fdt, return PTR_ERROR(FDT_ERR_NOTFOUND); } -void *fdt_getprop(const struct fdt_header *fdt, int nodeoffset, +void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp) { const struct fdt_property *prop; diff --git a/fdt_rw.c b/fdt_rw.c index 8049205..4b7d1d5 100644 --- a/fdt_rw.c +++ b/fdt_rw.c @@ -23,7 +23,7 @@ #include "libfdt_internal.h" -static int rw_check_header(struct fdt_header *fdt) +static int rw_check_header(void *fdt) { int err; @@ -31,7 +31,7 @@ static int rw_check_header(struct fdt_header *fdt) return err; if (fdt_version(fdt) < 0x11) return FDT_ERR_BADVERSION; - if (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(*fdt), 8)) + if (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8)) return FDT_ERR_BADLAYOUT; if (fdt_off_dt_struct(fdt) < (fdt_off_mem_rsvmap(fdt) + sizeof(struct fdt_reserve_entry))) @@ -52,25 +52,24 @@ static int rw_check_header(struct fdt_header *fdt) return OFFSET_ERROR(err); \ } -static inline int _blob_data_size(struct fdt_header *fdt) +static inline int _blob_data_size(void *fdt) { return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); } -static int _blob_splice(struct fdt_header *fdt, void *p, int oldlen, int newlen) +static int _blob_splice(void *fdt, void *p, int oldlen, int newlen) { - void *blob = fdt; - void *end = blob + _blob_data_size(fdt); + void *end = fdt + _blob_data_size(fdt); if (((p + oldlen) < p) || ((p + oldlen) > end)) return FDT_ERR_BADOFFSET; - if ((end - oldlen + newlen) > (blob + fdt_totalsize(fdt))) + if ((end - oldlen + newlen) > (fdt + fdt_totalsize(fdt))) return FDT_ERR_NOSPACE; memmove(p + newlen, p + oldlen, end - p - oldlen); return 0; } -static int _blob_splice_struct(struct fdt_header *fdt, void *p, +static int _blob_splice_struct(void *fdt, void *p, int oldlen, int newlen) { int delta = newlen - oldlen; @@ -79,25 +78,24 @@ static int _blob_splice_struct(struct fdt_header *fdt, void *p, if ((err = _blob_splice(fdt, p, oldlen, newlen))) return err; - fdt->size_dt_struct = cpu_to_fdt32(fdt_size_dt_struct(fdt) + delta); - fdt->off_dt_strings = cpu_to_fdt32(fdt_off_dt_strings(fdt) + delta); + fdt_set_header(fdt, size_dt_struct, fdt_size_dt_struct(fdt) + delta); + fdt_set_header(fdt, off_dt_strings, fdt_off_dt_strings(fdt) + delta); return 0; } -static int _blob_splice_string(struct fdt_header *fdt, int newlen) +static int _blob_splice_string(void *fdt, int newlen) { - void *blob = fdt; - void *p = blob + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); + void *p = fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); int err; if ((err = _blob_splice(fdt, p, 0, newlen))) return err; - fdt->size_dt_strings = cpu_to_fdt32(fdt_size_dt_strings(fdt) + newlen); + fdt_set_header(fdt, size_dt_strings, fdt_size_dt_strings(fdt) + newlen); return 0; } -static int _find_add_string(struct fdt_header *fdt, const char *s) +static int _find_add_string(void *fdt, const char *s) { char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); const char *p; @@ -119,7 +117,7 @@ static int _find_add_string(struct fdt_header *fdt, const char *s) return (new - strtab); } -static struct fdt_property *_resize_property(struct fdt_header *fdt, int nodeoffset, +static struct fdt_property *_resize_property(void *fdt, int nodeoffset, const char *name, int len) { struct fdt_property *prop; @@ -139,7 +137,7 @@ static struct fdt_property *_resize_property(struct fdt_header *fdt, int nodeoff return prop; } -static struct fdt_property *_add_property(struct fdt_header *fdt, int nodeoffset, +static struct fdt_property *_add_property(void *fdt, int nodeoffset, const char *name, int len) { uint32_t tag; @@ -170,7 +168,7 @@ static struct fdt_property *_add_property(struct fdt_header *fdt, int nodeoffset return prop; } -int fdt_setprop(struct fdt_header *fdt, int nodeoffset, const char *name, +int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len) { struct fdt_property *prop; @@ -192,7 +190,7 @@ int fdt_setprop(struct fdt_header *fdt, int nodeoffset, const char *name, return 0; } -int fdt_delprop(struct fdt_header *fdt, int nodeoffset, const char *name) +int fdt_delprop(void *fdt, int nodeoffset, const char *name) { struct fdt_property *prop; int len, proplen; @@ -208,7 +206,7 @@ int fdt_delprop(struct fdt_header *fdt, int nodeoffset, const char *name) return _blob_splice_struct(fdt, prop, proplen, 0); } -int fdt_add_subnode_namelen(struct fdt_header *fdt, int parentoffset, +int fdt_add_subnode_namelen(void *fdt, int parentoffset, const char *name, int namelen) { struct fdt_node_header *nh; @@ -249,12 +247,12 @@ int fdt_add_subnode_namelen(struct fdt_header *fdt, int parentoffset, return offset; } -int fdt_add_subnode(struct fdt_header *fdt, int parentoffset, const char *name) +int fdt_add_subnode(void *fdt, int parentoffset, const char *name) { return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); } -int fdt_del_node(struct fdt_header *fdt, int nodeoffset) +int fdt_del_node(void *fdt, int nodeoffset) { int endoffset; int err; @@ -267,35 +265,36 @@ int fdt_del_node(struct fdt_header *fdt, int nodeoffset) endoffset - nodeoffset, 0); } -struct fdt_header *fdt_open_into(struct fdt_header *fdt, void *buf, int bufsize) +int fdt_open_into(void *fdt, void *buf, int bufsize) { int err; - fdt = fdt_move(fdt, buf, bufsize); - if ((err = fdt_ptr_error(fdt))) - return PTR_ERROR(err); + err = fdt_move(fdt, buf, bufsize); + if (err) + return err; - fdt->totalsize = cpu_to_fdt32(bufsize); + fdt = buf; + + fdt_set_header(fdt, totalsize, bufsize); /* FIXME: re-order if necessary */ err = rw_check_header(fdt); if (err) - return PTR_ERROR(err); + return err; - return fdt; + return FDT_ERR_OK; } -struct fdt_header *fdt_pack(struct fdt_header *fdt) +int fdt_pack(void *fdt) { int err; err = rw_check_header(fdt); if (err) - return PTR_ERROR(err); + return err; /* FIXME: pack components */ - - fdt->totalsize = cpu_to_fdt32(_blob_data_size(fdt)); - return fdt; + fdt_set_header(fdt, totalsize, _blob_data_size(fdt)); + return FDT_ERR_OK; } diff --git a/fdt_sw.c b/fdt_sw.c index 1a6b2cf..806b259 100644 --- a/fdt_sw.c +++ b/fdt_sw.c @@ -23,14 +23,14 @@ #include "libfdt_internal.h" -static int check_header_sw(struct fdt_header *fdt) +static int check_header_sw(void *fdt) { if (fdt_magic(fdt) != SW_MAGIC) return FDT_ERR_BADMAGIC; return 0; } -static void *grab_space(struct fdt_header *fdt, int len) +static void *grab_space(void *fdt, int len) { int offset = fdt_size_dt_struct(fdt); int spaceleft; @@ -41,33 +41,33 @@ static void *grab_space(struct fdt_header *fdt, int len) if ((offset + len < offset) || (offset + len > spaceleft)) return NULL; - fdt->size_dt_struct = cpu_to_fdt32(offset + len); + fdt_set_header(fdt, size_dt_struct, offset + len); return fdt_offset_ptr(fdt, offset, len); } -struct fdt_header *fdt_create(void *buf, int bufsize) +int fdt_create(void *buf, int bufsize) { - struct fdt_header *fdt = buf; + void *fdt = buf; if (bufsize < sizeof(struct fdt_header)) - return NULL; + return FDT_ERR_NOSPACE; memset(buf, 0, bufsize); - fdt->magic = cpu_to_fdt32(SW_MAGIC); - fdt->version = cpu_to_fdt32(FDT_LAST_SUPPORTED_VERSION); - fdt->last_comp_version= cpu_to_fdt32(FDT_FIRST_SUPPORTED_VERSION); - fdt->totalsize = cpu_to_fdt32(bufsize); + fdt_set_header(fdt, magic, SW_MAGIC); + fdt_set_header(fdt, version, FDT_LAST_SUPPORTED_VERSION); + fdt_set_header(fdt, last_comp_version, FDT_FIRST_SUPPORTED_VERSION); + fdt_set_header(fdt, totalsize, bufsize); - fdt->off_mem_rsvmap = cpu_to_fdt32(ALIGN(sizeof(*fdt), - sizeof(struct fdt_reserve_entry))); - fdt->off_dt_struct = fdt->off_mem_rsvmap; - fdt->off_dt_strings = fdt32_to_cpu(bufsize); + fdt_set_header(fdt, off_mem_rsvmap, ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry))); + fdt_set_header(fdt, off_dt_struct, fdt_off_mem_rsvmap(fdt)); + fdt_set_header(fdt, off_dt_strings, bufsize); - return fdt; + return FDT_ERR_OK; } -int fdt_add_reservemap_entry(struct fdt_header *fdt, uint64_t addr, uint64_t size) +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) { struct fdt_reserve_entry *re; int err = check_header_sw(fdt); @@ -86,17 +86,17 @@ int fdt_add_reservemap_entry(struct fdt_header *fdt, uint64_t addr, uint64_t siz re->address = cpu_to_fdt64(addr); re->size = cpu_to_fdt64(size); - fdt->off_dt_struct = cpu_to_fdt32(offset + sizeof(*re)); + fdt_set_header(fdt, off_dt_struct, offset + sizeof(*re)); return 0; } -int fdt_finish_reservemap(struct fdt_header *fdt) +int fdt_finish_reservemap(void *fdt) { return fdt_add_reservemap_entry(fdt, 0, 0); } -int fdt_begin_node(struct fdt_header *fdt, const char *name) +int fdt_begin_node(void *fdt, const char *name) { struct fdt_node_header *nh; int err = check_header_sw(fdt); @@ -114,7 +114,7 @@ int fdt_begin_node(struct fdt_header *fdt, const char *name) return 0; } -int fdt_end_node(struct fdt_header *fdt) +int fdt_end_node(void *fdt) { uint32_t *en; int err = check_header_sw(fdt); @@ -130,7 +130,7 @@ int fdt_end_node(struct fdt_header *fdt) return 0; } -static int find_add_string(struct fdt_header *fdt, const char *s) +static int find_add_string(void *fdt, const char *s) { char *strtab = (char *)fdt + fdt_totalsize(fdt); const char *p; @@ -149,11 +149,11 @@ static int find_add_string(struct fdt_header *fdt, const char *s) return 0; /* no more room :( */ memcpy(strtab + offset, s, len); - fdt->size_dt_strings = cpu_to_fdt32(strtabsize + len); + fdt_set_header(fdt, size_dt_strings, strtabsize + len); return offset; } -int fdt_property(struct fdt_header *fdt, const char *name, const void *val, int len) +int fdt_property(void *fdt, const char *name, const void *val, int len) { struct fdt_property *prop; int err = check_header_sw(fdt); @@ -177,7 +177,7 @@ int fdt_property(struct fdt_header *fdt, const char *name, const void *val, int return 0; } -int fdt_finish(struct fdt_header *fdt) +int fdt_finish(void *fdt) { int err = check_header_sw(fdt); char *p = (char *)fdt; @@ -199,7 +199,7 @@ int fdt_finish(struct fdt_header *fdt) oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); - fdt->off_dt_strings = fdt32_to_cpu(newstroffset); + fdt_set_header(fdt, off_dt_strings, newstroffset); /* Walk the structure, correcting string offsets */ offset = 0; @@ -220,7 +220,7 @@ int fdt_finish(struct fdt_header *fdt) } /* Finally, adjust the header */ - fdt->totalsize = cpu_to_fdt32(newstroffset + fdt_size_dt_strings(fdt)); - fdt->magic = cpu_to_fdt32(FDT_MAGIC); + fdt_set_header(fdt, totalsize, newstroffset + fdt_size_dt_strings(fdt)); + fdt_set_header(fdt, magic, FDT_MAGIC); return 0; } diff --git a/fdt_wip.c b/fdt_wip.c index fa0df78..d353377 100644 --- a/fdt_wip.c +++ b/fdt_wip.c @@ -23,7 +23,7 @@ #include "libfdt_internal.h" -int fdt_setprop_inplace(struct fdt_header *fdt, int nodeoffset, const char *name, +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len) { void *propval; @@ -49,7 +49,7 @@ static void nop_region(void *start, int len) *p = cpu_to_fdt32(FDT_NOP); } -int fdt_nop_property(struct fdt_header *fdt, int nodeoffset, const char *name) +int fdt_nop_property(void *fdt, int nodeoffset, const char *name) { struct fdt_property *prop; int len; @@ -64,7 +64,7 @@ int fdt_nop_property(struct fdt_header *fdt, int nodeoffset, const char *name) return 0; } -int _fdt_node_end_offset(struct fdt_header *fdt, int nodeoffset) +int _fdt_node_end_offset(void *fdt, int nodeoffset) { int level = 0; uint32_t tag; @@ -101,7 +101,7 @@ int _fdt_node_end_offset(struct fdt_header *fdt, int nodeoffset) return nextoffset; } -int fdt_nop_node(struct fdt_header *fdt, int nodeoffset) +int fdt_nop_node(void *fdt, int nodeoffset) { int endoffset; int err; diff --git a/libfdt.h b/libfdt.h index cee2b3c..ed834bd 100644 --- a/libfdt.h +++ b/libfdt.h @@ -45,18 +45,23 @@ #define FDT_ERR_MAX 14 -#define fdt_magic(fdt) (fdt32_to_cpu(fdt->magic)) -#define fdt_totalsize(fdt) (fdt32_to_cpu(fdt->totalsize)) -#define fdt_off_dt_struct(fdt) (fdt32_to_cpu(fdt->off_dt_struct)) -#define fdt_off_dt_strings(fdt) (fdt32_to_cpu(fdt->off_dt_strings)) -#define fdt_off_mem_rsvmap(fdt) (fdt32_to_cpu(fdt->off_mem_rsvmap)) -#define fdt_version(fdt) (fdt32_to_cpu(fdt->version)) -#define fdt_last_comp_version(fdt) (fdt32_to_cpu(fdt->last_comp_version)) -#define fdt_boot_cpuid_phys(fdt) (fdt32_to_cpu(fdt->boot_cpuid_phys)) -#define fdt_size_dt_strings(fdt) (fdt32_to_cpu(fdt->size_dt_strings)) -#define fdt_size_dt_struct(fdt) (fdt32_to_cpu(fdt->size_dt_struct)) +#define fdt_get_header(fdt, field) \ + (fdt32_to_cpu(((struct fdt_header *)(fdt))->field)) +#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) +#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) +#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) +#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) +#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) +#define fdt_version(fdt) (fdt_get_header(fdt, version)) +#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) +#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) +#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) +#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) -void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int checklen); +#define fdt_set_header(fdt, field, val) \ + ((struct fdt_header *)(fdt))->field = cpu_to_fdt32(val) + +void *fdt_offset_ptr(const void *fdt, int offset, int checklen); #define fdt_offset_ptr_typed(fdt, offset, var) \ ((typeof(var))(fdt_offset_ptr((fdt), (offset), sizeof(*(var))))) @@ -67,26 +72,24 @@ void *fdt_offset_ptr(const struct fdt_header *fdt, int offset, int checklen); #define fdt_ptr_error(ptr) \ ( (((long)(ptr) < 0) && ((long)(ptr) >= -FDT_ERR_MAX)) ? -(long)(ptr) : 0 ) -struct fdt_header *fdt_move(const struct fdt_header *fdt, void *buf, int bufsize); +int fdt_move(const void *fdt, void *buf, int bufsize); /* Read-only functions */ -char *fdt_string(const struct fdt_header *fdt, int stroffset); +char *fdt_string(const void *fdt, int stroffset); -int fdt_subnode_offset_namelen(const struct fdt_header *fdt, int parentoffset, +int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, const char *name, int namelen); -int fdt_subnode_offset(const struct fdt_header *fdt, int parentoffset, - const char *name); +int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); -int fdt_path_offset(const struct fdt_header *fdt, const char *path); +int fdt_path_offset(const void *fdt, const char *path); -struct fdt_property *fdt_get_property(const struct fdt_header *fdt, - int nodeoffset, +struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, const char *name, int *lenp); -void *fdt_getprop(const struct fdt_header *fdt, int nodeoffset, +void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp); /* Write-in-place functions */ -int fdt_setprop_inplace(struct fdt_header *fdt, int nodeoffset, const char *name, +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len); #define fdt_setprop_inplace_typed(fdt, nodeoffset, name, val) \ @@ -95,15 +98,15 @@ int fdt_setprop_inplace(struct fdt_header *fdt, int nodeoffset, const char *name fdt_setprop_inplace(fdt, nodeoffset, name, &x, sizeof(x)); \ }) -int fdt_nop_property(struct fdt_header *fdt, int nodeoffset, const char *name); -int fdt_nop_node(struct fdt_header *fdt, int nodeoffset); +int fdt_nop_property(void *fdt, int nodeoffset, const char *name); +int fdt_nop_node(void *fdt, int nodeoffset); /* Sequential-write functions */ -struct fdt_header *fdt_create(void *buf, int bufsize); -int fdt_add_reservemap_entry(struct fdt_header *fdt, uint64_t addr, uint64_t size); -int fdt_finish_reservemap(struct fdt_header *fdt); -int fdt_begin_node(struct fdt_header *fdt, const char *name); -int fdt_property(struct fdt_header *fdt, const char *name, const void *val, int len); +int fdt_create(void *buf, int bufsize); +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); +int fdt_finish_reservemap(void *fdt); +int fdt_begin_node(void *fdt, const char *name); +int fdt_property(void *fdt, const char *name, const void *val, int len); #define fdt_property_typed(fdt, name, val) \ ({ \ typeof(val) x = (val); \ @@ -111,14 +114,14 @@ int fdt_property(struct fdt_header *fdt, const char *name, const void *val, int }) #define fdt_property_string(fdt, name, str) \ fdt_property(fdt, name, str, strlen(str)+1) -int fdt_end_node(struct fdt_header *fdt); -int fdt_finish(struct fdt_header *fdt); +int fdt_end_node(void *fdt); +int fdt_finish(void *fdt); /* Read-write functions */ -struct fdt_header *fdt_open_into(struct fdt_header *fdt, void *buf, int bufsize); -struct fdt_header *fdt_pack(struct fdt_header *fdt); +int fdt_open_into(void *fdt, void *buf, int bufsize); +int fdt_pack(void *fdt); -int fdt_setprop(struct fdt_header *fdt, int nodeoffset, const char *name, +int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len); #define fdt_setprop_typed(fdt, nodeoffset, name, val) \ ({ \ @@ -127,10 +130,10 @@ int fdt_setprop(struct fdt_header *fdt, int nodeoffset, const char *name, }) #define fdt_setprop_string(fdt, nodeoffset, name, str) \ fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) -int fdt_delprop(struct fdt_header *fdt, int nodeoffset, const char *name); -int fdt_add_subnode_namelen(struct fdt_header *fdt, int parentoffset, +int fdt_delprop(void *fdt, int nodeoffset, const char *name); +int fdt_add_subnode_namelen(void *fdt, int parentoffset, const char *name, int namelen); -int fdt_add_subnode(struct fdt_header *fdt, int parentoffset, const char *name); -int fdt_del_node(struct fdt_header *fdt, int nodeoffset); +int fdt_add_subnode(void *fdt, int parentoffset, const char *name); +int fdt_del_node(void *fdt, int nodeoffset); #endif /* _LIBFDT_H */ diff --git a/libfdt_internal.h b/libfdt_internal.h index d8c7551..9cb8a8c 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -26,10 +26,10 @@ #define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) #define streq(p, q) (strcmp((p), (q)) == 0) -int _fdt_check_header(const struct fdt_header *fdt); -uint32_t _fdt_next_tag(const struct fdt_header *fdt, int startoffset, int *nextoffset); +int _fdt_check_header(const void *fdt); +uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset); const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); -int _fdt_node_end_offset(struct fdt_header *fdt, int nodeoffset); +int _fdt_node_end_offset(void *fdt, int nodeoffset); static inline void *_fdt_offset_ptr(const struct fdt_header *fdt, int offset) { diff --git a/tests/del_node.c b/tests/del_node.c index 71d6831..87be4b5 100644 --- a/tests/del_node.c +++ b/tests/del_node.c @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt; + void *fdt; int subnode1_offset, subnode2_offset, subsubnode2_offset; int err; int oldsize, delsize, newsize; @@ -98,8 +98,8 @@ int main(int argc, char *argv[]) delsize = fdt_totalsize(fdt); - fdt = fdt_pack(fdt); - if ((err = fdt_ptr_error(fdt))) + err = fdt_pack(fdt); + if (err) FAIL("fdt_pack(): %s", fdt_strerror(err)); newsize = fdt_totalsize(fdt); diff --git a/tests/del_property.c b/tests/del_property.c index 94bf47a..d63cf5a 100644 --- a/tests/del_property.c +++ b/tests/del_property.c @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt; + void *fdt; uint32_t *intp; char *strp; int err; @@ -72,8 +72,8 @@ int main(int argc, char *argv[]) delsize = fdt_totalsize(fdt); - fdt = fdt_pack(fdt); - if ((err = fdt_ptr_error(fdt))) + err = fdt_pack(fdt); + if (err) FAIL("fdt_pack(): %s\n", fdt_strerror(err)); newsize = fdt_totalsize(fdt); diff --git a/tests/dumptrees.c b/tests/dumptrees.c index f0a9b2c..bea943b 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -4,12 +4,13 @@ #include #include +#include #include #include "testdata.h" struct { - struct fdt_header *fdt; + void *blob; const char *filename; } trees[] = { #define TREE(name) { &_##name, #name ".dtb" } @@ -23,13 +24,13 @@ int main(int argc, char *argv[]) int i; for (i = 0; i < NUM_TREES; i++) { - struct fdt_header *fdt = trees[i].fdt; + void *blob = trees[i].blob; const char *filename = trees[i].filename; int size; int fd; int ret; - size = fdt32_to_cpu(fdt->totalsize); + size = fdt_totalsize(blob); printf("Tree \"%s\", %d bytes\n", filename, size); @@ -37,7 +38,7 @@ int main(int argc, char *argv[]) if (fd < 0) perror("open()"); - ret = write(fd, fdt, size); + ret = write(fd, blob, size); if (ret != size) perror("write()"); diff --git a/tests/find_property.c b/tests/find_property.c index 1745258..8a8e9aa 100644 --- a/tests/find_property.c +++ b/tests/find_property.c @@ -29,7 +29,7 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt; + void *fdt; test_init(argc, argv); fdt = load_blob_arg(argc, argv); diff --git a/tests/getprop.c b/tests/getprop.c index 962b912..22dc03b 100644 --- a/tests/getprop.c +++ b/tests/getprop.c @@ -30,7 +30,7 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt; + void *fdt; test_init(argc, argv); fdt = load_blob_arg(argc, argv); diff --git a/tests/move_and_save.c b/tests/move_and_save.c index 526f615..4b4824e 100644 --- a/tests/move_and_save.c +++ b/tests/move_and_save.c @@ -30,7 +30,7 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt, *fdt1, *fdt2, *fdt3; + void *fdt, *fdt1, *fdt2, *fdt3; void *buf; int shuntsize; int bufsize; @@ -46,22 +46,25 @@ int main(int argc, char *argv[]) bufsize = fdt_totalsize(fdt) + shuntsize; buf = xmalloc(bufsize); - fdt1 = fdt_move(fdt, buf, bufsize); - if ((err = fdt_ptr_error(fdt1))) + fdt1 = buf; + err = fdt_move(fdt, fdt1, bufsize); + if (err) FAIL("Failed to move tree into new buffer: %s", fdt_strerror(err)); sprintf(outname, "moved.%s", inname); save_blob(outname, fdt1); - fdt2 = fdt_move(fdt1, buf + shuntsize, bufsize-shuntsize); - if ((err = fdt_ptr_error(fdt2))) + fdt2 = buf + shuntsize; + err = fdt_move(fdt1, fdt2, bufsize-shuntsize); + if (err) FAIL("Failed to shunt tree %d bytes: %s", shuntsize, fdt_strerror(err)); sprintf(outname, "shunted.%s", inname); save_blob(outname, fdt2); - fdt3 = fdt_move(fdt2, buf, bufsize); - if ((err = fdt_ptr_error(fdt3))) + fdt3 = buf; + err = fdt_move(fdt2, fdt3, bufsize); + if (err) FAIL("Failed to deshunt tree %d bytes: %s", shuntsize, fdt_strerror(err)); sprintf(outname, "deshunted.%s", inname); diff --git a/tests/nop_node.c b/tests/nop_node.c index df421c0..2db1b29 100644 --- a/tests/nop_node.c +++ b/tests/nop_node.c @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt; + void *fdt; int subnode1_offset, subnode2_offset, subsubnode2_offset; int err; diff --git a/tests/nop_property.c b/tests/nop_property.c index 94c8e74..14754b0 100644 --- a/tests/nop_property.c +++ b/tests/nop_property.c @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt; + void *fdt; uint32_t *intp; char *strp; int err; diff --git a/tests/notfound.c b/tests/notfound.c index 9cdc29c..d2821a5 100644 --- a/tests/notfound.c +++ b/tests/notfound.c @@ -37,7 +37,7 @@ void check_error(const char *s, int err) int main(int argc, char *argv[]) { struct fdt_property *prop; - struct fdt_header *fdt; + void *fdt; int offset; int subnode1_offset; void *val; diff --git a/tests/open_pack.c b/tests/open_pack.c index c651694..1aa66e4 100644 --- a/tests/open_pack.c +++ b/tests/open_pack.c @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt, *fdt1, *fdt2; + void *fdt, *fdt1; void *buf; int oldsize, bufsize, packsize; int err; @@ -48,19 +48,20 @@ int main(int argc, char *argv[]) buf = xmalloc(bufsize); - fdt1 = fdt_open_into(fdt, buf, bufsize); - if ((err = fdt_ptr_error(fdt1))) + fdt1 = buf; + err = fdt_open_into(fdt, fdt1, bufsize); + if (err) FAIL("fdt_open_into(): %s", fdt_strerror(err)); sprintf(outname, "opened.%s", inname); save_blob(outname, fdt1); - fdt2 = fdt_pack(fdt1); - if ((err = fdt_ptr_error(fdt2))) + err = fdt_pack(fdt1); + if (err) FAIL("fdt_pack(): %s", fdt_strerror(err)); sprintf(outname, "repacked.%s", inname); - save_blob(outname, fdt2); + save_blob(outname, fdt1); - packsize = fdt_totalsize(fdt2); + packsize = fdt_totalsize(fdt1); verbose_printf("oldsize = %d, bufsize = %d, packsize = %d\n", oldsize, bufsize, packsize); diff --git a/tests/path_offset.c b/tests/path_offset.c index 32222be..5d5a246 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -27,7 +27,7 @@ #include "tests.h" #include "testdata.h" -int check_subnode(struct fdt_header *fdt, int parent, const char *name) +int check_subnode(void *fdt, int parent, const char *name) { int offset; int err; @@ -57,7 +57,7 @@ int check_subnode(struct fdt_header *fdt, int parent, const char *name) int main(int argc, char *argv[]) { - struct fdt_header *fdt; + void *fdt; int subnode1_offset, subnode2_offset; int subnode1_offset_p, subnode2_offset_p; int subsubnode1_offset, subsubnode2_offset; diff --git a/tests/root_node.c b/tests/root_node.c index d331bdf..4258b91 100644 --- a/tests/root_node.c +++ b/tests/root_node.c @@ -30,7 +30,7 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt; + void *fdt; struct fdt_node_header *nh; test_init(argc, argv); diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c index 8c5582a..cc5b926 100644 --- a/tests/rw_tree1.c +++ b/tests/rw_tree1.c @@ -38,13 +38,6 @@ FAIL(#code ": %s", fdt_strerror(err)); \ } -#define PTR_CHECK(ptr, code) \ - { \ - err = fdt_ptr_error((ptr) = (code)); \ - if (err) \ - FAIL(#code ": %s", fdt_strerror(err)); \ - } - #define OFF_CHECK(off, code) \ { \ err = fdt_offset_error((off) = (code)); \ @@ -54,17 +47,16 @@ int main(int argc, char *argv[]) { - void *buf; - struct fdt_header *fdt; + void *fdt; int err; int offset; test_init(argc, argv); - buf = xmalloc(SPACE); + fdt = xmalloc(SPACE); /* First create empty tree with SW */ - fdt = fdt_create(buf, SPACE); + CHECK(fdt_create(fdt, SPACE)); CHECK(fdt_finish_reservemap(fdt)); CHECK(fdt_begin_node(fdt, "")); @@ -72,9 +64,9 @@ int main(int argc, char *argv[]) CHECK(fdt_finish(fdt)); verbose_printf("Built empty tree, totalsize = %d\n", - fdt32_to_cpu(fdt->totalsize)); + fdt_totalsize(fdt)); - PTR_CHECK(fdt, fdt_open_into(fdt, buf, SPACE)); + CHECK(fdt_open_into(fdt, fdt, SPACE)); CHECK(fdt_setprop_typed(fdt, 0, "prop-int", TEST_VALUE_1)); CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1)); @@ -90,7 +82,7 @@ int main(int argc, char *argv[]) CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_2)); - PTR_CHECK(fdt, fdt_pack(fdt)); + CHECK(fdt_pack(fdt)); save_blob("rw_tree1.test.dtb", fdt); diff --git a/tests/setprop.c b/tests/setprop.c index 3df854d..fc70910 100644 --- a/tests/setprop.c +++ b/tests/setprop.c @@ -34,7 +34,7 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt; + void *fdt; void *buf; uint32_t *intp; char *strp; @@ -45,10 +45,12 @@ int main(int argc, char *argv[]) buf = xmalloc(SPACE); - fdt = fdt_open_into(fdt, buf, SPACE); - if ((err = fdt_ptr_error(fdt))) + err = fdt_open_into(fdt, buf, SPACE); + if (err) FAIL("fdt_open_into(): %s", fdt_strerror(err)); + fdt = buf; + intp = check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); verbose_printf("Old int value was 0x%08x\n", *intp); diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c index 61de789..f674ec6 100644 --- a/tests/setprop_inplace.c +++ b/tests/setprop_inplace.c @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) { - struct fdt_header *fdt; + void *fdt; uint32_t *intp; char *strp, *xstr; int xlen, i; diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c index 0552b05..3283e1a 100644 --- a/tests/subnode_offset.c +++ b/tests/subnode_offset.c @@ -57,7 +57,7 @@ int check_subnode(struct fdt_header *fdt, int parent, const char *name) int main(int argc, char *argv[]) { - struct fdt_header *fdt; + void *fdt; int subnode1_offset, subnode2_offset; int subsubnode1_offset, subsubnode2_offset; diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 6f72006..51aa4d7 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -40,14 +40,13 @@ int main(int argc, char *argv[]) { - void *buf; - struct fdt_header *fdt; + void *fdt; int err; test_init(argc, argv); - buf = xmalloc(SPACE); - fdt = fdt_create(buf, SPACE); + fdt = xmalloc(SPACE); + CHECK(fdt_create(fdt, SPACE)); CHECK(fdt_finish_reservemap(fdt)); CHECK(fdt_begin_node(fdt, "")); @@ -75,7 +74,7 @@ int main(int argc, char *argv[]) CHECK(fdt_finish(fdt)); verbose_printf("Completed tree, totalsize = %d\n", - fdt32_to_cpu(fdt->totalsize)); + fdt_totalsize(fdt)); save_blob("sw_tree1.test.dtb", fdt); diff --git a/tests/tests.h b/tests/tests.h index a673b61..b4dd10a 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -109,7 +109,7 @@ static inline void *xrealloc(void *p, size_t size) } const char *fdt_strerror(int errval); -void check_property(struct fdt_header *fdt, int nodeoffset, const char *name, +void check_property(void *fdt, int nodeoffset, const char *name, int len, const void *val); #define check_property_typed(fdt, nodeoffset, name, val) \ ({ \ @@ -118,7 +118,7 @@ void check_property(struct fdt_header *fdt, int nodeoffset, const char *name, }) -void *check_getprop(struct fdt_header *fdt, int nodeoffset, const char *name, +void *check_getprop(void *fdt, int nodeoffset, const char *name, int len, const void *val); #define check_getprop_typed(fdt, nodeoffset, name, val) \ ({ \ @@ -129,6 +129,6 @@ void *check_getprop(struct fdt_header *fdt, int nodeoffset, const char *name, check_getprop((fdt), (nodeoffset), (name), strlen(s)+1, (s)) //void *load_blob(const char *filename); void *load_blob_arg(int argc, char *argv[]); -void save_blob(const char *filename, struct fdt_header *fdt); +void save_blob(const char *filename, void *blob); #endif /* _TESTS_H */ diff --git a/tests/testutils.c b/tests/testutils.c index 994cdae..1f7a894 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -103,7 +103,7 @@ const char *fdt_strerror(int errval) return "Unknown FDT error code"; } -void check_property(struct fdt_header *fdt, int nodeoffset, const char *name, +void check_property(void *fdt, int nodeoffset, const char *name, int len, const void *val) { const struct fdt_property *prop; @@ -135,7 +135,7 @@ void check_property(struct fdt_header *fdt, int nodeoffset, const char *name, } -void *check_getprop(struct fdt_header *fdt, int nodeoffset, const char *name, +void *check_getprop(void *fdt, int nodeoffset, const char *name, int len, const void *val) { void *propval; @@ -195,7 +195,7 @@ void *load_blob_arg(int argc, char *argv[]) return load_blob(argv[1]); } -void save_blob(const char *filename, struct fdt_header *fdt) +void save_blob(const char *filename, void *fdt) { int fd; int totalsize; @@ -208,7 +208,7 @@ void save_blob(const char *filename, struct fdt_header *fdt) CONFIG("Couldn't open \"%s\" to write blob: %s", filename, strerror(errno)); - totalsize = fdt32_to_cpu(fdt->totalsize); + totalsize = fdt_totalsize(fdt); offset = 0; p = fdt; From a7ee95ded6a0d64c1c259b9c6fea090e19ca81f8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 15 Dec 2006 15:12:49 +1100 Subject: [PATCH 0030/1198] libfdt: Abolish encoding of error codes into pointers This patch abolishes the non-standard and confusing encoding of errors into pointer return values. The only functions still returning such a potentially encoded pointer are fdt_get_property() and fdt_getprop(). Those functions also return a length via an (int *). With this patch those functions instead now return NULL on any error, and return the code indicating the type of error in the length paramater. Signed-off-by: David Gibson --- fdt_ro.c | 41 ++++++++++++++------------- fdt_rw.c | 58 +++++++++++++++++--------------------- fdt_wip.c | 10 +++---- libfdt.h | 4 +-- libfdt_internal.h | 1 - tests/del_property.c | 16 +++++------ tests/nop_property.c | 15 +++++----- tests/notfound.c | 13 +++++---- tests/testutils.c | 5 ++-- tests/truncated_property.c | 4 +-- 10 files changed, 79 insertions(+), 88 deletions(-) diff --git a/fdt_ro.c b/fdt_ro.c index b58029a..e5446fb 100644 --- a/fdt_ro.c +++ b/fdt_ro.c @@ -30,13 +30,6 @@ return OFFSET_ERROR(err); \ } -#define PTR_CHECK_HEADER(fdt) \ - { \ - int err; \ - if ((err = _fdt_check_header(fdt)) != 0) \ - return PTR_ERROR(err); \ - } - static int offset_streq(const void *fdt, int offset, const char *s, int len) { @@ -153,25 +146,30 @@ struct fdt_property *fdt_get_property(const void *fdt, struct fdt_property *prop; int namestroff; int offset, nextoffset; + int err; - PTR_CHECK_HEADER(fdt); + if ((err = _fdt_check_header(fdt)) != 0) + goto fail; + err = FDT_ERR_BADOFFSET; if (nodeoffset % FDT_TAGSIZE) - return PTR_ERROR(FDT_ERR_BADOFFSET); + goto fail; tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); if (tag != FDT_BEGIN_NODE) - return PTR_ERROR(FDT_ERR_BADOFFSET); + goto fail; do { offset = nextoffset; + err = FDT_ERR_INTERNAL; if (offset % FDT_TAGSIZE) - return PTR_ERROR(FDT_ERR_INTERNAL); + goto fail; tag = _fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_END: - return PTR_ERROR(FDT_ERR_TRUNCATED); + err = FDT_ERR_TRUNCATED; + goto fail; case FDT_BEGIN_NODE: level++; @@ -185,9 +183,10 @@ struct fdt_property *fdt_get_property(const void *fdt, if (level != 0) continue; + err = FDT_ERR_BADSTRUCTURE; prop = fdt_offset_ptr_typed(fdt, offset, prop); if (! prop) - return PTR_ERROR(FDT_ERR_BADSTRUCTURE); + goto fail; namestroff = fdt32_to_cpu(prop->nameoff); if (streq(fdt_string(fdt, namestroff), name)) { /* Found it! */ @@ -195,7 +194,7 @@ struct fdt_property *fdt_get_property(const void *fdt, prop = fdt_offset_ptr(fdt, offset, sizeof(*prop)+len); if (! prop) - return PTR_ERROR(FDT_ERR_BADSTRUCTURE); + goto fail; if (lenp) *lenp = len; @@ -208,22 +207,26 @@ struct fdt_property *fdt_get_property(const void *fdt, break; default: - return PTR_ERROR(FDT_ERR_BADSTRUCTURE); + err = FDT_ERR_BADSTRUCTURE; + goto fail; } } while (level >= 0); - return PTR_ERROR(FDT_ERR_NOTFOUND); + err = FDT_ERR_NOTFOUND; + fail: + if (lenp) + *lenp = -err; + return NULL; } void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp) { const struct fdt_property *prop; - int err; prop = fdt_get_property(fdt, nodeoffset, name, lenp); - if ((err = fdt_ptr_error(prop))) - return PTR_ERROR(err); + if (! prop) + return NULL; return prop->data; } diff --git a/fdt_rw.c b/fdt_rw.c index 4b7d1d5..fe5d66d 100644 --- a/fdt_rw.c +++ b/fdt_rw.c @@ -117,31 +117,29 @@ static int _find_add_string(void *fdt, const char *s) return (new - strtab); } -static struct fdt_property *_resize_property(void *fdt, int nodeoffset, - const char *name, int len) +static int _resize_property(void *fdt, int nodeoffset, const char *name, int len, + struct fdt_property **prop) { - struct fdt_property *prop; int oldlen; int err; - prop = fdt_get_property(fdt, nodeoffset, name, &oldlen); - if ((err = fdt_ptr_error(prop))) - return PTR_ERROR(err); + *prop = fdt_get_property(fdt, nodeoffset, name, &oldlen); + if (! (*prop)) + return -oldlen; - if ((err = _blob_splice_struct(fdt, prop->data, + if ((err = _blob_splice_struct(fdt, (*prop)->data, ALIGN(oldlen, FDT_TAGSIZE), ALIGN(len, FDT_TAGSIZE)))) - return PTR_ERROR(err); + return err; - prop->len = cpu_to_fdt32(len); - return prop; + (*prop)->len = cpu_to_fdt32(len); + return 0; } -static struct fdt_property *_add_property(void *fdt, int nodeoffset, - const char *name, int len) +static int _add_property(void *fdt, int nodeoffset, const char *name, int len, + struct fdt_property **prop) { uint32_t tag; - struct fdt_property *prop; int proplen; int nextoffset; int namestroff; @@ -149,23 +147,23 @@ static struct fdt_property *_add_property(void *fdt, int nodeoffset, tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); if (tag != FDT_BEGIN_NODE) - return PTR_ERROR(FDT_ERR_BADOFFSET); + return FDT_ERR_BADOFFSET; namestroff = _find_add_string(fdt, name); if (namestroff < 0) - return PTR_ERROR(-namestroff); + return -namestroff; - prop = _fdt_offset_ptr(fdt, nextoffset); - proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE); + *prop = _fdt_offset_ptr(fdt, nextoffset); + proplen = sizeof(**prop) + ALIGN(len, FDT_TAGSIZE); - err = _blob_splice_struct(fdt, prop, 0, proplen); + err = _blob_splice_struct(fdt, *prop, 0, proplen); if (err) - return PTR_ERROR(err); + return err; - prop->tag = cpu_to_fdt32(FDT_PROP); - prop->nameoff = cpu_to_fdt32(namestroff); - prop->len = cpu_to_fdt32(len); - return prop; + (*prop)->tag = cpu_to_fdt32(FDT_PROP); + (*prop)->nameoff = cpu_to_fdt32(namestroff); + (*prop)->len = cpu_to_fdt32(len); + return 0; } int fdt_setprop(void *fdt, int nodeoffset, const char *name, @@ -177,12 +175,9 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, if ((err = rw_check_header(fdt))) return err; - prop = _resize_property(fdt, nodeoffset, name, len); - err = fdt_ptr_error(prop); - if (err == FDT_ERR_NOTFOUND) { - prop = _add_property(fdt, nodeoffset, name, len); - err = fdt_ptr_error(prop); - } + err = _resize_property(fdt, nodeoffset, name, len, &prop); + if (err == FDT_ERR_NOTFOUND) + err = _add_property(fdt, nodeoffset, name, len, &prop); if (err) return err; @@ -194,13 +189,12 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name) { struct fdt_property *prop; int len, proplen; - int err; RW_OFFSET_CHECK_HEADER(fdt); prop = fdt_get_property(fdt, nodeoffset, name, &len); - if ((err = fdt_ptr_error(prop))) - return err; + if (! prop) + return -len; proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE); return _blob_splice_struct(fdt, prop, proplen, 0); diff --git a/fdt_wip.c b/fdt_wip.c index d353377..88b9ba2 100644 --- a/fdt_wip.c +++ b/fdt_wip.c @@ -28,11 +28,10 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, { void *propval; int proplen; - int err; propval = fdt_getprop(fdt, nodeoffset, name, &proplen); - if ((err = fdt_ptr_error(propval))) - return err; + if (! propval) + return -proplen; if (proplen != len) return FDT_ERR_SIZE_MISMATCH; @@ -53,11 +52,10 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name) { struct fdt_property *prop; int len; - int err; prop = fdt_get_property(fdt, nodeoffset, name, &len); - if ((err = fdt_ptr_error(prop))) - return err; + if (! prop) + return -len; nop_region(prop, len + sizeof(*prop)); diff --git a/libfdt.h b/libfdt.h index ed834bd..062e8bf 100644 --- a/libfdt.h +++ b/libfdt.h @@ -69,8 +69,8 @@ void *fdt_offset_ptr(const void *fdt, int offset, int checklen); #define fdt_offset_error(offset) \ ( (offset) < 0 ? -(offset) : 0 ) -#define fdt_ptr_error(ptr) \ - ( (((long)(ptr) < 0) && ((long)(ptr) >= -FDT_ERR_MAX)) ? -(long)(ptr) : 0 ) +#define fdt_ptrlen_error(p, len) \ + ( (p) ? 0 : -(len) ) int fdt_move(const void *fdt, void *buf, int bufsize); diff --git a/libfdt_internal.h b/libfdt_internal.h index 9cb8a8c..b6c845f 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -37,7 +37,6 @@ static inline void *_fdt_offset_ptr(const struct fdt_header *fdt, int offset) } #define OFFSET_ERROR(code) -(code) -#define PTR_ERROR(code) (void *)(-(long)(code)) #define SW_MAGIC (~FDT_MAGIC) diff --git a/tests/del_property.c b/tests/del_property.c index d63cf5a..2f43dd9 100644 --- a/tests/del_property.c +++ b/tests/del_property.c @@ -34,7 +34,7 @@ int main(int argc, char *argv[]) void *fdt; uint32_t *intp; char *strp; - int err; + int err, lenerr; int oldsize, delsize, newsize; test_init(argc, argv); @@ -49,11 +49,10 @@ int main(int argc, char *argv[]) if (err) FAIL("Failed to delete \"prop-int\": %s", fdt_strerror(err)); - intp = fdt_getprop(fdt, 0, "prop-int", NULL); - err = fdt_ptr_error(intp); - if (! err) + intp = fdt_getprop(fdt, 0, "prop-int", &lenerr); + if (intp) FAIL("prop-int still present after deletion"); - if (err != FDT_ERR_NOTFOUND) + if ((err = fdt_ptrlen_error(intp, lenerr)) != FDT_ERR_NOTFOUND) FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, @@ -63,11 +62,10 @@ int main(int argc, char *argv[]) if (err) FAIL("Failed to delete \"prop-str\": %s", fdt_strerror(err)); - strp = fdt_getprop(fdt, 0, "prop-str", NULL); - err = fdt_ptr_error(strp); - if (! err) + strp = fdt_getprop(fdt, 0, "prop-str", &lenerr); + if (strp) FAIL("prop-str still present after deletion"); - if (err != FDT_ERR_NOTFOUND) + if ((err = fdt_ptrlen_error(strp, lenerr)) != FDT_ERR_NOTFOUND) FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); delsize = fdt_totalsize(fdt); diff --git a/tests/nop_property.c b/tests/nop_property.c index 14754b0..3314ee4 100644 --- a/tests/nop_property.c +++ b/tests/nop_property.c @@ -35,6 +35,7 @@ int main(int argc, char *argv[]) uint32_t *intp; char *strp; int err; + int lenerr; test_init(argc, argv); fdt = load_blob_arg(argc, argv); @@ -46,11 +47,10 @@ int main(int argc, char *argv[]) if (err) FAIL("Failed to nop \"prop-int\": %s", fdt_strerror(err)); - intp = fdt_getprop(fdt, 0, "prop-int", NULL); - err = fdt_ptr_error(intp); - if (! err) + intp = fdt_getprop(fdt, 0, "prop-int", &lenerr); + if (intp) FAIL("prop-int still present after nopping"); - if (err != FDT_ERR_NOTFOUND) + if ((err = fdt_ptrlen_error(intp, lenerr)) != FDT_ERR_NOTFOUND) FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, @@ -60,11 +60,10 @@ int main(int argc, char *argv[]) if (err) FAIL("Failed to nop \"prop-str\": %s", fdt_strerror(err)); - strp = fdt_getprop(fdt, 0, "prop-str", NULL); - err = fdt_ptr_error(strp); - if (! err) + strp = fdt_getprop(fdt, 0, "prop-str", &lenerr); + if (strp) FAIL("prop-str still present after nopping"); - if (err != FDT_ERR_NOTFOUND) + if ((err = fdt_ptrlen_error(strp, lenerr)) != FDT_ERR_NOTFOUND) FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); PASS(); diff --git a/tests/notfound.c b/tests/notfound.c index d2821a5..c1120ff 100644 --- a/tests/notfound.c +++ b/tests/notfound.c @@ -42,24 +42,25 @@ int main(int argc, char *argv[]) int subnode1_offset; void *val; int err; + int lenerr; test_init(argc, argv); fdt = load_blob_arg(argc, argv); - prop = fdt_get_property(fdt, 0, "nonexistant-property", NULL); + prop = fdt_get_property(fdt, 0, "nonexistant-property", &lenerr); check_error("fdt_get_property(\"nonexistant-property\")", - fdt_ptr_error(prop)); + fdt_ptrlen_error(prop, lenerr)); - val = fdt_getprop(fdt, 0, "nonexistant-property", NULL); + val = fdt_getprop(fdt, 0, "nonexistant-property", &lenerr); check_error("fdt_getprop(\"nonexistant-property\"", - fdt_ptr_error(val)); + fdt_ptrlen_error(val, lenerr)); subnode1_offset = fdt_subnode_offset(fdt, 0, "subnode1"); if ((err = fdt_offset_error(subnode1_offset))) FAIL("Couldn't find subnode1: %s", fdt_strerror(err)); - val = fdt_getprop(fdt, subnode1_offset, "prop-str", NULL); - check_error("fdt_getprop(\"prop-str\")", fdt_ptr_error(val)); + val = fdt_getprop(fdt, subnode1_offset, "prop-str", &lenerr); + check_error("fdt_getprop(\"prop-str\")", fdt_ptrlen_error(val, lenerr)); offset = fdt_subnode_offset(fdt, 0, "nonexistant-subnode"); check_error("fdt_subnode_offset(\"nonexistant-subnode\")", diff --git a/tests/testutils.c b/tests/testutils.c index 1f7a894..c3ec0fa 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -140,11 +140,10 @@ void *check_getprop(void *fdt, int nodeoffset, const char *name, { void *propval; int proplen; - int err; propval = fdt_getprop(fdt, nodeoffset, name, &proplen); - if ((err = fdt_ptr_error(propval))) - FAIL("fdt_getprop(\"%s\"): %s", name, fdt_strerror(err)); + if (! propval) + FAIL("fdt_getprop(\"%s\"): %s", name, fdt_strerror(-proplen)); if (proplen != len) FAIL("Size mismatch on property \"%s\": %d insead of %d", diff --git a/tests/truncated_property.c b/tests/truncated_property.c index e678b96..2bd25d4 100644 --- a/tests/truncated_property.c +++ b/tests/truncated_property.c @@ -38,9 +38,9 @@ int main(int argc, char *argv[]) test_init(argc, argv); prop = fdt_getprop(fdt, 0, "truncated", &len); - err = fdt_ptr_error(prop); - if (! err) + if (prop) FAIL("fdt_getprop() succeeded on truncated property"); + err = fdt_ptrlen_error(prop, len); if (err != FDT_ERR_BADSTRUCTURE) FAIL("fdt_getprop() failed with \"%s\" instead of \"%s\"", fdt_strerror(err), fdt_strerror(FDT_ERR_BADSTRUCTURE)); From 9a9fdf59913c6d14f1755fe653dc8161ec6b0b7b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 15 Dec 2006 15:12:51 +1100 Subject: [PATCH 0031/1198] libfdt: More consistent handling of returned error codes. At present, libfdt functions returning a structure offset return a zero-or-positive offset on success, and return a negative error code on failure. Functions which only return an error code return a positive version of the error code, or 0 on success. This patch improves consistency by always returning negative error codes on failure, for both types of function. With this change, we do away with the special fdt_offset_error() macro for checking whether a returned offset value is an error and extracting the encoded error value within. Instead an explicit (ret_value < 0) is now the preferred way of checking return values for both offset-returning and error-code-returning functions. The fdt_strerror() function in the test code is updated correspondingly to make more sense with the new conventions. Signed-off-by: David Gibson --- fdt.c | 12 ++++----- fdt_ro.c | 36 +++++++++++++------------- fdt_rw.c | 53 +++++++++++++++++++------------------- fdt_sw.c | 22 ++++++++-------- fdt_wip.c | 15 +++++------ libfdt.h | 6 ----- libfdt_internal.h | 2 -- tests/del_node.c | 43 ++++++++++++++++++------------- tests/del_property.c | 10 ++++--- tests/nop_node.c | 49 ++++++++++++++++++++--------------- tests/nop_property.c | 4 +-- tests/notfound.c | 26 +++++++------------ tests/path_offset.c | 5 ++-- tests/rw_tree1.c | 6 ++--- tests/subnode_offset.c | 5 ++-- tests/testutils.c | 8 +++--- tests/truncated_property.c | 5 ++-- 17 files changed, 153 insertions(+), 154 deletions(-) diff --git a/fdt.c b/fdt.c index bc3ec22..45568b1 100644 --- a/fdt.c +++ b/fdt.c @@ -28,15 +28,15 @@ int _fdt_check_header(const void *fdt) if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) - return FDT_ERR_BADVERSION; + return -FDT_ERR_BADVERSION; if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) - return FDT_ERR_BADVERSION; + return -FDT_ERR_BADVERSION; } else if (fdt_magic(fdt) == SW_MAGIC) { /* Unfinished sequential-write blob */ if (fdt_size_dt_struct(fdt) == 0) - return FDT_ERR_BADSTATE; + return -FDT_ERR_BADSTATE; } else { - return FDT_ERR_BADMAGIC; + return -FDT_ERR_BADMAGIC; } return 0; @@ -117,8 +117,8 @@ int fdt_move(const void *fdt, void *buf, int bufsize) return err; if (fdt_totalsize(fdt) > bufsize) - return FDT_ERR_NOSPACE; + return -FDT_ERR_NOSPACE; memmove(buf, fdt, fdt_totalsize(fdt)); - return FDT_ERR_OK; + return 0; } diff --git a/fdt_ro.c b/fdt_ro.c index e5446fb..7db7f12 100644 --- a/fdt_ro.c +++ b/fdt_ro.c @@ -23,11 +23,11 @@ #include "libfdt_internal.h" -#define OFFSET_CHECK_HEADER(fdt) \ +#define CHECK_HEADER(fdt) \ { \ int err; \ if ((err = _fdt_check_header(fdt)) != 0) \ - return OFFSET_ERROR(err); \ + return err; \ } static int offset_streq(const void *fdt, int offset, @@ -60,11 +60,11 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, uint32_t tag; int offset, nextoffset; - OFFSET_CHECK_HEADER(fdt); + CHECK_HEADER(fdt); tag = _fdt_next_tag(fdt, parentoffset, &nextoffset); if (tag != FDT_BEGIN_NODE) - return OFFSET_ERROR(FDT_ERR_BADOFFSET); + return -FDT_ERR_BADOFFSET; do { offset = nextoffset; @@ -72,7 +72,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, switch (tag) { case FDT_END: - return OFFSET_ERROR(FDT_ERR_TRUNCATED); + return -FDT_ERR_TRUNCATED; case FDT_BEGIN_NODE: level++; @@ -92,11 +92,11 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, break; default: - return OFFSET_ERROR(FDT_ERR_BADSTRUCTURE); + return -FDT_ERR_BADSTRUCTURE; } } while (level >= 0); - return OFFSET_ERROR(FDT_ERR_NOTFOUND); + return -FDT_ERR_NOTFOUND; } int fdt_subnode_offset(const void *fdt, int parentoffset, @@ -111,10 +111,10 @@ int fdt_path_offset(const void *fdt, const char *path) const char *p = path; int offset = 0; - OFFSET_CHECK_HEADER(fdt); + CHECK_HEADER(fdt); if (*path != '/') - return OFFSET_ERROR(FDT_ERR_BADPATH); + return -FDT_ERR_BADPATH; while (*p) { const char *q; @@ -122,13 +122,13 @@ int fdt_path_offset(const void *fdt, const char *path) while (*p == '/') p++; if (! *p) - return OFFSET_ERROR(FDT_ERR_BADPATH); + return -FDT_ERR_BADPATH; q = strchr(p, '/'); if (! q) q = end; offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); - if (fdt_offset_error(offset)) + if (offset < 0) return offset; p = q; @@ -151,7 +151,7 @@ struct fdt_property *fdt_get_property(const void *fdt, if ((err = _fdt_check_header(fdt)) != 0) goto fail; - err = FDT_ERR_BADOFFSET; + err = -FDT_ERR_BADOFFSET; if (nodeoffset % FDT_TAGSIZE) goto fail; @@ -161,14 +161,14 @@ struct fdt_property *fdt_get_property(const void *fdt, do { offset = nextoffset; - err = FDT_ERR_INTERNAL; + err = -FDT_ERR_INTERNAL; if (offset % FDT_TAGSIZE) goto fail; tag = _fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_END: - err = FDT_ERR_TRUNCATED; + err = -FDT_ERR_TRUNCATED; goto fail; case FDT_BEGIN_NODE: @@ -183,7 +183,7 @@ struct fdt_property *fdt_get_property(const void *fdt, if (level != 0) continue; - err = FDT_ERR_BADSTRUCTURE; + err = -FDT_ERR_BADSTRUCTURE; prop = fdt_offset_ptr_typed(fdt, offset, prop); if (! prop) goto fail; @@ -207,15 +207,15 @@ struct fdt_property *fdt_get_property(const void *fdt, break; default: - err = FDT_ERR_BADSTRUCTURE; + err = -FDT_ERR_BADSTRUCTURE; goto fail; } } while (level >= 0); - err = FDT_ERR_NOTFOUND; + err = -FDT_ERR_NOTFOUND; fail: if (lenp) - *lenp = -err; + *lenp = err; return NULL; } diff --git a/fdt_rw.c b/fdt_rw.c index fe5d66d..7396645 100644 --- a/fdt_rw.c +++ b/fdt_rw.c @@ -30,26 +30,26 @@ static int rw_check_header(void *fdt) if ((err = _fdt_check_header(fdt))) return err; if (fdt_version(fdt) < 0x11) - return FDT_ERR_BADVERSION; + return -FDT_ERR_BADVERSION; if (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8)) - return FDT_ERR_BADLAYOUT; + return -FDT_ERR_BADLAYOUT; if (fdt_off_dt_struct(fdt) < (fdt_off_mem_rsvmap(fdt) + sizeof(struct fdt_reserve_entry))) - return FDT_ERR_BADLAYOUT; + return -FDT_ERR_BADLAYOUT; if (fdt_off_dt_strings(fdt) < (fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt))) - return FDT_ERR_BADLAYOUT; + return -FDT_ERR_BADLAYOUT; if (fdt_totalsize(fdt) < (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))) - return FDT_ERR_BADLAYOUT; + return -FDT_ERR_BADLAYOUT; return 0; } -#define RW_OFFSET_CHECK_HEADER(fdt) \ +#define RW_CHECK_HEADER(fdt) \ { \ int err; \ if ((err = rw_check_header(fdt)) != 0) \ - return OFFSET_ERROR(err); \ + return err; \ } static inline int _blob_data_size(void *fdt) @@ -62,9 +62,9 @@ static int _blob_splice(void *fdt, void *p, int oldlen, int newlen) void *end = fdt + _blob_data_size(fdt); if (((p + oldlen) < p) || ((p + oldlen) > end)) - return FDT_ERR_BADOFFSET; + return -FDT_ERR_BADOFFSET; if ((end - oldlen + newlen) > (fdt + fdt_totalsize(fdt))) - return FDT_ERR_NOSPACE; + return -FDT_ERR_NOSPACE; memmove(p + newlen, p + oldlen, end - p - oldlen); return 0; } @@ -111,7 +111,7 @@ static int _find_add_string(void *fdt, const char *s) new = strtab + fdt_size_dt_strings(fdt); err = _blob_splice_string(fdt, len); if (err) - return -err; + return err; memcpy(new, s, len); return (new - strtab); @@ -125,7 +125,7 @@ static int _resize_property(void *fdt, int nodeoffset, const char *name, int len *prop = fdt_get_property(fdt, nodeoffset, name, &oldlen); if (! (*prop)) - return -oldlen; + return oldlen; if ((err = _blob_splice_struct(fdt, (*prop)->data, ALIGN(oldlen, FDT_TAGSIZE), @@ -147,11 +147,11 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len, tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); if (tag != FDT_BEGIN_NODE) - return FDT_ERR_BADOFFSET; + return -FDT_ERR_BADOFFSET; namestroff = _find_add_string(fdt, name); if (namestroff < 0) - return -namestroff; + return namestroff; *prop = _fdt_offset_ptr(fdt, nextoffset); proplen = sizeof(**prop) + ALIGN(len, FDT_TAGSIZE); @@ -176,7 +176,7 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, return err; err = _resize_property(fdt, nodeoffset, name, len, &prop); - if (err == FDT_ERR_NOTFOUND) + if (err == -FDT_ERR_NOTFOUND) err = _add_property(fdt, nodeoffset, name, len, &prop); if (err) return err; @@ -190,11 +190,11 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name) struct fdt_property *prop; int len, proplen; - RW_OFFSET_CHECK_HEADER(fdt); + RW_CHECK_HEADER(fdt); prop = fdt_get_property(fdt, nodeoffset, name, &len); if (! prop) - return -len; + return len; proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE); return _blob_splice_struct(fdt, prop, proplen, 0); @@ -210,13 +210,13 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, uint32_t tag; uint32_t *endtag; - RW_OFFSET_CHECK_HEADER(fdt); + RW_CHECK_HEADER(fdt); offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); - if ((err = fdt_offset_error(offset)) == 0) - return OFFSET_ERROR(FDT_ERR_EXISTS); - else if (err != FDT_ERR_NOTFOUND) - return OFFSET_ERROR(err); + if (offset >= 0) + return -FDT_ERR_EXISTS; + else if (offset != -FDT_ERR_NOTFOUND) + return offset; /* Try to place the new node after the parent's properties */ _fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ @@ -230,7 +230,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, err = _blob_splice_struct(fdt, nh, 0, nodelen); if (err) - return OFFSET_ERROR(err); + return err; nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); memset(nh->name, 0, ALIGN(namelen+1, FDT_TAGSIZE)); @@ -249,11 +249,10 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name) int fdt_del_node(void *fdt, int nodeoffset) { int endoffset; - int err; endoffset = _fdt_node_end_offset(fdt, nodeoffset); - if ((err = fdt_offset_error(endoffset))) - return err; + if (endoffset < 0) + return endoffset; return _blob_splice_struct(fdt, _fdt_offset_ptr(fdt, nodeoffset), endoffset - nodeoffset, 0); @@ -277,7 +276,7 @@ int fdt_open_into(void *fdt, void *buf, int bufsize) if (err) return err; - return FDT_ERR_OK; + return 0; } int fdt_pack(void *fdt) @@ -290,5 +289,5 @@ int fdt_pack(void *fdt) /* FIXME: pack components */ fdt_set_header(fdt, totalsize, _blob_data_size(fdt)); - return FDT_ERR_OK; + return 0; } diff --git a/fdt_sw.c b/fdt_sw.c index 806b259..41d4891 100644 --- a/fdt_sw.c +++ b/fdt_sw.c @@ -26,7 +26,7 @@ static int check_header_sw(void *fdt) { if (fdt_magic(fdt) != SW_MAGIC) - return FDT_ERR_BADMAGIC; + return -FDT_ERR_BADMAGIC; return 0; } @@ -50,7 +50,7 @@ int fdt_create(void *buf, int bufsize) void *fdt = buf; if (bufsize < sizeof(struct fdt_header)) - return FDT_ERR_NOSPACE; + return -FDT_ERR_NOSPACE; memset(buf, 0, bufsize); @@ -64,7 +64,7 @@ int fdt_create(void *buf, int bufsize) fdt_set_header(fdt, off_dt_struct, fdt_off_mem_rsvmap(fdt)); fdt_set_header(fdt, off_dt_strings, bufsize); - return FDT_ERR_OK; + return 0; } int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) @@ -76,11 +76,11 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) if (err) return err; if (fdt_size_dt_struct(fdt)) - return FDT_ERR_BADSTATE; + return -FDT_ERR_BADSTATE; offset = fdt_off_dt_struct(fdt); if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) - return FDT_ERR_NOSPACE; + return -FDT_ERR_NOSPACE; re = (struct fdt_reserve_entry *)((void *)fdt + offset); re->address = cpu_to_fdt64(addr); @@ -107,7 +107,7 @@ int fdt_begin_node(void *fdt, const char *name) nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE)); if (! nh) - return FDT_ERR_NOSPACE; + return -FDT_ERR_NOSPACE; nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); memcpy(nh->name, name, namelen); @@ -124,7 +124,7 @@ int fdt_end_node(void *fdt) en = grab_space(fdt, FDT_TAGSIZE); if (! en) - return FDT_ERR_NOSPACE; + return -FDT_ERR_NOSPACE; *en = cpu_to_fdt32(FDT_END_NODE); return 0; @@ -164,11 +164,11 @@ int fdt_property(void *fdt, const char *name, const void *val, int len) nameoff = find_add_string(fdt, name); if (nameoff == 0) - return FDT_ERR_NOSPACE; + return -FDT_ERR_NOSPACE; prop = grab_space(fdt, sizeof(*prop) + ALIGN(len, FDT_TAGSIZE)); if (! prop) - return FDT_ERR_NOSPACE; + return -FDT_ERR_NOSPACE; prop->tag = cpu_to_fdt32(FDT_PROP); prop->nameoff = cpu_to_fdt32(nameoff); @@ -192,7 +192,7 @@ int fdt_finish(void *fdt) /* Add terminator */ end = grab_space(fdt, sizeof(*end)); if (! end) - return FDT_ERR_NOSPACE; + return -FDT_ERR_NOSPACE; *end = cpu_to_fdt32(FDT_END); /* Relocate the string table */ @@ -210,7 +210,7 @@ int fdt_finish(void *fdt) int nameoff; if (! prop) - return FDT_ERR_BADSTRUCTURE; + return -FDT_ERR_BADSTRUCTURE; nameoff = fdt32_to_cpu(prop->nameoff); nameoff += fdt_size_dt_strings(fdt); diff --git a/fdt_wip.c b/fdt_wip.c index 88b9ba2..943fb68 100644 --- a/fdt_wip.c +++ b/fdt_wip.c @@ -31,10 +31,10 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, propval = fdt_getprop(fdt, nodeoffset, name, &proplen); if (! propval) - return -proplen; + return proplen; if (proplen != len) - return FDT_ERR_SIZE_MISMATCH; + return -FDT_ERR_SIZE_MISMATCH; memcpy(propval, val, len); return 0; @@ -55,7 +55,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name) prop = fdt_get_property(fdt, nodeoffset, name, &len); if (! prop) - return -len; + return len; nop_region(prop, len + sizeof(*prop)); @@ -70,7 +70,7 @@ int _fdt_node_end_offset(void *fdt, int nodeoffset) tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); if (tag != FDT_BEGIN_NODE) - return FDT_ERR_BADOFFSET; + return -FDT_ERR_BADOFFSET; do { offset = nextoffset; tag = _fdt_next_tag(fdt, offset, &nextoffset); @@ -92,7 +92,7 @@ int _fdt_node_end_offset(void *fdt, int nodeoffset) break; default: - return FDT_ERR_BADSTRUCTURE; + return -FDT_ERR_BADSTRUCTURE; } } while (level >= 0); @@ -102,11 +102,10 @@ int _fdt_node_end_offset(void *fdt, int nodeoffset) int fdt_nop_node(void *fdt, int nodeoffset) { int endoffset; - int err; endoffset = _fdt_node_end_offset(fdt, nodeoffset); - if ((err = fdt_offset_error(endoffset))) - return err; + if (endoffset < 0) + return endoffset; nop_region(fdt_offset_ptr(fdt, nodeoffset, 0), endoffset - nodeoffset); return 0; diff --git a/libfdt.h b/libfdt.h index 062e8bf..cf6ad19 100644 --- a/libfdt.h +++ b/libfdt.h @@ -66,12 +66,6 @@ void *fdt_offset_ptr(const void *fdt, int offset, int checklen); #define fdt_offset_ptr_typed(fdt, offset, var) \ ((typeof(var))(fdt_offset_ptr((fdt), (offset), sizeof(*(var))))) -#define fdt_offset_error(offset) \ - ( (offset) < 0 ? -(offset) : 0 ) - -#define fdt_ptrlen_error(p, len) \ - ( (p) ? 0 : -(len) ) - int fdt_move(const void *fdt, void *buf, int bufsize); /* Read-only functions */ diff --git a/libfdt_internal.h b/libfdt_internal.h index b6c845f..124bef7 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -36,8 +36,6 @@ static inline void *_fdt_offset_ptr(const struct fdt_header *fdt, int offset) return (void *)fdt + fdt_off_dt_struct(fdt) + offset; } -#define OFFSET_ERROR(code) -(code) - #define SW_MAGIC (~FDT_MAGIC) #endif /* _LIBFDT_INTERNAL_H */ diff --git a/tests/del_node.c b/tests/del_node.c index 87be4b5..56f7cf5 100644 --- a/tests/del_node.c +++ b/tests/del_node.c @@ -42,19 +42,21 @@ int main(int argc, char *argv[]) oldsize = fdt_totalsize(fdt); subnode1_offset = fdt_path_offset(fdt, "/subnode1"); - if ((err = fdt_offset_error(subnode1_offset))) - FAIL("Couldn't find \"/subnode1\": %s", fdt_strerror(err)); + if (subnode1_offset < 0) + FAIL("Couldn't find \"/subnode1\": %s", + fdt_strerror(subnode1_offset)); check_getprop_typed(fdt, subnode1_offset, "prop-int", TEST_VALUE_1); subnode2_offset = fdt_path_offset(fdt, "/subnode2"); - if ((err = fdt_offset_error(subnode2_offset))) - FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(err)); + if (subnode2_offset < 0) + FAIL("Couldn't find \"/subnode2\": %s", + fdt_strerror(subnode2_offset)); check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); - if ((err = fdt_offset_error(subsubnode2_offset))) + if (subsubnode2_offset < 0) FAIL("Couldn't find \"/subnode2/subsubnode\": %s", - fdt_strerror(err)); + fdt_strerror(subsubnode2_offset)); check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); err = fdt_del_node(fdt, subnode1_offset); @@ -62,19 +64,21 @@ int main(int argc, char *argv[]) FAIL("fdt_del_node(subnode1): %s", fdt_strerror(err)); subnode1_offset = fdt_path_offset(fdt, "/subnode1"); - if ((err = fdt_offset_error(subnode1_offset)) != FDT_ERR_NOTFOUND) + if (subnode1_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"", - fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + fdt_strerror(subnode1_offset), + fdt_strerror(-FDT_ERR_NOTFOUND)); subnode2_offset = fdt_path_offset(fdt, "/subnode2"); - if ((err = fdt_offset_error(subnode2_offset))) - FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(err)); + if (subnode2_offset < 0) + FAIL("Couldn't find \"/subnode2\": %s", + fdt_strerror(subnode2_offset)); check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); - if ((err = fdt_offset_error(subsubnode2_offset))) + if (subsubnode2_offset < 0) FAIL("Couldn't find \"/subnode2/subsubnode\": %s", - fdt_strerror(err)); + fdt_strerror(subsubnode2_offset)); check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); err = fdt_del_node(fdt, subnode2_offset); @@ -82,19 +86,22 @@ int main(int argc, char *argv[]) FAIL("fdt_del_node(subnode2): %s", fdt_strerror(err)); subnode1_offset = fdt_path_offset(fdt, "/subnode1"); - if ((err = fdt_offset_error(subnode1_offset)) != FDT_ERR_NOTFOUND) + if (subnode1_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"", - fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + fdt_strerror(subnode1_offset), + fdt_strerror(-FDT_ERR_NOTFOUND)); subnode2_offset = fdt_path_offset(fdt, "/subnode2"); - if ((err = fdt_offset_error(subnode2_offset)) != FDT_ERR_NOTFOUND) + if (subnode2_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subnode2) returned \"%s\" instead of \"%s\"", - fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + fdt_strerror(subnode2_offset), + fdt_strerror(-FDT_ERR_NOTFOUND)); subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); - if ((err = fdt_offset_error(subsubnode2_offset)) != FDT_ERR_NOTFOUND) + if (subsubnode2_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subsubnode2) returned \"%s\" instead of \"%s\"", - fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + fdt_strerror(subsubnode2_offset), + fdt_strerror(-FDT_ERR_NOTFOUND)); delsize = fdt_totalsize(fdt); diff --git a/tests/del_property.c b/tests/del_property.c index 2f43dd9..cc0de98 100644 --- a/tests/del_property.c +++ b/tests/del_property.c @@ -52,8 +52,9 @@ int main(int argc, char *argv[]) intp = fdt_getprop(fdt, 0, "prop-int", &lenerr); if (intp) FAIL("prop-int still present after deletion"); - if ((err = fdt_ptrlen_error(intp, lenerr)) != FDT_ERR_NOTFOUND) - FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); + if (lenerr != -FDT_ERR_NOTFOUND) + FAIL("Unexpected error on second getprop: %s", + fdt_strerror(lenerr)); strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1); @@ -65,8 +66,9 @@ int main(int argc, char *argv[]) strp = fdt_getprop(fdt, 0, "prop-str", &lenerr); if (strp) FAIL("prop-str still present after deletion"); - if ((err = fdt_ptrlen_error(strp, lenerr)) != FDT_ERR_NOTFOUND) - FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); + if (lenerr != -FDT_ERR_NOTFOUND) + FAIL("Unexpected error on second getprop: %s", + fdt_strerror(lenerr)); delsize = fdt_totalsize(fdt); diff --git a/tests/nop_node.c b/tests/nop_node.c index 2db1b29..d09d9df 100644 --- a/tests/nop_node.c +++ b/tests/nop_node.c @@ -39,19 +39,21 @@ int main(int argc, char *argv[]) fdt = load_blob_arg(argc, argv); subnode1_offset = fdt_path_offset(fdt, "/subnode1"); - if ((err = fdt_offset_error(subnode1_offset))) - FAIL("Couldn't find \"/subnode1\": %s", fdt_strerror(err)); + if (subnode1_offset < 0) + FAIL("Couldn't find \"/subnode1\": %s", + fdt_strerror(subnode1_offset)); check_getprop_typed(fdt, subnode1_offset, "prop-int", TEST_VALUE_1); subnode2_offset = fdt_path_offset(fdt, "/subnode2"); - if ((err = fdt_offset_error(subnode2_offset))) - FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(err)); + if (subnode2_offset < 0) + FAIL("Couldn't find \"/subnode2\": %s", + fdt_strerror(subnode2_offset)); check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); - + subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); - if ((err = fdt_offset_error(subsubnode2_offset))) + if (subsubnode2_offset < 0) FAIL("Couldn't find \"/subnode2/subsubnode\": %s", - fdt_strerror(err)); + fdt_strerror(subsubnode2_offset)); check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); err = fdt_nop_node(fdt, subnode1_offset); @@ -59,19 +61,21 @@ int main(int argc, char *argv[]) FAIL("fdt_nop_node(subnode1): %s", fdt_strerror(err)); subnode1_offset = fdt_path_offset(fdt, "/subnode1"); - if ((err = fdt_offset_error(subnode1_offset)) != FDT_ERR_NOTFOUND) + if (subnode1_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"", - fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + fdt_strerror(subnode1_offset), + fdt_strerror(-FDT_ERR_NOTFOUND)); subnode2_offset = fdt_path_offset(fdt, "/subnode2"); - if ((err = fdt_offset_error(subnode2_offset))) - FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(err)); + if (subnode2_offset < 0) + FAIL("Couldn't find \"/subnode2\": %s", + fdt_strerror(subnode2_offset)); check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); - + subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); - if ((err = fdt_offset_error(subsubnode2_offset))) + if (subsubnode2_offset < 0) FAIL("Couldn't find \"/subnode2/subsubnode\": %s", - fdt_strerror(err)); + fdt_strerror(subsubnode2_offset)); check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); err = fdt_nop_node(fdt, subnode2_offset); @@ -79,19 +83,22 @@ int main(int argc, char *argv[]) FAIL("fdt_nop_node(subnode2): %s", fdt_strerror(err)); subnode1_offset = fdt_path_offset(fdt, "/subnode1"); - if ((err = fdt_offset_error(subnode1_offset)) != FDT_ERR_NOTFOUND) + if (subnode1_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"", - fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + fdt_strerror(subnode1_offset), + fdt_strerror(-FDT_ERR_NOTFOUND)); subnode2_offset = fdt_path_offset(fdt, "/subnode2"); - if ((err = fdt_offset_error(subnode2_offset)) != FDT_ERR_NOTFOUND) + if (subnode2_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subnode2) returned \"%s\" instead of \"%s\"", - fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); - + fdt_strerror(subnode2_offset), + fdt_strerror(-FDT_ERR_NOTFOUND)); + subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); - if ((err = fdt_offset_error(subsubnode2_offset)) != FDT_ERR_NOTFOUND) + if (subsubnode2_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subsubnode2) returned \"%s\" instead of \"%s\"", - fdt_strerror(err), fdt_strerror(FDT_ERR_NOTFOUND)); + fdt_strerror(subsubnode2_offset), + fdt_strerror(-FDT_ERR_NOTFOUND)); PASS(); } diff --git a/tests/nop_property.c b/tests/nop_property.c index 3314ee4..858527d 100644 --- a/tests/nop_property.c +++ b/tests/nop_property.c @@ -50,7 +50,7 @@ int main(int argc, char *argv[]) intp = fdt_getprop(fdt, 0, "prop-int", &lenerr); if (intp) FAIL("prop-int still present after nopping"); - if ((err = fdt_ptrlen_error(intp, lenerr)) != FDT_ERR_NOTFOUND) + if (lenerr != -FDT_ERR_NOTFOUND) FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) strp = fdt_getprop(fdt, 0, "prop-str", &lenerr); if (strp) FAIL("prop-str still present after nopping"); - if ((err = fdt_ptrlen_error(strp, lenerr)) != FDT_ERR_NOTFOUND) + if (lenerr != -FDT_ERR_NOTFOUND) FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); PASS(); diff --git a/tests/notfound.c b/tests/notfound.c index c1120ff..b411249 100644 --- a/tests/notfound.c +++ b/tests/notfound.c @@ -29,8 +29,8 @@ void check_error(const char *s, int err) { - if (err != FDT_ERR_NOTFOUND) - FAIL("%s return error %s instead of FDT_ERR_NOTFOUND", s, + if (err != -FDT_ERR_NOTFOUND) + FAIL("%s return error %s instead of -FDT_ERR_NOTFOUND", s, fdt_strerror(err)); } @@ -41,38 +41,32 @@ int main(int argc, char *argv[]) int offset; int subnode1_offset; void *val; - int err; int lenerr; test_init(argc, argv); fdt = load_blob_arg(argc, argv); prop = fdt_get_property(fdt, 0, "nonexistant-property", &lenerr); - check_error("fdt_get_property(\"nonexistant-property\")", - fdt_ptrlen_error(prop, lenerr)); + check_error("fdt_get_property(\"nonexistant-property\")", lenerr); val = fdt_getprop(fdt, 0, "nonexistant-property", &lenerr); - check_error("fdt_getprop(\"nonexistant-property\"", - fdt_ptrlen_error(val, lenerr)); + check_error("fdt_getprop(\"nonexistant-property\"", lenerr); subnode1_offset = fdt_subnode_offset(fdt, 0, "subnode1"); - if ((err = fdt_offset_error(subnode1_offset))) - FAIL("Couldn't find subnode1: %s", fdt_strerror(err)); + if (subnode1_offset < 0) + FAIL("Couldn't find subnode1: %s", fdt_strerror(subnode1_offset)); val = fdt_getprop(fdt, subnode1_offset, "prop-str", &lenerr); - check_error("fdt_getprop(\"prop-str\")", fdt_ptrlen_error(val, lenerr)); + check_error("fdt_getprop(\"prop-str\")", lenerr); offset = fdt_subnode_offset(fdt, 0, "nonexistant-subnode"); - check_error("fdt_subnode_offset(\"nonexistant-subnode\")", - fdt_offset_error(offset)); + check_error("fdt_subnode_offset(\"nonexistant-subnode\")", offset); offset = fdt_subnode_offset(fdt, 0, "subsubnode"); - check_error("fdt_subnode_offset(\"subsubnode\")", - fdt_offset_error(offset)); + check_error("fdt_subnode_offset(\"subsubnode\")", offset); offset = fdt_path_offset(fdt, "/nonexistant-subnode"); - check_error("fdt_path_offset(\"/nonexistant-subnode\")", - fdt_offset_error(offset)); + check_error("fdt_path_offset(\"/nonexistant-subnode\")", offset); PASS(); } diff --git a/tests/path_offset.c b/tests/path_offset.c index 5d5a246..42e5daa 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -30,15 +30,14 @@ int check_subnode(void *fdt, int parent, const char *name) { int offset; - int err; struct fdt_node_header *nh; uint32_t tag; verbose_printf("Checking subnode \"%s\" of %d...", name, parent); offset = fdt_subnode_offset(fdt, parent, name); verbose_printf("offset %d...", offset); - if ((err = fdt_offset_error(offset))) - FAIL("fdt_subnode_offset(\"%s\"): %s", name, fdt_strerror(err)); + if (offset < 0) + FAIL("fdt_subnode_offset(\"%s\"): %s", name, fdt_strerror(offset)); nh = fdt_offset_ptr_typed(fdt, offset, nh); verbose_printf("pointer %p\n", nh); if (! nh) diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c index cc5b926..ffd2c3a 100644 --- a/tests/rw_tree1.c +++ b/tests/rw_tree1.c @@ -40,9 +40,9 @@ #define OFF_CHECK(off, code) \ { \ - err = fdt_offset_error((off) = (code)); \ - if (err) \ - FAIL(#code ": %s", fdt_strerror(err)); \ + (off) = (code); \ + if (off < 0) \ + FAIL(#code ": %s", fdt_strerror(off)); \ } int main(int argc, char *argv[]) diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c index 3283e1a..a2b12eb 100644 --- a/tests/subnode_offset.c +++ b/tests/subnode_offset.c @@ -30,15 +30,14 @@ int check_subnode(struct fdt_header *fdt, int parent, const char *name) { int offset; - int err; struct fdt_node_header *nh; uint32_t tag; verbose_printf("Checking subnode \"%s\" of %d...", name, parent); offset = fdt_subnode_offset(fdt, parent, name); verbose_printf("offset %d...", offset); - if ((err = fdt_offset_error(offset))) - FAIL("fdt_subnode_offset(\"%s\"): %s", name, fdt_strerror(err)); + if (offset < 0) + FAIL("fdt_subnode_offset(\"%s\"): %s", name, fdt_strerror(offset)); nh = fdt_offset_ptr_typed(fdt, offset, nh); verbose_printf("pointer %p\n", nh); if (! nh) diff --git a/tests/testutils.c b/tests/testutils.c index c3ec0fa..aafcbb0 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -97,10 +97,12 @@ static struct errtabent errtable[] = { const char *fdt_strerror(int errval) { - if ((errval >= 0) && (errval < ERRTABSIZE)) - return errtable[errval].str; + if (errval > 0) + return ""; + else if (errval < -ERRTABSIZE) + return ""; else - return "Unknown FDT error code"; + return errtable[-errval].str; } void check_property(void *fdt, int nodeoffset, const char *name, diff --git a/tests/truncated_property.c b/tests/truncated_property.c index 2bd25d4..c5be466 100644 --- a/tests/truncated_property.c +++ b/tests/truncated_property.c @@ -40,10 +40,9 @@ int main(int argc, char *argv[]) prop = fdt_getprop(fdt, 0, "truncated", &len); if (prop) FAIL("fdt_getprop() succeeded on truncated property"); - err = fdt_ptrlen_error(prop, len); - if (err != FDT_ERR_BADSTRUCTURE) + if (len != -FDT_ERR_BADSTRUCTURE) FAIL("fdt_getprop() failed with \"%s\" instead of \"%s\"", - fdt_strerror(err), fdt_strerror(FDT_ERR_BADSTRUCTURE)); + fdt_strerror(err), fdt_strerror(-FDT_ERR_BADSTRUCTURE)); PASS(); } From 3aea82850164d49678a684bda11203da8d7e25ce Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 15 Dec 2006 15:12:52 +1100 Subject: [PATCH 0032/1198] libfdt: Clean up error codes First, this patch removes several underused error codes: FDT_ERR_BADPOINTER and FDT_ERR_BADHEADER were not used at all and are simply removed. FDT_ERR_SIZE_MISMATCH was very similar in spirit to FDT_ERR_NOSPACE, and used only in circumstances where there can be no confusion between the two, so is removed and folded into FDT_ERR_NOSPACE. FDT_ERR_INTERAL was used on only one place, on a "can't happen" check. It seems of little value so the check and error code are removed also. Second, the error codes have been re-numbered and grouped roughly by severity. That is codes which can reasonably occur in normal operation separated from those which indicate bad parameters (and therefore a bug in the caller) or a bad or corrupted device tree blob. Third the test function fdt_strerror() is cleaned up a little based on these changes. Signed-off-by: David Gibson --- fdt_ro.c | 3 --- fdt_wip.c | 2 +- libfdt.h | 35 +++++++++++++++++------------------ tests/testutils.c | 34 +++++++++++++++++++--------------- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/fdt_ro.c b/fdt_ro.c index 7db7f12..9112c6a 100644 --- a/fdt_ro.c +++ b/fdt_ro.c @@ -161,9 +161,6 @@ struct fdt_property *fdt_get_property(const void *fdt, do { offset = nextoffset; - err = -FDT_ERR_INTERNAL; - if (offset % FDT_TAGSIZE) - goto fail; tag = _fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { diff --git a/fdt_wip.c b/fdt_wip.c index 943fb68..0db7d25 100644 --- a/fdt_wip.c +++ b/fdt_wip.c @@ -34,7 +34,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, return proplen; if (proplen != len) - return -FDT_ERR_SIZE_MISMATCH; + return -FDT_ERR_NOSPACE; memcpy(propval, val, len); return 0; diff --git a/libfdt.h b/libfdt.h index cf6ad19..8ba2daf 100644 --- a/libfdt.h +++ b/libfdt.h @@ -25,25 +25,24 @@ #define FDT_FIRST_SUPPORTED_VERSION 0x10 #define FDT_LAST_SUPPORTED_VERSION 0x11 -/* Errors */ -#define FDT_ERR_OK 0 -#define FDT_ERR_BADMAGIC 1 -#define FDT_ERR_BADVERSION 2 -#define FDT_ERR_BADPOINTER 3 -#define FDT_ERR_BADHEADER 4 -#define FDT_ERR_BADSTRUCTURE 5 -#define FDT_ERR_BADOFFSET 6 -#define FDT_ERR_NOTFOUND 7 -#define FDT_ERR_BADPATH 8 -#define FDT_ERR_TRUNCATED 9 -#define FDT_ERR_NOSPACE 10 -#define FDT_ERR_BADSTATE 11 -#define FDT_ERR_SIZE_MISMATCH 12 -#define FDT_ERR_INTERNAL 13 -#define FDT_ERR_BADLAYOUT 14 -#define FDT_ERR_EXISTS 15 +/* Error codes: informative error codes */ +#define FDT_ERR_NOTFOUND 1 +#define FDT_ERR_EXISTS 2 +#define FDT_ERR_NOSPACE 3 -#define FDT_ERR_MAX 14 +/* Error codes: codes for bad parameters */ +#define FDT_ERR_BADOFFSET 4 +#define FDT_ERR_BADPATH 5 +#define FDT_ERR_BADSTATE 6 + +/* Error codes: codes for bad device tree blobs */ +#define FDT_ERR_TRUNCATED 7 +#define FDT_ERR_BADMAGIC 8 +#define FDT_ERR_BADVERSION 9 +#define FDT_ERR_BADSTRUCTURE 10 +#define FDT_ERR_BADLAYOUT 11 + +#define FDT_ERR_MAX 11 #define fdt_get_header(fdt, field) \ (fdt32_to_cpu(((struct fdt_header *)(fdt))->field)) diff --git a/tests/testutils.c b/tests/testutils.c index aafcbb0..f411067 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -77,20 +77,18 @@ struct errtabent { [(val)] = { .str = #val, } static struct errtabent errtable[] = { - ERRTABENT(FDT_ERR_OK), + ERRTABENT(FDT_ERR_NOTFOUND), + ERRTABENT(FDT_ERR_EXISTS), + ERRTABENT(FDT_ERR_NOSPACE), + + ERRTABENT(FDT_ERR_BADOFFSET), + ERRTABENT(FDT_ERR_BADPATH), + ERRTABENT(FDT_ERR_BADSTATE), + + ERRTABENT(FDT_ERR_TRUNCATED), ERRTABENT(FDT_ERR_BADMAGIC), ERRTABENT(FDT_ERR_BADVERSION), - ERRTABENT(FDT_ERR_BADPOINTER), - ERRTABENT(FDT_ERR_BADHEADER), ERRTABENT(FDT_ERR_BADSTRUCTURE), - ERRTABENT(FDT_ERR_BADOFFSET), - ERRTABENT(FDT_ERR_NOTFOUND), - ERRTABENT(FDT_ERR_BADPATH), - ERRTABENT(FDT_ERR_TRUNCATED), - ERRTABENT(FDT_ERR_NOSPACE), - ERRTABENT(FDT_ERR_BADSTATE), - ERRTABENT(FDT_ERR_SIZE_MISMATCH), - ERRTABENT(FDT_ERR_INTERNAL), }; #define ERRTABSIZE (sizeof(errtable) / sizeof(errtable[0])) @@ -99,10 +97,16 @@ const char *fdt_strerror(int errval) { if (errval > 0) return ""; - else if (errval < -ERRTABSIZE) - return ""; - else - return errtable[-errval].str; + else if (errval == 0) + return ""; + else if (errval > -ERRTABSIZE) { + const char *s = errtable[-errval].str; + + if (s) + return s; + } + + return ""; } void check_property(void *fdt, int nodeoffset, const char *name, From 209c5e56d2fcd1c7432f43f58f768855a6d655d3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 21 Dec 2006 09:57:02 +1100 Subject: [PATCH 0033/1198] libfdt: Add TODO file Add a TODO file to keep track of future plans for libfdt. Signed-off-by: David Gibson --- TODO | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 TODO diff --git a/TODO b/TODO new file mode 100644 index 0000000..cd796f6 --- /dev/null +++ b/TODO @@ -0,0 +1,6 @@ +- Move fdt_strerror() to core library for convenience +- Find node by linux,phandle property +- Tree traversal functions +- Graft function +- Merge into dtc +- Make fdt_open_into() re-arrange properly From 5b344f9c5aaff698715ffd113164c9cff45d5d2f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 21 Dec 2006 09:57:08 +1100 Subject: [PATCH 0034/1198] libfdt: Add fdt_strerror() function to library This function moves the fdt_strerror() function, currently found in the test code into the fdt library proper. This makes life easier for any library users who want to provide meaningful error messages. The function goes into a module of its own, so that users who don't need the function won't get a copy of it linked in. Signed-off-by: David Gibson --- Makefile | 2 +- TODO | 1 - fdt_strerror.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++ libfdt.h | 3 +++ tests/tests.h | 1 - tests/testutils.c | 41 ------------------------------ 6 files changed, 67 insertions(+), 44 deletions(-) create mode 100644 fdt_strerror.c diff --git a/Makefile b/Makefile index d464a82..c8240bb 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ PREFIX = /usr/local TARGETLIBS = libfdt.a -LIBOBJS = fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o +LIBOBJS = fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o fdt_strerror.o SOURCE = $(shell find . -maxdepth 1 ! -name version.h -a -name '*.[h]') SOURCE += *.c Makefile diff --git a/TODO b/TODO index cd796f6..794d0a6 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,3 @@ -- Move fdt_strerror() to core library for convenience - Find node by linux,phandle property - Tree traversal functions - Graft function diff --git a/fdt_strerror.c b/fdt_strerror.c new file mode 100644 index 0000000..74c97e7 --- /dev/null +++ b/fdt_strerror.c @@ -0,0 +1,63 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +struct errtabent { + const char *str; +}; + +#define ERRTABENT(val) \ + [(val)] = { .str = #val, } + +static struct errtabent errtable[] = { + ERRTABENT(FDT_ERR_NOTFOUND), + ERRTABENT(FDT_ERR_EXISTS), + ERRTABENT(FDT_ERR_NOSPACE), + + ERRTABENT(FDT_ERR_BADOFFSET), + ERRTABENT(FDT_ERR_BADPATH), + ERRTABENT(FDT_ERR_BADSTATE), + + ERRTABENT(FDT_ERR_TRUNCATED), + ERRTABENT(FDT_ERR_BADMAGIC), + ERRTABENT(FDT_ERR_BADVERSION), + ERRTABENT(FDT_ERR_BADSTRUCTURE), +}; +#define ERRTABSIZE (sizeof(errtable) / sizeof(errtable[0])) + +const char *fdt_strerror(int errval) +{ + if (errval > 0) + return ""; + else if (errval == 0) + return ""; + else if (errval > -ERRTABSIZE) { + const char *s = errtable[-errval].str; + + if (s) + return s; + } + + return ""; +} diff --git a/libfdt.h b/libfdt.h index 8ba2daf..acdc72e 100644 --- a/libfdt.h +++ b/libfdt.h @@ -129,4 +129,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, int fdt_add_subnode(void *fdt, int parentoffset, const char *name); int fdt_del_node(void *fdt, int nodeoffset); +/* Extra functions */ +const char *fdt_strerror(int errval); + #endif /* _LIBFDT_H */ diff --git a/tests/tests.h b/tests/tests.h index b4dd10a..b262e31 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -108,7 +108,6 @@ static inline void *xrealloc(void *p, size_t size) return p; } -const char *fdt_strerror(int errval); void check_property(void *fdt, int nodeoffset, const char *name, int len, const void *val); #define check_property_typed(fdt, nodeoffset, name, val) \ diff --git a/tests/testutils.c b/tests/testutils.c index f411067..9637415 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -68,47 +68,6 @@ void test_init(int argc, char *argv[]) test_name, getpid()); } - -struct errtabent { - const char *str; -}; - -#define ERRTABENT(val) \ - [(val)] = { .str = #val, } - -static struct errtabent errtable[] = { - ERRTABENT(FDT_ERR_NOTFOUND), - ERRTABENT(FDT_ERR_EXISTS), - ERRTABENT(FDT_ERR_NOSPACE), - - ERRTABENT(FDT_ERR_BADOFFSET), - ERRTABENT(FDT_ERR_BADPATH), - ERRTABENT(FDT_ERR_BADSTATE), - - ERRTABENT(FDT_ERR_TRUNCATED), - ERRTABENT(FDT_ERR_BADMAGIC), - ERRTABENT(FDT_ERR_BADVERSION), - ERRTABENT(FDT_ERR_BADSTRUCTURE), -}; - -#define ERRTABSIZE (sizeof(errtable) / sizeof(errtable[0])) - -const char *fdt_strerror(int errval) -{ - if (errval > 0) - return ""; - else if (errval == 0) - return ""; - else if (errval > -ERRTABSIZE) { - const char *s = errtable[-errval].str; - - if (s) - return s; - } - - return ""; -} - void check_property(void *fdt, int nodeoffset, const char *name, int len, const void *val) { From e6dd3f1d3cf54558187aa2a180cf4ad4ab10d8ad Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 29 Jan 2007 15:30:59 +1100 Subject: [PATCH 0035/1198] Remove check for linux,platform property in /chosen The linux,platform property in /chosen was obsolete almost as soon as it was invented. Remove the check for it from dtc, which just tends to lead to irritating spurious failures. Signed-off-by: David Gibson --- livetree.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/livetree.c b/livetree.c index 72d194a..3e06b31 100644 --- a/livetree.c +++ b/livetree.c @@ -568,8 +568,6 @@ static int check_chosen(struct node *root) return 0; } - CHECK_HAVE_ONECELL(chosen, "linux,platform"); - CHECK_HAVE_WARN_STRING(chosen, "bootargs"); CHECK_HAVE_WARN_STRING(chosen, "linux,stdout-path"); CHECK_HAVE_WARN_PHANDLE(chosen, "interrupt-controller", root); From 54382390e40654957e16da7ba48ee86822ffe590 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 31 Jan 2007 15:45:26 +1100 Subject: [PATCH 0036/1198] Bugfix for CHECK_HAVE_WARN_PHANDLE() At present, the tree checking code in dtc will die with an assertion failure if given a tree which has the invalid value 0 or -1 in a property which should contain a phandle. This patch fixes the check to die more gracefully with an error message indicating the invalid phandle value. Signed-off-by: David Gibson --- livetree.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/livetree.c b/livetree.c index 3e06b31..9ace56c 100644 --- a/livetree.c +++ b/livetree.c @@ -427,9 +427,14 @@ static int check_structure(struct node *tree) struct node *ref; \ CHECK_HAVE_WARN_ONECELL((xnode), (propname)); \ if (prop) {\ - ref = get_node_by_phandle((root), propval_cell(prop)); \ - if (! ref) \ - DO_ERR("\"%s\" property in %s refers to non-existant phandle %x\n", (propname), (xnode)->fullpath, propval_cell(prop)); \ + cell_t phandle = propval_cell(prop); \ + if ((phandle == 0) || (phandle == -1)) { \ + DO_ERR("\"%s\" property in %s contains an invalid phandle %x\n", (propname), (xnode)->fullpath, phandle); \ + } else { \ + ref = get_node_by_phandle((root), propval_cell(prop)); \ + if (! ref) \ + DO_ERR("\"%s\" property in %s refers to non-existant phandle %x\n", (propname), (xnode)->fullpath, propval_cell(prop)); \ + } \ } \ } while (0) From 32da475af165a0e1e274aa9a8bbdfb873831efa7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 7 Feb 2007 16:37:50 +1100 Subject: [PATCH 0037/1198] Allow multipart property values At present each property definition in a dts file must give as the value either a string ("abc..."), a bytestring ([12abcd...]) or a cell list (<1 2 3 ...>). This patch allows a property value to be given as several of these, comma-separated. The final property value is just the components appended together. So a property could have a list of cells followed by a string, or a bytestring followed by some cells. Cells are always aligned, so if cells are given following a string or bytestring which is not a multiple of 4 bytes long, zero bytes are inserted to align the following cells. The primary motivation for this feature, however, is to allow defining a property as a list of several strings. This is what's needed for defining OF 'compatible' properties, and is less ugly and fiddly than using embedded \0s in the strings. Signed-off-by: David Gibson Signed-off-by: Jon Loeliger --- data.c | 27 +++++++++++++++++++++++++++ dtc-lexer.l | 9 +++++++++ dtc-parser.y | 13 ++++++++++--- dtc.h | 1 + test.dts | 3 ++- 5 files changed, 49 insertions(+), 4 deletions(-) diff --git a/data.c b/data.c index d3b55f9..1907a1a 100644 --- a/data.c +++ b/data.c @@ -197,6 +197,33 @@ struct data data_append_data(struct data d, void *p, int len) return d; } +struct data data_merge(struct data d1, struct data d2) +{ + struct data d; + struct fixup **ff; + struct fixup *f, *f2; + + d = data_append_data(d1, d2.val, d2.len); + + /* Extract d2's fixups */ + f2 = d2.refs; + d2.refs = NULL; + + /* Tack them onto d's list of fixups */ + ff = &d.refs; + while (*ff) + ff = &((*ff)->next); + *ff = f2; + + /* And correct them for their new position */ + for (f = f2; f; f = f->next) + f->offset += d1.len; + + data_free(d2); + + return d; +} + struct data data_append_cell(struct data d, cell_t word) { cell_t beword = cpu_to_be32(word); diff --git a/dtc-lexer.l b/dtc-lexer.l index c082228..6146bad 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -123,6 +123,15 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) return ']'; } +, { /* Technically this is a valid property name, + but we'd rather use it as punctuation, so detect it + here in preference */ + yylloc.first_line = yylineno; + DPRINT("Char (propname like): %c (\\x%02x)\n", yytext[0], + (unsigned)yytext[0]); + return yytext[0]; + } + {PROPCHAR}+ { yylloc.first_line = yylineno; DPRINT("PropName: %s\n", yytext); diff --git a/dtc-parser.y b/dtc-parser.y index 16d2277..bd725fe 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -58,6 +58,7 @@ extern struct boot_info *the_boot_info; %token DT_REF %type propdata +%type propdataprefix %type memreserve %type memreserves %type celllist @@ -121,9 +122,15 @@ propdef: label DT_PROPNAME '=' propdata ';' { } ; -propdata: DT_STRING { $$ = $1; } - | '<' celllist '>' { $$ = $2; } - | '[' bytestring ']' { $$ = $2; } +propdata: propdataprefix DT_STRING { $$ = data_merge($1, $2); } + | propdataprefix '<' celllist '>' { + $$ = data_merge(data_append_align($1, sizeof(cell_t)), $3); + } + | propdataprefix '[' bytestring ']' { $$ = data_merge($1, $3); } + ; + +propdataprefix: propdata ',' { $$ = $1; } + | /* empty */ { $$ = empty_data; } ; celllist: celllist DT_CELL { $$ = data_append_cell($1, $2); } diff --git a/dtc.h b/dtc.h index 42e9de0..8d3964c 100644 --- a/dtc.h +++ b/dtc.h @@ -119,6 +119,7 @@ struct data data_copy_escape_string(char *s, int len); struct data data_copy_file(FILE *f, size_t len); struct data data_append_data(struct data d, void *p, int len); +struct data data_merge(struct data d1, struct data d2); struct data data_append_cell(struct data d, cell_t word); struct data data_append_re(struct data d, struct reserve_entry *re); struct data data_append_addr(struct data d, u64 addr); diff --git a/test.dts b/test.dts index 742d874..ed2b178 100644 --- a/test.dts +++ b/test.dts @@ -4,7 +4,7 @@ / { model = "MyBoardName"; - compatible = "MyBoardFamilyName"; + compatible = "MyBoardName", "MyBoardFamilyName"; #address-cells = <2>; #size-cells = <2>; @@ -39,6 +39,7 @@ string = "\xff\0stuffstuff\t\t\t\n\n\n"; blob = [0a 0b 0c 0d de ea ad be ef]; ref = < &/memory@0 >; + mixed = "abc", [1234], ; }; memory@0 { From c226ddcabc4272b0734d237d3aee2c21a2fe2387 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 7 Feb 2007 14:29:07 +1100 Subject: [PATCH 0038/1198] Allow references to labels dtc allows nodes to have labels, which at present are just re-emitted as symbols at the appropriate places when using asm-mode output. It also allows "references" where the notation &/path/to/node in a cell list will be replaced with the phandle of the referenced node. This patch extends the reference syntax to allow references to labels instead of just full device paths. This allows nodes deep within the tree to be referenced with a shorter more convenient name. References to labels are distinguished from reference to paths by the fact that paths must start with a /, but labels can never start with a /. Signed-off-by: David Gibson Signed-off-by: Jon Loeliger --- livetree.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/livetree.c b/livetree.c index 9ace56c..ede29fb 100644 --- a/livetree.c +++ b/livetree.c @@ -212,6 +212,24 @@ static struct node *get_node_by_path(struct node *tree, char *path) return NULL; } +static struct node *get_node_by_label(struct node *tree, const char *label) +{ + struct node *child, *node; + + assert(label && (strlen(label) > 0)); + + if (tree->label && streq(tree->label, label)) + return tree; + + for_each_child(tree, child) { + node = get_node_by_label(child, label); + if (node) + return node; + } + + return NULL; +} + static struct node *get_node_by_phandle(struct node *tree, cell_t phandle) { struct node *child, *node; @@ -229,6 +247,7 @@ static struct node *get_node_by_phandle(struct node *tree, cell_t phandle) return NULL; } + /* * Tree checking functions */ @@ -673,9 +692,16 @@ static void apply_fixup(struct node *root, struct property *prop, struct node *refnode; cell_t phandle; - refnode = get_node_by_path(root, f->ref); - if (! refnode) - die("Reference to non-existent node \"%s\"\n", f->ref); + if (f->ref[0] == '/') { + /* Reference to full path */ + refnode = get_node_by_path(root, f->ref); + if (! refnode) + die("Reference to non-existent node \"%s\"\n", f->ref); + } else { + refnode = get_node_by_label(root, f->ref); + if (! refnode) + die("Reference to non-existent node label \"%s\"\n", f->ref); + } phandle = get_node_phandle(root, refnode); From af0278a3a04fabe8349cae89613274da196509ca Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Thu, 15 Feb 2007 10:59:27 -0600 Subject: [PATCH 0039/1198] Add support for decimal, octal and binary based cell values. New syntax d#, b#, o# and h# allow for an explicit prefix on cell values to specify their base. Eg: Signed-off-by: Jon Loeliger --- data.c | 21 +++++++++++++++++++++ dtc-lexer.l | 21 +++++++++++++++------ dtc-parser.y | 16 ++++++++++++++-- dtc.h | 1 + 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/data.c b/data.c index 1907a1a..c6c2350 100644 --- a/data.c +++ b/data.c @@ -19,6 +19,7 @@ */ #include "dtc.h" +#include "dtc-parser.tab.h" void fixup_free(struct fixup *f) { @@ -224,6 +225,26 @@ struct data data_merge(struct data d1, struct data d2) return d; } +/* + * Convert a string representation of a numberic cell + * in the given base into a cell. + */ +cell_t data_convert_cell(char *s, unsigned int base) +{ + cell_t c; + extern YYLTYPE yylloc; + + c = strtoul(s, NULL, base); + if (errno == EINVAL || errno == ERANGE) { + fprintf(stderr, + "Line %d: Invalid cell value '%s'; %d assumed\n", + yylloc.first_line, s, c); + } + + return c; +} + + struct data data_append_cell(struct data d, cell_t word) { cell_t beword = cpu_to_be32(word); diff --git a/dtc-lexer.l b/dtc-lexer.l index 6146bad..93f3268 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -83,15 +83,24 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) BEGIN(INITIAL); return ';'; } +[bodh]# { + yylloc.first_line = yylineno; + if (*yytext == 'b') + yylval.cbase = 2; + else if (*yytext == 'o') + yylval.cbase = 8; + else if (*yytext == 'd') + yylval.cbase = 10; + else + yylval.cbase = 16; + DPRINT("Base: %d\n", yylval.cbase); + return DT_BASE; + } [0-9a-fA-F]+ { yylloc.first_line = yylineno; - if (yyleng > 2*sizeof(yylval.cval)) { - fprintf(stderr, - "Cell value %s too long\n", yytext); - } - yylval.cval = strtoul(yytext, NULL, 16); - DPRINT("Cell: %x\n", yylval.cval); + yylval.str = strdup(yytext); + DPRINT("Cell: '%s'\n", yylval.str); return DT_CELL; } diff --git a/dtc-parser.y b/dtc-parser.y index bd725fe..992fdb1 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -33,6 +33,7 @@ extern struct boot_info *the_boot_info; %union { cell_t cval; + unsigned int cbase; u8 byte; char *str; struct data data; @@ -50,7 +51,8 @@ extern struct boot_info *the_boot_info; %token DT_ADDR %token DT_PROPNAME %token DT_NODENAME -%token DT_CELL +%token DT_BASE +%token DT_CELL %token DT_BYTE %token DT_STRING %token DT_UNIT @@ -61,6 +63,7 @@ extern struct boot_info *the_boot_info; %type propdataprefix %type memreserve %type memreserves +%type opt_cell_base %type celllist %type bytestring %type propdef @@ -133,7 +136,16 @@ propdataprefix: propdata ',' { $$ = $1; } | /* empty */ { $$ = empty_data; } ; -celllist: celllist DT_CELL { $$ = data_append_cell($1, $2); } +opt_cell_base: + /* empty */ + { $$ = 16; } + | DT_BASE + ; + +celllist: celllist opt_cell_base DT_CELL { + $$ = data_append_cell($1, + data_convert_cell($3, $2)); + } | celllist DT_REF { $$ = data_append_cell(data_add_fixup($1, $2), -1); } diff --git a/dtc.h b/dtc.h index 8d3964c..7ee96a5 100644 --- a/dtc.h +++ b/dtc.h @@ -118,6 +118,7 @@ struct data data_copy_mem(char *mem, int len); struct data data_copy_escape_string(char *s, int len); struct data data_copy_file(FILE *f, size_t len); +cell_t data_convert_cell(char *s, unsigned int base); struct data data_append_data(struct data d, void *p, int len); struct data data_merge(struct data d1, struct data d2); struct data data_append_cell(struct data d, cell_t word); From fd84d97deecc23b8519f8bc1f384a418bb69181b Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Thu, 15 Feb 2007 11:02:44 -0600 Subject: [PATCH 0040/1198] Add some initial test cases. Add the original simple test case and a case with different based cell values. Correct output asm files as well as stderr is captured. Signed-off-by: Jon Loeliger --- tests/base01.asm | 175 +++++++++++++++++++++ tests/base01.cmd | 1 + tests/base01.dts | 31 ++++ tests/base01.stderr | 6 + tests/test01.asm | 294 +++++++++++++++++++++++++++++++++++ test.dts => tests/test01.dts | 0 tests/test01.stderr | 4 + 7 files changed, 511 insertions(+) create mode 100644 tests/base01.asm create mode 100644 tests/base01.cmd create mode 100644 tests/base01.dts create mode 100644 tests/base01.stderr create mode 100644 tests/test01.asm rename test.dts => tests/test01.dts (100%) create mode 100644 tests/test01.stderr diff --git a/tests/base01.asm b/tests/base01.asm new file mode 100644 index 0000000..266e446 --- /dev/null +++ b/tests/base01.asm @@ -0,0 +1,175 @@ +/* autogenerated by dtc, do not edit */ + +#define OF_DT_HEADER 0xd00dfeed +#define OF_DT_BEGIN_NODE 0x1 +#define OF_DT_END_NODE 0x2 +#define OF_DT_PROP 0x3 +#define OF_DT_END 0x9 + + .globl dt_blob_start +dt_blob_start: +_dt_blob_start: + .globl dt_header +dt_header: +_dt_header: + .long OF_DT_HEADER /* magic */ + .long _dt_blob_end - _dt_blob_start /* totalsize */ + .long _dt_struct_start - _dt_blob_start /* off_dt_struct */ + .long _dt_strings_start - _dt_blob_start /* off_dt_strings */ + .long _dt_reserve_map - _dt_blob_start /* off_dt_strings */ + .long 16 /* version */ + .long 16 /* last_comp_version */ + .long 0 /*boot_cpuid_phys*/ + .long _dt_strings_end - _dt_strings_start /* size_dt_strings */ + .balign 8 + .globl dt_reserve_map +dt_reserve_map: +_dt_reserve_map: +/* Memory reserve map from source file */ + .long 0, 0 + .long 0, 0 + .globl dt_struct_start +dt_struct_start: +_dt_struct_start: + .long OF_DT_BEGIN_NODE + .string "" + .balign 4 + .long OF_DT_PROP + .long 0xa + .long 0x0 + .long 0x536f6d65 + .long 0x4d6f6465 + .short 0x6c00 + .balign 4 + .long OF_DT_PROP + .long 0x8 + .long 0x6 + .long 0x4e6f7468 + .long 0x696e6700 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x11 + .long 0x2 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x20 + .long 0x2 + .balign 4 + .long OF_DT_BEGIN_NODE + .string "memory@0" + .balign 4 + .long OF_DT_PROP + .long 0x7 + .long 0x2c + .long 0x6d656d6f + .short 0x7279 + .byte 0x0 + .balign 4 + .long OF_DT_PROP + .long 0x10 + .long 0x38 + .long 0x0 + .long 0x0 + .long 0x0 + .long 0x20000000 + .balign 4 + .long OF_DT_END_NODE + .long OF_DT_BEGIN_NODE + .string "cpus" + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x11 + .long 0x1 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x20 + .long 0x0 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x3c + .long 0xa + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x40 + .long 0x17 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x44 + .long 0x5 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x49 + .long 0xf + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x4d + .long 0xd00d + .balign 4 + .long OF_DT_PROP + .long 0x10 + .long 0x53 + .long 0x4d2 + .long 0x162e + .long 0x2334 + .long 0xd80 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x59 + .long 0x0 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x61 + .long 0xffffffff + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x69 + .long 0x0 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x71 + .long 0xffffffff + .balign 4 + .long OF_DT_END_NODE + .long OF_DT_END_NODE + .long OF_DT_END + .globl dt_struct_end +dt_struct_end: +_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" + .globl dt_strings_end +dt_strings_end: +_dt_strings_end: + .globl dt_blob_end +dt_blob_end: +_dt_blob_end: diff --git a/tests/base01.cmd b/tests/base01.cmd new file mode 100644 index 0000000..e1fce6c --- /dev/null +++ b/tests/base01.cmd @@ -0,0 +1 @@ +dtc -f -b 0 -V 16 -I dts -O asm diff --git a/tests/base01.dts b/tests/base01.dts new file mode 100644 index 0000000..f84bc49 --- /dev/null +++ b/tests/base01.dts @@ -0,0 +1,31 @@ +/ { + model = "SomeModel"; + compatible = "Nothing"; + #address-cells = <2>; + #size-cells = <2>; + + memory@0 { + device_type = "memory"; + reg = <00000000 00000000 00000000 20000000>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + d10 = ; // hex: 0xa + d23 = ; // hex: 0x17 + b101 = ; // hex: 0x5 + o17 = ; // hex: 0xf + hd00d = ; // hex: 0xd00d + + // hex: 0x4d2 0x163e 0x2334 0xd80 + stuff = ; + + + bad-d-1 = ; // Hrm. 0 + bad-d-2 = ; + bad-o-1 = ; + bad-o-2 = ; + }; + +}; diff --git a/tests/base01.stderr b/tests/base01.stderr new file mode 100644 index 0000000..0510b0f --- /dev/null +++ b/tests/base01.stderr @@ -0,0 +1,6 @@ +DTC: dts->asm on file "tests/base01.dts" +Line 26: Invalid cell value '123456789012345'; -1 assumed +Line 27: Invalid cell value '891'; 0 assumed +Line 28: Invalid cell value '123456123456'; -1 assumed +ERROR: Missing /chosen node +Input tree has errors diff --git a/tests/test01.asm b/tests/test01.asm new file mode 100644 index 0000000..bbf66c7 --- /dev/null +++ b/tests/test01.asm @@ -0,0 +1,294 @@ +/* autogenerated by dtc, do not edit */ + +#define OF_DT_HEADER 0xd00dfeed +#define OF_DT_BEGIN_NODE 0x1 +#define OF_DT_END_NODE 0x2 +#define OF_DT_PROP 0x3 +#define OF_DT_END 0x9 + + .globl dt_blob_start +dt_blob_start: +_dt_blob_start: + .globl dt_header +dt_header: +_dt_header: + .long OF_DT_HEADER /* magic */ + .long _dt_blob_end - _dt_blob_start /* totalsize */ + .long _dt_struct_start - _dt_blob_start /* off_dt_struct */ + .long _dt_strings_start - _dt_blob_start /* off_dt_strings */ + .long _dt_reserve_map - _dt_blob_start /* off_dt_strings */ + .long 16 /* version */ + .long 16 /* last_comp_version */ + .long 0 /*boot_cpuid_phys*/ + .long _dt_strings_end - _dt_strings_start /* size_dt_strings */ + .balign 8 + .globl dt_reserve_map +dt_reserve_map: +_dt_reserve_map: +/* Memory reserve map from source file */ + .long 0x10000000 + .long 0x00000000 + .long 0x00000000 + .long 0x02000000 + .long 0x20000000 + .long 0x00000000 + .long 0x01000000 + .long 0x00000000 + .long 0x00000000 + .long 0x00000000 + .long 0x00000000 + .long 0x00000014 + .long 0, 0 + .long 0, 0 + .globl dt_struct_start +dt_struct_start: +_dt_struct_start: + .long OF_DT_BEGIN_NODE + .string "" + .balign 4 + .long OF_DT_PROP + .long 0xc + .long 0x0 + .long 0x4d79426f + .long 0x6172644e + .long 0x616d6500 + .balign 4 + .long OF_DT_PROP + .long 0x1e + .long 0x6 + .long 0x4d79426f + .long 0x6172644e + .long 0x616d6500 + .long 0x4d79426f + .long 0x61726446 + .long 0x616d696c + .long 0x794e616d + .short 0x6500 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x11 + .long 0x2 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x20 + .long 0x2 + .balign 4 + .long OF_DT_BEGIN_NODE + .string "cpus" + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x2c + .long 0x1 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x11 + .long 0x1 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x20 + .long 0x0 + .balign 4 + .long OF_DT_BEGIN_NODE + .string "PowerPC,970@0" + .balign 4 + .long OF_DT_PROP + .long 0xc + .long 0x3a + .long 0x506f7765 + .long 0x7250432c + .long 0x39373000 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x3f + .long 0x63707500 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x4b + .long 0x0 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x4f + .long 0x5f5e1000 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x5f + .long 0x1fca055 + .balign 4 + .long OF_DT_PROP + .long 0x0 + .long 0x72 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x81 + .long 0x10000 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x8e + .long 0x8000 + .balign 4 + .long OF_DT_END_NODE + .long OF_DT_BEGIN_NODE + .string "PowerPC,970@1" + .balign 4 + .long OF_DT_PROP + .long 0xc + .long 0x3a + .long 0x506f7765 + .long 0x7250432c + .long 0x39373000 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x3f + .long 0x63707500 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x4b + .long 0x1 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x4f + .long 0x5f5e1000 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x5f + .long 0x1fca055 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x81 + .long 0x10000 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x8e + .long 0x8000 + .balign 4 + .long OF_DT_END_NODE + .long OF_DT_END_NODE + .long OF_DT_BEGIN_NODE + .string "randomnode" + .balign 4 + .long OF_DT_PROP + .long 0x13 + .long 0x9b + .long 0xff007374 + .long 0x75666673 + .long 0x74756666 + .long 0x909090a + .short 0xa0a + .byte 0x0 + .balign 4 + .long OF_DT_PROP + .long 0x9 + .long 0xa2 + .long 0xa0b0c0d + .long 0xdeeaadbe + .byte 0xef + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0xa7 + .long 0x2 + .balign 4 + .long OF_DT_PROP + .long 0x14 + .long 0xab + .long 0x61626300 + .long 0x12340000 + .long 0xa + .long 0xb + .long 0xc + .balign 4 + .long OF_DT_END_NODE + .long OF_DT_BEGIN_NODE + .string "memory@0" + .balign 4 + .long OF_DT_PROP + .long 0x7 + .long 0x3f + .long 0x6d656d6f + .short 0x7279 + .byte 0x0 + .balign 4 + .globl memreg +memreg: + .long OF_DT_PROP + .long 0x10 + .long 0x4b + .long 0x0 + .long 0x0 + .long 0x0 + .long 0x20000000 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0x2c + .long 0x2 + .balign 4 + .long OF_DT_END_NODE + .long OF_DT_BEGIN_NODE + .string "chosen" + .balign 4 + .long OF_DT_PROP + .long 0xf + .long 0xb1 + .long 0x726f6f74 + .long 0x3d2f6465 + .long 0x762f7364 + .short 0x6132 + .byte 0x0 + .balign 4 + .long OF_DT_PROP + .long 0x4 + .long 0xba + .long 0x600 + .balign 4 + .long OF_DT_END_NODE + .long OF_DT_END_NODE + .long OF_DT_END + .globl dt_struct_end +dt_struct_end: +_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" + .globl dt_strings_end +dt_strings_end: +_dt_strings_end: + .globl dt_blob_end +dt_blob_end: +_dt_blob_end: diff --git a/test.dts b/tests/test01.dts similarity index 100% rename from test.dts rename to tests/test01.dts diff --git a/tests/test01.stderr b/tests/test01.stderr new file mode 100644 index 0000000..82ea3f6 --- /dev/null +++ b/tests/test01.stderr @@ -0,0 +1,4 @@ +DTC: dts->asm on file "test.dts" +Warning: "linux,boot-cpu" property is deprecated in blob version 2 or higher +Warning: /chosen has no "linux,stdout-path" property +Warning: /chosen has no "interrupt-controller" property From 3948849fd0cdcaf0b91c7cc4774e86c05ba097ef Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Fri, 16 Feb 2007 09:33:54 -0600 Subject: [PATCH 0041/1198] Moved data_convert_cell() out of data.c to the parser. It constructs a cell_t, not data objects. Renamed it to cell_from_string() as well. Signed-off-by: Jon Loeliger --- data.c | 20 -------------------- dtc-parser.y | 30 +++++++++++++++++++++++++++--- dtc.h | 1 - 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/data.c b/data.c index c6c2350..5d7db17 100644 --- a/data.c +++ b/data.c @@ -225,26 +225,6 @@ struct data data_merge(struct data d1, struct data d2) return d; } -/* - * Convert a string representation of a numberic cell - * in the given base into a cell. - */ -cell_t data_convert_cell(char *s, unsigned int base) -{ - cell_t c; - extern YYLTYPE yylloc; - - c = strtoul(s, NULL, base); - if (errno == EINVAL || errno == ERANGE) { - fprintf(stderr, - "Line %d: Invalid cell value '%s'; %d assumed\n", - yylloc.first_line, s, c); - } - - return c; -} - - struct data data_append_cell(struct data d, cell_t word) { cell_t beword = cpu_to_be32(word); diff --git a/dtc-parser.y b/dtc-parser.y index 992fdb1..a8902fc 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -24,8 +24,9 @@ %{ #include "dtc.h" -int yylex (void); -void yyerror (char const *); +int yylex(void); +void yyerror(char const *); +cell_t cell_from_string(char *s, unsigned int base); extern struct boot_info *the_boot_info; @@ -144,7 +145,7 @@ opt_cell_base: celllist: celllist opt_cell_base DT_CELL { $$ = data_append_cell($1, - data_convert_cell($3, $2)); + cell_from_string($3, $2)); } | celllist DT_REF { $$ = data_append_cell(data_add_fixup($1, $2), -1); @@ -179,3 +180,26 @@ void yyerror (char const *s) { fprintf (stderr, "%s at line %d\n", s, yylloc.first_line); } + + +/* + * Convert a string representation of a numeric cell + * in the given base into a cell. + * + * FIXME: The string "abc123", base 10, should be flagged + * as an error due to the leading "a", but isn't yet. + */ + +cell_t cell_from_string(char *s, unsigned int base) +{ + cell_t c; + + c = strtoul(s, NULL, base); + if (errno == EINVAL || errno == ERANGE) { + fprintf(stderr, + "Line %d: Invalid cell value '%s'; %d assumed\n", + yylloc.first_line, s, c); + } + + return c; +} diff --git a/dtc.h b/dtc.h index 7ee96a5..8d3964c 100644 --- a/dtc.h +++ b/dtc.h @@ -118,7 +118,6 @@ struct data data_copy_mem(char *mem, int len); struct data data_copy_escape_string(char *s, int len); struct data data_copy_file(FILE *f, size_t len); -cell_t data_convert_cell(char *s, unsigned int base); struct data data_append_data(struct data d, void *p, int len); struct data data_merge(struct data d1, struct data d2); struct data data_append_cell(struct data d, cell_t word); From 5ae78ad8f8b3e39788dfb4090b03e147e71b0211 Mon Sep 17 00:00:00 2001 From: Stuart Yoder Date: Mon, 19 Feb 2007 11:28:27 -0600 Subject: [PATCH 0042/1198] remove check for interrupt-controller property under /chosen Remove warning for missing interrupt-controller property under /chosen. There is consensus that this property does not belong here. Also, add a warning if interrupt-controller _is_ found under /chosen. Signed-off-by: Stuart Yoder Signed-off-by: Jon Loeliger --- livetree.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/livetree.c b/livetree.c index ede29fb..84f2f64 100644 --- a/livetree.c +++ b/livetree.c @@ -594,9 +594,16 @@ static int check_chosen(struct node *root) CHECK_HAVE_WARN_STRING(chosen, "bootargs"); CHECK_HAVE_WARN_STRING(chosen, "linux,stdout-path"); - CHECK_HAVE_WARN_PHANDLE(chosen, "interrupt-controller", root); - return ok; + /* give warning for obsolete interrupt-controller property */ + do { + if ((prop = get_property(chosen, "interrupt-controller")) != NULL) { + WARNMSG("%s has obsolete \"%s\" property\n", + chosen->fullpath, "interrupt-controller"); + } + } while (0); + + return ok; } static int check_addr_size_reg(struct node *node, From 5434fcc7e05e86b61530999d48548e6f18036cf7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 23 Feb 2007 14:40:10 +1100 Subject: [PATCH 0043/1198] libfdt: Fix fdt_strerror() bugs This fixes several small bugs related to fdt_strerror(). - an entry is added to the error table for FDT_ERR_BADLAYOUT. - Incorrect usage of fdt_strerror() in check_property() and check_getprop() is corrected (they were passing a positive error code, when fdt_strerror() expects a negative code). - Add code to properly retreive an error code from fdt_get_property() in check_property(). With that a check that the length returned by fdt_get_property() matches that stored in the retreived property. Signed-off-by: David Gibson --- fdt_strerror.c | 3 ++- tests/testutils.c | 12 +++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/fdt_strerror.c b/fdt_strerror.c index 74c97e7..7f231ce 100644 --- a/fdt_strerror.c +++ b/fdt_strerror.c @@ -43,13 +43,14 @@ static struct errtabent errtable[] = { ERRTABENT(FDT_ERR_BADMAGIC), ERRTABENT(FDT_ERR_BADVERSION), ERRTABENT(FDT_ERR_BADSTRUCTURE), + ERRTABENT(FDT_ERR_BADLAYOUT), }; #define ERRTABSIZE (sizeof(errtable) / sizeof(errtable[0])) const char *fdt_strerror(int errval) { if (errval > 0) - return ""; + return ""; else if (errval == 0) return ""; else if (errval > -ERRTABSIZE) { diff --git a/tests/testutils.c b/tests/testutils.c index 9637415..c7b4b9e 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -72,14 +72,16 @@ void check_property(void *fdt, int nodeoffset, const char *name, int len, const void *val) { const struct fdt_property *prop; + int retlen; uint32_t tag, nameoff, proplen; const char *propname; verbose_printf("Checking property \"%s\"...", name); - prop = fdt_get_property(fdt, nodeoffset, name, NULL); + prop = fdt_get_property(fdt, nodeoffset, name, &retlen); verbose_printf("pointer %p\n", prop); if (! prop) - FAIL("NULL retreiving \"%s\" pointer", name); + FAIL("Error retreiving \"%s\" pointer: %s", name, + fdt_strerror(retlen)); tag = fdt32_to_cpu(prop->tag); nameoff = fdt32_to_cpu(prop->nameoff); @@ -92,6 +94,10 @@ void check_property(void *fdt, int nodeoffset, const char *name, if (!propname || !streq(propname, name)) FAIL("Property name mismatch \"%s\" instead of \"%s\"", propname, name); + if (proplen != retlen) + FAIL("Length retrieved for \"%s\" by fdt_get_property()" + " differs from stored length (%d != %d)", + name, retlen, proplen); if (proplen != len) FAIL("Size mismatch on property \"%s\": %d insead of %d", name, proplen, len); @@ -108,7 +114,7 @@ void *check_getprop(void *fdt, int nodeoffset, const char *name, propval = fdt_getprop(fdt, nodeoffset, name, &proplen); if (! propval) - FAIL("fdt_getprop(\"%s\"): %s", name, fdt_strerror(-proplen)); + FAIL("fdt_getprop(\"%s\"): %s", name, fdt_strerror(proplen)); if (proplen != len) FAIL("Size mismatch on property \"%s\": %d insead of %d", From 07a12a08005f3b5cd9337900a6551e450c07b515 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 23 Feb 2007 14:40:14 +1100 Subject: [PATCH 0044/1198] libfdt: Use correct property format Since its beginning, libfdt has used an incorrect definition of the format for a property, putting the name offset before length, rather than the other way around as described in booting-without-of.txt. This corrects the error, making libfdt actually produce and use trees which are compatible with the kernel and dtc. Signed-of-by: David Gibson --- fdt.c | 2 +- fdt.h | 2 +- tests/trees.S | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fdt.c b/fdt.c index 45568b1..772da46 100644 --- a/fdt.c +++ b/fdt.c @@ -83,7 +83,7 @@ uint32_t _fdt_next_tag(const void *fdt, int offset, int *nextoffset) return FDT_END; break; case FDT_PROP: - lenp = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, sizeof(*lenp)); + lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); if (! lenp) return FDT_END; /* skip name offset, length and value */ diff --git a/fdt.h b/fdt.h index fff533e..4687a31 100644 --- a/fdt.h +++ b/fdt.h @@ -36,8 +36,8 @@ struct fdt_node_header { struct fdt_property { uint32_t tag; - uint32_t nameoff; uint32_t len; + uint32_t nameoff; char data[0]; }; diff --git a/tests/trees.S b/tests/trees.S index 397c151..6057668 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -39,8 +39,8 @@ tree: \ #define PROPHDR(tree, name, len) \ FDTLONG(FDT_PROP) ; \ - FDTLONG(tree##_##name - tree##_strings) ; \ - FDTLONG(len) ; + FDTLONG(len) ; \ + FDTLONG(tree##_##name - tree##_strings) ; #define PROP_INT(tree, name, val) \ PROPHDR(tree, name, 4) \ From 6ae55f9f9bf5db8c05f851db27ed923451b44181 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 26 Feb 2007 11:02:24 +1100 Subject: [PATCH 0045/1198] Fix flat_dt_property structure The structure in flat_dt.h defining the layout of a proprety within the flat device tree is incorrect. It has the offset to the property's name, then the length when in fact (according to booting-without-of.txt and the output of dtc) then length should come first, followed by the name offset. In fact, this structure is never used so the mistake doesn't break anything, but it should still be fixed to avoid misleading people. Signed-off-by: David Gibson --- flat_dt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flat_dt.h b/flat_dt.h index 5b1dcb6..2850044 100644 --- a/flat_dt.h +++ b/flat_dt.h @@ -37,8 +37,8 @@ struct reserve_entry { }; struct flat_dt_property { - uint32_t nameoff; uint32_t len; + uint32_t nameoff; char data[0]; }; From 46c88dfcca9aedda24364e082374dba1f6182a53 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 14 Mar 2007 11:02:40 +1100 Subject: [PATCH 0046/1198] Add support for flat device tree format version 17 libfdt defined a new version of the flattened device tree format, version 17. It is backwards compatible with version 16, just adding an extra header field giving the size of the blob's structure blob. This patch adds support to dtc allowing it to read and write version 17 blobs. It also makes version 17 the default output version for blobs. At the same time we change the code to consistently using decimal numbers for versions. Previously we sometimes used 16 and sometimes 0x10 to refer to version 16. Signed-off-by: David Gibson --- dtc.c | 2 +- flat_dt.h | 4 ++++ flattree.c | 18 +++++++++++++++--- ftdump.c | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/dtc.c b/dtc.c index fe4637c..f15d90f 100644 --- a/dtc.c +++ b/dtc.c @@ -113,7 +113,7 @@ int main(int argc, char *argv[]) int opt; FILE *inf = NULL; FILE *outf = NULL; - int outversion = 0x10; + int outversion = 17; int reservenum = 1; int boot_cpuid_phys = 0xfeedbeef; diff --git a/flat_dt.h b/flat_dt.h index 2850044..d5abd80 100644 --- a/flat_dt.h +++ b/flat_dt.h @@ -25,11 +25,15 @@ struct boot_param_header { booting on */ /* version 3 fields below */ uint32_t size_dt_strings; /* size of the strings block */ + + /* version 17 fields below */ + uint32_t size_dt_struct; /* size of the DT structure block */ }; #define BPH_V1_SIZE (7*sizeof(uint32_t)) #define BPH_V2_SIZE (BPH_V1_SIZE + sizeof(uint32_t)) #define BPH_V3_SIZE (BPH_V2_SIZE + sizeof(uint32_t)) +#define BPH_V17_SIZE (BPH_V3_SIZE + sizeof(uint32_t)) struct reserve_entry { uint64_t address; diff --git a/flattree.c b/flattree.c index f2dc4dc..780142f 100644 --- a/flattree.c +++ b/flattree.c @@ -26,6 +26,7 @@ #define FTF_NAMEPROPS 0x4 #define FTF_BOOTCPUID 0x8 #define FTF_STRTABSIZE 0x10 +#define FTF_STRUCTSIZE 0x20 static struct version_info { int version; @@ -39,8 +40,10 @@ static struct version_info { FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID}, {3, 1, BPH_V3_SIZE, FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE}, - {0x10, 0x10, BPH_V3_SIZE, + {16, 16, BPH_V3_SIZE, FTF_BOOTCPUID|FTF_STRTABSIZE}, + {17, 16, BPH_V17_SIZE, + FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE}, }; struct emitter { @@ -328,6 +331,8 @@ static void make_bph(struct boot_param_header *bph, bph->boot_cpuid_phys = cpu_to_be32(boot_cpuid_phys); if (vi->flags & FTF_STRTABSIZE) bph->size_dt_strings = cpu_to_be32(strsize); + if (vi->flags & FTF_STRUCTSIZE) + bph->size_dt_struct = cpu_to_be32(dtsize); } void dt_to_blob(FILE *f, struct boot_info *bi, int version, @@ -742,7 +747,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, struct boot_info *dt_from_blob(FILE *f) { - u32 magic, totalsize, version, size_str; + u32 magic, totalsize, version, size_str, size_dt; u32 off_dt, off_str, off_mem_rsvmap; int rc; char *blob; @@ -841,8 +846,15 @@ struct boot_info *dt_from_blob(FILE *f) if (off_str+size_str > totalsize) die("String table extends past total size\n"); } + + if (version >= 17) { + size_dt = be32_to_cpu(bph->size_dt_struct); + fprintf(stderr, "\tsize_dt_struct:\t\t%d\n", size_dt); + if (off_dt+size_dt > totalsize) + die("Structure block extends past total size\n"); + } - if (version < 0x10) { + if (version < 16) { flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN; } diff --git a/ftdump.c b/ftdump.c index 4d4354b..67c5228 100644 --- a/ftdump.c +++ b/ftdump.c @@ -144,7 +144,7 @@ static void dump_blob(void *blob) } sz = GET_CELL(p); s = p_strings + be32_to_cpu(GET_CELL(p)); - if (version < 0x10 && sz >= 8) + if (version < 16 && sz >= 8) p = PALIGN(p, 8); t = p; From b299ac76a7c2f58a0f44483b35b2d4d46bb6c0d9 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 14 Mar 2007 11:06:23 +1100 Subject: [PATCH 0047/1198] Get rid of libdt.c libdt.c was an attempt at creating a device tree handling library within the dtc codebase. However, it was never even close to completion, and is entirely obsoleted by it's spiritual descendent, libfdt (currently a separate package). This patch, therefore, removes libdt.c entirely, along with its only reference in the Makefile, an unused variable. Signed-off-by: David Gibson --- Makefile | 2 - libdt.c | 230 ------------------------------------------------------- 2 files changed, 232 deletions(-) delete mode 100644 libdt.c diff --git a/Makefile b/Makefile index 8439f56..cdea9a2 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,6 @@ BISON = bison DTC_OBJS = dtc.o livetree.o flattree.o data.o treesource.o fstree.o \ dtc-parser.tab.o lex.yy.o -OBJS = $(DTC_OBJS) libdt.o ftdump.o - DEPFILES = $(DTC_OBJS:.o=.d) all: $(TARGETS) diff --git a/libdt.c b/libdt.c deleted file mode 100644 index d187ca9..0000000 --- a/libdt.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include -#include - -#include "flat_dt.h" - -#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) -#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) -#define GET_CELL(p) (p += 4, *((uint32_t *)(p-4))) - -static char *skip_name(char *p) -{ - while (*p != '\0') - p++; - - return PALIGN(p, sizeof(uint32_t)); -} - -static char *skip_prop(void *blob, char *p) -{ - struct boot_param_header *bph = blob; - uint32_t len, nameoff; - - len = GET_CELL(p); - nameoff = GET_CELL(p); - if ((bph->version < 0x10) && (len >= sizeof(uint64_t))) - p = PALIGN(p, sizeof(uint64_t)); - return PALIGN(p + len, sizeof(uint32_t)); -} - -static char *get_unit(char *dtpath) -{ - char *p; - - if (dtpath[0] != '/') - return dtpath; - - p = dtpath + strlen(dtpath); - while (*p != '/') - p--; - - return p+1; -} - -static int first_seg_len(char *dtpath) -{ - int len = 0; - - while ((dtpath[len] != '/') && (dtpath[len] != '\0')) - len++; - - return len; -} - -char *flat_dt_get_string(void *blob, uint32_t offset) -{ - struct boot_param_header *bph = blob; - - return (char *)blob + bph->off_dt_strings + offset; -} - -void *flat_dt_get_subnode(void *blob, void *node, char *uname, int unamelen) -{ - struct boot_param_header *bph = blob; - char *p = node; - uint32_t tag; - int depth = 0; - char *nuname; - - if (! unamelen) - unamelen = strlen(uname); - - do { - tag = GET_CELL(p); - - switch (tag) { - case OF_DT_PROP: - p = skip_prop(blob, p); - break; - - case OF_DT_BEGIN_NODE: - if (depth == 0) { - nuname = p; - - if (bph->version < 0x10) - nuname = get_unit(nuname); - - p = skip_name(p); - - if (strncmp(nuname, uname, unamelen) == 0) - return p; - } - depth++; - break; - - case OF_DT_END_NODE: - depth--; - break; - - case OF_DT_END: - /* looks like a malformed tree */ - return NULL; - break; - - default: - /* FIXME: throw some sort of error */ - return NULL; - } - } while (depth >= 0); - - return NULL; -} - -void *flat_dt_get_node(void *blob, char *path) -{ - struct boot_param_header *bph = blob; - char *node; - int seglen; - - node = blob + bph->off_dt_struct; - node += sizeof(uint32_t); /* skip initial OF_DT_BEGIN_NODE */ - node = skip_name(node); /* skip root node name */ - - while (node && (*path)) { - if (path[0] == '/') - path++; - - seglen = first_seg_len(path); - - node = flat_dt_get_subnode(blob, node, path, seglen); - - path += seglen; - } - - return node; -} - -void flat_dt_traverse(void *blob, - int (*fn)(void *blob, void *node, void *priv), - void *private) -{ - struct boot_param_header *bph = blob; - char *p; - uint32_t tag; - int depth = 0; - char *uname; - - p = (char *)blob + bph->off_dt_struct; - - tag = GET_CELL(p); - while (tag != OF_DT_END) { - switch (tag) { - case OF_DT_BEGIN_NODE: - uname = p; - - if (bph->version < 0x10) - uname = get_unit(uname); - - p = skip_name(p); - - (*fn)(blob, p, private); - depth++; - break; - - case OF_DT_END_NODE: - depth--; - break; - - case OF_DT_PROP: - p = skip_prop(blob, p); - break; - - default: - /* FIXME: badly formed tree */ - return; - } - } -} - -void *flat_dt_get_prop(void *blob, void *node, char *name, uint32_t *len) -{ - struct boot_param_header *bph = blob; - char *p = node; - - do { - uint32_t tag = GET_CELL(p); - uint32_t sz, noff; - const char *nstr; - - if (tag != OF_DT_PROP) - return NULL; - - sz = GET_CELL(p); - noff = GET_CELL(p); - - /* Old versions have variable alignment of the - * property value */ - if ((bph->version < 0x10) && (sz >= 8)) - p = PALIGN(p, 8); - - nstr = flat_dt_get_string(blob, noff); - - if (strcmp(name, nstr) == 0) { - if (len) - *len = sz; - return (void *)p; - } - - p = PALIGN(p + sz, sizeof(uint32_t)); - } while(1); -} From cd1da8711641a4c7722742ce8b692b2b7cdadfc7 Mon Sep 17 00:00:00 2001 From: Jerry Van Baren Date: Sun, 18 Mar 2007 16:49:24 -0400 Subject: [PATCH 0048/1198] Improve options, #define default version. Add -h option for help Add -q quiet option to reduce or suppress the whining Create #define for the default version value. Signed-off-by: vanbaren@cideas.com --- dtc.c | 23 ++++++++++++++++++----- dtc.h | 5 +++++ flat_dt.h | 2 ++ livetree.c | 9 +++++---- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/dtc.c b/dtc.c index f15d90f..051a68b 100644 --- a/dtc.c +++ b/dtc.c @@ -81,6 +81,10 @@ static void usage(void) fprintf(stderr, "Usage:\n"); fprintf(stderr, "\tdtc [options] \n"); fprintf(stderr, "\nOptions:\n"); + fprintf(stderr, "\t-h\n"); + fprintf(stderr, "\t\tThis help text\n"); + fprintf(stderr, "\t-q\n"); + fprintf(stderr, "\t\tQuiet: -q suppress warnings, -qq errors, -qqq all\n"); fprintf(stderr, "\t-I \n"); fprintf(stderr, "\t\tInput formats are:\n"); fprintf(stderr, "\t\t\tdts - device tree source text\n"); @@ -92,7 +96,7 @@ static void usage(void) fprintf(stderr, "\t\t\tdtb - device tree blob\n"); fprintf(stderr, "\t\t\tasm - assembler source\n"); fprintf(stderr, "\t-V \n"); - fprintf(stderr, "\t\tBlob version to produce, defaults to 16 (relevant for dtb\n\t\tand asm output only)\n"); + fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", OF_DEFAULT_VERSION); fprintf(stderr, "\t-R \n"); fprintf(stderr, "\t\tMake space for reserve map entries (relevant for \n\t\tdtb and asm output only)\n"); fprintf(stderr, "\t-b \n"); @@ -113,11 +117,13 @@ int main(int argc, char *argv[]) int opt; FILE *inf = NULL; FILE *outf = NULL; - int outversion = 17; + int outversion = OF_DEFAULT_VERSION; int reservenum = 1; int boot_cpuid_phys = 0xfeedbeef; - while ((opt = getopt(argc, argv, "I:O:o:V:R:fb:")) != EOF) { + quiet = 0; + + while ((opt = getopt(argc, argv, "hI:O:o:V:R:fqb:")) != EOF) { switch (opt) { case 'I': inform = optarg; @@ -137,9 +143,13 @@ int main(int argc, char *argv[]) case 'f': force = 1; break; + case 'q': + quiet++; + break; case 'b': boot_cpuid_phys = strtol(optarg, NULL, 0); break; + case 'h': default: usage(); } @@ -174,9 +184,12 @@ int main(int argc, char *argv[]) die("Couldn't read input tree\n"); if (! check_device_tree(bi->dt, outversion, boot_cpuid_phys)) { - fprintf(stderr, "Input tree has errors\n"); - if (! force) + if ((force) && (quiet < 3)) + fprintf(stderr, "Input tree has errors, output forced\n"); + if (! force) { + fprintf(stderr, "Input tree has errors, not writing output (use -f to force output)\n"); exit(1); + } } if (streq(outname, "-")) { diff --git a/dtc.h b/dtc.h index 8d3964c..e3e2863 100644 --- a/dtc.h +++ b/dtc.h @@ -36,6 +36,11 @@ #include "flat_dt.h" +/* + * Level of quietness + */ +int quiet; + static inline void die(char * str, ...) { va_list ap; diff --git a/flat_dt.h b/flat_dt.h index d5abd80..a8482b4 100644 --- a/flat_dt.h +++ b/flat_dt.h @@ -2,6 +2,8 @@ #define _FLAT_DT_H_ +#define OF_DEFAULT_VERSION 17 + #define OF_DT_HEADER 0xd00dfeed /* 4: version, 4: total size */ #define OF_DT_BEGIN_NODE 0x1 /* Start node: full name */ diff --git a/livetree.c b/livetree.c index 84f2f64..45642dc 100644 --- a/livetree.c +++ b/livetree.c @@ -252,8 +252,8 @@ static struct node *get_node_by_phandle(struct node *tree, cell_t phandle) * Tree checking functions */ -#define ERRMSG(...) fprintf(stderr, "ERROR: " __VA_ARGS__) -#define WARNMSG(...) fprintf(stderr, "Warning: " __VA_ARGS__) +#define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__) +#define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__) static int must_be_one_cell(struct property *prop, struct node *node) { @@ -512,13 +512,14 @@ static int check_cpus(struct node *root, int outversion, int boot_cpuid_phys) char *eptr; unitnum = strtol(get_unitname(cpu), &eptr, 16); - if (*eptr) + if (*eptr) { WARNMSG("%s has bad format unit name %s (should be CPU number\n", cpu->fullpath, get_unitname(cpu)); - else if (unitnum != propval_cell(prop)) + } else if (unitnum != propval_cell(prop)) { WARNMSG("%s unit name \"%s\" does not match \"reg\" property <%x>\n", cpu->fullpath, get_unitname(cpu), propval_cell(prop)); + } } /* CHECK_HAVE_ONECELL(cpu, "d-cache-line-size"); */ From 001430072fe321fe41c82478917b06c8d9ffdbbe Mon Sep 17 00:00:00 2001 From: Ed Swarthout Date: Wed, 14 Mar 2007 17:33:19 -0500 Subject: [PATCH 0049/1198] ftdump missing be32_to_cpu() on size cell. --- ftdump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ftdump.c b/ftdump.c index 67c5228..55209b6 100644 --- a/ftdump.c +++ b/ftdump.c @@ -142,7 +142,7 @@ static void dump_blob(void *blob) fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag); break; } - sz = GET_CELL(p); + sz = be32_to_cpu(GET_CELL(p)); s = p_strings + be32_to_cpu(GET_CELL(p)); if (version < 16 && sz >= 8) p = PALIGN(p, 8); From 857f54e79f74429af20c2b5ecc00ee98af6a3b8b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 23 Mar 2007 15:16:54 +1100 Subject: [PATCH 0050/1198] libfdt: Remove #includes from fdt.h At present fdt.h #includes stdint.h. This makes some sense, because fdt.h uses the standard fixed-width integer types. However, this can make life difficult when building in different environments which may not have a stdint.h. Therefore, this patch removes the #include from fdt.h, instead requiring that users of fdt.h define the fixed-width integer types before including fdt.h, either by themselves including stdint.h, or by any other means. --- fdt.h | 2 -- tests/del_node.c | 1 + tests/del_property.c | 1 + tests/dumptrees.c | 1 + tests/find_property.c | 1 + tests/getprop.c | 1 + tests/move_and_save.c | 2 ++ tests/nop_node.c | 1 + tests/nop_property.c | 1 + tests/notfound.c | 1 + tests/open_pack.c | 1 + tests/path_offset.c | 1 + tests/root_node.c | 1 + tests/rw_tree1.c | 1 + tests/setprop.c | 1 + tests/setprop_inplace.c | 1 + tests/subnode_offset.c | 1 + tests/sw_tree1.c | 1 + tests/testutils.c | 1 + tests/truncated_property.c | 1 + 20 files changed, 20 insertions(+), 2 deletions(-) diff --git a/fdt.h b/fdt.h index 4687a31..e00559a 100644 --- a/fdt.h +++ b/fdt.h @@ -3,8 +3,6 @@ #ifndef __ASSEMBLY__ -#include - struct fdt_header { uint32_t magic; /* magic word FDT_MAGIC */ uint32_t totalsize; /* total size of DT block */ diff --git a/tests/del_node.c b/tests/del_node.c index 56f7cf5..26bb061 100644 --- a/tests/del_node.c +++ b/tests/del_node.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/tests/del_property.c b/tests/del_property.c index cc0de98..a7928a3 100644 --- a/tests/del_property.c +++ b/tests/del_property.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/tests/dumptrees.c b/tests/dumptrees.c index bea943b..3db0e2b 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include diff --git a/tests/find_property.c b/tests/find_property.c index 8a8e9aa..ced14ae 100644 --- a/tests/find_property.c +++ b/tests/find_property.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include diff --git a/tests/getprop.c b/tests/getprop.c index 22dc03b..f124951 100644 --- a/tests/getprop.c +++ b/tests/getprop.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff --git a/tests/move_and_save.c b/tests/move_and_save.c index 4b4824e..da73157 100644 --- a/tests/move_and_save.c +++ b/tests/move_and_save.c @@ -22,6 +22,8 @@ #include #include #include +#include + #include #include diff --git a/tests/nop_node.c b/tests/nop_node.c index d09d9df..80cf4d0 100644 --- a/tests/nop_node.c +++ b/tests/nop_node.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/tests/nop_property.c b/tests/nop_property.c index 858527d..84e735a 100644 --- a/tests/nop_property.c +++ b/tests/nop_property.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/tests/notfound.c b/tests/notfound.c index b411249..3b18664 100644 --- a/tests/notfound.c +++ b/tests/notfound.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include diff --git a/tests/open_pack.c b/tests/open_pack.c index 1aa66e4..d614024 100644 --- a/tests/open_pack.c +++ b/tests/open_pack.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/tests/path_offset.c b/tests/path_offset.c index 42e5daa..05b0c32 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include diff --git a/tests/root_node.c b/tests/root_node.c index 4258b91..6e2c391 100644 --- a/tests/root_node.c +++ b/tests/root_node.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c index ffd2c3a..3fb9307 100644 --- a/tests/rw_tree1.c +++ b/tests/rw_tree1.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/tests/setprop.c b/tests/setprop.c index fc70910..f58a33d 100644 --- a/tests/setprop.c +++ b/tests/setprop.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c index f674ec6..bcfd357 100644 --- a/tests/setprop_inplace.c +++ b/tests/setprop_inplace.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c index a2b12eb..d4edfe4 100644 --- a/tests/subnode_offset.c +++ b/tests/subnode_offset.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 51aa4d7..7b54359 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/tests/testutils.c b/tests/testutils.c index c7b4b9e..efc4f4a 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include diff --git a/tests/truncated_property.c b/tests/truncated_property.c index c5be466..dbd3652 100644 --- a/tests/truncated_property.c +++ b/tests/truncated_property.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include From b29597d9a343761f768a9d78a63f1c09e71b43d2 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Thu, 22 Mar 2007 11:11:09 -0500 Subject: [PATCH 0051/1198] Remove bogus errors from check_chosen. It is not an error for /chosen (or any of its children) to be missing. It is not a requirement that the output of dtc be a complete, valid device tree, as it may be intended that the dtb be passed through boot code that will complete it. Thus, do not complain. Signed-off-by: Scott Wood Acked-by: David Gibson --- livetree.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/livetree.c b/livetree.c index 45642dc..ce73f50 100644 --- a/livetree.c +++ b/livetree.c @@ -588,13 +588,8 @@ static int check_chosen(struct node *root) int ok = 1; chosen = get_subnode(root, "chosen"); - if (! chosen) { - ERRMSG("Missing /chosen node\n"); - return 0; - } - - CHECK_HAVE_WARN_STRING(chosen, "bootargs"); - CHECK_HAVE_WARN_STRING(chosen, "linux,stdout-path"); + if (!chosen) + return ok; /* give warning for obsolete interrupt-controller property */ do { From e45e6fd274826991c2b7e01fde4d73110487e0e0 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Fri, 23 Mar 2007 15:18:41 -0500 Subject: [PATCH 0052/1198] DTC: Add support for a C-like #include "file" mechanism. Keeps track of open files in a stack, and assigns a filenum to source positions for each lexical token. Modified error reporting to show source file as well. No policy on file directory basis has been decided. Still handles stdin. Tested on all arch/powerpc/boot/dts DTS files Signed-off-by: Jon Loeliger --- Makefile | 3 +- dtc-lexer.l | 39 +++++++++++++- dtc-parser.y | 9 +++- dtc.c | 19 +------ dtc.h | 2 +- srcpos.c | 105 ++++++++++++++++++++++++++++++++++++++ srcpos.h | 71 ++++++++++++++++++++++++++ srcposstack.h | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++ treesource.c | 6 ++- 9 files changed, 369 insertions(+), 23 deletions(-) create mode 100644 srcpos.c create mode 100644 srcpos.h create mode 100644 srcposstack.h diff --git a/Makefile b/Makefile index cdea9a2..280db78 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,8 @@ CFLAGS = -Wall -g BISON = bison -DTC_OBJS = dtc.o livetree.o flattree.o data.o treesource.o fstree.o \ +DTC_OBJS = dtc.o flattree.o fstree.o data.o livetree.o \ + srcpos.o treesource.o \ dtc-parser.tab.o lex.yy.o DEPFILES = $(DTC_OBJS:.o=.d) diff --git a/dtc-lexer.l b/dtc-lexer.l index 93f3268..45f66ef 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -20,6 +20,7 @@ %option noyywrap nounput yylineno +%x INCLUDE %x CELLDATA %x BYTESTRING %x MEMRESERVE @@ -32,8 +33,9 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) %{ #include "dtc.h" - #include "dtc-parser.tab.h" +#include "srcposstack.h" + /*#define LEXDEBUG 1*/ @@ -49,7 +51,27 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) %% +#[ \t]*include BEGIN(INCLUDE); + +[ \t]* /* whitespace before file name */ +\"[^"\n]*\" { + yytext[strlen(yytext) - 1] = 0; + if (!push_input_file(yytext + 1)) { + /* Some unrecoverable error.*/ + exit(1); + } + BEGIN(INITIAL); + } + + +<> { + if (!pop_input_file()) { + yyterminate(); + } + } + \"[^"]*\" { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("String: %s\n", yytext); yylval.data = data_copy_escape_string(yytext+1, @@ -59,6 +81,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } "/memreserve/" { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Keyword: /memreserve/\n"); BEGIN(MEMRESERVE); @@ -66,6 +89,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } [0-9a-fA-F]+ { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; if (yyleng > 2*sizeof(yylval.addr)) { fprintf(stderr, "Address value %s too large\n", @@ -78,12 +102,14 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } ";" { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("/MEMRESERVE\n"); BEGIN(INITIAL); return ';'; } [bodh]# { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; if (*yytext == 'b') yylval.cbase = 2; @@ -98,6 +124,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } [0-9a-fA-F]+ { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; yylval.str = strdup(yytext); DPRINT("Cell: '%s'\n", yylval.str); @@ -105,6 +132,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } ">" { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("/CELLDATA\n"); BEGIN(INITIAL); @@ -112,6 +140,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } \&{REFCHAR}* { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Ref: %s\n", yytext+1); yylval.str = strdup(yytext+1); @@ -119,6 +148,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } [0-9a-fA-F]{2} { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; yylval.byte = strtol(yytext, NULL, 16); DPRINT("Byte: %02x\n", (int)yylval.byte); @@ -126,6 +156,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } "]" { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("/BYTESTRING\n"); BEGIN(INITIAL); @@ -135,6 +166,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) , { /* Technically this is a valid property name, but we'd rather use it as punctuation, so detect it here in preference */ + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Char (propname like): %c (\\x%02x)\n", yytext[0], (unsigned)yytext[0]); @@ -142,6 +174,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } {PROPCHAR}+ { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("PropName: %s\n", yytext); yylval.str = strdup(yytext); @@ -149,6 +182,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } {PROPCHAR}+(@{UNITCHAR}+)? { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("NodeName: %s\n", yytext); yylval.str = strdup(yytext); @@ -157,6 +191,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) [a-zA-Z_][a-zA-Z0-9_]*: { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Label: %s\n", yytext); yylval.str = strdup(yytext); @@ -167,6 +202,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) <*>{WS}+ /* eat whitespace */ <*>"/*"([^*]|\*+[^*/])*\*+"/" { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Comment: %s\n", yytext); /* eat comments */ @@ -175,6 +211,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) <*>"//".*\n /* eat line comments */ <*>. { + yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; switch (yytext[0]) { case '<': diff --git a/dtc-parser.y b/dtc-parser.y index a8902fc..39d9dac 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -23,6 +23,7 @@ %{ #include "dtc.h" +#include "srcpos.h" int yylex(void); void yyerror(char const *); @@ -178,7 +179,13 @@ label: DT_LABEL { $$ = $1; } void yyerror (char const *s) { - fprintf (stderr, "%s at line %d\n", s, yylloc.first_line); + const char *fname = srcpos_filename_for_num(yylloc.filenum); + + if (strcmp(fname, "-") == 0) + fname = "stdin"; + + fprintf(stderr, "%s:%d %s\n", + fname, yylloc.first_line, s); } diff --git a/dtc.c b/dtc.c index 051a68b..a009605 100644 --- a/dtc.c +++ b/dtc.c @@ -19,6 +19,7 @@ */ #include "dtc.h" +#include "srcpos.h" char *join_path(char *path, char *name) { @@ -61,21 +62,6 @@ void fill_fullpaths(struct node *tree, char *prefix) fill_fullpaths(child, tree->fullpath); } -static FILE *dtc_open_file(char *fname) -{ - FILE *f; - - if (streq(fname, "-")) - f = stdin; - else - f = fopen(fname, "r"); - - if (! f) - die("Couldn't open \"%s\": %s\n", fname, strerror(errno)); - - return f; -} - static void usage(void) { fprintf(stderr, "Usage:\n"); @@ -166,8 +152,7 @@ int main(int argc, char *argv[]) inform, outform, arg); if (streq(inform, "dts")) { - inf = dtc_open_file(arg); - bi = dt_from_source(inf); + bi = dt_from_source(arg); } else if (streq(inform, "fs")) { bi = dt_from_fs(arg); } else if(streq(inform, "dtb")) { diff --git a/dtc.h b/dtc.h index e3e2863..7ed3df2 100644 --- a/dtc.h +++ b/dtc.h @@ -223,7 +223,7 @@ struct boot_info *dt_from_blob(FILE *f); /* Tree source */ void dt_to_source(FILE *f, struct boot_info *bi); -struct boot_info *dt_from_source(FILE *f); +struct boot_info *dt_from_source(const char *f); /* FS trees */ diff --git a/srcpos.c b/srcpos.c new file mode 100644 index 0000000..352b0fe --- /dev/null +++ b/srcpos.c @@ -0,0 +1,105 @@ +/* + * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "dtc.h" +#include "srcpos.h" + + +/* + * Record the complete unique set of opened file names. + * Primarily used to cache source position file names. + */ +#define MAX_N_FILE_NAMES (100) + +const char *file_names[MAX_N_FILE_NAMES]; +static int n_file_names = 0; + +/* + * Like yylineno, this is the current open file pos. + */ + +int srcpos_filenum = -1; + + + +FILE *dtc_open_file(const char *fname) +{ + FILE *f; + + if (lookup_file_name(fname, 1) < 0) + die("Too many files opened\n"); + + if (streq(fname, "-")) + f = stdin; + else + f = fopen(fname, "r"); + + if (! f) + die("Couldn't open \"%s\": %s\n", fname, strerror(errno)); + + return f; +} + + + +/* + * Locate and optionally add filename fname in the file_names[] array. + * + * If the filename is currently not in the array and the boolean + * add_it is non-zero, an attempt to add the filename will be made. + * + * Returns; + * Index [0..MAX_N_FILE_NAMES) where the filename is kept + * -1 if the name can not be recorded + */ + +int lookup_file_name(const char *fname, int add_it) +{ + int i; + + for (i = 0; i < n_file_names; i++) { + if (strcmp(file_names[i], fname) == 0) + return i; + } + + if (add_it) { + if (n_file_names < MAX_N_FILE_NAMES) { + file_names[n_file_names] = strdup(fname); + return n_file_names++; + } + } + + return -1; +} + + +const char *srcpos_filename_for_num(int filenum) +{ + if (0 <= filenum && filenum < n_file_names) { + return file_names[filenum]; + } + + return 0; +} + + +const char *srcpos_get_filename(void) +{ + return srcpos_filename_for_num(srcpos_filenum); +} diff --git a/srcpos.h b/srcpos.h new file mode 100644 index 0000000..d591e7e --- /dev/null +++ b/srcpos.h @@ -0,0 +1,71 @@ +/* + * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +/* + * Augment the standard YYLTYPE with a filenum index into an + * array of all opened filenames. + */ + +#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED +typedef struct YYLTYPE { + int first_line; + int first_column; + int last_line; + int last_column; + int filenum; +} YYLTYPE; + +#define YYLTYPE_IS_DECLARED 1 +#define YYLTYPE_IS_TRIVIAL 1 +#endif + + +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + (Current).filenum = YYRHSLOC (Rhs, N).filenum; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + (Current).filenum = YYRHSLOC (Rhs, 0).filenum; \ + } \ + while (YYID (0)) + + + + +extern int srcpos_filenum; + +extern int push_input_file(const char *filename); +extern int pop_input_file(void); + +extern FILE *dtc_open_file(const char *fname); +extern int lookup_file_name(const char *fname, int add_it); +extern const char *srcpos_filename_for_num(int filenum); +const char *srcpos_get_filename(void); + diff --git a/srcposstack.h b/srcposstack.h new file mode 100644 index 0000000..a95a179 --- /dev/null +++ b/srcposstack.h @@ -0,0 +1,138 @@ +/* + * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "srcpos.h" + + +/* + * This code should only be included into the lexical analysis. + * It references global context symbols that are only present + * in the generated lex.yy,c file. + */ + +#ifdef FLEX_SCANNER + + +/* + * Stack of nested include file contexts. + */ + +struct incl_file { + int filenum; + FILE *file; + YY_BUFFER_STATE yy_prev_buf; + int yy_prev_lineno; + struct incl_file *prev; +}; + +struct incl_file *incl_file_stack; + + +/* + * Detect infinite include recursion. + */ +#define MAX_INCLUDE_DEPTH (100) + +static int incl_depth = 0; + + + +int push_input_file(const char *filename) +{ + FILE *f; + struct incl_file *incl_file; + + if (!filename) { + yyerror("No include file name given."); + return 0; + } + + if (incl_depth++ >= MAX_INCLUDE_DEPTH) { + yyerror("Includes nested too deeply"); + return 0; + } + + f = dtc_open_file(filename); + + incl_file = malloc(sizeof(struct incl_file)); + if (!incl_file) { + yyerror("Can not allocate include file space."); + return 0; + } + + /* + * Save current context. + */ + incl_file->yy_prev_buf = YY_CURRENT_BUFFER; + incl_file->yy_prev_lineno = yylineno; + incl_file->filenum = srcpos_filenum; + incl_file->file = yyin; + incl_file->prev = incl_file_stack; + + incl_file_stack = incl_file; + + /* + * Establish new context. + */ + srcpos_filenum = lookup_file_name(filename, 0); + yylineno = 1; + yyin = f; + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + + return 1; +} + + +int pop_input_file(void) +{ + struct incl_file *incl_file; + + if (incl_file_stack == 0) + return 0; + + fclose(yyin); + + /* + * Pop. + */ + --incl_depth; + incl_file = incl_file_stack; + incl_file_stack = incl_file->prev; + + /* + * Recover old context. + */ + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(incl_file->yy_prev_buf); + yylineno = incl_file->yy_prev_lineno; + srcpos_filenum = incl_file->filenum; + yyin = incl_file->file; + + /* + * Free old state. + */ + free(incl_file); + + if (YY_CURRENT_BUFFER == 0) + return 0; + + return 1; +} + +#endif /* FLEX_SCANNER */ diff --git a/treesource.c b/treesource.c index e9bbaa5..c067b20 100644 --- a/treesource.c +++ b/treesource.c @@ -19,6 +19,7 @@ */ #include "dtc.h" +#include "srcpos.h" extern FILE *yyin; extern int yyparse(void); @@ -26,11 +27,12 @@ extern void yyerror(char const *); struct boot_info *the_boot_info; -struct boot_info *dt_from_source(FILE *f) +struct boot_info *dt_from_source(const char *fname) { the_boot_info = NULL; - yyin = f; + push_input_file(fname); + if (yyparse() != 0) return NULL; From ce34ae3b238c562a215df0dddea56da866f16c0f Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Wed, 28 Mar 2007 17:05:33 -0500 Subject: [PATCH 0053/1198] DTC: Incorporate some review suggestions. - Change include syntax to: /include/ "filename" - Move private functions directly into dtc-lexer.l - Define YYID for some older parser templates Also fix a #include ordering problem around YYLTPE. Signed-off-by; Jon Loeliger Acked-by: Haiying Wang --- dtc-lexer.l | 111 ++++++++++++++++++++++++++++++++++++++-- srcpos.h | 7 ++- srcposstack.h | 138 -------------------------------------------------- 3 files changed, 113 insertions(+), 143 deletions(-) delete mode 100644 srcposstack.h diff --git a/dtc-lexer.l b/dtc-lexer.l index 45f66ef..d237181 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -33,8 +33,8 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) %{ #include "dtc.h" +#include "srcpos.h" #include "dtc-parser.tab.h" -#include "srcposstack.h" /*#define LEXDEBUG 1*/ @@ -51,9 +51,8 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) %% -#[ \t]*include BEGIN(INCLUDE); +"/include/" BEGIN(INCLUDE); -[ \t]* /* whitespace before file name */ \"[^"\n]*\" { yytext[strlen(yytext) - 1] = 0; if (!push_input_file(yytext + 1)) { @@ -233,3 +232,109 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } %% + + +/* + * Stack of nested include file contexts. + */ + +struct incl_file { + int filenum; + FILE *file; + YY_BUFFER_STATE yy_prev_buf; + int yy_prev_lineno; + struct incl_file *prev; +}; + +struct incl_file *incl_file_stack; + + +/* + * Detect infinite include recursion. + */ +#define MAX_INCLUDE_DEPTH (100) + +static int incl_depth = 0; + + +int push_input_file(const char *filename) +{ + FILE *f; + struct incl_file *incl_file; + + if (!filename) { + yyerror("No include file name given."); + return 0; + } + + if (incl_depth++ >= MAX_INCLUDE_DEPTH) { + yyerror("Includes nested too deeply"); + return 0; + } + + f = dtc_open_file(filename); + + incl_file = malloc(sizeof(struct incl_file)); + if (!incl_file) { + yyerror("Can not allocate include file space."); + return 0; + } + + /* + * Save current context. + */ + incl_file->yy_prev_buf = YY_CURRENT_BUFFER; + incl_file->yy_prev_lineno = yylineno; + incl_file->filenum = srcpos_filenum; + incl_file->file = yyin; + incl_file->prev = incl_file_stack; + + incl_file_stack = incl_file; + + /* + * Establish new context. + */ + srcpos_filenum = lookup_file_name(filename, 0); + yylineno = 1; + yyin = f; + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + + return 1; +} + + +int pop_input_file(void) +{ + struct incl_file *incl_file; + + if (incl_file_stack == 0) + return 0; + + fclose(yyin); + + /* + * Pop. + */ + --incl_depth; + incl_file = incl_file_stack; + incl_file_stack = incl_file->prev; + + /* + * Recover old context. + */ + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(incl_file->yy_prev_buf); + yylineno = incl_file->yy_prev_lineno; + srcpos_filenum = incl_file->filenum; + yyin = incl_file->file; + + /* + * Free old state. + */ + free(incl_file); + + if (YY_CURRENT_BUFFER == 0) + return 0; + + return 1; +} diff --git a/srcpos.h b/srcpos.h index d591e7e..bc5b525 100644 --- a/srcpos.h +++ b/srcpos.h @@ -22,7 +22,7 @@ * array of all opened filenames. */ -#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED +#if ! defined(YYLTYPE) && ! defined(YYLTYPE_IS_DECLARED) typedef struct YYLTYPE { int first_line; int first_column; @@ -35,6 +35,10 @@ typedef struct YYLTYPE { #define YYLTYPE_IS_TRIVIAL 1 #endif +/* Cater to old parser templates. */ +#ifndef YYID +#define YYID(n) (n) +#endif #define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ @@ -68,4 +72,3 @@ extern FILE *dtc_open_file(const char *fname); extern int lookup_file_name(const char *fname, int add_it); extern const char *srcpos_filename_for_num(int filenum); const char *srcpos_get_filename(void); - diff --git a/srcposstack.h b/srcposstack.h deleted file mode 100644 index a95a179..0000000 --- a/srcposstack.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include "srcpos.h" - - -/* - * This code should only be included into the lexical analysis. - * It references global context symbols that are only present - * in the generated lex.yy,c file. - */ - -#ifdef FLEX_SCANNER - - -/* - * Stack of nested include file contexts. - */ - -struct incl_file { - int filenum; - FILE *file; - YY_BUFFER_STATE yy_prev_buf; - int yy_prev_lineno; - struct incl_file *prev; -}; - -struct incl_file *incl_file_stack; - - -/* - * Detect infinite include recursion. - */ -#define MAX_INCLUDE_DEPTH (100) - -static int incl_depth = 0; - - - -int push_input_file(const char *filename) -{ - FILE *f; - struct incl_file *incl_file; - - if (!filename) { - yyerror("No include file name given."); - return 0; - } - - if (incl_depth++ >= MAX_INCLUDE_DEPTH) { - yyerror("Includes nested too deeply"); - return 0; - } - - f = dtc_open_file(filename); - - incl_file = malloc(sizeof(struct incl_file)); - if (!incl_file) { - yyerror("Can not allocate include file space."); - return 0; - } - - /* - * Save current context. - */ - incl_file->yy_prev_buf = YY_CURRENT_BUFFER; - incl_file->yy_prev_lineno = yylineno; - incl_file->filenum = srcpos_filenum; - incl_file->file = yyin; - incl_file->prev = incl_file_stack; - - incl_file_stack = incl_file; - - /* - * Establish new context. - */ - srcpos_filenum = lookup_file_name(filename, 0); - yylineno = 1; - yyin = f; - yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); - - return 1; -} - - -int pop_input_file(void) -{ - struct incl_file *incl_file; - - if (incl_file_stack == 0) - return 0; - - fclose(yyin); - - /* - * Pop. - */ - --incl_depth; - incl_file = incl_file_stack; - incl_file_stack = incl_file->prev; - - /* - * Recover old context. - */ - yy_delete_buffer(YY_CURRENT_BUFFER); - yy_switch_to_buffer(incl_file->yy_prev_buf); - yylineno = incl_file->yy_prev_lineno; - srcpos_filenum = incl_file->filenum; - yyin = incl_file->file; - - /* - * Free old state. - */ - free(incl_file); - - if (YY_CURRENT_BUFFER == 0) - return 0; - - return 1; -} - -#endif /* FLEX_SCANNER */ From 4384b23454a939852d679aee93ee624cf210287f Mon Sep 17 00:00:00 2001 From: Jerry Van Baren Date: Wed, 4 Apr 2007 22:04:33 -0400 Subject: [PATCH 0054/1198] Implement the -R option and add a -S option. Implement the -R option to add memory reserve slots. Add a -S option makes the blob at least this number of bytes. Signed-off-by: Gerald Van Baren --- dtc.c | 19 ++++++++++++++++--- dtc.h | 6 ++++-- flattree.c | 22 ++++++++++++++++++++-- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/dtc.c b/dtc.c index a009605..a94a402 100644 --- a/dtc.c +++ b/dtc.c @@ -21,6 +21,13 @@ #include "dtc.h" #include "srcpos.h" +/* + * Command line options + */ +int quiet; /* Level of quietness */ +int reservenum; /* Number of memory reservation slots */ +int minsize; /* Minimum blob size */ + char *join_path(char *path, char *name) { int lenp = strlen(path); @@ -85,6 +92,8 @@ static void usage(void) fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", OF_DEFAULT_VERSION); fprintf(stderr, "\t-R \n"); fprintf(stderr, "\t\tMake space for reserve map entries (relevant for \n\t\tdtb and asm output only)\n"); + fprintf(stderr, "\t-S \n"); + fprintf(stderr, "\t\tMake the blob at least long (extra space)\n"); fprintf(stderr, "\t-b \n"); fprintf(stderr, "\t\tSet the physical boot cpu\n"); fprintf(stderr, "\t-f\n"); @@ -104,12 +113,13 @@ int main(int argc, char *argv[]) FILE *inf = NULL; FILE *outf = NULL; int outversion = OF_DEFAULT_VERSION; - int reservenum = 1; int boot_cpuid_phys = 0xfeedbeef; - quiet = 0; + quiet = 0; + reservenum = 0; + minsize = 0; - while ((opt = getopt(argc, argv, "hI:O:o:V:R:fqb:")) != EOF) { + while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:fqb:")) != EOF) { switch (opt) { case 'I': inform = optarg; @@ -126,6 +136,9 @@ int main(int argc, char *argv[]) case 'R': reservenum = strtol(optarg, NULL, 0); break; + case 'S': + minsize = strtol(optarg, NULL, 0); + break; case 'f': force = 1; break; diff --git a/dtc.h b/dtc.h index 7ed3df2..8cfe1a1 100644 --- a/dtc.h +++ b/dtc.h @@ -37,9 +37,11 @@ #include "flat_dt.h" /* - * Level of quietness + * Command line options */ -int quiet; +extern int quiet; /* Level of quietness */ +extern int reservenum; /* Number of memory reservation slots */ +extern int minsize; /* Minimum blob size */ static inline void die(char * str, ...) { diff --git a/flattree.c b/flattree.c index 780142f..151d16e 100644 --- a/flattree.c +++ b/flattree.c @@ -295,10 +295,18 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist, { struct reserve_info *re; struct data d = empty_data; + static struct reserve_entry null_re = {0,0}; + int j; for (re = reservelist; re; re = re->next) { d = data_append_re(d, &re->re); } + /* + * Add additional reserved slots if the user asked for them. + */ + for (j = 0; j < reservenum; j++) { + d = data_append_re(d, &null_re); + } return d; } @@ -324,8 +332,18 @@ static void make_bph(struct boot_param_header *bph, bph->off_dt_struct = cpu_to_be32(reserve_off + reservesize); bph->off_dt_strings = cpu_to_be32(reserve_off + reservesize + dtsize); - bph->totalsize = cpu_to_be32(reserve_off + reservesize - + dtsize + strsize); + bph->totalsize = reserve_off + reservesize + dtsize + strsize; + if (minsize > 0) { + if (bph->totalsize >= minsize) { + if (quiet < 1) + fprintf(stderr, + "Warning: blob size %d >= minimum size %d\n", + bph->totalsize, minsize); + + } else + bph->totalsize = minsize; + } + bph->totalsize = cpu_to_be32(bph->totalsize); if (vi->flags & FTF_BOOTCPUID) bph->boot_cpuid_phys = cpu_to_be32(boot_cpuid_phys); From 4f5370a13864eec0c370b8a2adbb527321a376f6 Mon Sep 17 00:00:00 2001 From: Jerry Van Baren Date: Sat, 14 Apr 2007 18:16:47 -0400 Subject: [PATCH 0055/1198] Add -o to the usage message. Signed-off-by: Gerald Van Baren Acked-by: David Gibson --- dtc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dtc.c b/dtc.c index a94a402..5767834 100644 --- a/dtc.c +++ b/dtc.c @@ -83,6 +83,7 @@ static void usage(void) fprintf(stderr, "\t\t\tdts - device tree source text\n"); fprintf(stderr, "\t\t\tdtb - device tree blob\n"); fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n"); + fprintf(stderr, "\t-o \n"); fprintf(stderr, "\t-O \n"); fprintf(stderr, "\t\tOutput formats are:\n"); fprintf(stderr, "\t\t\tdts - device tree source text\n"); From ca25e54ddd4efbc4c9165bc0ba45ab898693da4e Mon Sep 17 00:00:00 2001 From: Jerry Van Baren Date: Tue, 17 Apr 2007 18:14:41 -0400 Subject: [PATCH 0056/1198] Fix reserve map output for asm format. Add extra reserve map slots output for asm format (previously done for dtb output). Signed-off-by: Gerald Van Baren --- flattree.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flattree.c b/flattree.c index 151d16e..8159848 100644 --- a/flattree.c +++ b/flattree.c @@ -490,6 +490,9 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) (unsigned int)(re->re.size >> 32), (unsigned int)(re->re.size & 0xffffffff)); } + for (i = 0; i < reservenum; i++) { + fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); + } fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); From 86c01ee6dfc68c633eaaee6ab62d0742fd82b24f Mon Sep 17 00:00:00 2001 From: Jerry Van Baren Date: Wed, 18 Apr 2007 21:59:51 -0400 Subject: [PATCH 0057/1198] Assemble the blob in memory before writing it out. This makes padding out the blob if the user requested extra size much easer. The assembly and writing to the file is more straight forward too. Signed-off-by: Gerald Van Baren Acked-by: David Gibson --- flattree.c | 83 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/flattree.c b/flattree.c index 8159848..913b02f 100644 --- a/flattree.c +++ b/flattree.c @@ -307,9 +307,10 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist, for (j = 0; j < reservenum; j++) { d = data_append_re(d, &null_re); } - + return d; } + static void make_bph(struct boot_param_header *bph, struct version_info *vi, int reservesize, int dtsize, int strsize, @@ -332,19 +333,8 @@ static void make_bph(struct boot_param_header *bph, bph->off_dt_struct = cpu_to_be32(reserve_off + reservesize); bph->off_dt_strings = cpu_to_be32(reserve_off + reservesize + dtsize); - bph->totalsize = reserve_off + reservesize + dtsize + strsize; - if (minsize > 0) { - if (bph->totalsize >= minsize) { - if (quiet < 1) - fprintf(stderr, - "Warning: blob size %d >= minimum size %d\n", - bph->totalsize, minsize); + bph->totalsize = cpu_to_be32(reserve_off + reservesize + dtsize + strsize); - } else - bph->totalsize = minsize; - } - bph->totalsize = cpu_to_be32(bph->totalsize); - if (vi->flags & FTF_BOOTCPUID) bph->boot_cpuid_phys = cpu_to_be32(boot_cpuid_phys); if (vi->flags & FTF_STRTABSIZE) @@ -358,11 +348,11 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, { struct version_info *vi = NULL; int i; - struct data dtbuf = empty_data; - struct data strbuf = empty_data; - struct data reservebuf; + struct data blob = empty_data; + struct data reservebuf = empty_data; + struct data dtbuf = empty_data; + struct data strbuf = empty_data; struct boot_param_header bph; - struct reserve_entry termre = {.address = 0, .size = 0}; for (i = 0; i < ARRAY_SIZE(version_table); i++) { if (version_table[i].version == version) @@ -371,9 +361,6 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, if (!vi) die("Unknown device tree blob version %d\n", version); - dtbuf = empty_data; - strbuf = empty_data; - flatten_tree(bi->dt, &bin_emitter, &dtbuf, &strbuf, vi); bin_emit_cell(&dtbuf, OF_DT_END); @@ -383,28 +370,45 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, make_bph(&bph, vi, reservebuf.len, dtbuf.len, strbuf.len, boot_cpuid_phys); - fwrite(&bph, vi->hdr_size, 1, f); - - /* Align the reserve map to an 8 byte boundary */ - for (i = vi->hdr_size; i < be32_to_cpu(bph.off_mem_rsvmap); i++) - fputc(0, f); + /* + * Assemble the blob: start with the header, add with alignment + * the reserve buffer, add the reserve map terminating zeroes, + * the device tree itself, and finally the strings. + */ + blob = data_append_data(blob, &bph, sizeof(bph)); + blob = data_append_align(blob, 8); + blob = data_merge(blob, reservebuf); + blob = data_append_zeroes(blob, sizeof(struct reserve_entry)); + blob = data_merge(blob, dtbuf); + blob = data_merge(blob, strbuf); /* - * Reserve map entries. - * Each entry is an (address, size) pair of u64 values. - * Always supply a zero-sized temination entry. + * If the user asked for more space than is used, pad out the blob. */ - fwrite(reservebuf.val, reservebuf.len, 1, f); - fwrite(&termre, sizeof(termre), 1, f); + if (minsize > 0) { + int padlen = minsize - be32_to_cpu(bph.totalsize); - fwrite(dtbuf.val, dtbuf.len, 1, f); - fwrite(strbuf.val, strbuf.len, 1, f); + if (padlen > 0) { + blob = data_append_zeroes(blob, padlen); + bph.totalsize = cpu_to_be32(minsize); + } else { + if (quiet < 1) + fprintf(stderr, + "Warning: blob size %d >= minimum size %d\n", + be32_to_cpu(bph.totalsize), minsize); + } + } + + fwrite(blob.val, blob.len, 1, f); if (ferror(f)) die("Error writing device tree blob: %s\n", strerror(errno)); - data_free(dtbuf); - data_free(strbuf); + /* + * data_merge() frees the right-hand element so only the blob + * remains to be freed. + */ + data_free(blob); } static void dump_stringtable_asm(FILE *f, struct data strbuf) @@ -447,7 +451,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) emit_label(f, symprefix, "blob_start"); emit_label(f, symprefix, "header"); fprintf(f, "\t.long\tOF_DT_HEADER /* magic */\n"); - fprintf(f, "\t.long\t_%s_blob_end - _%s_blob_start /* totalsize */\n", + fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start /* totalsize */\n", symprefix, symprefix); fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start /* off_dt_struct */\n", symprefix, symprefix); @@ -507,6 +511,15 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) emit_label(f, symprefix, "blob_end"); + /* + * If the user asked for more space than is used, pad it out. + */ + if (minsize > 0) { + fprintf(f, "\t.space\t%d - (_%s_blob_end - _%s_blob_start), 0\n", + minsize, symprefix, symprefix); + } + emit_label(f, symprefix, "blob_abs_end"); + data_free(strbuf); } From 7ea144f4c0b47c6f25cb4862b3299b7e5d7f7813 Mon Sep 17 00:00:00 2001 From: Jerry Van Baren Date: Thu, 19 Apr 2007 22:22:35 -0400 Subject: [PATCH 0058/1198] Fix the -S to modify the totalsize properly. With the last improvement to pad out the blob, I broke the blob header totalsize adjustment. The adjustment was moved up in the code before the memory image of the blob is created. Signed-off-by: Gerald Van Baren --- flattree.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/flattree.c b/flattree.c index 913b02f..b54f7ef 100644 --- a/flattree.c +++ b/flattree.c @@ -353,6 +353,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, struct data dtbuf = empty_data; struct data strbuf = empty_data; struct boot_param_header bph; + int padlen; for (i = 0; i < ARRAY_SIZE(version_table); i++) { if (version_table[i].version == version) @@ -370,6 +371,19 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, make_bph(&bph, vi, reservebuf.len, dtbuf.len, strbuf.len, boot_cpuid_phys); + /* + * If the user asked for more space than is used, adjust the totalsize. + */ + padlen = minsize - be32_to_cpu(bph.totalsize); + if (padlen > 0) { + bph.totalsize = cpu_to_be32(minsize); + } else { + if ((minsize > 0) && (quiet < 1)) + fprintf(stderr, + "Warning: blob size %d >= minimum size %d\n", + be32_to_cpu(bph.totalsize), minsize); + } + /* * Assemble the blob: start with the header, add with alignment * the reserve buffer, add the reserve map terminating zeroes, @@ -385,18 +399,9 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, /* * If the user asked for more space than is used, pad out the blob. */ - if (minsize > 0) { - int padlen = minsize - be32_to_cpu(bph.totalsize); - - if (padlen > 0) { - blob = data_append_zeroes(blob, padlen); - bph.totalsize = cpu_to_be32(minsize); - } else { - if (quiet < 1) - fprintf(stderr, - "Warning: blob size %d >= minimum size %d\n", - be32_to_cpu(bph.totalsize), minsize); - } + if (padlen > 0) { + blob = data_append_zeroes(blob, padlen); + bph.totalsize = cpu_to_be32(minsize); } fwrite(blob.val, blob.len, 1, f); From 41eecd4c2acaca01295fdb48ddc9ec5520f5a7d4 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 7 Jun 2007 12:07:35 +1000 Subject: [PATCH 0059/1198] dtc: Fix recognition of whitespace characters At present, the lexer in dtc recognizes only space, tab and newline as whitespace characters. This is broken; in particular this means that dtc will get syntax errors on files with DOS-style (CR-LF) newlines. This patch fixes the problem, using flex's built-int [:space:] character class. 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 d237181..77ccd54 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -27,7 +27,7 @@ PROPCHAR [a-zA-Z0-9,._+*#?-] UNITCHAR [0-9a-f,] -WS [ \t\n] +WS [[:space:]] REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) From ce243227f1fd9d0353b428481b5a599db16a9d05 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Sat, 9 Jun 2007 23:21:31 -0500 Subject: [PATCH 0060/1198] dtc: parse NOP in dtb input Version 16 and later of the flat device tree format allow NOPs to be placed in the tree. When processing dtb input, dtc must recognise them. Previously it would produce the error message FATAL ERROR: Invalid opcode word 00000004 in device tree blob Signed-off-by: Milton Miller --- flattree.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/flattree.c b/flattree.c index b54f7ef..b802e2c 100644 --- a/flattree.c +++ b/flattree.c @@ -27,6 +27,7 @@ #define FTF_BOOTCPUID 0x8 #define FTF_STRTABSIZE 0x10 #define FTF_STRUCTSIZE 0x20 +#define FTF_NOPS 0x40 static struct version_info { int version; @@ -41,9 +42,9 @@ static struct version_info { {3, 1, BPH_V3_SIZE, FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE}, {16, 16, BPH_V3_SIZE, - FTF_BOOTCPUID|FTF_STRTABSIZE}, + FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_NOPS}, {17, 16, BPH_V17_SIZE, - FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE}, + FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS}, }; struct emitter { @@ -774,6 +775,13 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, die("Premature OF_DT_END in device tree blob\n"); break; + case OF_DT_NOP: + if (flags & FTF_NOPS) + break; + + die("OF_DT_NOP in device tree blob\n"); + break; + default: die("Invalid opcode word %08x in device tree blob\n", val); @@ -895,6 +903,8 @@ struct boot_info *dt_from_blob(FILE *f) if (version < 16) { flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN; + } else { + flags |= FTF_NOPS; } inbuf_init(&memresvbuf, From a6c76f923dcc42102fac58375eaca28057811c20 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 13 Jun 2007 14:18:10 +1000 Subject: [PATCH 0061/1198] libfdt: More thorough use of constification As a read-only functions, which take a const pointer to the fdt, treat fdt_get_property() and fdt_getprop() as returning const pointers to within the blob. fdt_get_property_w() and fdt_getprop_w() versions are supplied which take a non-const fdt pointer and return a non-const pointer for the benefit of callers wishing to alter the device tree contents. Likewise the lower-level fdt_offset_ptr() and _fdt_offset_ptr() functions are changed to return const pointers, with *_w() versions supplied. Signed-off-by: David Gibson --- fdt.c | 4 ++-- fdt_ro.c | 10 +++++----- fdt_rw.c | 10 +++++----- fdt_sw.c | 8 ++++---- fdt_wip.c | 6 +++--- libfdt.h | 33 +++++++++++++++++++++++++++------ libfdt_internal.h | 9 +++++++-- tests/del_property.c | 4 ++-- tests/nop_property.c | 4 ++-- tests/notfound.c | 4 ++-- tests/setprop.c | 4 ++-- tests/setprop_inplace.c | 5 +++-- tests/tests.h | 4 ++-- tests/testutils.c | 6 +++--- tests/truncated_property.c | 2 +- 15 files changed, 70 insertions(+), 43 deletions(-) diff --git a/fdt.c b/fdt.c index 772da46..3572ef8 100644 --- a/fdt.c +++ b/fdt.c @@ -42,9 +42,9 @@ int _fdt_check_header(const void *fdt) return 0; } -void *fdt_offset_ptr(const void *fdt, int offset, int len) +const void *fdt_offset_ptr(const void *fdt, int offset, int len) { - void *p; + const void *p; if (fdt_version(fdt) >= 0x11) if (((offset + len) < offset) diff --git a/fdt_ro.c b/fdt_ro.c index 9112c6a..28a6d16 100644 --- a/fdt_ro.c +++ b/fdt_ro.c @@ -137,13 +137,13 @@ int fdt_path_offset(const void *fdt, const char *path) return offset; } -struct fdt_property *fdt_get_property(const void *fdt, - int nodeoffset, - const char *name, int *lenp) +const struct fdt_property *fdt_get_property(const void *fdt, + int nodeoffset, + const char *name, int *lenp) { int level = 0; uint32_t tag; - struct fdt_property *prop; + const struct fdt_property *prop; int namestroff; int offset, nextoffset; int err; @@ -216,7 +216,7 @@ struct fdt_property *fdt_get_property(const void *fdt, return NULL; } -void *fdt_getprop(const void *fdt, int nodeoffset, +const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp) { const struct fdt_property *prop; diff --git a/fdt_rw.c b/fdt_rw.c index 7396645..02b36f0 100644 --- a/fdt_rw.c +++ b/fdt_rw.c @@ -123,7 +123,7 @@ static int _resize_property(void *fdt, int nodeoffset, const char *name, int len int oldlen; int err; - *prop = fdt_get_property(fdt, nodeoffset, name, &oldlen); + *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); if (! (*prop)) return oldlen; @@ -153,7 +153,7 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len, if (namestroff < 0) return namestroff; - *prop = _fdt_offset_ptr(fdt, nextoffset); + *prop = _fdt_offset_ptr_w(fdt, nextoffset); proplen = sizeof(**prop) + ALIGN(len, FDT_TAGSIZE); err = _blob_splice_struct(fdt, *prop, 0, proplen); @@ -192,7 +192,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name) RW_CHECK_HEADER(fdt); - prop = fdt_get_property(fdt, nodeoffset, name, &len); + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); if (! prop) return len; @@ -225,7 +225,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, tag = _fdt_next_tag(fdt, offset, &nextoffset); } while (tag == FDT_PROP); - nh = _fdt_offset_ptr(fdt, offset); + nh = _fdt_offset_ptr_w(fdt, offset); nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE; err = _blob_splice_struct(fdt, nh, 0, nodelen); @@ -254,7 +254,7 @@ int fdt_del_node(void *fdt, int nodeoffset) if (endoffset < 0) return endoffset; - return _blob_splice_struct(fdt, _fdt_offset_ptr(fdt, nodeoffset), + return _blob_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), endoffset - nodeoffset, 0); } diff --git a/fdt_sw.c b/fdt_sw.c index 41d4891..dd7a165 100644 --- a/fdt_sw.c +++ b/fdt_sw.c @@ -42,7 +42,7 @@ static void *grab_space(void *fdt, int len) return NULL; fdt_set_header(fdt, size_dt_struct, offset + len); - return fdt_offset_ptr(fdt, offset, len); + return fdt_offset_ptr_w(fdt, offset, len); } int fdt_create(void *buf, int bufsize) @@ -82,7 +82,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) return -FDT_ERR_NOSPACE; - re = (struct fdt_reserve_entry *)((void *)fdt + offset); + re = (struct fdt_reserve_entry *)(fdt + offset); re->address = cpu_to_fdt64(addr); re->size = cpu_to_fdt64(size); @@ -205,8 +205,8 @@ int fdt_finish(void *fdt) offset = 0; while ((tag = _fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { if (tag == FDT_PROP) { - struct fdt_property *prop = fdt_offset_ptr(fdt, offset, - sizeof(*prop)); + struct fdt_property *prop = + fdt_offset_ptr_w(fdt, offset, sizeof(*prop)); int nameoff; if (! prop) diff --git a/fdt_wip.c b/fdt_wip.c index 0db7d25..932a193 100644 --- a/fdt_wip.c +++ b/fdt_wip.c @@ -29,7 +29,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, void *propval; int proplen; - propval = fdt_getprop(fdt, nodeoffset, name, &proplen); + propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen); if (! propval) return proplen; @@ -53,7 +53,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name) struct fdt_property *prop; int len; - prop = fdt_get_property(fdt, nodeoffset, name, &len); + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); if (! prop) return len; @@ -107,6 +107,6 @@ int fdt_nop_node(void *fdt, int nodeoffset) if (endoffset < 0) return endoffset; - nop_region(fdt_offset_ptr(fdt, nodeoffset, 0), endoffset - nodeoffset); + nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), endoffset - nodeoffset); return 0; } diff --git a/libfdt.h b/libfdt.h index acdc72e..be75f9a 100644 --- a/libfdt.h +++ b/libfdt.h @@ -45,7 +45,7 @@ #define FDT_ERR_MAX 11 #define fdt_get_header(fdt, field) \ - (fdt32_to_cpu(((struct fdt_header *)(fdt))->field)) + (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) #define fdt_magic(fdt) (fdt_get_header(fdt, magic)) #define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) #define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) @@ -60,10 +60,17 @@ #define fdt_set_header(fdt, field, val) \ ((struct fdt_header *)(fdt))->field = cpu_to_fdt32(val) -void *fdt_offset_ptr(const void *fdt, int offset, int checklen); +const void *fdt_offset_ptr(const void *fdt, int offset, int checklen); +static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) +{ + return (void *)fdt_offset_ptr(fdt, offset, checklen); +} + #define fdt_offset_ptr_typed(fdt, offset, var) \ ((typeof(var))(fdt_offset_ptr((fdt), (offset), sizeof(*(var))))) +#define fdt_offset_ptr_typed_w(fdt, offset, var) \ + ((typeof(var))(fdt_offset_ptr_w((fdt), (offset), sizeof(*(var))))) int fdt_move(const void *fdt, void *buf, int bufsize); @@ -76,10 +83,24 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); int fdt_path_offset(const void *fdt, const char *path); -struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, - const char *name, int *lenp); -void *fdt_getprop(const void *fdt, int nodeoffset, - const char *name, int *lenp); +const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, + const char *name, int *lenp); + +static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, + const char *name, + int *lenp) +{ + return (struct fdt_property *)fdt_get_property(fdt, nodeoffset, + name, lenp); +} + +const void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp); +static inline void *fdt_getprop_w(void *fdt, int nodeoffset, + const char *name, int *lenp) +{ + return (void *)fdt_getprop(fdt, nodeoffset, name, lenp); +} /* Write-in-place functions */ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, diff --git a/libfdt_internal.h b/libfdt_internal.h index 124bef7..a46af51 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -31,9 +31,14 @@ uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset); const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); int _fdt_node_end_offset(void *fdt, int nodeoffset); -static inline void *_fdt_offset_ptr(const struct fdt_header *fdt, int offset) +static inline const void *_fdt_offset_ptr(const void *fdt, int offset) { - return (void *)fdt + fdt_off_dt_struct(fdt) + offset; + return fdt + fdt_off_dt_struct(fdt) + offset; +} + +static inline void *_fdt_offset_ptr_w(void *fdt, int offset) +{ + return (void *)_fdt_offset_ptr(fdt, offset); } #define SW_MAGIC (~FDT_MAGIC) diff --git a/tests/del_property.c b/tests/del_property.c index a7928a3..35dc932 100644 --- a/tests/del_property.c +++ b/tests/del_property.c @@ -33,8 +33,8 @@ int main(int argc, char *argv[]) { void *fdt; - uint32_t *intp; - char *strp; + const uint32_t *intp; + const char *strp; int err, lenerr; int oldsize, delsize, newsize; diff --git a/tests/nop_property.c b/tests/nop_property.c index 84e735a..56256c4 100644 --- a/tests/nop_property.c +++ b/tests/nop_property.c @@ -33,8 +33,8 @@ int main(int argc, char *argv[]) { void *fdt; - uint32_t *intp; - char *strp; + const uint32_t *intp; + const char *strp; int err; int lenerr; diff --git a/tests/notfound.c b/tests/notfound.c index 3b18664..a93b605 100644 --- a/tests/notfound.c +++ b/tests/notfound.c @@ -37,11 +37,11 @@ void check_error(const char *s, int err) int main(int argc, char *argv[]) { - struct fdt_property *prop; + const struct fdt_property *prop; void *fdt; int offset; int subnode1_offset; - void *val; + const void *val; int lenerr; test_init(argc, argv); diff --git a/tests/setprop.c b/tests/setprop.c index f58a33d..7f9be3e 100644 --- a/tests/setprop.c +++ b/tests/setprop.c @@ -37,8 +37,8 @@ int main(int argc, char *argv[]) { void *fdt; void *buf; - uint32_t *intp; - char *strp; + const uint32_t *intp; + const char *strp; int err; test_init(argc, argv); diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c index bcfd357..59c1209 100644 --- a/tests/setprop_inplace.c +++ b/tests/setprop_inplace.c @@ -33,8 +33,9 @@ int main(int argc, char *argv[]) { void *fdt; - uint32_t *intp; - char *strp, *xstr; + const uint32_t *intp; + const char *strp; + char *xstr; int xlen, i; int err; diff --git a/tests/tests.h b/tests/tests.h index b262e31..ace7ba3 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -117,8 +117,8 @@ void check_property(void *fdt, int nodeoffset, const char *name, }) -void *check_getprop(void *fdt, int nodeoffset, const char *name, - int len, const void *val); +const void *check_getprop(void *fdt, int nodeoffset, const char *name, + int len, const void *val); #define check_getprop_typed(fdt, nodeoffset, name, val) \ ({ \ typeof(val) x = val; \ diff --git a/tests/testutils.c b/tests/testutils.c index efc4f4a..fcb1c88 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -107,10 +107,10 @@ void check_property(void *fdt, int nodeoffset, const char *name, } -void *check_getprop(void *fdt, int nodeoffset, const char *name, - int len, const void *val) +const void *check_getprop(void *fdt, int nodeoffset, const char *name, + int len, const void *val) { - void *propval; + const void *propval; int proplen; propval = fdt_getprop(fdt, nodeoffset, name, &proplen); diff --git a/tests/truncated_property.c b/tests/truncated_property.c index dbd3652..5642d8d 100644 --- a/tests/truncated_property.c +++ b/tests/truncated_property.c @@ -32,7 +32,7 @@ int main(int argc, char *argv[]) { void *fdt = &_truncated_property; - void *prop; + const void *prop; int err; int len; From 948160520884b10f545bec792e0d37c1c14bbf2f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 13 Jun 2007 16:30:48 +1000 Subject: [PATCH 0062/1198] libfdt: Switch to dual GPL/BSD license Change the license information at the top of each file from LGPL to dual-GPL/BSD. Signed-off-by: David Gibson --- fdt.c | 54 +++++++++++++++++++++++++++++++++++++---------- fdt_ro.c | 54 +++++++++++++++++++++++++++++++++++++---------- fdt_rw.c | 54 +++++++++++++++++++++++++++++++++++++---------- fdt_strerror.c | 54 +++++++++++++++++++++++++++++++++++++---------- fdt_sw.c | 54 +++++++++++++++++++++++++++++++++++++---------- fdt_wip.c | 54 +++++++++++++++++++++++++++++++++++++---------- libfdt.h | 54 +++++++++++++++++++++++++++++++++++++---------- libfdt_internal.h | 54 +++++++++++++++++++++++++++++++++++++---------- 8 files changed, 344 insertions(+), 88 deletions(-) diff --git a/fdt.c b/fdt.c index 3572ef8..a29f1b0 100644 --- a/fdt.c +++ b/fdt.c @@ -2,19 +2,51 @@ * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/fdt_ro.c b/fdt_ro.c index 28a6d16..2ca1b22 100644 --- a/fdt_ro.c +++ b/fdt_ro.c @@ -2,19 +2,51 @@ * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/fdt_rw.c b/fdt_rw.c index 02b36f0..6e4c808 100644 --- a/fdt_rw.c +++ b/fdt_rw.c @@ -2,19 +2,51 @@ * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/fdt_strerror.c b/fdt_strerror.c index 7f231ce..f9d32ef 100644 --- a/fdt_strerror.c +++ b/fdt_strerror.c @@ -2,19 +2,51 @@ * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/fdt_sw.c b/fdt_sw.c index dd7a165..25f85d7 100644 --- a/fdt_sw.c +++ b/fdt_sw.c @@ -2,19 +2,51 @@ * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/fdt_wip.c b/fdt_wip.c index 932a193..78d530c 100644 --- a/fdt_wip.c +++ b/fdt_wip.c @@ -2,19 +2,51 @@ * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/libfdt.h b/libfdt.h index be75f9a..d33a64f 100644 --- a/libfdt.h +++ b/libfdt.h @@ -4,19 +4,51 @@ * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include diff --git a/libfdt_internal.h b/libfdt_internal.h index a46af51..a1a548d 100644 --- a/libfdt_internal.h +++ b/libfdt_internal.h @@ -4,19 +4,51 @@ * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include From 23cdf2379fee7902cd1aa295b2721fdef1163b33 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 14 Jun 2007 11:58:35 +1000 Subject: [PATCH 0063/1198] Move everything into a subdirectory in preparation for merge into dtc. --- .gitignore => libfdt/.gitignore | 0 GPL => libfdt/GPL | 0 Makefile => libfdt/Makefile | 0 TODO => libfdt/TODO | 0 fdt.c => libfdt/fdt.c | 0 fdt.h => libfdt/fdt.h | 0 fdt_ro.c => libfdt/fdt_ro.c | 0 fdt_rw.c => libfdt/fdt_rw.c | 0 fdt_strerror.c => libfdt/fdt_strerror.c | 0 fdt_sw.c => libfdt/fdt_sw.c | 0 fdt_wip.c => libfdt/fdt_wip.c | 0 libfdt.h => libfdt/libfdt.h | 0 libfdt_env.h => libfdt/libfdt_env.h | 0 libfdt_internal.h => libfdt/libfdt_internal.h | 0 {tests => libfdt/tests}/.gitignore | 0 {tests => libfdt/tests}/Makefile | 0 {tests => libfdt/tests}/del_node.c | 0 {tests => libfdt/tests}/del_property.c | 0 {tests => libfdt/tests}/dumptrees.c | 0 {tests => libfdt/tests}/find_property.c | 0 {tests => libfdt/tests}/getprop.c | 0 {tests => libfdt/tests}/move_and_save.c | 0 {tests => libfdt/tests}/nop_node.c | 0 {tests => libfdt/tests}/nop_property.c | 0 {tests => libfdt/tests}/notfound.c | 0 {tests => libfdt/tests}/open_pack.c | 0 {tests => libfdt/tests}/path_offset.c | 0 {tests => libfdt/tests}/root_node.c | 0 {tests => libfdt/tests}/run_tests.sh | 0 {tests => libfdt/tests}/rw_tree1.c | 0 {tests => libfdt/tests}/setprop.c | 0 {tests => libfdt/tests}/setprop_inplace.c | 0 {tests => libfdt/tests}/subnode_offset.c | 0 {tests => libfdt/tests}/sw_tree1.c | 0 {tests => libfdt/tests}/testdata.h | 0 {tests => libfdt/tests}/tests.h | 0 {tests => libfdt/tests}/testutils.c | 0 {tests => libfdt/tests}/trees.S | 0 {tests => libfdt/tests}/truncated_property.c | 0 39 files changed, 0 insertions(+), 0 deletions(-) rename .gitignore => libfdt/.gitignore (100%) rename GPL => libfdt/GPL (100%) rename Makefile => libfdt/Makefile (100%) rename TODO => libfdt/TODO (100%) rename fdt.c => libfdt/fdt.c (100%) rename fdt.h => libfdt/fdt.h (100%) rename fdt_ro.c => libfdt/fdt_ro.c (100%) rename fdt_rw.c => libfdt/fdt_rw.c (100%) rename fdt_strerror.c => libfdt/fdt_strerror.c (100%) rename fdt_sw.c => libfdt/fdt_sw.c (100%) rename fdt_wip.c => libfdt/fdt_wip.c (100%) rename libfdt.h => libfdt/libfdt.h (100%) rename libfdt_env.h => libfdt/libfdt_env.h (100%) rename libfdt_internal.h => libfdt/libfdt_internal.h (100%) rename {tests => libfdt/tests}/.gitignore (100%) rename {tests => libfdt/tests}/Makefile (100%) rename {tests => libfdt/tests}/del_node.c (100%) rename {tests => libfdt/tests}/del_property.c (100%) rename {tests => libfdt/tests}/dumptrees.c (100%) rename {tests => libfdt/tests}/find_property.c (100%) rename {tests => libfdt/tests}/getprop.c (100%) rename {tests => libfdt/tests}/move_and_save.c (100%) rename {tests => libfdt/tests}/nop_node.c (100%) rename {tests => libfdt/tests}/nop_property.c (100%) rename {tests => libfdt/tests}/notfound.c (100%) rename {tests => libfdt/tests}/open_pack.c (100%) rename {tests => libfdt/tests}/path_offset.c (100%) rename {tests => libfdt/tests}/root_node.c (100%) rename {tests => libfdt/tests}/run_tests.sh (100%) rename {tests => libfdt/tests}/rw_tree1.c (100%) rename {tests => libfdt/tests}/setprop.c (100%) rename {tests => libfdt/tests}/setprop_inplace.c (100%) rename {tests => libfdt/tests}/subnode_offset.c (100%) rename {tests => libfdt/tests}/sw_tree1.c (100%) rename {tests => libfdt/tests}/testdata.h (100%) rename {tests => libfdt/tests}/tests.h (100%) rename {tests => libfdt/tests}/testutils.c (100%) rename {tests => libfdt/tests}/trees.S (100%) rename {tests => libfdt/tests}/truncated_property.c (100%) diff --git a/.gitignore b/libfdt/.gitignore similarity index 100% rename from .gitignore rename to libfdt/.gitignore diff --git a/GPL b/libfdt/GPL similarity index 100% rename from GPL rename to libfdt/GPL diff --git a/Makefile b/libfdt/Makefile similarity index 100% rename from Makefile rename to libfdt/Makefile diff --git a/TODO b/libfdt/TODO similarity index 100% rename from TODO rename to libfdt/TODO diff --git a/fdt.c b/libfdt/fdt.c similarity index 100% rename from fdt.c rename to libfdt/fdt.c diff --git a/fdt.h b/libfdt/fdt.h similarity index 100% rename from fdt.h rename to libfdt/fdt.h diff --git a/fdt_ro.c b/libfdt/fdt_ro.c similarity index 100% rename from fdt_ro.c rename to libfdt/fdt_ro.c diff --git a/fdt_rw.c b/libfdt/fdt_rw.c similarity index 100% rename from fdt_rw.c rename to libfdt/fdt_rw.c diff --git a/fdt_strerror.c b/libfdt/fdt_strerror.c similarity index 100% rename from fdt_strerror.c rename to libfdt/fdt_strerror.c diff --git a/fdt_sw.c b/libfdt/fdt_sw.c similarity index 100% rename from fdt_sw.c rename to libfdt/fdt_sw.c diff --git a/fdt_wip.c b/libfdt/fdt_wip.c similarity index 100% rename from fdt_wip.c rename to libfdt/fdt_wip.c diff --git a/libfdt.h b/libfdt/libfdt.h similarity index 100% rename from libfdt.h rename to libfdt/libfdt.h diff --git a/libfdt_env.h b/libfdt/libfdt_env.h similarity index 100% rename from libfdt_env.h rename to libfdt/libfdt_env.h diff --git a/libfdt_internal.h b/libfdt/libfdt_internal.h similarity index 100% rename from libfdt_internal.h rename to libfdt/libfdt_internal.h diff --git a/tests/.gitignore b/libfdt/tests/.gitignore similarity index 100% rename from tests/.gitignore rename to libfdt/tests/.gitignore diff --git a/tests/Makefile b/libfdt/tests/Makefile similarity index 100% rename from tests/Makefile rename to libfdt/tests/Makefile diff --git a/tests/del_node.c b/libfdt/tests/del_node.c similarity index 100% rename from tests/del_node.c rename to libfdt/tests/del_node.c diff --git a/tests/del_property.c b/libfdt/tests/del_property.c similarity index 100% rename from tests/del_property.c rename to libfdt/tests/del_property.c diff --git a/tests/dumptrees.c b/libfdt/tests/dumptrees.c similarity index 100% rename from tests/dumptrees.c rename to libfdt/tests/dumptrees.c diff --git a/tests/find_property.c b/libfdt/tests/find_property.c similarity index 100% rename from tests/find_property.c rename to libfdt/tests/find_property.c diff --git a/tests/getprop.c b/libfdt/tests/getprop.c similarity index 100% rename from tests/getprop.c rename to libfdt/tests/getprop.c diff --git a/tests/move_and_save.c b/libfdt/tests/move_and_save.c similarity index 100% rename from tests/move_and_save.c rename to libfdt/tests/move_and_save.c diff --git a/tests/nop_node.c b/libfdt/tests/nop_node.c similarity index 100% rename from tests/nop_node.c rename to libfdt/tests/nop_node.c diff --git a/tests/nop_property.c b/libfdt/tests/nop_property.c similarity index 100% rename from tests/nop_property.c rename to libfdt/tests/nop_property.c diff --git a/tests/notfound.c b/libfdt/tests/notfound.c similarity index 100% rename from tests/notfound.c rename to libfdt/tests/notfound.c diff --git a/tests/open_pack.c b/libfdt/tests/open_pack.c similarity index 100% rename from tests/open_pack.c rename to libfdt/tests/open_pack.c diff --git a/tests/path_offset.c b/libfdt/tests/path_offset.c similarity index 100% rename from tests/path_offset.c rename to libfdt/tests/path_offset.c diff --git a/tests/root_node.c b/libfdt/tests/root_node.c similarity index 100% rename from tests/root_node.c rename to libfdt/tests/root_node.c diff --git a/tests/run_tests.sh b/libfdt/tests/run_tests.sh similarity index 100% rename from tests/run_tests.sh rename to libfdt/tests/run_tests.sh diff --git a/tests/rw_tree1.c b/libfdt/tests/rw_tree1.c similarity index 100% rename from tests/rw_tree1.c rename to libfdt/tests/rw_tree1.c diff --git a/tests/setprop.c b/libfdt/tests/setprop.c similarity index 100% rename from tests/setprop.c rename to libfdt/tests/setprop.c diff --git a/tests/setprop_inplace.c b/libfdt/tests/setprop_inplace.c similarity index 100% rename from tests/setprop_inplace.c rename to libfdt/tests/setprop_inplace.c diff --git a/tests/subnode_offset.c b/libfdt/tests/subnode_offset.c similarity index 100% rename from tests/subnode_offset.c rename to libfdt/tests/subnode_offset.c diff --git a/tests/sw_tree1.c b/libfdt/tests/sw_tree1.c similarity index 100% rename from tests/sw_tree1.c rename to libfdt/tests/sw_tree1.c diff --git a/tests/testdata.h b/libfdt/tests/testdata.h similarity index 100% rename from tests/testdata.h rename to libfdt/tests/testdata.h diff --git a/tests/tests.h b/libfdt/tests/tests.h similarity index 100% rename from tests/tests.h rename to libfdt/tests/tests.h diff --git a/tests/testutils.c b/libfdt/tests/testutils.c similarity index 100% rename from tests/testutils.c rename to libfdt/tests/testutils.c diff --git a/tests/trees.S b/libfdt/tests/trees.S similarity index 100% rename from tests/trees.S rename to libfdt/tests/trees.S diff --git a/tests/truncated_property.c b/libfdt/tests/truncated_property.c similarity index 100% rename from tests/truncated_property.c rename to libfdt/tests/truncated_property.c From 12578976fe9cef82f0c08db3f9a4f550f5085ba4 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 14 Jun 2007 15:05:55 +1000 Subject: [PATCH 0064/1198] Merge libfdt into dtc. Having pulled the libfdt repository into dtc, merge the makefiles and testsuites so that they build together usefully. --- .gitignore | 3 + Makefile | 36 +++++++++-- libfdt/.gitignore | 5 -- libfdt/Makefile | 28 +-------- libfdt/tests/.gitignore | 1 - libfdt/tests/Makefile | 62 ------------------- tests/Makefile | 63 ++++++++++++++++++-- {libfdt/tests => tests}/del_node.c | 0 {libfdt/tests => tests}/del_property.c | 0 {libfdt/tests => tests}/dumptrees.c | 0 {libfdt/tests => tests}/find_property.c | 0 {libfdt/tests => tests}/getprop.c | 0 {libfdt/tests => tests}/move_and_save.c | 0 {libfdt/tests => tests}/nop_node.c | 0 {libfdt/tests => tests}/nop_property.c | 0 {libfdt/tests => tests}/notfound.c | 0 {libfdt/tests => tests}/open_pack.c | 0 {libfdt/tests => tests}/path_offset.c | 0 {libfdt/tests => tests}/root_node.c | 0 tests/run_all_tests.sh | 2 - {libfdt/tests => tests}/run_tests.sh | 0 {libfdt/tests => tests}/rw_tree1.c | 0 {libfdt/tests => tests}/setprop.c | 0 {libfdt/tests => tests}/setprop_inplace.c | 0 {libfdt/tests => tests}/subnode_offset.c | 0 {libfdt/tests => tests}/sw_tree1.c | 0 {libfdt/tests => tests}/testdata.h | 0 {libfdt/tests => tests}/tests.h | 0 {libfdt/tests => tests}/testutils.c | 0 {libfdt/tests => tests}/trees.S | 0 {libfdt/tests => tests}/truncated_property.c | 0 31 files changed, 95 insertions(+), 105 deletions(-) delete mode 100644 libfdt/.gitignore delete mode 100644 libfdt/tests/.gitignore delete mode 100644 libfdt/tests/Makefile rename {libfdt/tests => tests}/del_node.c (100%) rename {libfdt/tests => tests}/del_property.c (100%) rename {libfdt/tests => tests}/dumptrees.c (100%) rename {libfdt/tests => tests}/find_property.c (100%) rename {libfdt/tests => tests}/getprop.c (100%) rename {libfdt/tests => tests}/move_and_save.c (100%) rename {libfdt/tests => tests}/nop_node.c (100%) rename {libfdt/tests => tests}/nop_property.c (100%) rename {libfdt/tests => tests}/notfound.c (100%) rename {libfdt/tests => tests}/open_pack.c (100%) rename {libfdt/tests => tests}/path_offset.c (100%) rename {libfdt/tests => tests}/root_node.c (100%) delete mode 100644 tests/run_all_tests.sh rename {libfdt/tests => tests}/run_tests.sh (100%) rename {libfdt/tests => tests}/rw_tree1.c (100%) rename {libfdt/tests => tests}/setprop.c (100%) rename {libfdt/tests => tests}/setprop_inplace.c (100%) rename {libfdt/tests => tests}/subnode_offset.c (100%) rename {libfdt/tests => tests}/sw_tree1.c (100%) rename {libfdt/tests => tests}/testdata.h (100%) rename {libfdt/tests => tests}/tests.h (100%) rename {libfdt/tests => tests}/testutils.c (100%) rename {libfdt/tests => tests}/trees.S (100%) rename {libfdt/tests => tests}/truncated_property.c (100%) diff --git a/.gitignore b/.gitignore index 85ccca2..92f9a34 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ *.o *.d +*.a +*.so +*~ *.tab.[ch] lex.yy.c dtc diff --git a/Makefile b/Makefile index 280db78..2dcc5c9 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,9 @@ DTC_OBJS = dtc.o flattree.o fstree.o data.o livetree.o \ DEPFILES = $(DTC_OBJS:.o=.d) -all: $(TARGETS) +.PHONY: libfdt tests + +all: $(TARGETS) tests libfdt dtc: $(DTC_OBJS) $(LINK.c) -o $@ $^ @@ -17,6 +19,9 @@ dtc: $(DTC_OBJS) ftdump: ftdump.o $(LINK.c) -o $@ $^ +libfdt: + cd libfdt && $(MAKE) all + dtc-parser.tab.c dtc-parser.tab.h dtc-parser.output: dtc-parser.y $(BISON) -d $< @@ -25,17 +30,38 @@ lex.yy.c: dtc-lexer.l lex.yy.o: lex.yy.c dtc-parser.tab.h -check: all - cd tests && $(MAKE) check +tests: tests/all + +tests/%: libfdt + $(MAKE) -C tests $* + +check: all + cd tests; ./run_tests.sh + +checkv: all + cd tests; ./run_tests.sh -v + +func: all + cd tests; ./run_tests.sh -t func + +funcv: all + cd tests; ./run_tests.sh -t func -v + +stress: all + cd tests; ./run_tests.sh -t stress + +stressv: all + cd tests; ./run_tests.sh -t stress -v clean: rm -f *~ *.o a.out core $(TARGETS) rm -f *.tab.[ch] lex.yy.c rm -f *.i *.output vgcore.* rm -f *.d - cd tests && $(MAKE) clean + $(MAKE) -C libfdt clean + $(MAKE) -C tests clean %.d: %.c - $(CC) -MM -MG -MT "$*.o $@" $< > $@ + $(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@ -include $(DEPFILES) diff --git a/libfdt/.gitignore b/libfdt/.gitignore deleted file mode 100644 index 4b147f1..0000000 --- a/libfdt/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.d -*.o -*.a -*.so -*~ diff --git a/libfdt/Makefile b/libfdt/Makefile index c8240bb..3f68877 100644 --- a/libfdt/Makefile +++ b/libfdt/Makefile @@ -26,35 +26,12 @@ endif DEPFILES = $(LIBOBJS:%.o=%.d) -all: libs tests +all: libs -.PHONY: tests libs +.PHONY: libs libs: $(TARGETLIBS) -tests: tests/all - -tests/%: libs - $(MAKE) -C tests $* - -check: all - cd tests; ./run_tests.sh - -checkv: all - cd tests; ./run_tests.sh -v - -func: all - cd tests; ./run_tests.sh -t func - -funcv: all - cd tests; ./run_tests.sh -t func -v - -stress: all - cd tests; ./run_tests.sh -t stress - -stressv: all - cd tests; ./run_tests.sh -t stress -v - %.o: %.c @$(VECHO) CC $@ $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< @@ -74,7 +51,6 @@ libfdt.a: $(LIBOBJS) clean: @$(VECHO) CLEAN rm -f *~ *.o *.so *.a *.d *.i *.s core a.out $(VERSION) - $(MAKE) -C tests clean %.d: %.c @$(CC) $(CPPFLAGS) -MM -MT "$*.o $@" $< > $@ diff --git a/libfdt/tests/.gitignore b/libfdt/tests/.gitignore deleted file mode 100644 index b60ed20..0000000 --- a/libfdt/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.dtb diff --git a/libfdt/tests/Makefile b/libfdt/tests/Makefile deleted file mode 100644 index 533c98e..0000000 --- a/libfdt/tests/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -PREFIX = /usr/local - -LIB_TESTS = root_node find_property subnode_offset path_offset getprop \ - notfound \ - setprop_inplace nop_property nop_node \ - sw_tree1 \ - move_and_save \ - open_pack rw_tree1 setprop del_property del_node -LIBTREE_TESTS = truncated_property -TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) -UTILS = dumptrees - -TREES = test_tree1.dtb - -CFLAGS = -Wall -g -CPPFLAGS = -I.. -LDFLAGS = -L.. - -LIBFDT = ../libfdt.a - -ifdef V -VECHO = : -else -VECHO = echo " " -.SILENT: -endif - -DEPFILES = $(TESTS:%=%.d) testutils.d - -all: $(TESTS) $(TREES) - -%.o: %.c - @$(VECHO) CC $@ - $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< - -%.o: %.S - @$(VECHO) AS $@ - $(CC) -D__ASSEMBLY__ $(CPPFLAGS) -o $@ -c $< - -%: %.o - @$(VECHO) LD $@ - $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) - -$(LIB_TESTS): %: testutils.o $(LIBFDT) - -$(LIBTREE_TESTS): %: testutils.o trees.o $(LIBFDT) - -dumptrees: %: trees.o - -$(TREES): dumptrees - @$(VECHO) DUMPTREES - ./dumptrees >/dev/null - -clean: - @$(VECHO) CLEAN "(tests)" - rm -f *~ *.o *.so *.a *.d *.s core a.out - rm -f $(TESTS) $(UTILS) *.dtb - -%.d: %.c - @$(CC) $(CPPFLAGS) -MM -MT "$*.o $@" $< > $@ - --include $(DEPFILES) diff --git a/tests/Makefile b/tests/Makefile index 912f832..5273028 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,12 +1,67 @@ DTC = ../dtc VG_DTC = valgrind --tool=memcheck ../dtc -check: all - ./run_all_tests.sh +LIB_TESTS = root_node find_property subnode_offset path_offset getprop \ + notfound \ + setprop_inplace nop_property nop_node \ + sw_tree1 \ + move_and_save \ + open_pack rw_tree1 setprop del_property del_node +LIBTREE_TESTS = truncated_property +TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) +UTILS = dumptrees -all: +TREES = test_tree1.dtb + +CFLAGS = -Wall -g +CPPFLAGS = -I../libfdt +LDFLAGS = -L../libfdt + +LIBFDT = ../libfdt/libfdt.a + +ifdef V +VECHO = : +else +VECHO = echo " " +.SILENT: +endif + +DEPFILES = $(TESTS:%=%.d) testutils.d + +check: all + ./run_tests.sh + +all: $(TESTS) $(TREES) + +%.o: %.c + @$(VECHO) CC $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< + +%.o: %.S + @$(VECHO) AS $@ + $(CC) -D__ASSEMBLY__ $(CPPFLAGS) -o $@ -c $< + +%: %.o + @$(VECHO) LD $@ + $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +$(LIB_TESTS): %: testutils.o $(LIBFDT) + +$(LIBTREE_TESTS): %: testutils.o trees.o $(LIBFDT) + +dumptrees: %: trees.o + +$(TREES): dumptrees + @$(VECHO) DUMPTREES + ./dumptrees >/dev/null clean: - rm -f *~ + rm -f $(TESTS) + rm -f *.dtb dumptrees + rm -f *~ *.d *.o a.out core + rm -f *.i *.output vgcore.* +%.d: %.c + @$(CC) $(CPPFLAGS) -MM -MT "$*.o $@" $< > $@ +-include $(DEPFILES) diff --git a/libfdt/tests/del_node.c b/tests/del_node.c similarity index 100% rename from libfdt/tests/del_node.c rename to tests/del_node.c diff --git a/libfdt/tests/del_property.c b/tests/del_property.c similarity index 100% rename from libfdt/tests/del_property.c rename to tests/del_property.c diff --git a/libfdt/tests/dumptrees.c b/tests/dumptrees.c similarity index 100% rename from libfdt/tests/dumptrees.c rename to tests/dumptrees.c diff --git a/libfdt/tests/find_property.c b/tests/find_property.c similarity index 100% rename from libfdt/tests/find_property.c rename to tests/find_property.c diff --git a/libfdt/tests/getprop.c b/tests/getprop.c similarity index 100% rename from libfdt/tests/getprop.c rename to tests/getprop.c diff --git a/libfdt/tests/move_and_save.c b/tests/move_and_save.c similarity index 100% rename from libfdt/tests/move_and_save.c rename to tests/move_and_save.c diff --git a/libfdt/tests/nop_node.c b/tests/nop_node.c similarity index 100% rename from libfdt/tests/nop_node.c rename to tests/nop_node.c diff --git a/libfdt/tests/nop_property.c b/tests/nop_property.c similarity index 100% rename from libfdt/tests/nop_property.c rename to tests/nop_property.c diff --git a/libfdt/tests/notfound.c b/tests/notfound.c similarity index 100% rename from libfdt/tests/notfound.c rename to tests/notfound.c diff --git a/libfdt/tests/open_pack.c b/tests/open_pack.c similarity index 100% rename from libfdt/tests/open_pack.c rename to tests/open_pack.c diff --git a/libfdt/tests/path_offset.c b/tests/path_offset.c similarity index 100% rename from libfdt/tests/path_offset.c rename to tests/path_offset.c diff --git a/libfdt/tests/root_node.c b/tests/root_node.c similarity index 100% rename from libfdt/tests/root_node.c rename to tests/root_node.c diff --git a/tests/run_all_tests.sh b/tests/run_all_tests.sh deleted file mode 100644 index a8b7c3e..0000000 --- a/tests/run_all_tests.sh +++ /dev/null @@ -1,2 +0,0 @@ -#! /bin/sh - diff --git a/libfdt/tests/run_tests.sh b/tests/run_tests.sh similarity index 100% rename from libfdt/tests/run_tests.sh rename to tests/run_tests.sh diff --git a/libfdt/tests/rw_tree1.c b/tests/rw_tree1.c similarity index 100% rename from libfdt/tests/rw_tree1.c rename to tests/rw_tree1.c diff --git a/libfdt/tests/setprop.c b/tests/setprop.c similarity index 100% rename from libfdt/tests/setprop.c rename to tests/setprop.c diff --git a/libfdt/tests/setprop_inplace.c b/tests/setprop_inplace.c similarity index 100% rename from libfdt/tests/setprop_inplace.c rename to tests/setprop_inplace.c diff --git a/libfdt/tests/subnode_offset.c b/tests/subnode_offset.c similarity index 100% rename from libfdt/tests/subnode_offset.c rename to tests/subnode_offset.c diff --git a/libfdt/tests/sw_tree1.c b/tests/sw_tree1.c similarity index 100% rename from libfdt/tests/sw_tree1.c rename to tests/sw_tree1.c diff --git a/libfdt/tests/testdata.h b/tests/testdata.h similarity index 100% rename from libfdt/tests/testdata.h rename to tests/testdata.h diff --git a/libfdt/tests/tests.h b/tests/tests.h similarity index 100% rename from libfdt/tests/tests.h rename to tests/tests.h diff --git a/libfdt/tests/testutils.c b/tests/testutils.c similarity index 100% rename from libfdt/tests/testutils.c rename to tests/testutils.c diff --git a/libfdt/tests/trees.S b/tests/trees.S similarity index 100% rename from libfdt/tests/trees.S rename to tests/trees.S diff --git a/libfdt/tests/truncated_property.c b/tests/truncated_property.c similarity index 100% rename from libfdt/tests/truncated_property.c rename to tests/truncated_property.c From 0738774fcc34b78a708a127fb4b2f193d08c94ba Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 26 Jun 2007 11:30:47 +1000 Subject: [PATCH 0065/1198] dtc: Accept NOPs in dtb input regardless of version Since Milton's patch, dtc will accept (and, correctly, ignore) NOP tags when given dtb input v16 or later. However, although NOPs weren't defined in earlier versions, they're not ambiguous, so should be accepted there as well. This patch does so, printing a mere warning when finding NOPs in a too-early dtb version. Signed-off-by: David Gibson --- flattree.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/flattree.c b/flattree.c index b802e2c..412177f 100644 --- a/flattree.c +++ b/flattree.c @@ -776,10 +776,12 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, break; case OF_DT_NOP: - if (flags & FTF_NOPS) + if (!(flags & FTF_NOPS)) + fprintf(stderr, "Warning: NOP tag found in flat tree" + " version <16\n"); break; - die("OF_DT_NOP in device tree blob\n"); + /* Ignore */ break; default: From 0c7cd1a08783b8efea84bdb78c38521f9cb89125 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 26 Jun 2007 11:33:10 +1000 Subject: [PATCH 0066/1198] dtc: Count testcases and results in the dtc/libfdt testsuite There are quite a lot of testcases in the dtc testsuite (recently imported from libfdt). It can be easy to miss a stray FAIL result in the midst of all the rest. To improve this, this patch adds a summary to the end of the testsuite results giving the total number of tests along with the number of PASSes FAILs and other results. Signed-off-by: David Gibson --- tests/run_tests.sh | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index f4a5a54..df368f9 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -4,9 +4,24 @@ export QUIET_TEST=1 ENV=/usr/bin/env +tot_tests=0 +tot_pass=0 +tot_fail=0 +tot_config=0 +tot_strange=0 + run_test () { + tot_tests=$[tot_tests + 1] echo -n "$@: " - PATH=".:$PATH" $ENV "$@" + if PATH=".:$PATH" $ENV "$@"; then + tot_pass=$[tot_pass + 1] + elif [ "$?" == "1" ]; then + tot_config=$[tot_config + 1] + elif [ "$?" == "2" ]; then + tot_fail=$[tot_fail + 1] + else + tot_strange=$[tot_strange + 1] + fi } tree1_tests () { @@ -92,3 +107,12 @@ for set in $TESTSETS; do ;; esac done + +echo -e "********** TEST SUMMARY" +echo -e "* Total testcases: $tot_tests" +echo -e "* PASS: $tot_pass" +echo -e "* FAIL: $tot_fail" +echo -e "* Bad configuration: $tot_config" +echo -e "* Strange test result: $tot_strange" +echo -e "**********" + From 6c65eab11e19117516ed6a86222295b55e8adc9b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 26 Jun 2007 11:44:49 +1000 Subject: [PATCH 0067/1198] dtc: Remove redundant copy of the GPL The dtc tree currently includes two copies of the GPL - one which was there originally, and one imported from the libfdt tree. This patch gets rid of the extra copy in the libfdt tree. In addition it renames the file containing the remaining copy from COPYING to GPL. Since libfdt is dual-licensed, this seems clearer. Signed-off-by: David Gibson --- COPYING => GPL | 0 libfdt/GPL | 340 ------------------------------------------------- 2 files changed, 340 deletions(-) rename COPYING => GPL (100%) delete mode 100644 libfdt/GPL diff --git a/COPYING b/GPL similarity index 100% rename from COPYING rename to GPL diff --git a/libfdt/GPL b/libfdt/GPL deleted file mode 100644 index b7b5f53..0000000 --- a/libfdt/GPL +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. From d9d679fb9690348730d5d274858d445f11e4cbd4 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 26 Jun 2007 12:45:51 +1000 Subject: [PATCH 0068/1198] dtc: Improve and better integrate dtc and libfdt Makefiles This patch substantially revamps the dtc Makefiles, in particular better integrating the Makefile for dtc proper with the Makefiles imported from libfdt for libfdt and the shared testsuite. Notable changes: - No recursive make calls. Instead subsidiary Makefiles are included into the top-level Makefile so we get a complete dependency information. - Common pattern rules, CFLAGS etc. shared between dtc, libfdt and testsuite, rather than separate copies. - Vaguely Kbuild-like non-verbose mode used by default, which makes warnings more prominent. - libfdt Makefile consists only of variable definitions and helper rules, to make it more easily embeddable into other Makefile systems. Signed-off-by: David Gibson --- Makefile | 152 +++++++++++++++++++++++++++-------------- libfdt/Makefile | 64 ----------------- libfdt/Makefile.libfdt | 19 ++++++ tests/Makefile | 67 ------------------ tests/Makefile.tests | 65 ++++++++++++++++++ 5 files changed, 184 insertions(+), 183 deletions(-) delete mode 100644 libfdt/Makefile create mode 100644 libfdt/Makefile.libfdt delete mode 100644 tests/Makefile create mode 100644 tests/Makefile.tests diff --git a/Makefile b/Makefile index 2dcc5c9..67eb4ce 100644 --- a/Makefile +++ b/Makefile @@ -1,67 +1,115 @@ -TARGETS = dtc ftdump +CPPFLAGS = -I libfdt CFLAGS = -Wall -g +LDFLAGS = -Llibfdt BISON = bison -DTC_OBJS = dtc.o flattree.o fstree.o data.o livetree.o \ - srcpos.o treesource.o \ - dtc-parser.tab.o lex.yy.o +# +# Overall rules +# +ifdef V +VECHO = : +else +VECHO = echo " " +ARFLAGS = rc +.SILENT: +endif -DEPFILES = $(DTC_OBJS:.o=.d) +NODEPTARGETS = clean +ifeq ($(MAKECMDGOALS),) +DEPTARGETS = all +else +DEPTARGETS = $(filter-out $(NODEPTARGETS),$(MAKECMDGOALS)) +endif -.PHONY: libfdt tests +all: dtc ftdump libfdt tests -all: $(TARGETS) tests libfdt +STD_CLEANFILES = *~ *.o *.d *.a *.i *.s core a.out -dtc: $(DTC_OBJS) - $(LINK.c) -o $@ $^ +clean: libfdt_clean tests_clean + @$(VECHO) CLEAN + rm -f $(STD_CLEANFILES) + rm -f *.tab.[ch] lex.yy.c *.output vgcore.* + rm -f $(BIN) -ftdump: ftdump.o - $(LINK.c) -o $@ $^ +# +# General rules +# -libfdt: - cd libfdt && $(MAKE) all +%.o: %.c + @$(VECHO) CC $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< -dtc-parser.tab.c dtc-parser.tab.h dtc-parser.output: dtc-parser.y - $(BISON) -d $< - -lex.yy.c: dtc-lexer.l - $(LEX) $< - -lex.yy.o: lex.yy.c dtc-parser.tab.h - -tests: tests/all - -tests/%: libfdt - $(MAKE) -C tests $* - -check: all - cd tests; ./run_tests.sh - -checkv: all - cd tests; ./run_tests.sh -v - -func: all - cd tests; ./run_tests.sh -t func - -funcv: all - cd tests; ./run_tests.sh -t func -v - -stress: all - cd tests; ./run_tests.sh -t stress - -stressv: all - cd tests; ./run_tests.sh -t stress -v - -clean: - rm -f *~ *.o a.out core $(TARGETS) - rm -f *.tab.[ch] lex.yy.c - rm -f *.i *.output vgcore.* - rm -f *.d - $(MAKE) -C libfdt clean - $(MAKE) -C tests clean +%.o: %.S + @$(VECHO) AS $@ + $(CC) $(CPPFLAGS) $(AFLAGS) -D__ASSEMBLY__ -o $@ -c $< %.d: %.c $(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@ --include $(DEPFILES) +%.i: %.c + @$(VECHO) CPP $@ + $(CC) $(CPPFLAGS) -E $< > $@ + +%.s: %.c + @$(VECHO) CC -S $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -S $< + +%.a: + @$(VECHO) AR $@ + $(AR) $(ARFLAGS) $@ $^ + +$(BIN): %: + @$(VECHO) LD $@ + $(LINK.c) -o $@ $^ + + +# +# Rules for dtc proper +# +DTC_PROGS = dtc ftdump +DTC_OBJS = dtc.o flattree.o fstree.o data.o livetree.o \ + srcpos.o treesource.o \ + dtc-parser.tab.o lex.yy.o +DTC_DEPFILES = $(DTC_OBJS:%.o=%.d) + +dtc-parser.tab.c dtc-parser.tab.h dtc-parser.output: dtc-parser.y + @$(VECHO) BISON $@ + $(BISON) -d $< + +lex.yy.c: dtc-lexer.l + @$(VECHO) LEX $@ + $(LEX) $< + +BIN += dtc ftdump + +dtc: $(DTC_OBJS) + +ftdump: ftdump.o + +ifneq ($(DEPTARGETS),) +-include $(DTC_DEPFILES) +endif + +# +# Rules for libfdt +# +LIBFDT_PREFIX = libfdt/ +include libfdt/Makefile.libfdt + +.PHONY: libfdt +libfdt: $(LIBFDT_LIB) + +libfdt_clean: + @$(VECHO) CLEAN "(libfdt)" + rm -f $(LIBFDT_CLEANFILES) + +ifneq ($(DEPTARGETS),) +-include $(LIBFDT_DEPFILES) +endif + +# +# Testsuite rules +# +TESTS_PREFIX=tests/ +include tests/Makefile.tests diff --git a/libfdt/Makefile b/libfdt/Makefile deleted file mode 100644 index 3f68877..0000000 --- a/libfdt/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -PREFIX = /usr/local -TARGETLIBS = libfdt.a -LIBOBJS = fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o fdt_strerror.o - -SOURCE = $(shell find . -maxdepth 1 ! -name version.h -a -name '*.[h]') -SOURCE += *.c Makefile -NODEPTARGETS= - -CPPFLAGS = -I. -CFLAGS = -Wall -g - -LIBDIR = $(PREFIX)/$(LIB32) - -EXTRA_DIST = \ - README \ - HOWTO \ - LGPL-2.1 - -ifdef V -VECHO = : -else -VECHO = echo " " -ARFLAGS = rc -.SILENT: -endif - -DEPFILES = $(LIBOBJS:%.o=%.d) - -all: libs - -.PHONY: libs - -libs: $(TARGETLIBS) - -%.o: %.c - @$(VECHO) CC $@ - $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< - -libfdt.a: $(LIBOBJS) - @$(VECHO) AR $@ - $(AR) $(ARFLAGS) $@ $^ - -%.i: %.c - @$(VECHO) CPP $@ - $(CC) $(CPPFLAGS) -E $< > $@ - -%.s: %.c - @$(VECHO) CC -S $@ - $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -S $< - -clean: - @$(VECHO) CLEAN - rm -f *~ *.o *.so *.a *.d *.i *.s core a.out $(VERSION) - -%.d: %.c - @$(CC) $(CPPFLAGS) -MM -MT "$*.o $@" $< > $@ - -# Workaround: Don't build dependencies for certain targets -# When the include below is executed, make will use the %.d target above to -# generate missing files. For certain targets (clean, version.h, etc) we don't -# need or want these dependency files, so don't include them in this case. -ifeq (,$(findstring <$(MAKECMDGOALS)>,$(NODEPTARGETS))) --include $(DEPFILES) -endif diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt new file mode 100644 index 0000000..3dfc1d4 --- /dev/null +++ b/libfdt/Makefile.libfdt @@ -0,0 +1,19 @@ +# Makefile.libfdt +# +# This is not a complete Makefile of itself. Instead, it is designed to +# be easily embeddable into other systems of Makefiles. +# + +LIBFDT_OBJS_L = fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o fdt_strerror.o +LIBFDT_OBJS = $(LIBFDT_OBJS_L:%=$(LIBFDT_PREFIX)%) + +LIBFDT_LIB_L = libfdt.a +LIBFDT_LIB = $(LIBFDT_LIB_L:%=$(LIBFDT_PREFIX)%) + +LIBFDT_CLEANFILES_L = *~ *.o *.d *.a $(LIBFDT_LIB) \ + *.i *.s a.out core +LIBFDT_CLEANFILES = $(LIBFDT_CLEANFILES_L:%=$(LIBFDT_PREFIX)%) + +$(LIBFDT_LIB): $(LIBFDT_OBJS) + +LIBFDT_DEPFILES = $(LIBFDT_OBJS:%.o=%.d) diff --git a/tests/Makefile b/tests/Makefile deleted file mode 100644 index 5273028..0000000 --- a/tests/Makefile +++ /dev/null @@ -1,67 +0,0 @@ -DTC = ../dtc -VG_DTC = valgrind --tool=memcheck ../dtc - -LIB_TESTS = root_node find_property subnode_offset path_offset getprop \ - notfound \ - setprop_inplace nop_property nop_node \ - sw_tree1 \ - move_and_save \ - open_pack rw_tree1 setprop del_property del_node -LIBTREE_TESTS = truncated_property -TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) -UTILS = dumptrees - -TREES = test_tree1.dtb - -CFLAGS = -Wall -g -CPPFLAGS = -I../libfdt -LDFLAGS = -L../libfdt - -LIBFDT = ../libfdt/libfdt.a - -ifdef V -VECHO = : -else -VECHO = echo " " -.SILENT: -endif - -DEPFILES = $(TESTS:%=%.d) testutils.d - -check: all - ./run_tests.sh - -all: $(TESTS) $(TREES) - -%.o: %.c - @$(VECHO) CC $@ - $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< - -%.o: %.S - @$(VECHO) AS $@ - $(CC) -D__ASSEMBLY__ $(CPPFLAGS) -o $@ -c $< - -%: %.o - @$(VECHO) LD $@ - $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) - -$(LIB_TESTS): %: testutils.o $(LIBFDT) - -$(LIBTREE_TESTS): %: testutils.o trees.o $(LIBFDT) - -dumptrees: %: trees.o - -$(TREES): dumptrees - @$(VECHO) DUMPTREES - ./dumptrees >/dev/null - -clean: - rm -f $(TESTS) - rm -f *.dtb dumptrees - rm -f *~ *.d *.o a.out core - rm -f *.i *.output vgcore.* - -%.d: %.c - @$(CC) $(CPPFLAGS) -MM -MT "$*.o $@" $< > $@ - --include $(DEPFILES) diff --git a/tests/Makefile.tests b/tests/Makefile.tests new file mode 100644 index 0000000..0087582 --- /dev/null +++ b/tests/Makefile.tests @@ -0,0 +1,65 @@ +LIB_TESTS_L = root_node find_property subnode_offset path_offset getprop \ + notfound \ + setprop_inplace nop_property nop_node \ + sw_tree1 \ + move_and_save \ + open_pack rw_tree1 setprop del_property del_node +LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) + +LIBTREE_TESTS_L = truncated_property +LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%) + +TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) + +TESTS_TREES_L = test_tree1.dtb +TESTS_TREES = $(TESTS_TREES_L:%=$(TESTS_PREFIX)%) + +TESTS_TARGETS = $(TESTS) $(TESTS_TREES) + +TESTS_DEPFILES = $(TESTS:%=%.d) $(TESTS_PREFIX)testutils.d + +TESTS_CLEANFILES_L = *.output vgcore.* *.dtb +TESTS_CLEANFILES = $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) + +BIN += $(TESTS) $(TESTS_PREFIX)dumptrees + +.PHONY: tests +tests: $(TESTS) $(TESTS_TREES) + +$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_LIB) + +$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o $(LIBFDT_LIB) + +$(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o + +$(TESTS_TREES): $(TESTS_PREFIX)dumptrees + @$(VECHO) DUMPTREES + cd $(TESTS_PREFIX); ./dumptrees >/dev/null + +tests_clean: + @$(VECHO) CLEAN "(tests)" + rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%) + rm -f $(TESTS_CLEANFILES) + +check: tests + cd $(TESTS_PREFIX); ./run_tests.sh + +checkv: tests + cd $(TESTS_PREFIX); ./run_tests.sh -v + +func: tests + cd $(TESTS_PREFIX); ./run_tests.sh -t func + +funcv: tests + cd $(TESTS_PREFIX); ./run_tests.sh -t func -v + +stress: tests + cd $(TESTS_PREFIX); ./run_tests.sh -t stress + +stressv: tests + cd $(TESTS_PREFIX); ./run_tests.sh -t stress -v + +ifneq ($(DEPTARGETS),) +-include $(TESTS_DEPFILES) +endif + From 6936273aa40371811a99c3516b613d299792831b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 28 Jun 2007 11:32:31 +1000 Subject: [PATCH 0069/1198] dtc: Remove bogus break statement Commit 0738774fcc34b78a708a127fb4b2f193d08c94ba introduced some incorrect indentation / bracketing in unflatten_tree(). By luck, the extra break statement intended to be within an if block, but actually afterwards has no semantic effect. Still, this patch gets rid of it for cleanliness. Signed-off-by: David Gibson --- flattree.c | 1 - 1 file changed, 1 deletion(-) diff --git a/flattree.c b/flattree.c index 412177f..68ada2f 100644 --- a/flattree.c +++ b/flattree.c @@ -779,7 +779,6 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, if (!(flags & FTF_NOPS)) fprintf(stderr, "Warning: NOP tag found in flat tree" " version <16\n"); - break; /* Ignore */ break; From 8cd4196ee3a9cc3d345f40f93e0a5f4493ce2d82 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 29 Jun 2007 09:53:23 -0500 Subject: [PATCH 0070/1198] dtc: Add install makefile target Signed-off-by: Josh Boyer --- Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Makefile b/Makefile index 67eb4ce..a919bfa 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,10 @@ LDFLAGS = -Llibfdt BISON = bison +INSTALL = /usr/bin/install +DESTDIR = +BINDIR = /usr/bin + # # Overall rules # @@ -113,3 +117,8 @@ endif # TESTS_PREFIX=tests/ include tests/Makefile.tests + +install: dtc ftdump + $(INSTALL) -d $(DESTDIR)$(BINDIR) + $(INSTALL) -m 755 dtc $(DESTDIR)$(BINDIR) + $(INSTALL) -m 755 ftdump $(DESTDIR)$(BINDIR) From 81fda8a6f1cabbd9c08e27d3171394f7f90f7d3a Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Sat, 7 Jul 2007 01:18:47 -0500 Subject: [PATCH 0071/1198] dtc: fix asm for version 17 The version 17 flat device tree format added struct size. When writing version 17 assembly output the field must be emitted. Signed-off-by: Milton Miller --- flattree.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flattree.c b/flattree.c index 68ada2f..a6b66e7 100644 --- a/flattree.c +++ b/flattree.c @@ -477,6 +477,10 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n", symprefix, symprefix); + if (vi->flags & FTF_STRUCTSIZE) + fprintf(f, "\t.long\t_%s_struct_end - _%s_struct_start\t/* size_dt_struct */\n", + symprefix, symprefix); + /* * Reserve map entries. * Align the reserve map to a doubleword boundary. From 6d7b22243045dc514b5ea6c004fc50af8581ed9b Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Sat, 7 Jul 2007 01:18:47 -0500 Subject: [PATCH 0072/1198] dtc: move declaration of yyerror yyerror() is used by both dtc-parser.y and dtc-lexer.l, so move the declaration to srcpos.h. Signed-off-by: Milton Miller --- dtc-parser.y | 1 - srcpos.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/dtc-parser.y b/dtc-parser.y index 39d9dac..15caf5a 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -26,7 +26,6 @@ #include "srcpos.h" int yylex(void); -void yyerror(char const *); cell_t cell_from_string(char *s, unsigned int base); extern struct boot_info *the_boot_info; diff --git a/srcpos.h b/srcpos.h index bc5b525..ce7ab5b 100644 --- a/srcpos.h +++ b/srcpos.h @@ -62,6 +62,7 @@ typedef struct YYLTYPE { +extern void yyerror(char const *); extern int srcpos_filenum; From 85ab5cc6ec8442245a969a2f5a0e05962e0e7e67 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Sat, 7 Jul 2007 01:18:48 -0500 Subject: [PATCH 0073/1198] dtc: complain about unparsed digits in cell lists Check that strtoul() parsed the complete string. As with the number overflow case, write a non-fatal error message to stdout. Signed-off-by: Milton Miller --- dtc-parser.y | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 15caf5a..9e7fbcc 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -192,19 +192,27 @@ void yyerror (char const *s) * Convert a string representation of a numeric cell * in the given base into a cell. * - * FIXME: The string "abc123", base 10, should be flagged - * as an error due to the leading "a", but isn't yet. + * FIXME: should these specification errors be fatal instead? */ cell_t cell_from_string(char *s, unsigned int base) { cell_t c; + char *e; + + c = strtoul(s, &e, base); + if (*e) { + fprintf(stderr, + "Line %d: Invalid cell value '%s' : " + "%c is not a base %d digit; %d assumed\n", + yylloc.first_line, s, *e, base, c); + } - c = strtoul(s, NULL, base); if (errno == EINVAL || errno == ERANGE) { fprintf(stderr, "Line %d: Invalid cell value '%s'; %d assumed\n", yylloc.first_line, s, c); + errno = 0; } return c; From d4290338514abdfac372aa9a7af180543c0622ad Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Sat, 7 Jul 2007 01:18:49 -0500 Subject: [PATCH 0074/1198] dtc: implement labels on memory reserve slots Allow a label to be placed on a memory reserve entry. Change the parser to recognize and store them. Emit them when writing assembly output. Signed-off-by: Milton Miller --- dtc-parser.y | 8 ++++---- flattree.c | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 9e7fbcc..d88cbf1 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -92,11 +92,11 @@ memreserves: memreserve memreserves { } ; -memreserve: DT_MEMRESERVE DT_ADDR DT_ADDR ';' { - $$ = build_reserve_entry($2, $3, NULL); +memreserve: label DT_MEMRESERVE DT_ADDR DT_ADDR ';' { + $$ = build_reserve_entry($3, $4, $1); } - | DT_MEMRESERVE DT_ADDR '-' DT_ADDR ';' { - $$ = build_reserve_entry($2, $4 - $2 + 1, NULL); + | label DT_MEMRESERVE DT_ADDR '-' DT_ADDR ';' { + $$ = build_reserve_entry($3, $5 - $3 + 1, $1); } ; diff --git a/flattree.c b/flattree.c index a6b66e7..31609d6 100644 --- a/flattree.c +++ b/flattree.c @@ -497,6 +497,10 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) * as it appears .quad isn't available in some assemblers. */ for (re = bi->reservelist; re; re = re->next) { + if (re->label) { + fprintf(f, "\t.globl\t%s\n", re->label); + fprintf(f, "%s:\n", re->label); + } fprintf(f, "\t.long\t0x%08x\n\t.long\t0x%08x\n", (unsigned int)(re->re.address >> 32), (unsigned int)(re->re.address & 0xffffffff)); From 46779e8f8e5a13388835e9251fb741396e2d7f13 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Sat, 7 Jul 2007 01:18:49 -0500 Subject: [PATCH 0075/1198] dtc: clean up grow_data_for() Change the grow_data_for function to copy struct data and modifiy the fields it is updating instead of storing all fields individually to a stack allocated struct. This reduces maintence for future enhancements as now all instances of struct data are created by modifying a copy of an existing struct data or directly copying empty_data. Signed-off-by: Milton Miller --- data.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data.c b/data.c index 5d7db17..3d68792 100644 --- a/data.c +++ b/data.c @@ -57,6 +57,8 @@ struct data data_grow_for(struct data d, int xlen) if (xlen == 0) return d; + nd = d; + newsize = xlen; while ((d.len + xlen) > newsize) @@ -64,8 +66,6 @@ struct data data_grow_for(struct data d, int xlen) nd.asize = newsize; nd.val = xrealloc(d.val, newsize); - nd.len = d.len; - nd.refs = d.refs; assert(nd.asize >= (d.len + xlen)); From ac6a5e26b4f2239d77eb4aa25383466833949006 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Sat, 7 Jul 2007 01:18:50 -0500 Subject: [PATCH 0076/1198] dtc: allow a label: in any dts context Change the lexer to recognise a label in any context. Place before other celldata and bytestrings to avoid the initial characters being stolen by other matches. A label is a character sequence starting with an alphabetic or underscore optinally followed by the same plus digits and terminating in a colon. The included terminating colon will prevent matching hex numbers. Signed-off-by: Milton Miller --- dtc-lexer.l | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 77ccd54..384f848 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -107,6 +107,16 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) BEGIN(INITIAL); return ';'; } + +<*>[a-zA-Z_][a-zA-Z0-9_]*: { + yylloc.filenum = srcpos_filenum; + yylloc.first_line = yylineno; + DPRINT("Label: %s\n", yytext); + yylval.str = strdup(yytext); + yylval.str[yyleng-1] = '\0'; + return DT_LABEL; + } + [bodh]# { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; @@ -189,15 +199,6 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } -[a-zA-Z_][a-zA-Z0-9_]*: { - yylloc.filenum = srcpos_filenum; - yylloc.first_line = yylineno; - DPRINT("Label: %s\n", yytext); - yylval.str = strdup(yytext); - yylval.str[yyleng-1] = '\0'; - return DT_LABEL; - } - <*>{WS}+ /* eat whitespace */ <*>"/*"([^*]|\*+[^*/])*\*+"/" { From 6a99b1313208d05ba6d9c5d3858230d9ee785f8c Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Sat, 7 Jul 2007 01:18:51 -0500 Subject: [PATCH 0077/1198] dtc: implement labels on property data Extend the parser grammer to allow labels before or after any property data (string, cell list, or byte list), and any byte or cell within the property data. Store the labels using the same linked list structure as node references, but using a parallel list. When writing assembly output emit global labels as offsets from the start of the definition of the data. Note that the alignment for a cell list is done as part of the opening < delimiter, not the = or , before it. To label a cell after a string or byte list put the label inside the cell list. For example, prop = zero: [ aa bb ], two: < four: 1234 > eight: ; will produce labels with offsets 0, 2, 4, and 8 bytes from the beginning of the data for property prop. Signed-off-by: Milton Miller --- data.c | 50 ++++++++++++++++++++++++++++++++++++++++---------- dtc-parser.y | 4 ++++ dtc.h | 5 +++-- flattree.c | 13 +++++++++++++ 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/data.c b/data.c index 3d68792..3e96d11 100644 --- a/data.c +++ b/data.c @@ -29,12 +29,17 @@ void fixup_free(struct fixup *f) void data_free(struct data d) { - struct fixup *f; + struct fixup *f, *nf; f = d.refs; while (f) { - struct fixup *nf; + nf = f->next; + fixup_free(f); + f = nf; + } + f = d.labels; + while (f) { nf = f->next; fixup_free(f); f = nf; @@ -198,27 +203,36 @@ struct data data_append_data(struct data d, void *p, int len) return d; } -struct data data_merge(struct data d1, struct data d2) +void fixup_merge(struct fixup **fd, struct fixup **fd2, int d1_len) { - struct data d; struct fixup **ff; struct fixup *f, *f2; - d = data_append_data(d1, d2.val, d2.len); - /* Extract d2's fixups */ - f2 = d2.refs; - d2.refs = NULL; + f2 = *fd2; + *fd2 = NULL; /* Tack them onto d's list of fixups */ - ff = &d.refs; + ff = fd; while (*ff) ff = &((*ff)->next); *ff = f2; /* And correct them for their new position */ for (f = f2; f; f = f->next) - f->offset += d1.len; + f->offset += d1_len; + + +} + +struct data data_merge(struct data d1, struct data d2) +{ + struct data d; + + d = data_append_data(d1, d2.val, d2.len); + + fixup_merge(&d.refs, &d2.refs, d1.len); + fixup_merge(&d.labels, &d2.labels, d1.len); data_free(d2); @@ -285,6 +299,22 @@ struct data data_add_fixup(struct data d, char *ref) return nd; } +struct data data_add_label(struct data d, char *label) +{ + struct fixup *f; + struct data nd; + + f = xmalloc(sizeof(*f)); + f->offset = d.len; + f->ref = label; + f->next = d.labels; + + nd = d; + nd.labels = f; + + return nd; +} + int data_is_one_string(struct data d) { int i; diff --git a/dtc-parser.y b/dtc-parser.y index d88cbf1..19bc58e 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -131,9 +131,11 @@ propdata: propdataprefix DT_STRING { $$ = data_merge($1, $2); } $$ = data_merge(data_append_align($1, sizeof(cell_t)), $3); } | propdataprefix '[' bytestring ']' { $$ = data_merge($1, $3); } + | propdata DT_LABEL { $$ = data_add_label($1, $2); } ; propdataprefix: propdata ',' { $$ = $1; } + | propdataprefix DT_LABEL { $$ = data_add_label($1, $2); } | /* empty */ { $$ = empty_data; } ; @@ -150,10 +152,12 @@ celllist: celllist opt_cell_base DT_CELL { | celllist DT_REF { $$ = data_append_cell(data_add_fixup($1, $2), -1); } + | celllist DT_LABEL { $$ = data_add_label($1, $2); } | /* empty */ { $$ = empty_data; } ; bytestring: bytestring DT_BYTE { $$ = data_append_byte($1, $2); } + | bytestring DT_LABEL { $$ = data_add_label($1, $2); } | /* empty */ { $$ = empty_data; } ; diff --git a/dtc.h b/dtc.h index 8cfe1a1..0a1f960 100644 --- a/dtc.h +++ b/dtc.h @@ -111,10 +111,10 @@ struct data { char *val; int asize; struct fixup *refs; + struct fixup *labels; }; -#define empty_data \ - ((struct data){.len = 0, .val = NULL, .asize = 0, .refs = NULL}) +#define empty_data ((struct data){ /* all .members = 0 or NULL */ }) void fixup_free(struct fixup *f); void data_free(struct data d); @@ -135,6 +135,7 @@ struct data data_append_zeroes(struct data d, int len); struct data data_append_align(struct data d, int align); struct data data_add_fixup(struct data d, char *ref); +struct data data_add_label(struct data d, char *label); int data_is_one_string(struct data d); diff --git a/flattree.c b/flattree.c index 31609d6..c7817c6 100644 --- a/flattree.c +++ b/flattree.c @@ -121,6 +121,12 @@ static void emit_label(FILE *f, char *prefix, char *label) fprintf(f, "_%s_%s:\n", prefix, label); } +static void emit_offset_label(FILE *f, char *label, int offset) +{ + fprintf(f, "\t.globl\t%s\n", label); + fprintf(f, "%s\t= . + %d\n", label, offset); +} + static void asm_emit_cell(void *e, cell_t val) { FILE *f = e; @@ -157,6 +163,13 @@ static void asm_emit_data(void *e, struct data d) { FILE *f = e; int off = 0; + struct fixup *l; + + l = d.labels; + while (l) { + emit_offset_label(f, l->ref, l->offset); + l = l->next; + } while ((d.len - off) >= sizeof(u32)) { fprintf(f, "\t.long\t0x%x\n", From 43a68c63e46c88b94068c18255db2d6c7d9e3740 Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Sat, 7 Jul 2007 01:18:52 -0500 Subject: [PATCH 0078/1198] dtc: store labels in ascending order When adding a label, walk to the end of the list since the label reflects the end of the data. Since merging data buffers already preserved the order, this will cause the labels to be emitted in order when writing assembly output. It should also aid emiting labels when writing dts output should that be added in the future (data formatting would need to break at each label). Signed-off-by: Milton Miller --- data.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/data.c b/data.c index 3e96d11..f42ad58 100644 --- a/data.c +++ b/data.c @@ -301,16 +301,22 @@ struct data data_add_fixup(struct data d, char *ref) struct data data_add_label(struct data d, char *label) { - struct fixup *f; + struct fixup *f, **p; struct data nd; f = xmalloc(sizeof(*f)); f->offset = d.len; f->ref = label; - f->next = d.labels; nd = d; - nd.labels = f; + p = &nd.labels; + + /* adding to end keeps them sorted */ + while (*p) + p = &((*p)->next); + + f->next = *p; + *p = f; return nd; } From 9670eed1bce94c98ffefcfd49317f2cfb9256d6c Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Sat, 7 Jul 2007 01:18:53 -0500 Subject: [PATCH 0079/1198] dtc: add a testcase with labels Create a source file with labels for use as a testcase to check parsing dts files. Signed-off-by: Milton Miller --- tests/label01.dts | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 tests/label01.dts diff --git a/tests/label01.dts b/tests/label01.dts new file mode 100644 index 0000000..ad1f1e4 --- /dev/null +++ b/tests/label01.dts @@ -0,0 +1,60 @@ +/memreserve/ 1000000000000000 0000000002000000; +memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff; +/memreserve/ 0-13; + +/ { + model = "MyBoardName"; + compatible = "MyBoardName", "MyBoardFamilyName"; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + linux,phandle = <1>; + #address-cells = <1>; + #size-cells = <0>; + PowerPC,970@0 { + name = "PowerPC,970"; + device_type = "cpu"; + reg = <0>; + clock-frequency = <5f5e1000>; + timebase-frequency = <1FCA055>; + linux,boot-cpu; + i-cache-size = <10000>; + d-cache-size = <8000>; + }; + + PowerPC,970@1 { + name = "PowerPC,970"; + device_type = "cpu"; + reg = <1>; + clock-frequency = <5f5e1000>; + timebase-frequency = <1FCA055>; + i-cache-size = <10000>; + d-cache-size = <8000>; + }; + + }; + + node: randomnode { + prop: string = data: "\xff\0stuffstuff\t\t\t\n\n\n" data_end: ; + blob = [byte: 0a 0b 0c 0d de ea ad be ef byte_end: ]; + ref = < cell: &/memory@0 cell_end: >; + mixed = "abc", pre: [1234] post: , gap: < aligned: a b c>; + subnode: child { + }; + /* subnode_end: is auto-generated by node emit */ + }; + /* node_end: is auto-generated by node emit */ + + memory@0 { + device_type = "memory"; + memreg: reg = <00000000 00000000 00000000 20000000>; + }; + + chosen { + bootargs = "root=/dev/sda2"; + linux,platform = <00000600>; + }; + +}; + From 7f45666273f18f2aa9546ba42a083bded463459b Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Sat, 7 Jul 2007 01:18:53 -0500 Subject: [PATCH 0080/1198] dtc: align header comments in asm output Insert tabs to align the comments describing the fields of the boot parameters header struct. Signed-off-by: Milton Miller --- flattree.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/flattree.c b/flattree.c index c7817c6..e7b10c7 100644 --- a/flattree.c +++ b/flattree.c @@ -469,21 +469,21 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) emit_label(f, symprefix, "blob_start"); emit_label(f, symprefix, "header"); - fprintf(f, "\t.long\tOF_DT_HEADER /* magic */\n"); - fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start /* totalsize */\n", + fprintf(f, "\t.long\tOF_DT_HEADER\t\t\t\t/* magic */\n"); + fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start\t/* totalsize */\n", symprefix, symprefix); - fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start /* off_dt_struct */\n", + fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start\t/* off_dt_struct */\n", symprefix, symprefix); - fprintf(f, "\t.long\t_%s_strings_start - _%s_blob_start /* off_dt_strings */\n", + fprintf(f, "\t.long\t_%s_strings_start - _%s_blob_start\t/* off_dt_strings */\n", symprefix, symprefix); - fprintf(f, "\t.long\t_%s_reserve_map - _%s_blob_start /* off_dt_strings */\n", + fprintf(f, "\t.long\t_%s_reserve_map - _%s_blob_start\t/* off_dt_strings */\n", symprefix, symprefix); - fprintf(f, "\t.long\t%d /* version */\n", vi->version); - fprintf(f, "\t.long\t%d /* last_comp_version */\n", + fprintf(f, "\t.long\t%d\t\t\t\t\t/* version */\n", vi->version); + fprintf(f, "\t.long\t%d\t\t\t\t\t/* last_comp_version */\n", vi->last_comp_version); if (vi->flags & FTF_BOOTCPUID) - fprintf(f, "\t.long\t%i\t/*boot_cpuid_phys*/\n", + fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n", boot_cpuid_phys); if (vi->flags & FTF_STRTABSIZE) From 445d55d2cc82097dea0feb564cc479c40291fffe Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Sat, 7 Jul 2007 01:18:54 -0500 Subject: [PATCH 0081/1198] dtc: format memory reserve as pairs on two lines When writing the memory reserve table in assembly output, emit both halves of each 64 bit number on a single .long statement. This results in two lines per memory reserve slot instead of four, each line contains one field (start or size). Signed-off-by: Milton Miller --- flattree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flattree.c b/flattree.c index e7b10c7..5b15e9c 100644 --- a/flattree.c +++ b/flattree.c @@ -514,10 +514,10 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) fprintf(f, "\t.globl\t%s\n", re->label); fprintf(f, "%s:\n", re->label); } - fprintf(f, "\t.long\t0x%08x\n\t.long\t0x%08x\n", + fprintf(f, "\t.long\t0x%08x, 0x%08x\n", (unsigned int)(re->re.address >> 32), (unsigned int)(re->re.address & 0xffffffff)); - fprintf(f, "\t.long\t0x%08x\n\t.long\t0x%08x\n", + fprintf(f, "\t.long\t0x%08x, 0x%08x\n", (unsigned int)(re->re.size >> 32), (unsigned int)(re->re.size & 0xffffffff)); } From 74e6d2128439c53ad9d4a9c1613c82ee92491e84 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 7 Jul 2007 10:38:27 -0500 Subject: [PATCH 0082/1198] Add a note to the build about the expected parser warnings. Signed-off-by: Jon Loeliger --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index a919bfa..6b278b9 100644 --- a/Makefile +++ b/Makefile @@ -79,6 +79,7 @@ DTC_DEPFILES = $(DTC_OBJS:%.o=%.d) dtc-parser.tab.c dtc-parser.tab.h dtc-parser.output: dtc-parser.y @$(VECHO) BISON $@ + @$(VECHO) ---- Expect 2 s/r and 2 r/r. ---- $(BISON) -d $< lex.yy.c: dtc-lexer.l From a657ce8fb7da5bca364f717fb981059639dbd0d1 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 7 Jul 2007 13:52:25 -0500 Subject: [PATCH 0083/1198] Add DTC release version information. Adopted the version information and implementation from of the Linux Kernel Makefiles. Signed-off-by: Jon Loeliger --- Makefile | 67 +++++++++++++++++++++++++++++++++++++++++ dtc.c | 9 +++++- scripts/setlocalversion | 22 ++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-) create mode 100755 scripts/setlocalversion diff --git a/Makefile b/Makefile index 6b278b9..4740bff 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,49 @@ +# +# Device Tree Compiler +# + +# +# Version information will be constructed in this order: +# EXTRAVERSION might be "-rc", for example. +# LOCAL_VERSION is likely from command line. +# CONFIG_LOCALVERSION from some future config system. +# +VERSION = 1 +PATCHLEVEL = 0 +SUBLEVEL = 0 +EXTRAVERSION = +LOCAL_VERSION = +CONFIG_LOCALVERSION = + +DTC_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) +VERSION_FILE = version_gen.h + +CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ + else if [ -x /bin/bash ]; then echo /bin/bash; \ + else echo sh; fi ; fi) + +nullstring := +space := $(nullstring) # end of line + +localver_config = $(subst $(space),, $(string) \ + $(patsubst "%",%,$(CONFIG_LOCALVERSION))) + +localver_cmd = $(subst $(space),, $(string) \ + $(patsubst "%",%,$(LOCALVERSION))) + +localver_scm = $(shell $(CONFIG_SHELL) ./scripts/setlocalversion) +localver_full = $(localver_config)$(localver_cmd)$(localver_scm) + +dtc_version = $(DTC_VERSION)$(localver_full) + +# +# Contents of the generated version file. +# +define filechk_version + (echo "#define DTC_VERSION \"DTC $(dtc_version)\""; ) +endef + + CPPFLAGS = -I libfdt CFLAGS = -Wall -g LDFLAGS = -Llibfdt @@ -28,11 +74,14 @@ endif all: dtc ftdump libfdt tests + STD_CLEANFILES = *~ *.o *.d *.a *.i *.s core a.out +GEN_CLEANFILES = $(VERSION_FILE) clean: libfdt_clean tests_clean @$(VECHO) CLEAN rm -f $(STD_CLEANFILES) + rm -f $(GEN_CLEANFILES) rm -f *.tab.[ch] lex.yy.c *.output vgcore.* rm -f $(BIN) @@ -82,6 +131,9 @@ dtc-parser.tab.c dtc-parser.tab.h dtc-parser.output: dtc-parser.y @$(VECHO) ---- Expect 2 s/r and 2 r/r. ---- $(BISON) -d $< +$(VERSION_FILE): Makefile FORCE + $(call filechk,version) + lex.yy.c: dtc-lexer.l @$(VECHO) LEX $@ $(LEX) $< @@ -123,3 +175,18 @@ install: dtc ftdump $(INSTALL) -d $(DESTDIR)$(BINDIR) $(INSTALL) -m 755 dtc $(DESTDIR)$(BINDIR) $(INSTALL) -m 755 ftdump $(DESTDIR)$(BINDIR) + +define filechk + set -e; \ + echo ' CHK $@'; \ + mkdir -p $(dir $@); \ + $(filechk_$(1)) < $< > $@.tmp; \ + if [ -r $@ ] && cmp -s $@ $@.tmp; then \ + rm -f $@.tmp; \ + else \ + echo ' UPD $@'; \ + mv -f $@.tmp $@; \ + fi; +endef + +FORCE: diff --git a/dtc.c b/dtc.c index 5767834..ecd9fe5 100644 --- a/dtc.c +++ b/dtc.c @@ -21,6 +21,8 @@ #include "dtc.h" #include "srcpos.h" +#include "version_gen.h" + /* * Command line options */ @@ -99,6 +101,8 @@ static void usage(void) fprintf(stderr, "\t\tSet the physical boot cpu\n"); fprintf(stderr, "\t-f\n"); fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n"); + fprintf(stderr, "\t-v\n"); + fprintf(stderr, "\t\tPrint DTC version and exit\n"); exit(2); } @@ -120,7 +124,7 @@ int main(int argc, char *argv[]) reservenum = 0; minsize = 0; - while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:fqb:")) != EOF) { + while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:fqb:v")) != EOF) { switch (opt) { case 'I': inform = optarg; @@ -149,6 +153,9 @@ int main(int argc, char *argv[]) case 'b': boot_cpuid_phys = strtol(optarg, NULL, 0); break; + case 'v': + printf("Version: %s\n", DTC_VERSION); + exit(0); case 'h': default: usage(); diff --git a/scripts/setlocalversion b/scripts/setlocalversion new file mode 100755 index 0000000..82e4993 --- /dev/null +++ b/scripts/setlocalversion @@ -0,0 +1,22 @@ +#!/bin/sh +# Print additional version information for non-release trees. + +usage() { + echo "Usage: $0 [srctree]" >&2 + exit 1 +} + +cd "${1:-.}" || usage + +# Check for git and a git repo. +if head=`git rev-parse --verify HEAD 2>/dev/null`; then + # Do we have an untagged version? + if git name-rev --tags HEAD | grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then + printf '%s%s' -g `echo "$head" | cut -c1-8` + fi + + # Are there uncommitted changes? + if git diff-index HEAD | read dummy; then + printf '%s' -dirty + fi +fi From fdd2e6f9455020972b762a993046351f7845e7b5 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 7 Jul 2007 14:18:02 -0500 Subject: [PATCH 0084/1198] Reorganized Makefile into better top-down structure. Also removed a generic "LD" target that wasn't actually used. Signed-off-by: Jon Loeliger --- Makefile | 85 ++++++++++++++++++++++++++------------------------------ 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/Makefile b/Makefile index 4740bff..04574c9 100644 --- a/Makefile +++ b/Makefile @@ -74,49 +74,6 @@ endif all: dtc ftdump libfdt tests - -STD_CLEANFILES = *~ *.o *.d *.a *.i *.s core a.out -GEN_CLEANFILES = $(VERSION_FILE) - -clean: libfdt_clean tests_clean - @$(VECHO) CLEAN - rm -f $(STD_CLEANFILES) - rm -f $(GEN_CLEANFILES) - rm -f *.tab.[ch] lex.yy.c *.output vgcore.* - rm -f $(BIN) - -# -# General rules -# - -%.o: %.c - @$(VECHO) CC $@ - $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< - -%.o: %.S - @$(VECHO) AS $@ - $(CC) $(CPPFLAGS) $(AFLAGS) -D__ASSEMBLY__ -o $@ -c $< - -%.d: %.c - $(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@ - -%.i: %.c - @$(VECHO) CPP $@ - $(CC) $(CPPFLAGS) -E $< > $@ - -%.s: %.c - @$(VECHO) CC -S $@ - $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -S $< - -%.a: - @$(VECHO) AR $@ - $(AR) $(ARFLAGS) $@ $^ - -$(BIN): %: - @$(VECHO) LD $@ - $(LINK.c) -o $@ $^ - - # # Rules for dtc proper # @@ -126,6 +83,8 @@ DTC_OBJS = dtc.o flattree.o fstree.o data.o livetree.o \ dtc-parser.tab.o lex.yy.o DTC_DEPFILES = $(DTC_OBJS:%.o=%.d) +BIN += dtc ftdump + dtc-parser.tab.c dtc-parser.tab.h dtc-parser.output: dtc-parser.y @$(VECHO) BISON $@ @$(VECHO) ---- Expect 2 s/r and 2 r/r. ---- @@ -138,9 +97,9 @@ lex.yy.c: dtc-lexer.l @$(VECHO) LEX $@ $(LEX) $< -BIN += dtc ftdump - dtc: $(DTC_OBJS) + @$(VECHO) LD $@ + $(LINK.c) -o $@ $^ ftdump: ftdump.o @@ -171,6 +130,16 @@ endif TESTS_PREFIX=tests/ include tests/Makefile.tests +STD_CLEANFILES = *~ *.o *.d *.a *.i *.s core a.out +GEN_CLEANFILES = $(VERSION_FILE) + +clean: libfdt_clean tests_clean + @$(VECHO) CLEAN + rm -f $(STD_CLEANFILES) + rm -f $(GEN_CLEANFILES) + rm -f *.tab.[ch] lex.yy.c *.output vgcore.* + rm -f $(BIN) + install: dtc ftdump $(INSTALL) -d $(DESTDIR)$(BINDIR) $(INSTALL) -m 755 dtc $(DESTDIR)$(BINDIR) @@ -189,4 +158,30 @@ define filechk fi; endef +# +# Generic compile rules +# +%.o: %.c + @$(VECHO) CC $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< + +%.o: %.S + @$(VECHO) AS $@ + $(CC) $(CPPFLAGS) $(AFLAGS) -D__ASSEMBLY__ -o $@ -c $< + +%.d: %.c + $(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@ + +%.i: %.c + @$(VECHO) CPP $@ + $(CC) $(CPPFLAGS) -E $< > $@ + +%.s: %.c + @$(VECHO) CC -S $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -S $< + +%.a: + @$(VECHO) AR $@ + $(AR) $(ARFLAGS) $@ $^ + FORCE: From 4f61ae162780585aacf90ff80e4abf3ab05201ca Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 24 Jul 2007 15:14:52 +1000 Subject: [PATCH 0085/1198] dtc: Improve the make install target This patch makes various improvements to dtc's make install target: - libfdt is also installed. Specifically, libfdt.a and the two export relevant header files, fdt.h and libfdt.h are installed. - ftdump is no longer installed. It was only ever a development debugging tool and may well go away at some point. - In keeping with normal conventions, there is now a PREFIX variable, allowing control of where things are installed (in /usr, /usr/local, /opt, etc.). - By default, installed into the user's home directory, instead of /usr. This is friendlier for self-installers, package builders can easily override PREFIX to restore the old behaviour. Signed-off-by: David Gibson --- Makefile | 13 ++++++++++--- libfdt/Makefile.libfdt | 4 +++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 04574c9..24ce91a 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,10 @@ BISON = bison INSTALL = /usr/bin/install DESTDIR = -BINDIR = /usr/bin +PREFIX = $(HOME) +BINDIR = $(PREFIX)/bin +LIBDIR = $(PREFIX)/lib +INCLUDEDIR = $(PREFIX)/include # # Overall rules @@ -140,10 +143,14 @@ clean: libfdt_clean tests_clean rm -f *.tab.[ch] lex.yy.c *.output vgcore.* rm -f $(BIN) -install: dtc ftdump +install: all + @$(VECHO) INSTALL $(INSTALL) -d $(DESTDIR)$(BINDIR) $(INSTALL) -m 755 dtc $(DESTDIR)$(BINDIR) - $(INSTALL) -m 755 ftdump $(DESTDIR)$(BINDIR) + $(INSTALL) -d $(DESTDIR)$(LIBDIR) + $(INSTALL) -m 644 $(LIBFDT_LIB) $(DESTDIR)$(LIBDIR) + $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) + $(INSTALL) -m 644 $(LIBFDT_INCLUDES) $(DESTDIR)$(INCLUDEDIR) define filechk set -e; \ diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index 3dfc1d4..3be2b21 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -3,13 +3,15 @@ # This is not a complete Makefile of itself. Instead, it is designed to # be easily embeddable into other systems of Makefiles. # - LIBFDT_OBJS_L = fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o fdt_strerror.o LIBFDT_OBJS = $(LIBFDT_OBJS_L:%=$(LIBFDT_PREFIX)%) LIBFDT_LIB_L = libfdt.a LIBFDT_LIB = $(LIBFDT_LIB_L:%=$(LIBFDT_PREFIX)%) +LIBFDT_INCLUDES_L = fdt.h libfdt.h +LIBFDT_INCLUDES = $(LIBFDT_INCLUDES_L:%=$(LIBFDT_PREFIX)%) + LIBFDT_CLEANFILES_L = *~ *.o *.d *.a $(LIBFDT_LIB) \ *.i *.s a.out core LIBFDT_CLEANFILES = $(LIBFDT_CLEANFILES_L:%=$(LIBFDT_PREFIX)%) From 74ce242bf3307c7ec77b9ddfff443c247ac8c0a3 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Wed, 25 Jul 2007 10:53:42 -0500 Subject: [PATCH 0086/1198] Make release 1.0.0-rc1! Signed-off-by: Jon Loeliger --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 24ce91a..7d27de9 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ VERSION = 1 PATCHLEVEL = 0 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION =-rc1 LOCAL_VERSION = CONFIG_LOCALVERSION = From 1dc6ca5edcfed7cfb055b9cbf41f516e196ba813 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Wed, 11 Jul 2007 16:46:11 -0500 Subject: [PATCH 0087/1198] Add initial Device Tree Compiler manual This is the new location for technical descriptions of the DTC. Derived from the kernel's Documentation/powerpc/booting-without-of.txt. The booting-without-of.txt that was here was very old and out of date. Signed-off-by: Jon Loeliger --- Documentation/booting-without-of.txt | 1420 -------------------------- Documentation/manual.txt | 618 +++++++++++ 2 files changed, 618 insertions(+), 1420 deletions(-) delete mode 100644 Documentation/booting-without-of.txt create mode 100644 Documentation/manual.txt diff --git a/Documentation/booting-without-of.txt b/Documentation/booting-without-of.txt deleted file mode 100644 index 60d5b7a..0000000 --- a/Documentation/booting-without-of.txt +++ /dev/null @@ -1,1420 +0,0 @@ - Booting the Linux/ppc kernel without Open Firmware - -------------------------------------------------- - - -(c) 2005 Benjamin Herrenschmidt , - IBM Corp. -(c) 2005 Becky Bruce , - Freescale Semiconductor, FSL SOC and 32-bit additions - - May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet. - - May 19, 2005: Rev 0.2 - Add chapter III and bits & pieces here or - clarifies the fact that a lot of things are - optional, the kernel only requires a very - small device tree, though it is encouraged - to provide an as complete one as possible. - - May 24, 2005: Rev 0.3 - Precise that DT block has to be in RAM - - Misc fixes - - Define version 3 and new format version 16 - for the DT block (version 16 needs kernel - patches, will be fwd separately). - String block now has a size, and full path - is replaced by unit name for more - compactness. - linux,phandle is made optional, only nodes - that are referenced by other nodes need it. - "name" property is now automatically - deduced from the unit name - - June 1, 2005: Rev 0.4 - Correct confusion between OF_DT_END and - OF_DT_END_NODE in structure definition. - - Change version 16 format to always align - property data to 4 bytes. Since tokens are - already aligned, that means no specific - required alignement between property size - and property data. The old style variable - alignment would make it impossible to do - "simple" insertion of properties using - memove (thanks Milton for - noticing). Updated kernel patch as well - - Correct a few more alignement constraints - - Add a chapter about the device-tree - compiler and the textural representation of - the tree that can be "compiled" by dtc. - - - November 21, 2005: Rev 0.5 - - Additions/generalizations for 32-bit - - Changed to reflect the new arch/powerpc - structure - - Added chapter VI - - - ToDo: - - Add some definitions of interrupt tree (simple/complex) - - Add some definitions for pci host bridges - - Add some common address format examples - - Add definitions for standard properties and "compatible" - names for cells that are not already defined by the existing - OF spec. - - Compare FSL SOC use of PCI to standard and make sure no new - node definition required. - - Add more information about node definitions for SOC devices - that currently have no standard, like the FSL CPM. - - -I - Introduction -================ - -During the recent development of the Linux/ppc64 kernel, and more -specifically, the addition of new platform types outside of the old -IBM pSeries/iSeries pair, it was decided to enforce some strict rules -regarding the kernel entry and bootloader <-> kernel interfaces, in -order to avoid the degeneration that had become the ppc32 kernel entry -point and the way a new platform should be added to the kernel. The -legacy iSeries platform breaks those rules as it predates this scheme, -but no new board support will be accepted in the main tree that -doesn't follows them properly. In addition, since the advent of the -arch/powerpc merged architecture for ppc32 and ppc64, new 32-bit -platforms and 32-bit platforms which move into arch/powerpc will be -required to use these rules as well. - -The main requirement that will be defined in more detail below is -the presence of a device-tree whose format is defined after Open -Firmware specification. However, in order to make life easier -to embedded board vendors, the kernel doesn't require the device-tree -to represent every device in the system and only requires some nodes -and properties to be present. This will be described in detail in -section III, but, for example, the kernel does not require you to -create a node for every PCI device in the system. It is a requirement -to have a node for PCI host bridges in order to provide interrupt -routing informations and memory/IO ranges, among others. It is also -recommended to define nodes for on chip devices and other busses that -don't specifically fit in an existing OF specification. This creates a -great flexibility in the way the kernel can then probe those and match -drivers to device, without having to hard code all sorts of tables. It -also makes it more flexible for board vendors to do minor hardware -upgrades without significantly impacting the kernel code or cluttering -it with special cases. - - -1) Entry point for arch/powerpc -------------------------------- - - There is one and one single entry point to the kernel, at the start - of the kernel image. That entry point supports two calling - conventions: - - a) Boot from Open Firmware. If your firmware is compatible - with Open Firmware (IEEE 1275) or provides an OF compatible - client interface API (support for "interpret" callback of - forth words isn't required), you can enter the kernel with: - - r5 : OF callback pointer as defined by IEEE 1275 - bindings to powerpc. Only the 32 bit client interface - is currently supported - - r3, r4 : address & length of an initrd if any or 0 - - The MMU is either on or off; the kernel will run the - trampoline located in arch/powerpc/kernel/prom_init.c to - extract the device-tree and other information from open - firmware and build a flattened device-tree as described - in b). prom_init() will then re-enter the kernel using - the second method. This trampoline code runs in the - context of the firmware, which is supposed to handle all - exceptions during that time. - - b) Direct entry with a flattened device-tree block. This entry - point is called by a) after the OF trampoline and can also be - called directly by a bootloader that does not support the Open - Firmware client interface. It is also used by "kexec" to - implement "hot" booting of a new kernel from a previous - running one. This method is what I will describe in more - details in this document, as method a) is simply standard Open - Firmware, and thus should be implemented according to the - various standard documents defining it and its binding to the - PowerPC platform. The entry point definition then becomes: - - r3 : physical pointer to the device-tree block - (defined in chapter II) in RAM - - r4 : physical pointer to the kernel itself. This is - used by the assembly code to properly disable the MMU - in case you are entering the kernel with MMU enabled - and a non-1:1 mapping. - - r5 : NULL (as to differenciate with method a) - - Note about SMP entry: Either your firmware puts your other - CPUs in some sleep loop or spin loop in ROM where you can get - them out via a soft reset or some other means, in which case - you don't need to care, or you'll have to enter the kernel - with all CPUs. The way to do that with method b) will be - described in a later revision of this document. - - -2) Board support ----------------- - -64-bit kernels: - - Board supports (platforms) are not exclusive config options. An - arbitrary set of board supports can be built in a single kernel - image. The kernel will "know" what set of functions to use for a - given platform based on the content of the device-tree. Thus, you - should: - - a) add your platform support as a _boolean_ option in - arch/powerpc/Kconfig, following the example of PPC_PSERIES, - PPC_PMAC and PPC_MAPLE. The later is probably a good - example of a board support to start from. - - b) create your main platform file as - "arch/powerpc/platforms/myplatform/myboard_setup.c" and add it - to the Makefile under the condition of your CONFIG_ - option. This file will define a structure of type "ppc_md" - containing the various callbacks that the generic code will - use to get to your platform specific code - - c) Add a reference to your "ppc_md" structure in the - "machines" table in arch/powerpc/kernel/setup_64.c if you are - a 64-bit platform. - - d) request and get assigned a platform number (see PLATFORM_* - constants in include/asm-powerpc/processor.h - -32-bit embedded kernels: - - Currently, board support is essentially an exclusive config option. - The kernel is configured for a single platform. Part of the reason - for this is to keep kernels on embedded systems small and efficient; - part of this is due to the fact the code is already that way. In the - future, a kernel may support multiple platforms, but only if the - platforms feature the same core architectire. A single kernel build - cannot support both configurations with Book E and configurations - with classic Powerpc architectures. - - 32-bit embedded platforms that are moved into arch/powerpc using a - flattened device tree should adopt the merged tree practice of - setting ppc_md up dynamically, even though the kernel is currently - built with support for only a single platform at a time. This allows - unification of the setup code, and will make it easier to go to a - multiple-platform-support model in the future. - -NOTE: I believe the above will be true once Ben's done with the merge -of the boot sequences.... someone speak up if this is wrong! - - To add a 32-bit embedded platform support, follow the instructions - for 64-bit platforms above, with the exception that the Kconfig - option should be set up such that the kernel builds exclusively for - the platform selected. The processor type for the platform should - enable another config option to select the specific board - supported. - -NOTE: If ben doesn't merge the setup files, may need to change this to -point to setup_32.c - - - I will describe later the boot process and various callbacks that - your platform should implement. - - -II - The DT block format -======================== - - -This chapter defines the actual format of the flattened device-tree -passed to the kernel. The actual content of it and kernel requirements -are described later. You can find example of code manipulating that -format in various places, including arch/powerpc/kernel/prom_init.c -which will generate a flattened device-tree from the Open Firmware -representation, or the fs2dt utility which is part of the kexec tools -which will generate one from a filesystem representation. It is -expected that a bootloader like uboot provides a bit more support, -that will be discussed later as well. - -Note: The block has to be in main memory. It has to be accessible in -both real mode and virtual mode with no mapping other than main -memory. If you are writing a simple flash bootloader, it should copy -the block to RAM before passing it to the kernel. - - -1) Header ---------- - - The kernel is entered with r3 pointing to an area of memory that is - roughtly described in include/asm-powerpc/prom.h by the structure - boot_param_header: - -struct boot_param_header { - u32 magic; /* magic word OF_DT_HEADER */ - u32 totalsize; /* total size of DT block */ - u32 off_dt_struct; /* offset to structure */ - u32 off_dt_strings; /* offset to strings */ - u32 off_mem_rsvmap; /* offset to memory reserve map -*/ - u32 version; /* format version */ - u32 last_comp_version; /* last compatible version */ - - /* version 2 fields below */ - u32 boot_cpuid_phys; /* Which physical CPU id we're - booting on */ - /* version 3 fields below */ - u32 size_dt_strings; /* size of the strings block */ -}; - - Along with the constants: - -/* Definitions used by the flattened device tree */ -#define OF_DT_HEADER 0xd00dfeed /* 4: version, - 4: total size */ -#define OF_DT_BEGIN_NODE 0x1 /* Start node: full name -*/ -#define OF_DT_END_NODE 0x2 /* End node */ -#define OF_DT_PROP 0x3 /* Property: name off, - size, content */ -#define OF_DT_END 0x9 - - All values in this header are in big endian format, the various - fields in this header are defined more precisely below. All - "offset" values are in bytes from the start of the header; that is - from the value of r3. - - - magic - - This is a magic value that "marks" the beginning of the - device-tree block header. It contains the value 0xd00dfeed and is - defined by the constant OF_DT_HEADER - - - totalsize - - This is the total size of the DT block including the header. The - "DT" block should enclose all data structures defined in this - chapter (who are pointed to by offsets in this header). That is, - the device-tree structure, strings, and the memory reserve map. - - - off_dt_struct - - This is an offset from the beginning of the header to the start - of the "structure" part the device tree. (see 2) device tree) - - - off_dt_strings - - This is an offset from the beginning of the header to the start - of the "strings" part of the device-tree - - - off_mem_rsvmap - - This is an offset from the beginning of the header to the start - of the reserved memory map. This map is a list of pairs of 64 - bit integers. Each pair is a physical address and a size. The - - list is terminated by an entry of size 0. This map provides the - kernel with a list of physical memory areas that are "reserved" - and thus not to be used for memory allocations, especially during - early initialization. The kernel needs to allocate memory during - boot for things like un-flattening the device-tree, allocating an - MMU hash table, etc... Those allocations must be done in such a - way to avoid overriding critical things like, on Open Firmware - capable machines, the RTAS instance, or on some pSeries, the TCE - tables used for the iommu. Typically, the reserve map should - contain _at least_ this DT block itself (header,total_size). If - you are passing an initrd to the kernel, you should reserve it as - well. You do not need to reserve the kernel image itself. The map - should be 64 bit aligned. - - - version - - This is the version of this structure. Version 1 stops - here. Version 2 adds an additional field boot_cpuid_phys. - Version 3 adds the size of the strings block, allowing the kernel - to reallocate it easily at boot and free up the unused flattened - structure after expansion. Version 16 introduces a new more - "compact" format for the tree itself that is however not backward - compatible. You should always generate a structure of the highest - version defined at the time of your implementation. Currently - that is version 16, unless you explicitely aim at being backward - compatible. - - - last_comp_version - - Last compatible version. This indicates down to what version of - the DT block you are backward compatible. For example, version 2 - is backward compatible with version 1 (that is, a kernel build - for version 1 will be able to boot with a version 2 format). You - should put a 1 in this field if you generate a device tree of - version 1 to 3, or 0x10 if you generate a tree of version 0x10 - using the new unit name format. - - - boot_cpuid_phys - - This field only exist on version 2 headers. It indicate which - physical CPU ID is calling the kernel entry point. This is used, - among others, by kexec. If you are on an SMP system, this value - should match the content of the "reg" property of the CPU node in - the device-tree corresponding to the CPU calling the kernel entry - point (see further chapters for more informations on the required - device-tree contents) - - - So the typical layout of a DT block (though the various parts don't - need to be in that order) looks like this (addresses go from top to - bottom): - - - ------------------------------ - r3 -> | struct boot_param_header | - ------------------------------ - | (alignment gap) (*) | - ------------------------------ - | memory reserve map | - ------------------------------ - | (alignment gap) | - ------------------------------ - | | - | device-tree structure | - | | - ------------------------------ - | (alignment gap) | - ------------------------------ - | | - | device-tree strings | - | | - -----> ------------------------------ - | - | - --- (r3 + totalsize) - - (*) The alignment gaps are not necessarily present; their presence - and size are dependent on the various alignment requirements of - the individual data blocks. - - -2) Device tree generalities ---------------------------- - -This device-tree itself is separated in two different blocks, a -structure block and a strings block. Both need to be aligned to a 4 -byte boundary. - -First, let's quickly describe the device-tree concept before detailing -the storage format. This chapter does _not_ describe the detail of the -required types of nodes & properties for the kernel, this is done -later in chapter III. - -The device-tree layout is strongly inherited from the definition of -the Open Firmware IEEE 1275 device-tree. It's basically a tree of -nodes, each node having two or more named properties. A property can -have a value or not. - -It is a tree, so each node has one and only one parent except for the -root node who has no parent. - -A node has 2 names. The actual node name is generally contained in a -property of type "name" in the node property list whose value is a -zero terminated string and is mandatory for version 1 to 3 of the -format definition (as it is in Open Firmware). Version 0x10 makes it -optional as it can generate it from the unit name defined below. - -There is also a "unit name" that is used to differenciate nodes with -the same name at the same level, it is usually made of the node -name's, the "@" sign, and a "unit address", which definition is -specific to the bus type the node sits on. - -The unit name doesn't exist as a property per-se but is included in -the device-tree structure. It is typically used to represent "path" in -the device-tree. More details about the actual format of these will be -below. - -The kernel powerpc generic code does not make any formal use of the -unit address (though some board support code may do) so the only real -requirement here for the unit address is to ensure uniqueness of -the node unit name at a given level of the tree. Nodes with no notion -of address and no possible sibling of the same name (like /memory or -/cpus) may omit the unit address in the context of this specification, -or use the "@0" default unit address. The unit name is used to define -a node "full path", which is the concatenation of all parent node -unit names separated with "/". - -The root node doesn't have a defined name, and isn't required to have -a name property either if you are using version 3 or earlier of the -format. It also has no unit address (no @ symbol followed by a unit -address). The root node unit name is thus an empty string. The full -path to the root node is "/". - -Every node which actually represents an actual device (that is, a node -which isn't only a virtual "container" for more nodes, like "/cpus" -is) is also required to have a "device_type" property indicating the -type of node . - -Finally, every node that can be referenced from a property in another -node is required to have a "linux,phandle" property. Real open -firmware implementations provide a unique "phandle" value for every -node that the "prom_init()" trampoline code turns into -"linux,phandle" properties. However, this is made optional if the -flattened device tree is used directly. An example of a node -referencing another node via "phandle" is when laying out the -interrupt tree which will be described in a further version of this -document. - -This "linux, phandle" property is a 32 bit value that uniquely -identifies a node. You are free to use whatever values or system of -values, internal pointers, or whatever to generate these, the only -requirement is that every node for which you provide that property has -a unique value for it. - -Here is an example of a simple device-tree. In this example, an "o" -designates a node followed by the node unit name. Properties are -presented with their name followed by their content. "content" -represents an ASCII string (zero terminated) value, while -represents a 32 bit hexadecimal value. The various nodes in this -example will be discussed in a later chapter. At this point, it is -only meant to give you a idea of what a device-tree looks like. I have -purposefully kept the "name" and "linux,phandle" properties which -aren't necessary in order to give you a better idea of what the tree -looks like in practice. - - / o device-tree - |- name = "device-tree" - |- model = "MyBoardName" - |- compatible = "MyBoardFamilyName" - |- #address-cells = <2> - |- #size-cells = <2> - |- linux,phandle = <0> - | - o cpus - | | - name = "cpus" - | | - linux,phandle = <1> - | | - #address-cells = <1> - | | - #size-cells = <0> - | | - | o PowerPC,970@0 - | |- name = "PowerPC,970" - | |- device_type = "cpu" - | |- reg = <0> - | |- clock-frequency = <5f5e1000> - | |- linux,boot-cpu - | |- linux,phandle = <2> - | - o memory@0 - | |- name = "memory" - | |- device_type = "memory" - | |- reg = <00000000 00000000 00000000 20000000> - | |- linux,phandle = <3> - | - o chosen - |- name = "chosen" - |- bootargs = "root=/dev/sda2" - |- linux,platform = <00000600> - |- linux,phandle = <4> - -This tree is almost a minimal tree. It pretty much contains the -minimal set of required nodes and properties to boot a linux kernel; -that is, some basic model informations at the root, the CPUs, and the -physical memory layout. It also includes misc information passed -through /chosen, like in this example, the platform type (mandatory) -and the kernel command line arguments (optional). - -The /cpus/PowerPC,970@0/linux,boot-cpu property is an example of a -property without a value. All other properties have a value. The -significance of the #address-cells and #size-cells properties will be -explained in chapter IV which defines precisely the required nodes and -properties and their content. - - -3) Device tree "structure" block - -The structure of the device tree is a linearized tree structure. The -"OF_DT_BEGIN_NODE" token starts a new node, and the "OF_DT_END_NODE" -ends that node definition. Child nodes are simply defined before -"OF_DT_END_NODE" (that is nodes within the node). A 'token' is a 32 -bit value. The tree has to be "finished" with a OF_DT_END token - -Here's the basic structure of a single node: - - * token OF_DT_BEGIN_NODE (that is 0x00000001) - * for version 1 to 3, this is the node full path as a zero - terminated string, starting with "/". For version 16 and later, - this is the node unit name only (or an empty string for the - root node) - * [align gap to next 4 bytes boundary] - * for each property: - * token OF_DT_PROP (that is 0x00000003) - * 32 bit value of property value size in bytes (or 0 of no - * value) - * 32 bit value of offset in string block of property name - * property value data if any - * [align gap to next 4 bytes boundary] - * [child nodes if any] - * token OF_DT_END_NODE (that is 0x00000002) - -So the node content can be summmarised as a start token, a full path, -a list of properties, a list of child node and an end token. Every -child node is a full node structure itself as defined above. - -4) Device tree 'strings" block - -In order to save space, property names, which are generally redundant, -are stored separately in the "strings" block. This block is simply the -whole bunch of zero terminated strings for all property names -concatenated together. The device-tree property definitions in the -structure block will contain offset values from the beginning of the -strings block. - - -III - Required content of the device tree -========================================= - -WARNING: All "linux,*" properties defined in this document apply only -to a flattened device-tree. If your platform uses a real -implementation of Open Firmware or an implementation compatible with -the Open Firmware client interface, those properties will be created -by the trampoline code in the kernel's prom_init() file. For example, -that's where you'll have to add code to detect your board model and -set the platform number. However, when using the flatenned device-tree -entry point, there is no prom_init() pass, and thus you have to -provide those properties yourself. - - -1) Note about cells and address representation ----------------------------------------------- - -The general rule is documented in the various Open Firmware -documentations. If you chose to describe a bus with the device-tree -and there exist an OF bus binding, then you should follow the -specification. However, the kernel does not require every single -device or bus to be described by the device tree. - -In general, the format of an address for a device is defined by the -parent bus type, based on the #address-cells and #size-cells -property. In the absence of such a property, the parent's parent -values are used, etc... The kernel requires the root node to have -those properties defining addresses format for devices directly mapped -on the processor bus. - -Those 2 properties define 'cells' for representing an address and a -size. A "cell" is a 32 bit number. For example, if both contain 2 -like the example tree given above, then an address and a size are both -composed of 2 cells, and each is a 64 bit number (cells are -concatenated and expected to be in big endian format). Another example -is the way Apple firmware defines them, with 2 cells for an address -and one cell for a size. Most 32-bit implementations should define -#address-cells and #size-cells to 1, which represents a 32-bit value. -Some 32-bit processors allow for physical addresses greater than 32 -bits; these processors should define #address-cells as 2. - -"reg" properties are always a tuple of the type "address size" where -the number of cells of address and size is specified by the bus -#address-cells and #size-cells. When a bus supports various address -spaces and other flags relative to a given address allocation (like -prefetchable, etc...) those flags are usually added to the top level -bits of the physical address. For example, a PCI physical address is -made of 3 cells, the bottom two containing the actual address itself -while the top cell contains address space indication, flags, and pci -bus & device numbers. - -For busses that support dynamic allocation, it's the accepted practice -to then not provide the address in "reg" (keep it 0) though while -providing a flag indicating the address is dynamically allocated, and -then, to provide a separate "assigned-addresses" property that -contains the fully allocated addresses. See the PCI OF bindings for -details. - -In general, a simple bus with no address space bits and no dynamic -allocation is preferred if it reflects your hardware, as the existing -kernel address parsing functions will work out of the box. If you -define a bus type with a more complex address format, including things -like address space bits, you'll have to add a bus translator to the -prom_parse.c file of the recent kernels for your bus type. - -The "reg" property only defines addresses and sizes (if #size-cells -is -non-0) within a given bus. In order to translate addresses upward -(that is into parent bus addresses, and possibly into cpu physical -addresses), all busses must contain a "ranges" property. If the -"ranges" property is missing at a given level, it's assumed that -translation isn't possible. The format of the "ranges" proprety for a -bus is a list of: - - bus address, parent bus address, size - -"bus address" is in the format of the bus this bus node is defining, -that is, for a PCI bridge, it would be a PCI address. Thus, (bus -address, size) defines a range of addresses for child devices. "parent -bus address" is in the format of the parent bus of this bus. For -example, for a PCI host controller, that would be a CPU address. For a -PCI<->ISA bridge, that would be a PCI address. It defines the base -address in the parent bus where the beginning of that range is mapped. - -For a new 64 bit powerpc board, I recommend either the 2/2 format or -Apple's 2/1 format which is slightly more compact since sizes usually -fit in a single 32 bit word. New 32 bit powerpc boards should use a -1/1 format, unless the processor supports physical addresses greater -than 32-bits, in which case a 2/1 format is recommended. - - -2) Note about "compatible" properties -------------------------------------- - -These properties are optional, but recommended in devices and the root -node. The format of a "compatible" property is a list of concatenated -zero terminated strings. They allow a device to express its -compatibility with a family of similar devices, in some cases, -allowing a single driver to match against several devices regardless -of their actual names. - -3) Note about "name" properties -------------------------------- - -While earlier users of Open Firmware like OldWorld macintoshes tended -to use the actual device name for the "name" property, it's nowadays -considered a good practice to use a name that is closer to the device -class (often equal to device_type). For example, nowadays, ethernet -controllers are named "ethernet", an additional "model" property -defining precisely the chip type/model, and "compatible" property -defining the family in case a single driver can driver more than one -of these chips. However, the kernel doesn't generally put any -restriction on the "name" property; it is simply considered good -practice to follow the standard and its evolutions as closely as -possible. - -Note also that the new format version 16 makes the "name" property -optional. If it's absent for a node, then the node's unit name is then -used to reconstruct the name. That is, the part of the unit name -before the "@" sign is used (or the entire unit name if no "@" sign -is present). - -4) Note about node and property names and character set -------------------------------------------------------- - -While open firmware provides more flexibe usage of 8859-1, this -specification enforces more strict rules. Nodes and properties should -be comprised only of ASCII characters 'a' to 'z', '0' to -'9', ',', '.', '_', '+', '#', '?', and '-'. Node names additionally -allow uppercase characters 'A' to 'Z' (property names should be -lowercase. The fact that vendors like Apple don't respect this rule is -irrelevant here). Additionally, node and property names should always -begin with a character in the range 'a' to 'z' (or 'A' to 'Z' for node -names). - -The maximum number of characters for both nodes and property names -is 31. In the case of node names, this is only the leftmost part of -a unit name (the pure "name" property), it doesn't include the unit -address which can extend beyond that limit. - - -5) Required nodes and properties --------------------------------- - These are all that are currently required. However, it is strongly - recommended that you expose PCI host bridges as documented in the - PCI binding to open firmware, and your interrupt tree as documented - in OF interrupt tree specification. - - a) The root node - - The root node requires some properties to be present: - - - model : this is your board name/model - - #address-cells : address representation for "root" devices - - #size-cells: the size representation for "root" devices - - Additionally, some recommended properties are: - - - compatible : the board "family" generally finds its way here, - for example, if you have 2 board models with a similar layout, - that typically get driven by the same platform code in the - kernel, you would use a different "model" property but put a - value in "compatible". The kernel doesn't directly use that - value (see /chosen/linux,platform for how the kernel choses a - platform type) but it is generally useful. - - The root node is also generally where you add additional properties - specific to your board like the serial number if any, that sort of - thing. it is recommended that if you add any "custom" property whose - name may clash with standard defined ones, you prefix them with your - vendor name and a comma. - - b) The /cpus node - - This node is the parent of all individual CPU nodes. It doesn't - have any specific requirements, though it's generally good practice - to have at least: - - #address-cells = <00000001> - #size-cells = <00000000> - - This defines that the "address" for a CPU is a single cell, and has - no meaningful size. This is not necessary but the kernel will assume - that format when reading the "reg" properties of a CPU node, see - below - - c) The /cpus/* nodes - - So under /cpus, you are supposed to create a node for every CPU on - the machine. There is no specific restriction on the name of the - CPU, though It's common practice to call it PowerPC,. For - example, Apple uses PowerPC,G5 while IBM uses PowerPC,970FX. - - Required properties: - - - device_type : has to be "cpu" - - reg : This is the physical cpu number, it's a single 32 bit cell - and is also used as-is as the unit number for constructing the - unit name in the full path. For example, with 2 CPUs, you would - have the full path: - /cpus/PowerPC,970FX@0 - /cpus/PowerPC,970FX@1 - (unit addresses do not require leading zeroes) - - d-cache-line-size : one cell, L1 data cache line size in bytes - - i-cache-line-size : one cell, L1 instruction cache line size in - bytes - - d-cache-size : one cell, size of L1 data cache in bytes - - i-cache-size : one cell, size of L1 instruction cache in bytes - - linux, boot-cpu : Should be defined if this cpu is the boot cpu. - - Recommended properties: - - - timebase-frequency : a cell indicating the frequency of the - timebase in Hz. This is not directly used by the generic code, - but you are welcome to copy/paste the pSeries code for setting - the kernel timebase/decrementer calibration based on this - value. - - clock-frequency : a cell indicating the CPU core clock frequency - in Hz. A new property will be defined for 64 bit values, but if - your frequency is < 4Ghz, one cell is enough. Here as well as - for the above, the common code doesn't use that property, but - you are welcome to re-use the pSeries or Maple one. A future - kernel version might provide a common function for this. - - You are welcome to add any property you find relevant to your board, - like some information about the mechanism used to soft-reset the - CPUs. For example, Apple puts the GPIO number for CPU soft reset - lines in there as a "soft-reset" property since they start secondary - CPUs by soft-resetting them. - - - d) the /memory node(s) - - To define the physical memory layout of your board, you should - create one or more memory node(s). You can either create a single - node with all memory ranges in its reg property, or you can create - several nodes, as you wish. The unit address (@ part) used for the - full path is the address of the first range of memory defined by a - given node. If you use a single memory node, this will typically be - @0. - - Required properties: - - - device_type : has to be "memory" - - reg : This property contains all the physical memory ranges of - your board. It's a list of addresses/sizes concatenated - together, with the number of cells of each defined by the - #address-cells and #size-cells of the root node. For example, - with both of these properties beeing 2 like in the example given - earlier, a 970 based machine with 6Gb of RAM could typically - have a "reg" property here that looks like: - - 00000000 00000000 00000000 80000000 - 00000001 00000000 00000001 00000000 - - That is a range starting at 0 of 0x80000000 bytes and a range - starting at 0x100000000 and of 0x100000000 bytes. You can see - that there is no memory covering the IO hole between 2Gb and - 4Gb. Some vendors prefer splitting those ranges into smaller - segments, but the kernel doesn't care. - - e) The /chosen node - - This node is a bit "special". Normally, that's where open firmware - puts some variable environment information, like the arguments, or - phandle pointers to nodes like the main interrupt controller, or the - default input/output devices. - - This specification makes a few of these mandatory, but also defines - some linux-specific properties that would be normally constructed by - the prom_init() trampoline when booting with an OF client interface, - but that you have to provide yourself when using the flattened format. - - Required properties: - - - linux,platform : This is your platform number as assigned by the - architecture maintainers - - Recommended properties: - - - bootargs : This zero-terminated string is passed as the kernel - command line - - linux,stdout-path : This is the full path to your standard - console device if any. Typically, if you have serial devices on - your board, you may want to put the full path to the one set as - the default console in the firmware here, for the kernel to pick - it up as it's own default console. If you look at the funciton - set_preferred_console() in arch/ppc64/kernel/setup.c, you'll see - that the kernel tries to find out the default console and has - knowledge of various types like 8250 serial ports. You may want - to extend this function to add your own. - - interrupt-controller : This is one cell containing a phandle - value that matches the "linux,phandle" property of your main - interrupt controller node. May be used for interrupt routing. - - - Note that u-boot creates and fills in the chosen node for platforms - that use it. - - f) the /soc node - - This node is used to represent a system-on-a-chip (SOC) and must be - present if the processor is a SOC. The top-level soc node contains - information that is global to all devices on the SOC. The node name - should contain a unit address for the SOC, which is the base address - of the memory-mapped register set for the SOC. The name of an soc - node should start with "soc", and the remainder of the name should - represent the part number for the soc. For example, the MPC8540's - soc node would be called "soc8540". - - Required properties: - - - device_type : Should be "soc" - - ranges : Should be defined as specified in 1) to describe the - translation of SOC addresses for memory mapped SOC registers. - - Recommended properties: - - - reg : This property defines the address and size of the - memory-mapped registers that are used for the SOC node itself. - It does not include the child device registers - these will be - defined inside each child node. The address specified in the - "reg" property should match the unit address of the SOC node. - - #address-cells : Address representation for "soc" devices. The - format of this field may vary depending on whether or not the - device registers are memory mapped. For memory mapped - registers, this field represents the number of cells needed to - represent the address of the registers. For SOCs that do not - use MMIO, a special address format should be defined that - contains enough cells to represent the required information. - See 1) above for more details on defining #address-cells. - - #size-cells : Size representation for "soc" devices - - #interrupt-cells : Defines the width of cells used to represent - interrupts. Typically this value is <2>, which includes a - 32-bit number that represents the interrupt number, and a - 32-bit number that represents the interrupt sense and level. - This field is only needed if the SOC contains an interrupt - controller. - - The SOC node may contain child nodes for each SOC device that the - platform uses. Nodes should not be created for devices which exist - on the SOC but are not used by a particular platform. See chapter VI - for more information on how to specify devices that are part of an -SOC. - - Example SOC node for the MPC8540: - - soc8540@e0000000 { - #address-cells = <1>; - #size-cells = <1>; - #interrupt-cells = <2>; - device_type = "soc"; - ranges = <00000000 e0000000 00100000> - reg = ; - } - - - -IV - "dtc", the device tree compiler -==================================== - - -dtc source code can be found at - - -WARNING: This version is still in early development stage; the -resulting device-tree "blobs" have not yet been validated with the -kernel. The current generated bloc lacks a useful reserve map (it will -be fixed to generate an empty one, it's up to the bootloader to fill -it up) among others. The error handling needs work, bugs are lurking, -etc... - -dtc basically takes a device-tree in a given format and outputs a -device-tree in another format. The currently supported formats are: - - Input formats: - ------------- - - - "dtb": "blob" format, that is a flattened device-tree block - with - header all in a binary blob. - - "dts": "source" format. This is a text file containing a - "source" for a device-tree. The format is defined later in this - chapter. - - "fs" format. This is a representation equivalent to the - output of /proc/device-tree, that is nodes are directories and - properties are files - - Output formats: - --------------- - - - "dtb": "blob" format - - "dts": "source" format - - "asm": assembly language file. This is a file that can be - sourced by gas to generate a device-tree "blob". That file can - then simply be added to your Makefile. Additionally, the - assembly file exports some symbols that can be use - - -The syntax of the dtc tool is - - dtc [-I ] [-O ] - [-o output-filename] [-V output_version] input_filename - - -The "output_version" defines what versio of the "blob" format will be -generated. Supported versions are 1,2,3 and 16. The default is -currently version 3 but that may change in the future to version 16. - -Additionally, dtc performs various sanity checks on the tree, like the -uniqueness of linux,phandle properties, validity of strings, etc... - -The format of the .dts "source" file is "C" like, supports C and C++ -style commments. - -/ { -} - -The above is the "device-tree" definition. It's the only statement -supported currently at the toplevel. - -/ { - property1 = "string_value"; /* define a property containing a 0 - * terminated string - */ - - property2 = <1234abcd>; /* define a property containing a - * numerical 32 bits value (hexadecimal) - */ - - property3 = <12345678 12345678 deadbeef>; - /* define a property containing 3 - * numerical 32 bits values (cells) in - * hexadecimal - */ - property4 = [0a 0b 0c 0d de ea ad be ef]; - /* define a property whose content is - * an arbitrary array of bytes - */ - - childnode@addresss { /* define a child node named "childnode" - * whose unit name is "childnode at - * address" - */ - - childprop = "hello\n"; /* define a property "childprop" of - * childnode (in this case, a string) - */ - }; -}; - -Nodes can contain other nodes etc... thus defining the hierarchical -structure of the tree. - -Strings support common escape sequences from C: "\n", "\t", "\r", -"\(octal value)", "\x(hex value)". - -It is also suggested that you pipe your source file through cpp (gcc -preprocessor) so you can use #include's, #define for constants, etc... - -Finally, various options are planned but not yet implemented, like -automatic generation of phandles, labels (exported to the asm file so -you can point to a property content and change it easily from whatever -you link the device-tree with), label or path instead of numeric value -in some cells to "point" to a node (replaced by a phandle at compile -time), export of reserve map address to the asm file, ability to -specify reserve map content at compile time, etc... - -We may provide a .h include file with common definitions of that -proves useful for some properties (like building PCI properties or -interrupt maps) though it may be better to add a notion of struct -definitions to the compiler... - - -V - Recommendations for a bootloader -==================================== - - -Here are some various ideas/recommendations that have been proposed -while all this has been defined and implemented. - - - The bootloader may want to be able to use the device-tree itself - and may want to manipulate it (to add/edit some properties, - like physical memory size or kernel arguments). At this point, 2 - choices can be made. Either the bootloader works directly on the - flattened format, or the bootloader has its own internal tree - representation with pointers (similar to the kernel one) and - re-flattens the tree when booting the kernel. The former is a bit - more difficult to edit/modify, the later requires probably a bit - more code to handle the tree structure. Note that the structure - format has been designed so it's relatively easy to "insert" - properties or nodes or delete them by just memmoving things - around. It contains no internal offsets or pointers for this - purpose. - - - An example of code for iterating nodes & retreiving properties - directly from the flattened tree format can be found in the kernel - file arch/ppc64/kernel/prom.c, look at scan_flat_dt() function, - it's usage in early_init_devtree(), and the corresponding various - early_init_dt_scan_*() callbacks. That code can be re-used in a - GPL bootloader, and as the author of that code, I would be happy - do discuss possible free licencing to any vendor who wishes to - integrate all or part of this code into a non-GPL bootloader. - - - -VI - System-on-a-chip devices and nodes -======================================= - -Many companies are now starting to develop system-on-a-chip -processors, where the processor core (cpu) and many peripheral devices -exist on a single piece of silicon. For these SOCs, an SOC node -should be used that defines child nodes for the devices that make -up the SOC. While platforms are not required to use this model in -order to boot the kernel, it is highly encouraged that all SOC -implementations define as complete a flat-device-tree as possible to -describe the devices on the SOC. This will allow for the -genericization of much of the kernel code. - - -1) Defining child nodes of an SOC ---------------------------------- - -Each device that is part of an SOC may have its own node entry inside -the SOC node. For each device that is included in the SOC, the unit -address property represents the address offset for this device's -memory-mapped registers in the parent's address space. The parent's -address space is defined by the "ranges" property in the top-level soc -node. The "reg" property for each node that exists directly under the -SOC node should contain the address mapping from the child address space -to the parent SOC address space and the size of the device's -memory-mapped register file. - -For many devices that may exist inside an SOC, there are predefined -specifications for the format of the device tree node. All SOC child -nodes should follow these specifications, except where noted in this -document. - -See appendix A for an example partial SOC node definition for the -MPC8540. - - -2) Specifying interrupt information for SOC devices ---------------------------------------------------- - -Each device that is part of an SOC and which generates interrupts -should have the following properties: - - - interrupt-parent : contains the phandle of the interrupt - controller which handles interrupts for this device - - interrupts : a list of tuples representing the interrupt - number and the interrupt sense and level for each interupt - for this device. - -This information is used by the kernel to build the interrupt table -for the interrupt controllers in the system. - -Sense and level information should be encoded as follows: - - Devices connected to openPIC-compatible controllers should encode - sense and polarity as follows: - - 0 = high to low edge sensitive type enabled - 1 = active low level sensitive type enabled - 2 = low to high edge sensitive type enabled - 3 = active high level sensitive type enabled - - ISA PIC interrupt controllers should adhere to the ISA PIC - encodings listed below: - - 0 = active low level sensitive type enabled - 1 = active high level sensitive type enabled - 2 = high to low edge sensitive type enabled - 3 = low to high edge sensitive type enabled - - - -3) Representing devices without a current OF specification ----------------------------------------------------------- - -Currently, there are many devices on SOCs that do not have a standard -representation pre-defined as part of the open firmware -specifications, mainly because the boards that contain these SOCs are -not currently booted using open firmware. This section contains -descriptions for the SOC devices for which new nodes have been -defined; this list will expand as more and more SOC-containing -platforms are moved over to use the flattened-device-tree model. - - a) MDIO IO device - - The MDIO is a bus to which the PHY devices are connected. For each - device that exists on this bus, a child node should be created. See - the definition of the PHY node below for an example of how to define - a PHY. - - Required properties: - - reg : Offset and length of the register set for the device - - device_type : Should be "mdio" - - compatible : Should define the compatible device type for the - mdio. Currently, this is most likely to be "gianfar" - - Example: - - mdio@24520 { - reg = <24520 20>; - - ethernet-phy@0 { - ...... - }; - }; - - - b) Gianfar-compatible ethernet nodes - - Required properties: - - - device_type : Should be "network" - - model : Model of the device. Can be "TSEC", "eTSEC", or "FEC" - - compatible : Should be "gianfar" - - reg : Offset and length of the register set for the device - - address : List of bytes representing the ethernet address of - this controller - - interrupts : where a is the interrupt number and b is a - field that represents an encoding of the sense and level - information for the interrupt. This should be encoded based on - the information in section 2) depending on the type of interrupt - controller you have. - - interrupt-parent : the phandle for the interrupt controller that - services interrupts for this device. - - phy-handle : The phandle for the PHY connected to this ethernet - controller. - - Example: - - ethernet@24000 { - #size-cells = <0>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <24000 1000>; - address = [ 00 E0 0C 00 73 00 ]; - interrupts = ; - interrupt-parent = <40000>; - phy-handle = <2452000> - }; - - - - c) PHY nodes - - Required properties: - - - device_type : Should be "ethernet-phy" - - interrupts : where a is the interrupt number and b is a - field that represents an encoding of the sense and level - information for the interrupt. This should be encoded based on - the information in section 2) depending on the type of interrupt - controller you have. - - interrupt-parent : the phandle for the interrupt controller that - services interrupts for this device. - - reg : The ID number for the phy, usually a small integer - - linux,phandle : phandle for this node; likely referenced by an - ethernet controller node. - - - Example: - - ethernet-phy@0 { - linux,phandle = <2452000> - interrupt-parent = <40000>; - interrupts = <35 1>; - reg = <0>; - device_type = "ethernet-phy"; - }; - - - d) Interrupt controllers - - Some SOC devices contain interrupt controllers that are different - from the standard Open PIC specification. The SOC device nodes for - these types of controllers should be specified just like a standard - OpenPIC controller. Sense and level information should be encoded - as specified in section 2) of this chapter for each device that - specifies an interrupt. - - Example : - - pic@40000 { - linux,phandle = <40000>; - clock-frequency = <0>; - interrupt-controller; - #address-cells = <0>; - reg = <40000 40000>; - built-in; - compatible = "chrp,open-pic"; - device_type = "open-pic"; - big-endian; - }; - - - e) I2C - - Required properties : - - - device_type : Should be "i2c" - - reg : Offset and length of the register set for the device - - Recommended properties : - - - compatible : Should be "fsl-i2c" for parts compatible with - Freescale I2C specifications. - - interrupts : where a is the interrupt number and b is a - field that represents an encoding of the sense and level - information for the interrupt. This should be encoded based on - the information in section 2) depending on the type of interrupt - controller you have. - - interrupt-parent : the phandle for the interrupt controller that - services interrupts for this device. - - dfsrr : boolean; if defined, indicates that this I2C device has - a digital filter sampling rate register - - fsl5200-clocking : boolean; if defined, indicated that this device - uses the FSL 5200 clocking mechanism. - - Example : - - i2c@3000 { - interrupt-parent = <40000>; - interrupts = <1b 3>; - reg = <3000 18>; - device_type = "i2c"; - compatible = "fsl-i2c"; - dfsrr; - }; - - - More devices will be defined as this spec matures. - - -Appendix A - Sample SOC node for MPC8540 -======================================== - -Note that the #address-cells and #size-cells for the SoC node -in this example have been explicitly listed; these are likely -not necessary as they are usually the same as the root node. - - soc8540@e0000000 { - #address-cells = <1>; - #size-cells = <1>; - #interrupt-cells = <2>; - device_type = "soc"; - ranges = <00000000 e0000000 00100000> - reg = ; - - mdio@24520 { - reg = <24520 20>; - device_type = "mdio"; - compatible = "gianfar"; - - ethernet-phy@0 { - linux,phandle = <2452000> - interrupt-parent = <40000>; - interrupts = <35 1>; - reg = <0>; - device_type = "ethernet-phy"; - }; - - ethernet-phy@1 { - linux,phandle = <2452001> - interrupt-parent = <40000>; - interrupts = <35 1>; - reg = <1>; - device_type = "ethernet-phy"; - }; - - ethernet-phy@3 { - linux,phandle = <2452002> - interrupt-parent = <40000>; - interrupts = <35 1>; - reg = <3>; - device_type = "ethernet-phy"; - }; - - }; - - ethernet@24000 { - #size-cells = <0>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <24000 1000>; - address = [ 00 E0 0C 00 73 00 ]; - interrupts = ; - interrupt-parent = <40000>; - phy-handle = <2452000>; - }; - - ethernet@25000 { - #address-cells = <1>; - #size-cells = <0>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <25000 1000>; - address = [ 00 E0 0C 00 73 01 ]; - interrupts = <13 3 14 3 18 3>; - interrupt-parent = <40000>; - phy-handle = <2452001>; - }; - - ethernet@26000 { - #address-cells = <1>; - #size-cells = <0>; - device_type = "network"; - model = "FEC"; - compatible = "gianfar"; - reg = <26000 1000>; - address = [ 00 E0 0C 00 73 02 ]; - interrupts = <19 3>; - interrupt-parent = <40000>; - phy-handle = <2452002>; - }; - - serial@4500 { - device_type = "serial"; - compatible = "ns16550"; - reg = <4500 100>; - clock-frequency = <0>; - interrupts = <1a 3>; - interrupt-parent = <40000>; - }; - - pic@40000 { - linux,phandle = <40000>; - clock-frequency = <0>; - interrupt-controller; - #address-cells = <0>; - reg = <40000 40000>; - built-in; - compatible = "chrp,open-pic"; - device_type = "open-pic"; - big-endian; - }; - - i2c@3000 { - interrupt-parent = <40000>; - interrupts = <1b 3>; - reg = <3000 18>; - device_type = "i2c"; - compatible = "fsl-i2c"; - dfsrr; - }; - - }; diff --git a/Documentation/manual.txt b/Documentation/manual.txt new file mode 100644 index 0000000..1f720e9 --- /dev/null +++ b/Documentation/manual.txt @@ -0,0 +1,618 @@ +Device Tree Compiler Manual +=========================== + +I - "dtc", the device tree compiler + 1) Obtaining Sources + 2) Description + 3) Command Line + 4) Source File + 4.1) Overview + 4.2) Properties + 4.3) Labels and References + +II - The DT block format + 1) Header + 2) Device tree generalities + 3) Device tree "structure" block + 4) Device tree "strings" block + + +III - libfdt + + +I - "dtc", the device tree compiler +=================================== + +1) Sources + +Source code for the Device Tree Compiler can be found at jdl.com. +The gitweb interface is: + + http://www.jdl.com/git_repos/ + +The repository is here: + + git://www.jdl.com/software/dtc.git + http://www.jdl.com/software/dtc.git + +Tarballs of the 1.0.0 and latest releases are here: + + http://www.jdl.com/software/dtc-1.0.0.tgz + http://www.jdl.com/software/dtc-latest.tgz + + +2) Description + +The Device Tree Compiler, dtc, takes as input a device-tree in +a given format and outputs a device-tree in another format. +Typically, the input format is "dts", a human readable source +format, and creates a "dtb", or binary format as output. + +The currently supported Input Formats are: + + - "dtb": "blob" format. A flattened device-tree block with + header in one binary blob. + + - "dts": "source" format. A text file containing a "source" + for a device-tree. + + - "fs" format. A representation equivalent to the output of + /proc/device-tree where nodes are directories and + properties are files. + +The currently supported Output Formats are: + + - "dtb": "blob" format + + - "dts": "source" format + + - "asm": assembly language file. A file that can be sourced + by gas to generate a device-tree "blob". That file can + then simply be added to your Makefile. Additionally, the + assembly file exports some symbols that can be used. + + +3) Command Line + +The syntax of the dtc command line is: + + dtc [options] [] + +Options: + + + The name of the input source file. If no + or "-" is given, stdin is used. + + -b + Set the physical boot cpu. + + -f + Force. Try to produce output even if the input tree has errors. + + -h + Emit a brief usage and help message. + + -I + The source input format, as listed above. + + -o + The name of the generated output file. Use "-" for stdout. + + -O + The generated output format, as listed above. + + -q + Quiet: -q suppress warnings, -qq errors, -qqq all + + -R + Make space for reserve map entries + Relevant for dtb and asm output only. + + -S + Ensure the blob at least long, adding additional + space if needed. + + -v + Print DTC version and exit. + + -V + Generate output conforming to the given . + By default the most recent version is generated. + Relevant for dtb and asm output only. + + +The defines what version of the "blob" format will be +generated. Supported versions are 1, 2, 3, 16 and 17. The default is +always the most recent version and is likely the highest number. + +Additionally, dtc performs various sanity checks on the tree. + + +4) Device Tree Source file + +4.1) Overview + +Here is a very rough overview of the layout of a DTS source file: + + + sourcefile: list_of_memreserve devicetree + + memreserve: label 'memreserve' ADDR ADDR ';' + | label 'memreserve' ADDR '-' ADDR ';' + + devicetree: '/' nodedef + + nodedef: '{' list_of_property list_of_subnode '}' ';' + + property: label PROPNAME '=' propdata ';' + + propdata: STRING + | '<' list_of_cells '>' + | '[' list_of_bytes ']' + + subnode: label nodename nodedef + +That structure forms a hierarchical layout of nodes and properties +rooted at an initial node as: + + / { + } + +Both classic C style and C++ style comments are supported. + +Source files may be directly included using the syntax: + + /include/ "filename" + + +4.2) Properties + +Properties are named, possibly labeled, values. Each value +is one of: + + - A null-teminated C-like string, + - A numeric value fitting in 32 bits, + - A list of 32-bit values + - A byte sequence + +Here are some example property definitions: + + - A property containing a 0 terminated string + + property1 = "string_value"; + + - A property containing a numerical 32-bit hexadecimal value + + property2 = <1234abcd>; + + - A property containing 3 numerical 32-bit hexadecimal values + + property3 = <12345678 12345678 deadbeef>; + + - A property whose content is an arbitrary array of bytes + + property4 = [0a 0b 0c 0d de ea ad be ef]; + + +Node may contain sub-nodes to obtain a hierarchical structure. +For example: + + - A child node named "childnode" whose unit name is + "childnode at address". It it turn has a string property + called "childprop". + + childnode@addresss { + childprop = "hello\n"; + }; + + +By default, all numeric values are hexadecimal. Alternate bases +may be specified using a prefix "d#" for decimal, "b#" for binary, +and "o#" for octal. + +Strings support common escape sequences from C: "\n", "\t", "\r", +"\(octal value)", "\x(hex value)". + + +4.3) Labels and References + +Labels may be applied to nodes or properties. Labels appear +before a node name, and are referenced using an ampersand: &label. +Absolute node path names are also allowed in node references. + +In this exmaple, a node is labled "mpic" and then referenced: + + mpic: interrupt-controller@40000 { + ... + }; + + ethernet-phy@3 { + interrupt-parent = <&mpic>; + ... + }; + +And used in properties, lables may appear before or after any value: + + randomnode { + prop: string = data: "mystring\n" data_end: ; + ... + }; + + + +II - The DT block format +======================== + +This chapter defines the format of the flattened device-tree +passed to the kernel. The actual content of the device tree +are described in the kernel documentation in the file + + linux-2.6/Documentation/powerpc/booting-without-of.txt + +You can find example of code manipulating that format within +the kernel. For example, the file: + + including arch/powerpc/kernel/prom_init.c + +will generate a flattened device-tree from the Open Firmware +representation. Other utilities such as fs2dt, which is part of +the kexec tools, will generate one from a filesystem representation. +Some bootloaders such as U-Boot provide a bit more support by +using the libfdt code. + +For booting the kernel, the device tree block has to be in main memory. +It has to be accessible in both real mode and virtual mode with no +mapping other than main memory. If you are writing a simple flash +bootloader, it should copy the block to RAM before passing it to +the kernel. + + +1) Header +--------- + +The kernel is entered with r3 pointing to an area of memory that is +roughly described in include/asm-powerpc/prom.h by the structure +boot_param_header: + + struct boot_param_header { + u32 magic; /* magic word OF_DT_HEADER */ + u32 totalsize; /* total size of DT block */ + u32 off_dt_struct; /* offset to structure */ + u32 off_dt_strings; /* offset to strings */ + u32 off_mem_rsvmap; /* offset to memory reserve map */ + u32 version; /* format version */ + u32 last_comp_version; /* last compatible version */ + + /* version 2 fields below */ + u32 boot_cpuid_phys; /* Which physical CPU id we're + booting on */ + /* version 3 fields below */ + u32 size_dt_strings; /* size of the strings block */ + + /* version 17 fields below */ + u32 size_dt_struct; /* size of the DT structure block */ + }; + +Along with the constants: + + /* Definitions used by the flattened device tree */ + #define OF_DT_HEADER 0xd00dfeed /* 4: version, + 4: total size */ + #define OF_DT_BEGIN_NODE 0x1 /* Start node: full name + */ + #define OF_DT_END_NODE 0x2 /* End node */ + #define OF_DT_PROP 0x3 /* Property: name off, + size, content */ + #define OF_DT_END 0x9 + +All values in this header are in big endian format, the various +fields in this header are defined more precisely below. All "offset" +values are in bytes from the start of the header; that is from the +value of r3. + + - magic + + This is a magic value that "marks" the beginning of the + device-tree block header. It contains the value 0xd00dfeed and is + defined by the constant OF_DT_HEADER + + - totalsize + + This is the total size of the DT block including the header. The + "DT" block should enclose all data structures defined in this + chapter (who are pointed to by offsets in this header). That is, + the device-tree structure, strings, and the memory reserve map. + + - off_dt_struct + + This is an offset from the beginning of the header to the start + of the "structure" part the device tree. (see 2) device tree) + + - off_dt_strings + + This is an offset from the beginning of the header to the start + of the "strings" part of the device-tree + + - off_mem_rsvmap + + This is an offset from the beginning of the header to the start + of the reserved memory map. This map is a list of pairs of 64- + bit integers. Each pair is a physical address and a size. The + list is terminated by an entry of size 0. This map provides the + kernel with a list of physical memory areas that are "reserved" + and thus not to be used for memory allocations, especially during + early initialization. The kernel needs to allocate memory during + boot for things like un-flattening the device-tree, allocating an + MMU hash table, etc... Those allocations must be done in such a + way to avoid overriding critical things like, on Open Firmware + capable machines, the RTAS instance, or on some pSeries, the TCE + tables used for the iommu. Typically, the reserve map should + contain _at least_ this DT block itself (header,total_size). If + you are passing an initrd to the kernel, you should reserve it as + well. You do not need to reserve the kernel image itself. The map + should be 64-bit aligned. + + - version + + This is the version of this structure. Version 1 stops + here. Version 2 adds an additional field boot_cpuid_phys. + Version 3 adds the size of the strings block, allowing the kernel + to reallocate it easily at boot and free up the unused flattened + structure after expansion. Version 16 introduces a new more + "compact" format for the tree itself that is however not backward + compatible. Version 17 adds an additional field, size_dt_struct, + allowing it to be reallocated or moved more easily (this is + particularly useful for bootloaders which need to make + adjustments to a device tree based on probed information). You + should always generate a structure of the highest version defined + at the time of your implementation. Currently that is version 17, + unless you explicitly aim at being backward compatible. + + - last_comp_version + + Last compatible version. This indicates down to what version of + the DT block you are backward compatible. For example, version 2 + is backward compatible with version 1 (that is, a kernel build + for version 1 will be able to boot with a version 2 format). You + should put a 1 in this field if you generate a device tree of + version 1 to 3, or 16 if you generate a tree of version 16 or 17 + using the new unit name format. + + - boot_cpuid_phys + + This field only exist on version 2 headers. It indicate which + physical CPU ID is calling the kernel entry point. This is used, + among others, by kexec. If you are on an SMP system, this value + should match the content of the "reg" property of the CPU node in + the device-tree corresponding to the CPU calling the kernel entry + point (see further chapters for more informations on the required + device-tree contents) + + - size_dt_strings + + This field only exists on version 3 and later headers. It + gives the size of the "strings" section of the device tree (which + starts at the offset given by off_dt_strings). + + - size_dt_struct + + This field only exists on version 17 and later headers. It gives + the size of the "structure" section of the device tree (which + starts at the offset given by off_dt_struct). + +So the typical layout of a DT block (though the various parts don't +need to be in that order) looks like this (addresses go from top to +bottom): + + ------------------------------ + r3 -> | struct boot_param_header | + ------------------------------ + | (alignment gap) (*) | + ------------------------------ + | memory reserve map | + ------------------------------ + | (alignment gap) | + ------------------------------ + | | + | device-tree structure | + | | + ------------------------------ + | (alignment gap) | + ------------------------------ + | | + | device-tree strings | + | | + -----> ------------------------------ + | + | + --- (r3 + totalsize) + + (*) The alignment gaps are not necessarily present; their presence + and size are dependent on the various alignment requirements of + the individual data blocks. + + +2) Device tree generalities +--------------------------- + +This device-tree itself is separated in two different blocks, a +structure block and a strings block. Both need to be aligned to a 4 +byte boundary. + +First, let's quickly describe the device-tree concept before detailing +the storage format. This chapter does _not_ describe the detail of the +required types of nodes & properties for the kernel, this is done +later in chapter III. + +The device-tree layout is strongly inherited from the definition of +the Open Firmware IEEE 1275 device-tree. It's basically a tree of +nodes, each node having two or more named properties. A property can +have a value or not. + +It is a tree, so each node has one and only one parent except for the +root node who has no parent. + +A node has 2 names. The actual node name is generally contained in a +property of type "name" in the node property list whose value is a +zero terminated string and is mandatory for version 1 to 3 of the +format definition (as it is in Open Firmware). Version 16 makes it +optional as it can generate it from the unit name defined below. + +There is also a "unit name" that is used to differentiate nodes with +the same name at the same level, it is usually made of the node +names, the "@" sign, and a "unit address", which definition is +specific to the bus type the node sits on. + +The unit name doesn't exist as a property per-se but is included in +the device-tree structure. It is typically used to represent "path" in +the device-tree. More details about the actual format of these will be +below. + +The kernel powerpc generic code does not make any formal use of the +unit address (though some board support code may do) so the only real +requirement here for the unit address is to ensure uniqueness of +the node unit name at a given level of the tree. Nodes with no notion +of address and no possible sibling of the same name (like /memory or +/cpus) may omit the unit address in the context of this specification, +or use the "@0" default unit address. The unit name is used to define +a node "full path", which is the concatenation of all parent node +unit names separated with "/". + +The root node doesn't have a defined name, and isn't required to have +a name property either if you are using version 3 or earlier of the +format. It also has no unit address (no @ symbol followed by a unit +address). The root node unit name is thus an empty string. The full +path to the root node is "/". + +Every node which actually represents an actual device (that is, a node +which isn't only a virtual "container" for more nodes, like "/cpus" +is) is also required to have a "device_type" property indicating the +type of node . + +Finally, every node that can be referenced from a property in another +node is required to have a "linux,phandle" property. Real open +firmware implementations provide a unique "phandle" value for every +node that the "prom_init()" trampoline code turns into +"linux,phandle" properties. However, this is made optional if the +flattened device tree is used directly. An example of a node +referencing another node via "phandle" is when laying out the +interrupt tree which will be described in a further version of this +document. + +This "linux, phandle" property is a 32-bit value that uniquely +identifies a node. You are free to use whatever values or system of +values, internal pointers, or whatever to generate these, the only +requirement is that every node for which you provide that property has +a unique value for it. + +Here is an example of a simple device-tree. In this example, an "o" +designates a node followed by the node unit name. Properties are +presented with their name followed by their content. "content" +represents an ASCII string (zero terminated) value, while +represents a 32-bit hexadecimal value. The various nodes in this +example will be discussed in a later chapter. At this point, it is +only meant to give you a idea of what a device-tree looks like. I have +purposefully kept the "name" and "linux,phandle" properties which +aren't necessary in order to give you a better idea of what the tree +looks like in practice. + + / o device-tree + |- name = "device-tree" + |- model = "MyBoardName" + |- compatible = "MyBoardFamilyName" + |- #address-cells = <2> + |- #size-cells = <2> + |- linux,phandle = <0> + | + o cpus + | | - name = "cpus" + | | - linux,phandle = <1> + | | - #address-cells = <1> + | | - #size-cells = <0> + | | + | o PowerPC,970@0 + | |- name = "PowerPC,970" + | |- device_type = "cpu" + | |- reg = <0> + | |- clock-frequency = <5f5e1000> + | |- 64-bit + | |- linux,phandle = <2> + | + o memory@0 + | |- name = "memory" + | |- device_type = "memory" + | |- reg = <00000000 00000000 00000000 20000000> + | |- linux,phandle = <3> + | + o chosen + |- name = "chosen" + |- bootargs = "root=/dev/sda2" + |- linux,phandle = <4> + +This tree is almost a minimal tree. It pretty much contains the +minimal set of required nodes and properties to boot a linux kernel; +that is, some basic model informations at the root, the CPUs, and the +physical memory layout. It also includes misc information passed +through /chosen, like in this example, the platform type (mandatory) +and the kernel command line arguments (optional). + +The /cpus/PowerPC,970@0/64-bit property is an example of a +property without a value. All other properties have a value. The +significance of the #address-cells and #size-cells properties will be +explained in chapter IV which defines precisely the required nodes and +properties and their content. + + +3) Device tree "structure" block + +The structure of the device tree is a linearized tree structure. The +"OF_DT_BEGIN_NODE" token starts a new node, and the "OF_DT_END_NODE" +ends that node definition. Child nodes are simply defined before +"OF_DT_END_NODE" (that is nodes within the node). A 'token' is a 32 +bit value. The tree has to be "finished" with a OF_DT_END token + +Here's the basic structure of a single node: + + * token OF_DT_BEGIN_NODE (that is 0x00000001) + * for version 1 to 3, this is the node full path as a zero + terminated string, starting with "/". For version 16 and later, + this is the node unit name only (or an empty string for the + root node) + * [align gap to next 4 bytes boundary] + * for each property: + * token OF_DT_PROP (that is 0x00000003) + * 32-bit value of property value size in bytes (or 0 if no + value) + * 32-bit value of offset in string block of property name + * property value data if any + * [align gap to next 4 bytes boundary] + * [child nodes if any] + * token OF_DT_END_NODE (that is 0x00000002) + +So the node content can be summarized as a start token, a full path, +a list of properties, a list of child nodes, and an end token. Every +child node is a full node structure itself as defined above. + +NOTE: The above definition requires that all property definitions for +a particular node MUST precede any subnode definitions for that node. +Although the structure would not be ambiguous if properties and +subnodes were intermingled, the kernel parser requires that the +properties come first (up until at least 2.6.22). Any tools +manipulating a flattened tree must take care to preserve this +constraint. + +4) Device tree "strings" block + +In order to save space, property names, which are generally redundant, +are stored separately in the "strings" block. This block is simply the +whole bunch of zero terminated strings for all property names +concatenated together. The device-tree property definitions in the +structure block will contain offset values from the beginning of the +strings block. + + +III - libfdt + +This library should be merged into dtc proper. +This library should likely be worked into U-Boot and the kernel. From 5cb1fbdd7cf82e1909e27c81073cf3272cb63fa3 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Thu, 9 Aug 2007 19:31:32 -0500 Subject: [PATCH 0088/1198] DTC 1.0.0 For better or worse, it's about damned time! Signed-off-by: Jon Loeliger --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7d27de9..24ce91a 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ VERSION = 1 PATCHLEVEL = 0 SUBLEVEL = 0 -EXTRAVERSION =-rc1 +EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = From bd2ae2f41cb1ef7612e3b2cb7179bc6be6ec7f44 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 29 Aug 2007 12:22:50 +1000 Subject: [PATCH 0089/1198] libfdt: Fix handling of trailing / in fdt_path_offset() Currently, fdt_path_offset() returns FDL_ERR_BADOFFSET if given a path with a trailing '/'. In particular this means that fdt_path_offset("/") returns FDT_ERR_BADOFFSET rather than 0 as one would expect. This patch fixes the function to accept and ignore trailing '/' characters. As well as allowing fdt_path_offset("/") this means that fdt_path_offset("/foo/") will return the same as fdt_path_offset("/foo") which seems in keeping with the principle of least surprise. This also adds a testcase to ensure that fdt_path_offset("/") returns 0 as it should. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 2 +- tests/path_offset.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 2ca1b22..e7a78de 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -154,7 +154,7 @@ int fdt_path_offset(const void *fdt, const char *path) while (*p == '/') p++; if (! *p) - return -FDT_ERR_BADPATH; + return offset; q = strchr(p, '/'); if (! q) q = end; diff --git a/tests/path_offset.c b/tests/path_offset.c index 05b0c32..c962000 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -58,6 +58,7 @@ int check_subnode(void *fdt, int parent, const char *name) int main(int argc, char *argv[]) { void *fdt; + int root_offset; int subnode1_offset, subnode2_offset; int subnode1_offset_p, subnode2_offset_p; int subsubnode1_offset, subsubnode2_offset; @@ -66,6 +67,13 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); + root_offset = fdt_path_offset(fdt, "/"); + if (root_offset < 0) + FAIL("fdt_path_offset(\"/\") failed: %s", + fdt_strerror(root_offset)); + else if (root_offset != 0) + FAIL("fdt_path_offset(\"/\") returns incorrect offset %d", + root_offset); subnode1_offset = check_subnode(fdt, 0, "subnode1"); subnode2_offset = check_subnode(fdt, 0, "subnode2"); From 9d26eabdc6ff9d9676436596876c732de741b9af Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 30 Aug 2007 14:54:04 +1000 Subject: [PATCH 0090/1198] libfdt: Add fdt_get_name() to retrieve a node's name This patch adds a new fdt_get_name() function to libfdt which will return a node's name string (including unit address, if any). Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 24 +++++++++++++ libfdt/libfdt.h | 2 ++ tests/Makefile.tests | 3 +- tests/get_name.c | 83 ++++++++++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 1 + 5 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 tests/get_name.c diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index e7a78de..9ff862b 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -169,6 +169,30 @@ int fdt_path_offset(const void *fdt, const char *path) return offset; } +const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) +{ + const struct fdt_node_header *nh; + int err; + + if ((err = _fdt_check_header(fdt)) != 0) + goto fail; + + err = -FDT_ERR_BADOFFSET; + nh = fdt_offset_ptr(fdt, nodeoffset, sizeof(*nh)); + if (!nh || (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE)) + goto fail; + + if (len) + *len = strlen(nh->name); + + return nh->name; + + fail: + if (len) + *len = err; + return NULL; +} + const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, const char *name, int *lenp) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index d33a64f..f8fd459 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -115,6 +115,8 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); int fdt_path_offset(const void *fdt, const char *path); +const char *fdt_get_name(const void *fdt, int nodeoffset, int *baselen); + const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, const char *name, int *lenp); diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 0087582..ae9b78c 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -1,4 +1,5 @@ -LIB_TESTS_L = root_node find_property subnode_offset path_offset getprop \ +LIB_TESTS_L = root_node find_property subnode_offset path_offset \ + get_name getprop \ notfound \ setprop_inplace nop_property nop_node \ sw_tree1 \ diff --git a/tests/get_name.c b/tests/get_name.c new file mode 100644 index 0000000..aef4d9c --- /dev/null +++ b/tests/get_name.c @@ -0,0 +1,83 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_get_name() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void check_name(void *fdt, const char *path) +{ + int offset; + const char *getname, *getname2, *checkname; + int len; + + checkname = strrchr(path, '/'); + if (!checkname) + TEST_BUG(); + checkname += 1; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("Couldn't find %s", path); + + getname = fdt_get_name(fdt, offset, &len); + verbose_printf("fdt_get_name(%d) returns \"%s\" (len=%d)\n", + offset, getname, len); + if (!getname) + FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len)); + + if (strcmp(getname, checkname) != 0) + FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"", + path, getname, checkname); + + if (len != strlen(getname)) + FAIL("fdt_get_name(%s) returned length %d instead of %d", + path, len, strlen(getname)); + + /* Now check that it doesn't break if we omit len */ + getname2 = fdt_get_name(fdt, offset, NULL); + if (!getname2) + FAIL("fdt_get_name(%d, NULL) failed", offset); + if (strcmp(getname2, getname) != 0) + FAIL("fdt_get_name(%d, NULL) returned \"%s\" instead of \"%s\"", + offset, getname2, getname); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_name(fdt, "/"); + check_name(fdt, "/subnode1"); + check_name(fdt, "/subnode2"); + check_name(fdt, "/subnode1/subsubnode"); + check_name(fdt, "/subnode2/subsubnode"); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index df368f9..4198f5f 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -32,6 +32,7 @@ tree1_tests () { run_test find_property $TREE run_test subnode_offset $TREE run_test path_offset $TREE + run_test get_name $TREE run_test getprop $TREE run_test notfound $TREE From 037db263e04f43cb113064fa24e1b441ff761528 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 30 Aug 2007 14:54:04 +1000 Subject: [PATCH 0091/1198] libfdt: Add fdt_get_path() function This patch adds an fdt_get_path() function to libfdt, which returns the full path of a given node in a caller supplied buffer. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 66 ++++++++++++++++++++++++++++++++ libfdt/libfdt.h | 2 + tests/Makefile.tests | 2 +- tests/get_path.c | 91 ++++++++++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 1 + 5 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 tests/get_path.c diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 9ff862b..0e9deb5 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -283,3 +283,69 @@ const void *fdt_getprop(const void *fdt, int nodeoffset, return prop->data; } + +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) +{ + uint32_t tag; + int p = 0, overflow = 0; + int offset, nextoffset, namelen; + const char *name; + + CHECK_HEADER(fdt); + + tag = _fdt_next_tag(fdt, 0, &nextoffset); + if (tag != FDT_BEGIN_NODE) + return -FDT_ERR_BADSTRUCTURE; + + if (buflen < 2) + return -FDT_ERR_NOSPACE; + buf[0] = '/'; + p = 1; + + while (offset < nodeoffset) { + offset = nextoffset; + tag = _fdt_next_tag(fdt, offset, &nextoffset); + switch (tag) { + case FDT_END: + return -FDT_ERR_BADOFFSET; + + case FDT_BEGIN_NODE: + name = fdt_get_name(fdt, offset, &namelen); + if (!name) + return namelen; + if (overflow || ((p + namelen + 1) > buflen)) { + overflow++; + break; + } + memcpy(buf + p, name, namelen); + p += namelen; + buf[p++] = '/'; + break; + + case FDT_END_NODE: + if (overflow) { + overflow--; + break; + } + do { + p--; + } while (buf[p-1] != '/'); + break; + + case FDT_PROP: + case FDT_NOP: + break; + + default: + return -FDT_ERR_BADSTRUCTURE; + } + } + + if (overflow) + return -FDT_ERR_NOSPACE; + + if (p > 1) /* special case so that root path is "/", not "" */ + p--; + buf[p] = '\0'; + return p; +} diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index f8fd459..c72db48 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -136,6 +136,8 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset, return (void *)fdt_getprop(fdt, nodeoffset, name, lenp); } +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); + /* Write-in-place functions */ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len); diff --git a/tests/Makefile.tests b/tests/Makefile.tests index ae9b78c..34dd0a4 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -1,5 +1,5 @@ LIB_TESTS_L = root_node find_property subnode_offset path_offset \ - get_name getprop \ + get_name getprop get_path \ notfound \ setprop_inplace nop_property nop_node \ sw_tree1 \ diff --git a/tests/get_path.c b/tests/get_path.c new file mode 100644 index 0000000..1f09479 --- /dev/null +++ b/tests/get_path.c @@ -0,0 +1,91 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_get_path() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#define _GNU_SOURCE + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +#define POISON ('\xff') + +void check_path_buf(void *fdt, const char *path, int pathlen, int buflen) +{ + int offset; + char buf[buflen+1]; + int len; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("Couldn't find path \"%s\": %s", path, fdt_strerror(offset)); + + memset(buf, POISON, sizeof(buf)); /* poison the buffer */ + + len = fdt_get_path(fdt, offset, buf, buflen); + if (buflen <= pathlen) { + if (len != -FDT_ERR_NOSPACE) + FAIL("fdt_get_path([%d bytes]) returns %d with " + "insufficient buffer space", buflen, len); + } else { + if (len < 0) + FAIL("fdt_get_path([%d bytes]): %s", buflen, + fdt_strerror(len)); + if (len != pathlen) + FAIL("fdt_get_path([%d bytes]) reports length %d " + "instead of %d", buflen, len, pathlen); + if (strcmp(buf, path) != 0) + FAIL("fdt_get_path([%d bytes]) returns \"%s\" " + "instead of \"%s\"", buflen, buf, path); + } + + if (buf[buflen] != POISON) + FAIL("fdt_get_path([%d bytes]) overran buffer", buflen); +} + +void check_path(void *fdt, const char *path) +{ + int pathlen = strlen(path); + + check_path_buf(fdt, path, pathlen, 1024); + check_path_buf(fdt, path, pathlen, pathlen+1); + check_path_buf(fdt, path, pathlen, pathlen); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_path(fdt, "/"); + check_path(fdt, "/subnode1"); + check_path(fdt, "/subnode2"); + check_path(fdt, "/subnode1/subsubnode"); + check_path(fdt, "/subnode2/subsubnode"); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 4198f5f..d0d4bb1 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -34,6 +34,7 @@ tree1_tests () { run_test path_offset $TREE run_test get_name $TREE run_test getprop $TREE + run_test get_path $TREE run_test notfound $TREE # Write-in-place tests From 1248237c7e3f949e974e42927645f82e03f9b115 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 30 Aug 2007 14:54:04 +1000 Subject: [PATCH 0092/1198] libfdt: Add fdt_parent_offset() and supporting functions This patch adds an fdt_parent_offset() function which returns an offset to the parent node of a given node. It also adds two helper functions which are used to implement fdt_parent_offset() but are also exported: fdt_supernode_atdepth_offset() which returns the ancestor of a given node at a specified depth from the root of the tree, and fdt_node_depth() which returns the depth of a given node. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 68 +++++++++++++++ libfdt/libfdt.h | 10 ++- tests/Makefile.tests | 2 +- tests/parent_offset.c | 90 +++++++++++++++++++ tests/run_tests.sh | 2 + tests/supernode_atdepth_offset.c | 144 +++++++++++++++++++++++++++++++ 6 files changed, 314 insertions(+), 2 deletions(-) create mode 100644 tests/parent_offset.c create mode 100644 tests/supernode_atdepth_offset.c diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 0e9deb5..dc4a596 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -349,3 +349,71 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) buf[p] = '\0'; return p; } + +int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, + int supernodedepth, int *nodedepth) +{ + int level = -1; + uint32_t tag; + int offset, nextoffset = 0; + int supernodeoffset = -FDT_ERR_INTERNAL; + + CHECK_HEADER(fdt); + + if (supernodedepth < 0) + return -FDT_ERR_NOTFOUND; + + do { + offset = nextoffset; + tag = _fdt_next_tag(fdt, offset, &nextoffset); + switch (tag) { + case FDT_END: + return -FDT_ERR_BADOFFSET; + + case FDT_BEGIN_NODE: + level++; + if (level == supernodedepth) + supernodeoffset = offset; + break; + + case FDT_END_NODE: + level--; + break; + + case FDT_PROP: + case FDT_NOP: + break; + + default: + return -FDT_ERR_BADSTRUCTURE; + } + } while (offset < nodeoffset); + + if (nodedepth) + *nodedepth = level; + + if (supernodedepth > level) + return -FDT_ERR_NOTFOUND; + return supernodeoffset; +} + +int fdt_node_depth(const void *fdt, int nodeoffset) +{ + int nodedepth; + int err; + + err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); + if (err) + return (err < 0) ? err : -FDT_ERR_INTERNAL; + return nodedepth; +} + +int fdt_parent_offset(const void *fdt, int nodeoffset) +{ + int nodedepth = fdt_node_depth(fdt, nodeoffset); + + if (nodedepth < 0) + return nodedepth; + return fdt_supernode_atdepth_offset(fdt, nodeoffset, + nodedepth - 1, NULL); +} diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index c72db48..a9acd5d 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -74,7 +74,10 @@ #define FDT_ERR_BADSTRUCTURE 10 #define FDT_ERR_BADLAYOUT 11 -#define FDT_ERR_MAX 11 +/* "Can't happen" error indicating a bug in libfdt */ +#define FDT_ERR_INTERNAL 12 + +#define FDT_ERR_MAX 12 #define fdt_get_header(fdt, field) \ (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) @@ -138,6 +141,11 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset, int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); +int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, + int supernodedepth, int *nodedepth); +int fdt_node_depth(const void *fdt, int nodeoffset); +int fdt_parent_offset(const void *fdt, int nodeoffset); + /* Write-in-place functions */ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len); diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 34dd0a4..6552869 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -1,5 +1,5 @@ LIB_TESTS_L = root_node find_property subnode_offset path_offset \ - get_name getprop get_path \ + get_name getprop get_path supernode_atdepth_offset parent_offset \ notfound \ setprop_inplace nop_property nop_node \ sw_tree1 \ diff --git a/tests/parent_offset.c b/tests/parent_offset.c new file mode 100644 index 0000000..f3d2c32 --- /dev/null +++ b/tests/parent_offset.c @@ -0,0 +1,90 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_parent_offset() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#define _GNU_SOURCE + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int path_parent_len(const char *path) +{ + const char *p = strrchr(path, '/'); + + if (!p) + TEST_BUG(); + if (p == path) + return 1; + else + return p - path; +} + +void check_path(struct fdt_header *fdt, const char *path) +{ + char *parentpath; + int nodeoffset, parentoffset, parentpathoffset; + + parentpath = strndupa(path, path_parent_len(path)); + + verbose_printf("Path: \"%s\"\tParent: \"%s\"\n", path, parentpath); + + nodeoffset = fdt_path_offset(fdt, path); + if (nodeoffset < 0) + FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset)); + + parentpathoffset = fdt_path_offset(fdt, parentpath); + if (parentpathoffset < 0) + FAIL("fdt_path_offset(%s): %s", parentpath, + fdt_strerror(parentpathoffset)); + + parentoffset = fdt_parent_offset(fdt, nodeoffset); + if (parentoffset < 0) + FAIL("fdt_parent_offset(): %s", fdt_strerror(parentoffset)); + + if (parentoffset != parentpathoffset) + FAIL("fdt_parent_offset() returns %d instead of %d", + parentoffset, parentpathoffset); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + int err; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_path(fdt, "/subnode1"); + check_path(fdt, "/subnode2"); + check_path(fdt, "/subnode1/subsubnode"); + check_path(fdt, "/subnode2/subsubnode"); + err = fdt_parent_offset(fdt, 0); + if (err != -FDT_ERR_NOTFOUND) + FAIL("fdt_parent_offset(/) returns %d instead of " + "-FDT_ERR_NOTFOUND", err); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index d0d4bb1..381d665 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -35,6 +35,8 @@ tree1_tests () { run_test get_name $TREE run_test getprop $TREE run_test get_path $TREE + run_test supernode_atdepth_offset $TREE + run_test parent_offset $TREE run_test notfound $TREE # Write-in-place tests diff --git a/tests/supernode_atdepth_offset.c b/tests/supernode_atdepth_offset.c new file mode 100644 index 0000000..6736aca --- /dev/null +++ b/tests/supernode_atdepth_offset.c @@ -0,0 +1,144 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_supernode_atdepth_offset() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#define _GNU_SOURCE + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int path_depth(const char *path) +{ + const char *p; + int depth = 0; + + if (path[0] != '/') + TEST_BUG(); + + if (strcmp(path, "/") == 0) + return 0; + for (p = path; *p; p++) + if (*p == '/') + depth++; + + /* Special case for path == "/" */ + if (p == (path + 1)) + return 0; + else + return depth; +} + +int path_prefix(const char *path, int depth) +{ + const char *p; + int i; + + if (path[0] != '/') + TEST_BUG(); + + if (depth == 0) + return 1; + + p = path; + for (i = 0; i < depth; i++) + p = strchrnul(p+1, '/'); + + return p - path; +} + +void check_supernode_atdepth(struct fdt_header *fdt, const char *path, + int depth) +{ + int pdepth = path_depth(path); + char *superpath; + int nodeoffset, supernodeoffset, superpathoffset; + int nodedepth; + + superpath = strndupa(path, path_prefix(path, depth)); + verbose_printf("Path %s (%d), depth %d, supernode is %s\n", + path, pdepth, depth, superpath); + + nodeoffset = fdt_path_offset(fdt, path); + if (nodeoffset < 0) + FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset)); + superpathoffset = fdt_path_offset(fdt, superpath); + if (superpathoffset < 0) + FAIL("fdt_path_offset(%s): %s", superpath, + fdt_strerror(superpathoffset)); + + supernodeoffset = fdt_supernode_atdepth_offset(fdt, nodeoffset, + depth, &nodedepth); + if (supernodeoffset < 0) + FAIL("fdt_supernode_atdepth_offset(): %s", + fdt_strerror(supernodeoffset)); + + if (supernodeoffset != superpathoffset) + FAIL("fdt_supernode_atdepth_offset() returns %d instead of %d", + supernodeoffset, superpathoffset); + + if (nodedepth != pdepth) + FAIL("fdt_supernode_atdept_offset() returns node depth %d " + "instead of %d", nodedepth, pdepth); +} + +void check_supernode_overdepth(struct fdt_header *fdt, const char *path) +{ + int pdepth = path_depth(path); + int nodeoffset, err; + + nodeoffset = fdt_path_offset(fdt, path); + if (nodeoffset < 0) + FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset)); + + err = fdt_supernode_atdepth_offset(fdt, nodeoffset, pdepth + 1, NULL); + if (err != -FDT_ERR_NOTFOUND) + FAIL("fdt_supernode_atdept_offset(%s, %d) returns %d instead " + "of FDT_ERR_NOTFOUND", path, pdepth+1, err); +} + +void check_path(struct fdt_header *fdt, const char *path) +{ + int i; + + for (i = 0; i <= path_depth(path); i++) + check_supernode_atdepth(fdt, path, i); + check_supernode_overdepth(fdt, path); +} +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_path(fdt, "/"); + check_path(fdt, "/subnode1"); + check_path(fdt, "/subnode2"); + check_path(fdt, "/subnode1/subsubnode"); + check_path(fdt, "/subnode2/subsubnode"); + + PASS(); +} From 7ca330865e9e4bf0f32a9875a364d00951373999 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 29 Aug 2007 12:18:51 +1000 Subject: [PATCH 0093/1198] dtc: Fix summary calculation in testsuite The bookkeeping for producing the testsuite summary (total number of tests passed, failed and so forth) is broken. It uses $? across several tests, but for checks after the first, the value of $? will no longer contain the original return code, but just that from the previous test. This patch fixes the problem. Signed-off-by: David Gibson --- tests/run_tests.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 381d665..b7cad42 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -15,12 +15,15 @@ run_test () { echo -n "$@: " if PATH=".:$PATH" $ENV "$@"; then tot_pass=$[tot_pass + 1] - elif [ "$?" == "1" ]; then - tot_config=$[tot_config + 1] - elif [ "$?" == "2" ]; then - tot_fail=$[tot_fail + 1] else - tot_strange=$[tot_strange + 1] + ret="$?" + if [ "$ret" == "1" ]; then + tot_config=$[tot_config + 1] + elif [ "$ret" == "2" ]; then + tot_fail=$[tot_fail + 1] + else + tot_strange=$[tot_strange + 1] + fi fi } From e2b3bb32276252a922c0b02981d0fd998766feef Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 31 Aug 2007 14:30:16 +1000 Subject: [PATCH 0094/1198] libfdt: Fix use of uninitialized variable in fdt_get_path() My recent implemenetation of fdt_get_path() had a bug - the while loop tested offset which was unitialized on the first iteration. Depending on code surrounding the call, this could cause fdt_get_path() to return incorrect results. This patch corrects the problem by applying some more correct thinking to the loop condition. 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 dc4a596..65bd1a2 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -302,7 +302,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) buf[0] = '/'; p = 1; - while (offset < nodeoffset) { + while (nextoffset <= nodeoffset) { offset = nextoffset; tag = _fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { From ed0117a0c059ec0e1257573b0850081787bd651d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 31 Aug 2007 16:04:27 +1000 Subject: [PATCH 0095/1198] dtc: Make make print a message when linking testcases Currently, dtc relies on make's implicit rule to build the testcases. This means that when not making verbosely (V=0, the default) there is no message at all while relinking the testsuites. This can be very confusing when updating libfdt.a (upon which the testcases depend) and make appears to do nothing. This patch corrects the situation, borrowing the rule used to link dtc itself to link all the testcases as well. Signed-off-by: David Gibson --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 24ce91a..5766012 100644 --- a/Makefile +++ b/Makefile @@ -101,8 +101,6 @@ lex.yy.c: dtc-lexer.l $(LEX) $< dtc: $(DTC_OBJS) - @$(VECHO) LD $@ - $(LINK.c) -o $@ $^ ftdump: ftdump.o @@ -168,6 +166,10 @@ endef # # Generic compile rules # +%: %.o + @$(VECHO) LD $@ + $(LINK.c) -o $@ $^ + %.o: %.c @$(VECHO) CC $@ $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< From bf944970317820867895680cf0e2c4e72eefa8b1 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 31 Aug 2007 16:21:23 +1000 Subject: [PATCH 0096/1198] dtc: Optimise by default, fix warnings thus uncovered This patch turns on optimisation in the Makefile by default. With the optimizer on, some uninitialized variable warnings (one real, two bogus) are now generated. This patch also squashes those again. --- Makefile | 2 +- dtc.c | 2 +- dtc.h | 2 +- flattree.c | 9 +++++---- tests/truncated_property.c | 3 +-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 5766012..27e1499 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ endef CPPFLAGS = -I libfdt -CFLAGS = -Wall -g +CFLAGS = -Wall -g -Os LDFLAGS = -Llibfdt BISON = bison diff --git a/dtc.c b/dtc.c index ecd9fe5..8f5fe2f 100644 --- a/dtc.c +++ b/dtc.c @@ -71,7 +71,7 @@ void fill_fullpaths(struct node *tree, char *prefix) fill_fullpaths(child, tree->fullpath); } -static void usage(void) +static void __attribute__ ((noreturn)) usage(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, "\tdtc [options] \n"); diff --git a/dtc.h b/dtc.h index 0a1f960..458403a 100644 --- a/dtc.h +++ b/dtc.h @@ -43,7 +43,7 @@ extern int quiet; /* Level of quietness */ extern int reservenum; /* Number of memory reservation slots */ extern int minsize; /* Minimum blob size */ -static inline void die(char * str, ...) +static inline void __attribute__((noreturn)) die(char * str, ...) { va_list ap; diff --git a/flattree.c b/flattree.c index 5b15e9c..e857b08 100644 --- a/flattree.c +++ b/flattree.c @@ -909,6 +909,7 @@ struct boot_info *dt_from_blob(FILE *f) fprintf(stderr, "\tboot_cpuid_phys:\t0x%x\n", be32_to_cpu(bph->boot_cpuid_phys)); + size_str = -1; if (version >= 3) { size_str = be32_to_cpu(bph->size_dt_strings); fprintf(stderr, "\tsize_dt_strings:\t%d\n", size_str); @@ -932,10 +933,10 @@ struct boot_info *dt_from_blob(FILE *f) inbuf_init(&memresvbuf, blob + off_mem_rsvmap, blob + totalsize); inbuf_init(&dtbuf, blob + off_dt, blob + totalsize); - inbuf_init(&strbuf, blob + off_str, blob + totalsize); - - if (version >= 3) - strbuf.limit = strbuf.base + size_str; + if (size_str >= 0) + inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str); + else + inbuf_init(&strbuf, blob + off_str, blob + totalsize); reservelist = flat_read_mem_reserve(&memresvbuf); diff --git a/tests/truncated_property.c b/tests/truncated_property.c index 5642d8d..56daa22 100644 --- a/tests/truncated_property.c +++ b/tests/truncated_property.c @@ -33,7 +33,6 @@ int main(int argc, char *argv[]) { void *fdt = &_truncated_property; const void *prop; - int err; int len; test_init(argc, argv); @@ -43,7 +42,7 @@ int main(int argc, char *argv[]) FAIL("fdt_getprop() succeeded on truncated property"); if (len != -FDT_ERR_BADSTRUCTURE) FAIL("fdt_getprop() failed with \"%s\" instead of \"%s\"", - fdt_strerror(err), fdt_strerror(-FDT_ERR_BADSTRUCTURE)); + fdt_strerror(len), fdt_strerror(-FDT_ERR_BADSTRUCTURE)); PASS(); } From 592ea5888c27b154e6dc4b9b3ed98978369271c8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 4 Sep 2007 10:43:03 +1000 Subject: [PATCH 0097/1198] dtc: Assume properties preced subnodes in the flattened tree With kernel commit eff2ebd207af9f501af0ef667a7d14befcb36c1b, we clarified that in the flattened tree format, a particular nodes properties are required to precede its subdnodes. At present however, both dtc and libfdt will process trees which don't meet this condition. This patch simplifies the code for fdt_get_property() based on assuming that constraint. dtc continues to be able to handle such an invalid tree - on the grounds that it's useful for dtc to be able to correct such a broken tree - but this patch adds a warning when this condition is not met while reading a flattened tree. Signed-off-by: David Gibson --- flattree.c | 3 +++ libfdt/fdt_ro.c | 14 ++------------ 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/flattree.c b/flattree.c index e857b08..d7dc6b0 100644 --- a/flattree.c +++ b/flattree.c @@ -779,6 +779,9 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, val = flat_read_word(dtbuf); switch (val) { case OF_DT_PROP: + if (node->children) + fprintf(stderr, "Warning: Flat tree input has " + "subnodes preceding a property.\n"); prop = flat_read_property(dtbuf, strbuf, flags); add_property(node, prop); break; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 65bd1a2..6e4d3c8 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -197,7 +197,6 @@ const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, const char *name, int *lenp) { - int level = 0; uint32_t tag; const struct fdt_property *prop; int namestroff; @@ -225,17 +224,11 @@ const struct fdt_property *fdt_get_property(const void *fdt, goto fail; case FDT_BEGIN_NODE: - level++; - break; - case FDT_END_NODE: - level--; + case FDT_NOP: break; case FDT_PROP: - if (level != 0) - continue; - err = -FDT_ERR_BADSTRUCTURE; prop = fdt_offset_ptr_typed(fdt, offset, prop); if (! prop) @@ -256,14 +249,11 @@ const struct fdt_property *fdt_get_property(const void *fdt, } break; - case FDT_NOP: - break; - default: err = -FDT_ERR_BADSTRUCTURE; goto fail; } - } while (level >= 0); + } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE)); err = -FDT_ERR_NOTFOUND; fail: From ae1454b3111e4653895dbba18d594bd78c91d086 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 17 Sep 2007 14:28:34 +1000 Subject: [PATCH 0098/1198] libfdt: Add fdt_node_offset_by_prop_value() This patch adds a function to libfdt to locate nodes containing a property with a specific value. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 51 ++++++++++++++ libfdt/libfdt.h | 4 ++ tests/Makefile.tests | 1 + tests/node_offset_by_prop_value.c | 110 ++++++++++++++++++++++++++++++ tests/run_tests.sh | 1 + 5 files changed, 167 insertions(+) create mode 100644 tests/node_offset_by_prop_value.c diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 6e4d3c8..0ee3f57 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -407,3 +407,54 @@ int fdt_parent_offset(const void *fdt, int nodeoffset) return fdt_supernode_atdepth_offset(fdt, nodeoffset, nodedepth - 1, NULL); } + +int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, + const char *propname, + const void *propval, int proplen) +{ + uint32_t tag; + int offset, nextoffset; + const void *val; + int len; + + CHECK_HEADER(fdt); + + if (startoffset >= 0) { + tag = _fdt_next_tag(fdt, startoffset, &nextoffset); + if (tag != FDT_BEGIN_NODE) + return -FDT_ERR_BADOFFSET; + } else { + nextoffset = 0; + } + + /* FIXME: The algorithm here is pretty horrible: we scan each + * property of a node in fdt_getprop(), then if that didn't + * find what we want, we scan over them again making our way + * to the next node. Still it's the easiest to implement + * approach; performance can come later. */ + do { + offset = nextoffset; + tag = _fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_BEGIN_NODE: + val = fdt_getprop(fdt, offset, propname, &len); + if (val + && (len == proplen) + && (memcmp(val, propval, len) == 0)) + return offset; + break; + + case FDT_PROP: + case FDT_END: + case FDT_END_NODE: + case FDT_NOP: + break; + + default: + return -FDT_ERR_BADSTRUCTURE; + } + } while (tag != FDT_END); + + return -FDT_ERR_NOTFOUND; +} diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index a9acd5d..c059bdc 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -146,6 +146,10 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int fdt_node_depth(const void *fdt, int nodeoffset); int fdt_parent_offset(const void *fdt, int nodeoffset); +int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, + const char *propname, + const void *propval, int proplen); + /* Write-in-place functions */ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len); diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 6552869..e865daf 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -1,5 +1,6 @@ LIB_TESTS_L = root_node find_property subnode_offset path_offset \ get_name getprop get_path supernode_atdepth_offset parent_offset \ + node_offset_by_prop_value \ notfound \ setprop_inplace nop_property nop_node \ sw_tree1 \ diff --git a/tests/node_offset_by_prop_value.c b/tests/node_offset_by_prop_value.c new file mode 100644 index 0000000..b56cdf5 --- /dev/null +++ b/tests/node_offset_by_prop_value.c @@ -0,0 +1,110 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_path_offset() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void vcheck_search(void *fdt, const char *propname, const void *propval, + int proplen, va_list ap) +{ + int offset = -1, target; + + do { + target = va_arg(ap, int); + verbose_printf("Searching (target = %d): %d ->", + target, offset); + offset = fdt_node_offset_by_prop_value(fdt, offset, propname, + propval, proplen); + verbose_printf("%d\n", offset); + + if (offset != target) + FAIL("fdt_node_offset_by_prop_value() returns %d " + "instead of %d", offset, target); + } while (target >= 0); +} + +void check_search(void *fdt, const char *propname, const void *propval, + int proplen, ...) +{ + va_list ap; + + va_start(ap, proplen); + vcheck_search(fdt, propname, propval, proplen, ap); + va_end(ap); +} + +void check_search_str(void *fdt, const char *propname, const char *propval, ...) +{ + va_list ap; + + va_start(ap, propval); + vcheck_search(fdt, propname, propval, strlen(propval)+1, ap); + va_end(ap); +} + +#define check_search_val(fdt, propname, propval, ...) \ + { \ + typeof(propval) val = (propval); \ + check_search((fdt), (propname), &val, sizeof(val), \ + ##__VA_ARGS__); \ + } + +int main(int argc, char *argv[]) +{ + void *fdt; + int subnode1_offset, subnode2_offset; + int subsubnode1_offset, subsubnode2_offset; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + subnode1_offset = fdt_path_offset(fdt, "/subnode1"); + subnode2_offset = fdt_path_offset(fdt, "/subnode2"); + subsubnode1_offset = fdt_path_offset(fdt, "/subnode1/subsubnode"); + subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + + if ((subnode1_offset < 0) || (subnode2_offset < 0) + || (subsubnode1_offset < 0) || (subsubnode2_offset < 0)) + FAIL("Can't find required nodes"); + + check_search_val(fdt, "prop-int", TEST_VALUE_1, 0, subnode1_offset, + subsubnode1_offset, -FDT_ERR_NOTFOUND); + + check_search_val(fdt, "prop-int", TEST_VALUE_2, subnode2_offset, + subsubnode2_offset, -FDT_ERR_NOTFOUND); + + check_search_str(fdt, "prop-str", TEST_STRING_1, 0, -FDT_ERR_NOTFOUND); + + check_search_str(fdt, "prop-str", "no such string", -FDT_ERR_NOTFOUND); + + check_search_val(fdt, "prop-int", TEST_VALUE_1+1, -FDT_ERR_NOTFOUND); + + check_search(fdt, "no-such-prop", NULL, 0, -FDT_ERR_NOTFOUND); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index b7cad42..d47677d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -40,6 +40,7 @@ tree1_tests () { run_test get_path $TREE run_test supernode_atdepth_offset $TREE run_test parent_offset $TREE + run_test node_offset_by_prop_value $TREE run_test notfound $TREE # Write-in-place tests From 874ff219afd310902707bf7d2362af7285ba559e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 17 Sep 2007 15:42:36 +1000 Subject: [PATCH 0099/1198] libfdt: Consistently use big-endian property data in testcases Flat device trees always have integers in their structure stored as big-endian. From this point of view, property values are bags-of-bytes and any endianness is up to users of the device tree to determine. The libfdt testcases which use properties with integer values, currently use native endian format for the architecture on which the testcases are run. This works ok for now, since both the creation and checking of the example device trees happen in the same endianness. This will become a problem, however, for tests of dtc which we want to add in the nearish future. dtc always uses big-endian format for 'cell' format data in properties; as it needs to in order to produce powerpc-usable device trees when hosted on a little-endian architecture. This patch, therefore, changes the libfdt testsuite to use big-endian format always for integer format data, in order to interoperate sanely with future dtc testcases. This also means that the example trees created by the testsuite should now be byte-for-byte identical regardless of dtc and libfdt's host platform, which is arguably an advantage. Signed-off-by: David Gibson --- tests/testdata.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/testdata.h b/tests/testdata.h index 822c69a..15a4a35 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -1,5 +1,16 @@ -#define TEST_VALUE_1 0xdeadbeef -#define TEST_VALUE_2 0xabcd1234 +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +#define cell_to_fdt(x) (x) +#else +/* We do this as a big hairy expression instead of using bswap_32() + * because we need it to work in asm as well as C. */ +#define cell_to_fdt(x) ((((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) \ + | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000)) +#endif + +#define TEST_VALUE_1 cell_to_fdt(0xdeadbeef) +#define TEST_VALUE_2 cell_to_fdt(0xabcd1234) #define TEST_STRING_1 "hello world" From ef90baa0c6405fe6d9400d2f091576ac0df87155 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 17 Sep 2007 14:39:24 +1000 Subject: [PATCH 0100/1198] dtc: Cleanup testsuite organization run_tests.sh from the dtc testsuite currently has a facility ro run just "functional" or just "stress" tests. This distinction is carried over from libhugetlbfs where the test framework originated, and where it made sense. In dtc, we have no stress tests, so running these subsections isn't particularly interesting. This patch removes these test subsets, instead defining a single "libfdt" test subset for testcases related to libfdt (and not dtc proper only. Currently that's all of the testcases, but with any luck we'll have some dtc testcases in the future. Signed-off-by: David Gibson --- tests/Makefile.tests | 12 ------------ tests/run_tests.sh | 15 ++++----------- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index e865daf..cc034bb 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -49,18 +49,6 @@ check: tests checkv: tests cd $(TESTS_PREFIX); ./run_tests.sh -v -func: tests - cd $(TESTS_PREFIX); ./run_tests.sh -t func - -funcv: tests - cd $(TESTS_PREFIX); ./run_tests.sh -t func -v - -stress: tests - cd $(TESTS_PREFIX); ./run_tests.sh -t stress - -stressv: tests - cd $(TESTS_PREFIX); ./run_tests.sh -t stress -v - ifneq ($(DEPTARGETS),) -include $(TESTS_DEPFILES) endif diff --git a/tests/run_tests.sh b/tests/run_tests.sh index d47677d..3973730 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -49,7 +49,7 @@ tree1_tests () { run_test nop_node $TREE } -functional_tests () { +libfdt_tests () { # Make sure we don't have stale blobs lying around rm -f *.test.dtb @@ -86,10 +86,6 @@ functional_tests () { run_test truncated_property } -stress_tests () { - ITERATIONS=10 # Number of iterations for looping tests -} - while getopts "vdt:" ARG ; do case $ARG in "v") @@ -102,16 +98,13 @@ while getopts "vdt:" ARG ; do done if [ -z "$TESTSETS" ]; then - TESTSETS="func stress" + TESTSETS="libfdt" fi for set in $TESTSETS; do case $set in - "func") - functional_tests - ;; - "stress") - stress_tests + "libfdt") + libfdt_tests ;; esac done From 8d59bd3b17ba04dc9bc906742ebe74e69fb0d1ad Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 18 Sep 2007 10:33:40 +1000 Subject: [PATCH 0101/1198] dtc: Add basic testcases for dtc This patch adds a handful of simple testcases for dtc. It adds a dts file which should generate the same sample tree as is used for the libfdt testcases, and tests invoking dtc on this dts, plus the standard batch of libfdt cases on the resulting dtb, which effectively checks that the dtb is correct. Because the test framework assumes each testcase is an executable with the right output conventions, we use a little shell script, dtc.sh, as a wrapper around dtc itself. It simply invokes dtc and returns a PASS or FAIL depending on whether dtc returned an error. It's not much, but it's a start. Signed-off-by: David Gibson --- tests/Makefile.tests | 4 ++-- tests/dtc.sh | 28 ++++++++++++++++++++++++++++ tests/run_tests.sh | 13 ++++++++++++- tests/test_tree1.dts | 20 ++++++++++++++++++++ 4 files changed, 62 insertions(+), 3 deletions(-) create mode 100755 tests/dtc.sh create mode 100644 tests/test_tree1.dts diff --git a/tests/Makefile.tests b/tests/Makefile.tests index cc034bb..e97e903 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -43,10 +43,10 @@ tests_clean: rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%) rm -f $(TESTS_CLEANFILES) -check: tests +check: tests dtc cd $(TESTS_PREFIX); ./run_tests.sh -checkv: tests +checkv: tests dtc cd $(TESTS_PREFIX); ./run_tests.sh -v ifneq ($(DEPTARGETS),) diff --git a/tests/dtc.sh b/tests/dtc.sh new file mode 100755 index 0000000..f704f55 --- /dev/null +++ b/tests/dtc.sh @@ -0,0 +1,28 @@ +#! /bin/sh + +PASS () { + echo "PASS" + exit 0 +} + +FAIL () { + echo "FAIL" "$@" + exit 2 +} + +DTC=../dtc + +verbose_run () { + if [ -z "$QUIET_TEST" ]; then + "$@" + else + "$@" > /dev/null 2> /dev/null + fi +} + +if verbose_run "$DTC" "$@"; then + PASS +else + ret="$?" + FAIL "dtc returned error code $ret" +fi diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 3973730..3c64e9d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -86,6 +86,14 @@ libfdt_tests () { run_test truncated_property } +dtc_tests () { + # Make sure we don't have stale blobs lying around + rm -f *.test.dtb + + run_test dtc.sh -f -I dts -O dtb -o dtc_tree1.test.dtb test_tree1.dts + tree1_tests dtc_tree1.test.dtb +} + while getopts "vdt:" ARG ; do case $ARG in "v") @@ -98,7 +106,7 @@ while getopts "vdt:" ARG ; do done if [ -z "$TESTSETS" ]; then - TESTSETS="libfdt" + TESTSETS="libfdt dtc" fi for set in $TESTSETS; do @@ -106,6 +114,9 @@ for set in $TESTSETS; do "libfdt") libfdt_tests ;; + "dtc") + dtc_tests + ;; esac done diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts new file mode 100644 index 0000000..5ddc208 --- /dev/null +++ b/tests/test_tree1.dts @@ -0,0 +1,20 @@ +/ { + prop-int = ; + prop-str = "hello world"; + + subnode1 { + prop-int = ; + + subsubnode { + prop-int = ; + }; + }; + + subnode2 { + prop-int = ; + + subsubnode { + prop-int = ; + }; + }; +}; From 63dc9c7113cd0fff60d04b05cd8053e70279f9d4 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 18 Sep 2007 11:44:04 +1000 Subject: [PATCH 0102/1198] dtc: Whitespace cleanup This large patch removes all trailing whitespace from dtc (including libfdt, the testsuite and documentation). It also removes a handful of redundant blank lines (at the end of functions, or when there are two blank lines together for no particular reason). As well as anything else, this means that quilt won't whinge when I go to convert the whole of libfdt into a patch to apply to the kernel. Signed-off-by: David Gibson --- Documentation/dtc-paper.tex | 2 +- Documentation/manual.txt | 2 +- Makefile | 2 +- data.c | 16 ++++++++-------- dtc-lexer.l | 12 ++++++------ dtc-parser.y | 12 ++++++------ dtc.c | 14 +++++++------- dtc.h | 12 ++++++------ flattree.c | 26 +++++++++++++------------- fstree.c | 14 +++++++------- ftdump.c | 2 +- libfdt/fdt_ro.c | 4 ++-- livetree.c | 27 +++++++++++++-------------- tests/nop_property.c | 2 +- tests/notfound.c | 2 +- tests/root_node.c | 2 +- tests/setprop.c | 2 +- tests/setprop_inplace.c | 4 ++-- tests/testutils.c | 1 - tests/trees.S | 6 +++--- treesource.c | 13 ++++++------- 21 files changed, 87 insertions(+), 90 deletions(-) diff --git a/Documentation/dtc-paper.tex b/Documentation/dtc-paper.tex index 91c4a49..4494226 100644 --- a/Documentation/dtc-paper.tex +++ b/Documentation/dtc-paper.tex @@ -193,7 +193,7 @@ particular, the following properties are desirable: \vdots & \multicolumn{1}{c|}{\vdots} & \\\cline{2-2} & \texttt{\dtendnode} \\\cline{2-2} & \texttt{\dtend} \\\cline{2-2} - \multicolumn{1}{r}{\vdots} & \multicolumn{1}{c}{\vdots} & \\\cline{2-2} + \multicolumn{1}{r}{\vdots} & \multicolumn{1}{c}{\vdots} & \\\cline{2-2} \multicolumn{1}{r}{\emph{totalsize}} \\ \end{tabular} \caption{Device tree blob layout} diff --git a/Documentation/manual.txt b/Documentation/manual.txt index 1f720e9..b957662 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -140,7 +140,7 @@ Here is a very rough overview of the layout of a DTS source file: memreserve: label 'memreserve' ADDR ADDR ';' | label 'memreserve' ADDR '-' ADDR ';' - + devicetree: '/' nodedef nodedef: '{' list_of_property list_of_subnode '}' ';' diff --git a/Makefile b/Makefile index 27e1499..e1f8987 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ PATCHLEVEL = 0 SUBLEVEL = 0 EXTRAVERSION = LOCAL_VERSION = -CONFIG_LOCALVERSION = +CONFIG_LOCALVERSION = DTC_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) VERSION_FILE = version_gen.h diff --git a/data.c b/data.c index f42ad58..2602249 100644 --- a/data.c +++ b/data.c @@ -1,7 +1,7 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the @@ -11,11 +11,11 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include "dtc.h" @@ -106,7 +106,7 @@ static char get_oct_char(char *s, int *i) val = strtol(x, &endx, 8); if ((endx - x) == 0) fprintf(stderr, "Empty \\nnn escape\n"); - + (*i) += endx - x; return val; } @@ -125,7 +125,7 @@ static char get_hex_char(char *s, int *i) val = strtol(x, &endx, 16); if ((endx - x) == 0) fprintf(stderr, "Empty \\x escape\n"); - + (*i) += endx - x; return val; } diff --git a/dtc-lexer.l b/dtc-lexer.l index 384f848..08ed106 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -1,7 +1,7 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the @@ -11,11 +11,11 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ %option noyywrap nounput yylineno diff --git a/dtc-parser.y b/dtc-parser.y index 19bc58e..54fd787 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -1,7 +1,7 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the @@ -11,11 +11,11 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ %glr-parser diff --git a/dtc.c b/dtc.c index 8f5fe2f..92a338f 100644 --- a/dtc.c +++ b/dtc.c @@ -1,7 +1,7 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the @@ -11,11 +11,11 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include "dtc.h" @@ -218,6 +218,6 @@ int main(int argc, char *argv[]) } else { die("Unknown output format \"%s\"\n", outform); } - + exit(0); } diff --git a/dtc.h b/dtc.h index 458403a..213e553 100644 --- a/dtc.h +++ b/dtc.h @@ -4,7 +4,7 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the @@ -14,11 +14,11 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include diff --git a/flattree.c b/flattree.c index d7dc6b0..664548d 100644 --- a/flattree.c +++ b/flattree.c @@ -1,7 +1,7 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the @@ -11,11 +11,11 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include "dtc.h" @@ -111,7 +111,7 @@ static struct emitter bin_emitter = { .data = bin_emit_data, .beginnode = bin_emit_beginnode, .endnode = bin_emit_endnode, - .property = bin_emit_property, + .property = bin_emit_property, }; static void emit_label(FILE *f, char *prefix, char *label) @@ -144,7 +144,7 @@ static void asm_emit_string(void *e, char *str, int len) c = str[len]; str[len] = '\0'; } - + fprintf(f, "\t.string\t\"%s\"\n", str); if (len != 0) { @@ -178,7 +178,7 @@ static void asm_emit_data(void *e, struct data d) } if ((d.len - off) >= sizeof(u16)) { - fprintf(f, "\t.short\t0x%hx\n", + fprintf(f, "\t.short\t0x%hx\n", be16_to_cpu(*((u16 *)(d.val+off)))); off += sizeof(u16); } @@ -231,7 +231,7 @@ static struct emitter asm_emitter = { .data = asm_emit_data, .beginnode = asm_emit_beginnode, .endnode = asm_emit_endnode, - .property = asm_emit_property, + .property = asm_emit_property, }; static int stringtable_insert(struct data *d, char *str) @@ -717,7 +717,7 @@ static char *nodename_from_path(char *ppath, char *cpath) if (! strneq(ppath, cpath, plen)) return NULL; - + return strdup(lslash+1); } @@ -766,7 +766,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, node->name = flat_read_string(dtbuf); node->fullpath = join_path(parent_path, node->name); } - + node->basenamelen = check_node_name(node->name); if (node->basenamelen < 0) { fprintf(stderr, "Warning \"%s\" has incorrect format\n", node->name); @@ -926,7 +926,7 @@ struct boot_info *dt_from_blob(FILE *f) if (off_dt+size_dt > totalsize) die("Structure block extends past total size\n"); } - + if (version < 16) { flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN; } else { diff --git a/fstree.c b/fstree.c index a5bf9d3..28fd94c 100644 --- a/fstree.c +++ b/fstree.c @@ -1,7 +1,7 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the @@ -11,11 +11,11 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include "dtc.h" @@ -44,7 +44,7 @@ static struct node *read_fstree(char *dirname) continue; tmpnam = join_path(dirname, de->d_name); - + if (lstat(tmpnam, &st) < 0) die("stat(%s): %s\n", tmpnam, strerror(errno)); diff --git a/ftdump.c b/ftdump.c index 55209b6..4792ecd 100644 --- a/ftdump.c +++ b/ftdump.c @@ -81,7 +81,7 @@ static void print_data(const void *data, int len) static void dump_blob(void *blob) { struct boot_param_header *bph = blob; - struct reserve_entry *p_rsvmap = + struct reserve_entry *p_rsvmap = (struct reserve_entry *)(blob + be32_to_cpu(bph->off_mem_rsvmap)); char *p_struct = blob + be32_to_cpu(bph->off_dt_struct); diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 0ee3f57..f358a20 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -166,7 +166,7 @@ int fdt_path_offset(const void *fdt, const char *path) p = q; } - return offset; + return offset; } const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) @@ -244,7 +244,7 @@ const struct fdt_property *fdt_get_property(const void *fdt, if (lenp) *lenp = len; - + return prop; } break; diff --git a/livetree.c b/livetree.c index ce73f50..3b6542f 100644 --- a/livetree.c +++ b/livetree.c @@ -1,7 +1,7 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the @@ -11,11 +11,11 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include "dtc.h" @@ -41,9 +41,9 @@ struct property *build_property(char *name, struct data val, char *label) struct property *chain_property(struct property *first, struct property *list) { assert(first->next == NULL); - + first->next = list; - return first; + return first; } struct node *build_node(struct property *proplist, struct node *children) @@ -232,7 +232,7 @@ static struct node *get_node_by_label(struct node *tree, const char *label) static struct node *get_node_by_phandle(struct node *tree, cell_t phandle) { - struct node *child, *node; + struct node *child, *node; assert((phandle != 0) && (phandle != -1)); @@ -333,13 +333,12 @@ static int check_properties(struct node *node) prop->name, node->fullpath); } } - /* check name length */ if (strlen(prop->name) > MAX_PROPNAME_LEN) WARNMSG("Property name %s is too long in %s\n", prop->name, node->fullpath); - + /* check this property */ for (i = 0; i < ARRAY_SIZE(prop_checker_table); i++) { if (streq(prop->name, prop_checker_table[i].propname)) @@ -426,7 +425,7 @@ static int check_structure(struct node *tree) (node)->fullpath, (propname), \ prop->val.val, (value)); \ } while (0) - + #define CHECK_HAVE_ONECELL(node, propname) \ do { \ CHECK_HAVE((node), (propname)); \ @@ -553,7 +552,7 @@ static int check_cpus(struct node *root, int outversion, int boot_cpuid_phys) WARNMSG("physical boot CPU not set. Use -b option to set\n"); } - return ok; + return ok; } static int check_memory(struct node *root) @@ -578,7 +577,7 @@ static int check_memory(struct node *root) return 0; } - return ok; + return ok; } static int check_chosen(struct node *root) diff --git a/tests/nop_property.c b/tests/nop_property.c index 56256c4..02371ac 100644 --- a/tests/nop_property.c +++ b/tests/nop_property.c @@ -53,7 +53,7 @@ int main(int argc, char *argv[]) FAIL("prop-int still present after nopping"); if (lenerr != -FDT_ERR_NOTFOUND) FAIL("Unexpected error on second getprop: %s", fdt_strerror(err)); - + strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1); verbose_printf("string value was \"%s\"\n", strp); diff --git a/tests/notfound.c b/tests/notfound.c index a93b605..e8d0582 100644 --- a/tests/notfound.c +++ b/tests/notfound.c @@ -68,6 +68,6 @@ int main(int argc, char *argv[]) offset = fdt_path_offset(fdt, "/nonexistant-subnode"); check_error("fdt_path_offset(\"/nonexistant-subnode\")", offset); - + PASS(); } diff --git a/tests/root_node.c b/tests/root_node.c index 6e2c391..fa2dc90 100644 --- a/tests/root_node.c +++ b/tests/root_node.c @@ -36,7 +36,7 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); - + nh = fdt_offset_ptr_typed(fdt, 0, nh); if (! nh) diff --git a/tests/setprop.c b/tests/setprop.c index 7f9be3e..d771954 100644 --- a/tests/setprop.c +++ b/tests/setprop.c @@ -62,7 +62,7 @@ int main(int argc, char *argv[]) strp = check_getprop_string(fdt, 0, "prop-int", NEW_STRING); verbose_printf("New value is \"%s\"\n", strp); - + strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1); diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c index 59c1209..590dfeb 100644 --- a/tests/setprop_inplace.c +++ b/tests/setprop_inplace.c @@ -51,7 +51,7 @@ int main(int argc, char *argv[]) ~TEST_VALUE_1, fdt_strerror(err)); intp = check_getprop_typed(fdt, 0, "prop-int", ~TEST_VALUE_1); verbose_printf("New int value is 0x%08x\n", *intp); - + strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1); @@ -66,7 +66,7 @@ int main(int argc, char *argv[]) xstr, fdt_strerror(err)); strp = check_getprop(fdt, 0, "prop-str", xlen+1, xstr); - verbose_printf("New string value is \"%s\"\n", strp); + verbose_printf("New string value is \"%s\"\n", strp); PASS(); } diff --git a/tests/testutils.c b/tests/testutils.c index fcb1c88..82aebc5 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -104,7 +104,6 @@ void check_property(void *fdt, int nodeoffset, const char *name, name, proplen, len); if (memcmp(val, prop->data, len) != 0) FAIL("Data mismatch on property \"%s\"", name); - } const void *check_getprop(void *fdt, int nodeoffset, const char *name, diff --git a/tests/trees.S b/tests/trees.S index 6057668..60e1b55 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -65,7 +65,7 @@ tree: \ #define STRING(tree, name, str) \ tree##_##name: \ .string str - + .data TREE_HDR(test_tree1) @@ -77,7 +77,7 @@ test_tree1_struct: BEGIN_NODE("") PROP_INT(test_tree1, prop_int, TEST_VALUE_1) PROP_STR(test_tree1, prop_str, TEST_STRING_1) - + BEGIN_NODE("subnode1") PROP_INT(test_tree1, prop_int, TEST_VALUE_1) @@ -110,7 +110,7 @@ truncated_property_struct: BEGIN_NODE("") PROPHDR(truncated_property, prop_truncated, 4) /* Oops, no actual property data here */ - + truncated_property_strings: STRING(truncated_property, prop_truncated, "truncated") truncated_property_end: diff --git a/treesource.c b/treesource.c index c067b20..a04c173 100644 --- a/treesource.c +++ b/treesource.c @@ -1,7 +1,7 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the @@ -11,11 +11,11 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include "dtc.h" @@ -77,7 +77,6 @@ static enum proptype guess_type(struct property *prop) return PROP_CELLS; else return PROP_BYTES; - } From fb7c7acf5a4187ea810043ae17854625a313b725 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 26 Sep 2007 13:11:05 +1000 Subject: [PATCH 0103/1198] dtc: Use libfdt/fdt.h instead of flat_dt.h In the dtc tree, both flat_dt.h and libfdt/fdt.h have structures and constants relating to the flattened device tree format derived from asm-powerpc/prom.h in the kernel. The former is used in dtc, the latter in libfdt. libfdt/fdt.h is the more recent, revised version, so use that throughout, removing flat_dt.h. Signed-off-by: David Gibson --- data.c | 4 +- dtc.c | 4 +- dtc.h | 7 +-- flat_dt.h | 51 ------------------- flattree.c | 143 ++++++++++++++++++++++++++--------------------------- ftdump.c | 20 ++++---- 6 files changed, 89 insertions(+), 140 deletions(-) delete mode 100644 flat_dt.h diff --git a/data.c b/data.c index 2602249..1836f08 100644 --- a/data.c +++ b/data.c @@ -246,9 +246,9 @@ struct data data_append_cell(struct data d, cell_t word) return data_append_data(d, &beword, sizeof(beword)); } -struct data data_append_re(struct data d, struct reserve_entry *re) +struct data data_append_re(struct data d, struct fdt_reserve_entry *re) { - struct reserve_entry bere; + struct fdt_reserve_entry bere; bere.address = cpu_to_be64(re->address); bere.size = cpu_to_be64(re->size); diff --git a/dtc.c b/dtc.c index 92a338f..76a6dfe 100644 --- a/dtc.c +++ b/dtc.c @@ -92,7 +92,7 @@ static void __attribute__ ((noreturn)) usage(void) fprintf(stderr, "\t\t\tdtb - device tree blob\n"); fprintf(stderr, "\t\t\tasm - assembler source\n"); fprintf(stderr, "\t-V \n"); - fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", OF_DEFAULT_VERSION); + fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION); fprintf(stderr, "\t-R \n"); fprintf(stderr, "\t\tMake space for reserve map entries (relevant for \n\t\tdtb and asm output only)\n"); fprintf(stderr, "\t-S \n"); @@ -117,7 +117,7 @@ int main(int argc, char *argv[]) int opt; FILE *inf = NULL; FILE *outf = NULL; - int outversion = OF_DEFAULT_VERSION; + int outversion = DEFAULT_FDT_VERSION; int boot_cpuid_phys = 0xfeedbeef; quiet = 0; diff --git a/dtc.h b/dtc.h index 213e553..09dec54 100644 --- a/dtc.h +++ b/dtc.h @@ -34,8 +34,9 @@ #include #include -#include "flat_dt.h" +#include +#define DEFAULT_FDT_VERSION 17 /* * Command line options */ @@ -128,7 +129,7 @@ struct data data_copy_file(FILE *f, size_t len); struct data data_append_data(struct data d, void *p, int len); struct data data_merge(struct data d1, struct data d2); struct data data_append_cell(struct data d, cell_t word); -struct data data_append_re(struct data d, struct reserve_entry *re); +struct data data_append_re(struct data d, struct fdt_reserve_entry *re); struct data data_append_addr(struct data d, u64 addr); struct data data_append_byte(struct data d, uint8_t byte); struct data data_append_zeroes(struct data d, int len); @@ -192,7 +193,7 @@ int check_device_tree(struct node *dt, int outversion, int boot_cpuid_phys); /* Boot info (tree plus memreserve information */ struct reserve_info { - struct reserve_entry re; + struct fdt_reserve_entry re; struct reserve_info *next; diff --git a/flat_dt.h b/flat_dt.h deleted file mode 100644 index a8482b4..0000000 --- a/flat_dt.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _FLAT_DT_H_ -#define _FLAT_DT_H_ - - -#define OF_DEFAULT_VERSION 17 - -#define OF_DT_HEADER 0xd00dfeed /* 4: version, 4: total size */ - -#define OF_DT_BEGIN_NODE 0x1 /* Start node: full name */ -#define OF_DT_END_NODE 0x2 /* End node */ -#define OF_DT_PROP 0x3 /* Property: name off, - size, content */ -#define OF_DT_NOP 0x4 /* nop */ -#define OF_DT_END 0x9 - -struct boot_param_header { - uint32_t magic; /* magic word OF_DT_HEADER */ - uint32_t totalsize; /* total size of DT block */ - uint32_t off_dt_struct; /* offset to structure */ - uint32_t off_dt_strings; /* offset to strings */ - uint32_t off_mem_rsvmap; /* offset to memory reserve map */ - uint32_t version; /* format version */ - uint32_t last_comp_version; /* last compatible version */ - - /* version 2 fields below */ - uint32_t boot_cpuid_phys; /* Which physical CPU id we're - booting on */ - /* version 3 fields below */ - uint32_t size_dt_strings; /* size of the strings block */ - - /* version 17 fields below */ - uint32_t size_dt_struct; /* size of the DT structure block */ -}; - -#define BPH_V1_SIZE (7*sizeof(uint32_t)) -#define BPH_V2_SIZE (BPH_V1_SIZE + sizeof(uint32_t)) -#define BPH_V3_SIZE (BPH_V2_SIZE + sizeof(uint32_t)) -#define BPH_V17_SIZE (BPH_V3_SIZE + sizeof(uint32_t)) - -struct reserve_entry { - uint64_t address; - uint64_t size; -}; - -struct flat_dt_property { - uint32_t len; - uint32_t nameoff; - char data[0]; -}; - -#endif /* _FLAT_DT_H_ */ diff --git a/flattree.c b/flattree.c index 664548d..a26e71b 100644 --- a/flattree.c +++ b/flattree.c @@ -19,7 +19,6 @@ */ #include "dtc.h" -#include "flat_dt.h" #define FTF_FULLPATH 0x1 #define FTF_VARALIGN 0x2 @@ -35,15 +34,15 @@ static struct version_info { int hdr_size; int flags; } version_table[] = { - {1, 1, BPH_V1_SIZE, + {1, 1, FDT_V1_SIZE, FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS}, - {2, 1, BPH_V2_SIZE, + {2, 1, FDT_V2_SIZE, FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID}, - {3, 1, BPH_V3_SIZE, + {3, 1, FDT_V3_SIZE, FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE}, - {16, 16, BPH_V3_SIZE, + {16, 16, FDT_V3_SIZE, FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_NOPS}, - {17, 16, BPH_V17_SIZE, + {17, 16, FDT_V17_SIZE, FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS}, }; @@ -91,17 +90,17 @@ static void bin_emit_data(void *e, struct data d) static void bin_emit_beginnode(void *e, char *label) { - bin_emit_cell(e, OF_DT_BEGIN_NODE); + bin_emit_cell(e, FDT_BEGIN_NODE); } static void bin_emit_endnode(void *e, char *label) { - bin_emit_cell(e, OF_DT_END_NODE); + bin_emit_cell(e, FDT_END_NODE); } static void bin_emit_property(void *e, char *label) { - bin_emit_cell(e, OF_DT_PROP); + bin_emit_cell(e, FDT_PROP); } static struct emitter bin_emitter = { @@ -199,14 +198,14 @@ static void asm_emit_beginnode(void *e, char *label) fprintf(f, "\t.globl\t%s\n", label); fprintf(f, "%s:\n", label); } - fprintf(f, "\t.long\tOF_DT_BEGIN_NODE\n"); + fprintf(f, "\t.long\tFDT_BEGIN_NODE\n"); } static void asm_emit_endnode(void *e, char *label) { FILE *f = e; - fprintf(f, "\t.long\tOF_DT_END_NODE\n"); + fprintf(f, "\t.long\tFDT_END_NODE\n"); if (label) { fprintf(f, "\t.globl\t%s_end\n", label); fprintf(f, "%s_end:\n", label); @@ -221,7 +220,7 @@ static void asm_emit_property(void *e, char *label) fprintf(f, "\t.globl\t%s\n", label); fprintf(f, "%s:\n", label); } - fprintf(f, "\t.long\tOF_DT_PROP\n"); + fprintf(f, "\t.long\tFDT_PROP\n"); } static struct emitter asm_emitter = { @@ -309,7 +308,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist, { struct reserve_info *re; struct data d = empty_data; - static struct reserve_entry null_re = {0,0}; + static struct fdt_reserve_entry null_re = {0,0}; int j; for (re = reservelist; re; re = re->next) { @@ -325,36 +324,36 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist, return d; } -static void make_bph(struct boot_param_header *bph, - struct version_info *vi, - int reservesize, int dtsize, int strsize, - int boot_cpuid_phys) +static void make_fdt_header(struct fdt_header *fdt, + struct version_info *vi, + int reservesize, int dtsize, int strsize, + int boot_cpuid_phys) { int reserve_off; - reservesize += sizeof(struct reserve_entry); + reservesize += sizeof(struct fdt_reserve_entry); - memset(bph, 0xff, sizeof(*bph)); + memset(fdt, 0xff, sizeof(*fdt)); - bph->magic = cpu_to_be32(OF_DT_HEADER); - bph->version = cpu_to_be32(vi->version); - bph->last_comp_version = cpu_to_be32(vi->last_comp_version); + fdt->magic = cpu_to_be32(FDT_MAGIC); + fdt->version = cpu_to_be32(vi->version); + fdt->last_comp_version = cpu_to_be32(vi->last_comp_version); /* Reserve map should be doubleword aligned */ reserve_off = ALIGN(vi->hdr_size, 8); - bph->off_mem_rsvmap = cpu_to_be32(reserve_off); - bph->off_dt_struct = cpu_to_be32(reserve_off + reservesize); - bph->off_dt_strings = cpu_to_be32(reserve_off + reservesize + fdt->off_mem_rsvmap = cpu_to_be32(reserve_off); + fdt->off_dt_struct = cpu_to_be32(reserve_off + reservesize); + fdt->off_dt_strings = cpu_to_be32(reserve_off + reservesize + dtsize); - bph->totalsize = cpu_to_be32(reserve_off + reservesize + dtsize + strsize); + fdt->totalsize = cpu_to_be32(reserve_off + reservesize + dtsize + strsize); if (vi->flags & FTF_BOOTCPUID) - bph->boot_cpuid_phys = cpu_to_be32(boot_cpuid_phys); + fdt->boot_cpuid_phys = cpu_to_be32(boot_cpuid_phys); if (vi->flags & FTF_STRTABSIZE) - bph->size_dt_strings = cpu_to_be32(strsize); + fdt->size_dt_strings = cpu_to_be32(strsize); if (vi->flags & FTF_STRUCTSIZE) - bph->size_dt_struct = cpu_to_be32(dtsize); + fdt->size_dt_struct = cpu_to_be32(dtsize); } void dt_to_blob(FILE *f, struct boot_info *bi, int version, @@ -366,7 +365,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, struct data reservebuf = empty_data; struct data dtbuf = empty_data; struct data strbuf = empty_data; - struct boot_param_header bph; + struct fdt_header fdt; int padlen; for (i = 0; i < ARRAY_SIZE(version_table); i++) { @@ -377,25 +376,25 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, die("Unknown device tree blob version %d\n", version); flatten_tree(bi->dt, &bin_emitter, &dtbuf, &strbuf, vi); - bin_emit_cell(&dtbuf, OF_DT_END); + bin_emit_cell(&dtbuf, FDT_END); reservebuf = flatten_reserve_list(bi->reservelist, vi); /* Make header */ - make_bph(&bph, vi, reservebuf.len, dtbuf.len, strbuf.len, - boot_cpuid_phys); + make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len, + boot_cpuid_phys); /* * If the user asked for more space than is used, adjust the totalsize. */ - padlen = minsize - be32_to_cpu(bph.totalsize); + padlen = minsize - be32_to_cpu(fdt.totalsize); if (padlen > 0) { - bph.totalsize = cpu_to_be32(minsize); + fdt.totalsize = cpu_to_be32(minsize); } else { if ((minsize > 0) && (quiet < 1)) fprintf(stderr, "Warning: blob size %d >= minimum size %d\n", - be32_to_cpu(bph.totalsize), minsize); + be32_to_cpu(fdt.totalsize), minsize); } /* @@ -403,10 +402,10 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, * the reserve buffer, add the reserve map terminating zeroes, * the device tree itself, and finally the strings. */ - blob = data_append_data(blob, &bph, sizeof(bph)); + blob = data_append_data(blob, &fdt, sizeof(fdt)); blob = data_append_align(blob, 8); blob = data_merge(blob, reservebuf); - blob = data_append_zeroes(blob, sizeof(struct reserve_entry)); + blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry)); blob = data_merge(blob, dtbuf); blob = data_merge(blob, strbuf); @@ -415,7 +414,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, */ if (padlen > 0) { blob = data_append_zeroes(blob, padlen); - bph.totalsize = cpu_to_be32(minsize); + fdt.totalsize = cpu_to_be32(minsize); } fwrite(blob.val, blob.len, 1, f); @@ -460,16 +459,16 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) die("Unknown device tree blob version %d\n", version); fprintf(f, "/* autogenerated by dtc, do not edit */\n\n"); - fprintf(f, "#define OF_DT_HEADER 0x%x\n", OF_DT_HEADER); - fprintf(f, "#define OF_DT_BEGIN_NODE 0x%x\n", OF_DT_BEGIN_NODE); - fprintf(f, "#define OF_DT_END_NODE 0x%x\n", OF_DT_END_NODE); - fprintf(f, "#define OF_DT_PROP 0x%x\n", OF_DT_PROP); - fprintf(f, "#define OF_DT_END 0x%x\n", OF_DT_END); + fprintf(f, "#define FDT_MAGIC 0x%x\n", FDT_MAGIC); + fprintf(f, "#define FDT_BEGIN_NODE 0x%x\n", FDT_BEGIN_NODE); + fprintf(f, "#define FDT_END_NODE 0x%x\n", FDT_END_NODE); + fprintf(f, "#define FDT_PROP 0x%x\n", FDT_PROP); + fprintf(f, "#define FDT_END 0x%x\n", FDT_END); fprintf(f, "\n"); emit_label(f, symprefix, "blob_start"); emit_label(f, symprefix, "header"); - fprintf(f, "\t.long\tOF_DT_HEADER\t\t\t\t/* magic */\n"); + fprintf(f, "\t.long\tFDT_MAGIC\t\t\t\t/* magic */\n"); fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start\t/* totalsize */\n", symprefix, symprefix); fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start\t/* off_dt_struct */\n", @@ -529,7 +528,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) emit_label(f, symprefix, "struct_start"); flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi); - fprintf(f, "\t.long\tOF_DT_END\n"); + fprintf(f, "\t.long\tFDT_END\n"); emit_label(f, symprefix, "struct_end"); emit_label(f, symprefix, "strings_start"); @@ -674,7 +673,7 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) struct reserve_info *reservelist = NULL; struct reserve_info *new; char *p; - struct reserve_entry re; + struct fdt_reserve_entry re; /* * Each entry is a pair of u64 (addr, size) values for 4 cell_t's. @@ -778,7 +777,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, val = flat_read_word(dtbuf); switch (val) { - case OF_DT_PROP: + case FDT_PROP: if (node->children) fprintf(stderr, "Warning: Flat tree input has " "subnodes preceding a property.\n"); @@ -786,20 +785,20 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, add_property(node, prop); break; - case OF_DT_BEGIN_NODE: + case FDT_BEGIN_NODE: child = unflatten_tree(dtbuf,strbuf, node->fullpath, flags); add_child(node, child); break; - case OF_DT_END_NODE: + case FDT_END_NODE: break; - case OF_DT_END: - die("Premature OF_DT_END in device tree blob\n"); + case FDT_END: + die("Premature FDT_END in device tree blob\n"); break; - case OF_DT_NOP: + case FDT_NOP: if (!(flags & FTF_NOPS)) fprintf(stderr, "Warning: NOP tag found in flat tree" " version <16\n"); @@ -811,7 +810,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, die("Invalid opcode word %08x in device tree blob\n", val); } - } while (val != OF_DT_END_NODE); + } while (val != FDT_END_NODE); return node; } @@ -823,7 +822,7 @@ struct boot_info *dt_from_blob(FILE *f) u32 off_dt, off_str, off_mem_rsvmap; int rc; char *blob; - struct boot_param_header *bph; + struct fdt_header *fdt; char *p; struct inbuf dtbuf, strbuf; struct inbuf memresvbuf; @@ -845,7 +844,7 @@ struct boot_info *dt_from_blob(FILE *f) } magic = be32_to_cpu(magic); - if (magic != OF_DT_HEADER) + if (magic != FDT_MAGIC) die("Blob has incorrect magic number\n"); rc = fread(&totalsize, sizeof(totalsize), 1, f); @@ -859,14 +858,14 @@ struct boot_info *dt_from_blob(FILE *f) } totalsize = be32_to_cpu(totalsize); - if (totalsize < BPH_V1_SIZE) + if (totalsize < FDT_V1_SIZE) die("DT blob size (%d) is too small\n", totalsize); blob = xmalloc(totalsize); - bph = (struct boot_param_header *)blob; - bph->magic = cpu_to_be32(magic); - bph->totalsize = cpu_to_be32(totalsize); + fdt = (struct fdt_header *)blob; + fdt->magic = cpu_to_be32(magic); + fdt->totalsize = cpu_to_be32(totalsize); sizeleft = totalsize - sizeof(magic) - sizeof(totalsize); p = blob + sizeof(magic) + sizeof(totalsize); @@ -885,10 +884,10 @@ struct boot_info *dt_from_blob(FILE *f) p += rc; } - off_dt = be32_to_cpu(bph->off_dt_struct); - off_str = be32_to_cpu(bph->off_dt_strings); - off_mem_rsvmap = be32_to_cpu(bph->off_mem_rsvmap); - version = be32_to_cpu(bph->version); + off_dt = be32_to_cpu(fdt->off_dt_struct); + off_str = be32_to_cpu(fdt->off_dt_strings); + off_mem_rsvmap = be32_to_cpu(fdt->off_mem_rsvmap); + version = be32_to_cpu(fdt->version); fprintf(stderr, "\tmagic:\t\t\t0x%x\n", magic); fprintf(stderr, "\ttotalsize:\t\t%d\n", totalsize); @@ -897,7 +896,7 @@ struct boot_info *dt_from_blob(FILE *f) fprintf(stderr, "\toff_mem_rsvmap:\t\t0x%x\n", off_mem_rsvmap); fprintf(stderr, "\tversion:\t\t0x%x\n", version ); fprintf(stderr, "\tlast_comp_version:\t0x%x\n", - be32_to_cpu(bph->last_comp_version)); + be32_to_cpu(fdt->last_comp_version)); if (off_mem_rsvmap >= totalsize) die("Mem Reserve structure offset exceeds total size\n"); @@ -910,18 +909,18 @@ struct boot_info *dt_from_blob(FILE *f) if (version >= 2) fprintf(stderr, "\tboot_cpuid_phys:\t0x%x\n", - be32_to_cpu(bph->boot_cpuid_phys)); + be32_to_cpu(fdt->boot_cpuid_phys)); size_str = -1; if (version >= 3) { - size_str = be32_to_cpu(bph->size_dt_strings); + size_str = be32_to_cpu(fdt->size_dt_strings); fprintf(stderr, "\tsize_dt_strings:\t%d\n", size_str); if (off_str+size_str > totalsize) die("String table extends past total size\n"); } if (version >= 17) { - size_dt = be32_to_cpu(bph->size_dt_struct); + size_dt = be32_to_cpu(fdt->size_dt_struct); fprintf(stderr, "\tsize_dt_struct:\t\t%d\n", size_dt); if (off_dt+size_dt > totalsize) die("Structure block extends past total size\n"); @@ -945,14 +944,14 @@ struct boot_info *dt_from_blob(FILE *f) val = flat_read_word(&dtbuf); - if (val != OF_DT_BEGIN_NODE) - die("Device tree blob doesn't begin with OF_DT_BEGIN_NODE (begins with 0x%08x)\n", val); + if (val != FDT_BEGIN_NODE) + die("Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%08x)\n", val); tree = unflatten_tree(&dtbuf, &strbuf, "", flags); val = flat_read_word(&dtbuf); - if (val != OF_DT_END) - die("Device tree blob doesn't end with OF_DT_END\n"); + if (val != FDT_END) + die("Device tree blob doesn't end with FDT_END\n"); free(blob); diff --git a/ftdump.c b/ftdump.c index 4792ecd..577c2cf 100644 --- a/ftdump.c +++ b/ftdump.c @@ -9,7 +9,7 @@ #include #include -#include "flat_dt.h" +#include #define cpu_to_be16(x) htons(x) #define be16_to_cpu(x) ntohs(x) @@ -80,10 +80,10 @@ static void print_data(const void *data, int len) static void dump_blob(void *blob) { - struct boot_param_header *bph = blob; - struct reserve_entry *p_rsvmap = - (struct reserve_entry *)(blob - + be32_to_cpu(bph->off_mem_rsvmap)); + struct fdt_header *bph = blob; + struct fdt_reserve_entry *p_rsvmap = + (struct fdt_reserve_entry *)(blob + + be32_to_cpu(bph->off_mem_rsvmap)); char *p_struct = blob + be32_to_cpu(bph->off_dt_struct); char *p_strings = blob + be32_to_cpu(bph->off_dt_strings); uint32_t version = be32_to_cpu(bph->version); @@ -109,11 +109,11 @@ static void dump_blob(void *blob) } p = p_struct; - while ((tag = be32_to_cpu(GET_CELL(p))) != OF_DT_END) { + while ((tag = be32_to_cpu(GET_CELL(p))) != FDT_END) { /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */ - if (tag == OF_DT_BEGIN_NODE) { + if (tag == FDT_BEGIN_NODE) { s = p; p = PALIGN(p + strlen(s) + 1, 4); @@ -126,19 +126,19 @@ static void dump_blob(void *blob) continue; } - if (tag == OF_DT_END_NODE) { + if (tag == FDT_END_NODE) { depth--; printf("%*s};\n", depth * shift, ""); continue; } - if (tag == OF_DT_NOP) { + if (tag == FDT_NOP) { printf("%*s// [NOP]\n", depth * shift, ""); continue; } - if (tag != OF_DT_PROP) { + if (tag != FDT_PROP) { fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag); break; } From 02a5556850bbb64a73cd45b2dbca6579880bb424 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 28 Sep 2007 14:57:01 +1000 Subject: [PATCH 0104/1198] libfdt: Test rw functions on more trees At present, the testcases for read/write functions (setprop, del_property and del_node) are only invoked on the single asm-generated tree, not on any of the other tree images which should be equivalent. The functions in question will (correctly) not work on the "unfinished" tree output from sw_tree1, but should work on most of the others. This patch extends the run_tests script to invoke the r/w testcases on more example trees. The testsuite still passes clean with this addition. Signed-off-by: David Gibson --- tests/run_tests.sh | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 3c64e9d..b51bd8f 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -49,6 +49,15 @@ tree1_tests () { run_test nop_node $TREE } +tree1_tests_rw () { + TREE=$1 + + # Read-write tests + run_test setprop $TREE + run_test del_property $TREE + run_test del_node $TREE +} + libfdt_tests () { # Make sure we don't have stale blobs lying around rm -f *.test.dtb @@ -76,11 +85,16 @@ libfdt_tests () { tree1_tests opened.$tree tree1_tests repacked.$tree done - run_test setprop test_tree1.dtb - run_test del_property test_tree1.dtb - run_test del_node test_tree1.dtb + + for tree in test_tree1.dtb sw_tree1.test.dtb; do + tree1_tests_rw $tree + tree1_tests_rw moved.$tree + tree1_tests_rw shunted.$tree + tree1_tests_rw deshunted.$tree + done run_test rw_tree1 tree1_tests rw_tree1.test.dtb + tree1_tests_rw rw_tree1.test.dtb # Tests for behaviour on various sorts of corrupted trees run_test truncated_property @@ -92,6 +106,7 @@ dtc_tests () { run_test dtc.sh -f -I dts -O dtb -o dtc_tree1.test.dtb test_tree1.dts tree1_tests dtc_tree1.test.dtb + tree1_tests_rw dtc_tree1.test.dtb } while getopts "vdt:" ARG ; do From d2a9da045897c37071597d9aa473964717b14735 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 28 Sep 2007 15:51:04 +1000 Subject: [PATCH 0105/1198] libfdt: Make unit address optional for finding nodes At present, the fdt_subnode_offset() and fdt_path_offset() functions in libfdt require the exact name of the nodes in question be passed, including unit address. This is contrary to traditional OF-like finddevice() behaviour, which allows the unit address to be omitted (which is useful when the device name is unambiguous without the address). This patch introduces similar behaviour to fdt_subnode_offset_namelen(), and hence to fdt_subnode_offset() and fdt_path_offset() which are implemented in terms of the former. The unit address can be omitted from the given node name. If this is ambiguous, the first such node in the flattened tree will be selected (this behaviour is consistent with IEEE1275 which specifies only that an arbitrary node matching the given information be selected). This very small change is then followed by many more diffs which change the test examples and testcases to exercise this behaviour. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 14 ++++++++------ tests/del_node.c | 26 +++++++++++++------------- tests/get_name.c | 8 ++++---- tests/get_path.c | 8 ++++---- tests/node_offset_by_prop_value.c | 8 ++++---- tests/nop_node.c | 22 +++++++++++----------- tests/notfound.c | 2 +- tests/parent_offset.c | 8 ++++---- tests/path_offset.c | 22 ++++++++++++---------- tests/rw_tree1.c | 6 +++--- tests/subnode_offset.c | 15 ++++++++++----- tests/supernode_atdepth_offset.c | 8 ++++---- tests/sw_tree1.c | 6 +++--- tests/test_tree1.dts | 6 +++--- tests/tests.h | 1 + tests/testutils.c | 15 +++++++++++++++ tests/trees.S | 6 +++--- 17 files changed, 103 insertions(+), 78 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index f358a20..8dab7a8 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -62,8 +62,8 @@ return err; \ } -static int offset_streq(const void *fdt, int offset, - const char *s, int len) +static int nodename_eq(const void *fdt, int offset, + const char *s, int len) { const char *p = fdt_offset_ptr(fdt, offset, len+1); @@ -74,10 +74,12 @@ static int offset_streq(const void *fdt, int offset, if (memcmp(p, s, len) != 0) return 0; - if (p[len] != '\0') + if (p[len] == '\0') + return 1; + else if (!memchr(s, '@', len) && (p[len] == '@')) + return 1; + else return 0; - - return 1; } char *fdt_string(const void *fdt, int stroffset) @@ -110,7 +112,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, level++; if (level != 1) continue; - if (offset_streq(fdt, offset+FDT_TAGSIZE, name, namelen)) + if (nodename_eq(fdt, offset+FDT_TAGSIZE, name, namelen)) /* Found it! */ return offset; break; diff --git a/tests/del_node.c b/tests/del_node.c index 26bb061..51b12b2 100644 --- a/tests/del_node.c +++ b/tests/del_node.c @@ -42,21 +42,21 @@ int main(int argc, char *argv[]) oldsize = fdt_totalsize(fdt); - subnode1_offset = fdt_path_offset(fdt, "/subnode1"); + subnode1_offset = fdt_path_offset(fdt, "/subnode@1"); if (subnode1_offset < 0) - FAIL("Couldn't find \"/subnode1\": %s", + FAIL("Couldn't find \"/subnode@1\": %s", fdt_strerror(subnode1_offset)); check_getprop_typed(fdt, subnode1_offset, "prop-int", TEST_VALUE_1); - subnode2_offset = fdt_path_offset(fdt, "/subnode2"); + subnode2_offset = fdt_path_offset(fdt, "/subnode@2"); if (subnode2_offset < 0) - FAIL("Couldn't find \"/subnode2\": %s", + FAIL("Couldn't find \"/subnode@2\": %s", fdt_strerror(subnode2_offset)); check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); - subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode"); if (subsubnode2_offset < 0) - FAIL("Couldn't find \"/subnode2/subsubnode\": %s", + FAIL("Couldn't find \"/subnode@2/subsubnode\": %s", fdt_strerror(subsubnode2_offset)); check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); @@ -64,21 +64,21 @@ int main(int argc, char *argv[]) if (err) FAIL("fdt_del_node(subnode1): %s", fdt_strerror(err)); - subnode1_offset = fdt_path_offset(fdt, "/subnode1"); + subnode1_offset = fdt_path_offset(fdt, "/subnode@1"); if (subnode1_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"", fdt_strerror(subnode1_offset), fdt_strerror(-FDT_ERR_NOTFOUND)); - subnode2_offset = fdt_path_offset(fdt, "/subnode2"); + subnode2_offset = fdt_path_offset(fdt, "/subnode@2"); if (subnode2_offset < 0) FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(subnode2_offset)); check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); - subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode"); if (subsubnode2_offset < 0) - FAIL("Couldn't find \"/subnode2/subsubnode\": %s", + FAIL("Couldn't find \"/subnode@2/subsubnode\": %s", fdt_strerror(subsubnode2_offset)); check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); @@ -86,19 +86,19 @@ int main(int argc, char *argv[]) if (err) FAIL("fdt_del_node(subnode2): %s", fdt_strerror(err)); - subnode1_offset = fdt_path_offset(fdt, "/subnode1"); + subnode1_offset = fdt_path_offset(fdt, "/subnode@1"); if (subnode1_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"", fdt_strerror(subnode1_offset), fdt_strerror(-FDT_ERR_NOTFOUND)); - subnode2_offset = fdt_path_offset(fdt, "/subnode2"); + subnode2_offset = fdt_path_offset(fdt, "/subnode@2"); if (subnode2_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subnode2) returned \"%s\" instead of \"%s\"", fdt_strerror(subnode2_offset), fdt_strerror(-FDT_ERR_NOTFOUND)); - subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode"); if (subsubnode2_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subsubnode2) returned \"%s\" instead of \"%s\"", fdt_strerror(subsubnode2_offset), diff --git a/tests/get_name.c b/tests/get_name.c index aef4d9c..2481741 100644 --- a/tests/get_name.c +++ b/tests/get_name.c @@ -74,10 +74,10 @@ int main(int argc, char *argv[]) fdt = load_blob_arg(argc, argv); check_name(fdt, "/"); - check_name(fdt, "/subnode1"); - check_name(fdt, "/subnode2"); - check_name(fdt, "/subnode1/subsubnode"); - check_name(fdt, "/subnode2/subsubnode"); + check_name(fdt, "/subnode@1"); + check_name(fdt, "/subnode@2"); + check_name(fdt, "/subnode@1/subsubnode"); + check_name(fdt, "/subnode@2/subsubnode@0"); PASS(); } diff --git a/tests/get_path.c b/tests/get_path.c index 1f09479..eb217bd 100644 --- a/tests/get_path.c +++ b/tests/get_path.c @@ -82,10 +82,10 @@ int main(int argc, char *argv[]) fdt = load_blob_arg(argc, argv); check_path(fdt, "/"); - check_path(fdt, "/subnode1"); - check_path(fdt, "/subnode2"); - check_path(fdt, "/subnode1/subsubnode"); - check_path(fdt, "/subnode2/subsubnode"); + check_path(fdt, "/subnode@1"); + check_path(fdt, "/subnode@2"); + check_path(fdt, "/subnode@1/subsubnode"); + check_path(fdt, "/subnode@2/subsubnode@0"); PASS(); } diff --git a/tests/node_offset_by_prop_value.c b/tests/node_offset_by_prop_value.c index b56cdf5..651bc05 100644 --- a/tests/node_offset_by_prop_value.c +++ b/tests/node_offset_by_prop_value.c @@ -83,10 +83,10 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); - subnode1_offset = fdt_path_offset(fdt, "/subnode1"); - subnode2_offset = fdt_path_offset(fdt, "/subnode2"); - subsubnode1_offset = fdt_path_offset(fdt, "/subnode1/subsubnode"); - subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + subnode1_offset = fdt_path_offset(fdt, "/subnode@1"); + subnode2_offset = fdt_path_offset(fdt, "/subnode@2"); + subsubnode1_offset = fdt_path_offset(fdt, "/subnode@1/subsubnode"); + subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode@0"); if ((subnode1_offset < 0) || (subnode2_offset < 0) || (subsubnode1_offset < 0) || (subsubnode2_offset < 0)) diff --git a/tests/nop_node.c b/tests/nop_node.c index 80cf4d0..ab487a4 100644 --- a/tests/nop_node.c +++ b/tests/nop_node.c @@ -39,21 +39,21 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); - subnode1_offset = fdt_path_offset(fdt, "/subnode1"); + subnode1_offset = fdt_path_offset(fdt, "/subnode@1"); if (subnode1_offset < 0) FAIL("Couldn't find \"/subnode1\": %s", fdt_strerror(subnode1_offset)); check_getprop_typed(fdt, subnode1_offset, "prop-int", TEST_VALUE_1); - subnode2_offset = fdt_path_offset(fdt, "/subnode2"); + subnode2_offset = fdt_path_offset(fdt, "/subnode@2"); if (subnode2_offset < 0) FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(subnode2_offset)); check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); - subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode"); if (subsubnode2_offset < 0) - FAIL("Couldn't find \"/subnode2/subsubnode\": %s", + FAIL("Couldn't find \"/subnode@2/subsubnode\": %s", fdt_strerror(subsubnode2_offset)); check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); @@ -61,21 +61,21 @@ int main(int argc, char *argv[]) if (err) FAIL("fdt_nop_node(subnode1): %s", fdt_strerror(err)); - subnode1_offset = fdt_path_offset(fdt, "/subnode1"); + subnode1_offset = fdt_path_offset(fdt, "/subnode@1"); if (subnode1_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"", fdt_strerror(subnode1_offset), fdt_strerror(-FDT_ERR_NOTFOUND)); - subnode2_offset = fdt_path_offset(fdt, "/subnode2"); + subnode2_offset = fdt_path_offset(fdt, "/subnode@2"); if (subnode2_offset < 0) FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(subnode2_offset)); check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); - subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode"); if (subsubnode2_offset < 0) - FAIL("Couldn't find \"/subnode2/subsubnode\": %s", + FAIL("Couldn't find \"/subnode@2/subsubnode\": %s", fdt_strerror(subsubnode2_offset)); check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); @@ -83,19 +83,19 @@ int main(int argc, char *argv[]) if (err) FAIL("fdt_nop_node(subnode2): %s", fdt_strerror(err)); - subnode1_offset = fdt_path_offset(fdt, "/subnode1"); + subnode1_offset = fdt_path_offset(fdt, "/subnode@1"); if (subnode1_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"", fdt_strerror(subnode1_offset), fdt_strerror(-FDT_ERR_NOTFOUND)); - subnode2_offset = fdt_path_offset(fdt, "/subnode2"); + subnode2_offset = fdt_path_offset(fdt, "/subnode@2"); if (subnode2_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subnode2) returned \"%s\" instead of \"%s\"", fdt_strerror(subnode2_offset), fdt_strerror(-FDT_ERR_NOTFOUND)); - subsubnode2_offset = fdt_path_offset(fdt, "/subnode2/subsubnode"); + subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode"); if (subsubnode2_offset != -FDT_ERR_NOTFOUND) FAIL("fdt_path_offset(subsubnode2) returned \"%s\" instead of \"%s\"", fdt_strerror(subsubnode2_offset), diff --git a/tests/notfound.c b/tests/notfound.c index e8d0582..ae28c44 100644 --- a/tests/notfound.c +++ b/tests/notfound.c @@ -53,7 +53,7 @@ int main(int argc, char *argv[]) val = fdt_getprop(fdt, 0, "nonexistant-property", &lenerr); check_error("fdt_getprop(\"nonexistant-property\"", lenerr); - subnode1_offset = fdt_subnode_offset(fdt, 0, "subnode1"); + subnode1_offset = fdt_subnode_offset(fdt, 0, "subnode@1"); if (subnode1_offset < 0) FAIL("Couldn't find subnode1: %s", fdt_strerror(subnode1_offset)); diff --git a/tests/parent_offset.c b/tests/parent_offset.c index f3d2c32..309ef6c 100644 --- a/tests/parent_offset.c +++ b/tests/parent_offset.c @@ -77,10 +77,10 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); - check_path(fdt, "/subnode1"); - check_path(fdt, "/subnode2"); - check_path(fdt, "/subnode1/subsubnode"); - check_path(fdt, "/subnode2/subsubnode"); + check_path(fdt, "/subnode@1"); + check_path(fdt, "/subnode@2"); + check_path(fdt, "/subnode@1/subsubnode"); + check_path(fdt, "/subnode@2/subsubnode@0"); err = fdt_parent_offset(fdt, 0); if (err != -FDT_ERR_NOTFOUND) FAIL("fdt_parent_offset(/) returns %d instead of " diff --git a/tests/path_offset.c b/tests/path_offset.c index c962000..834bc93 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -48,7 +48,7 @@ int check_subnode(void *fdt, int parent, const char *name) if (tag != FDT_BEGIN_NODE) FAIL("Incorrect tag 0x%08x on property \"%s\"", tag, name); - if (!streq(nh->name, name)) + if (!nodename_eq(nh->name, name)) FAIL("Subnode name mismatch \"%s\" instead of \"%s\"", nh->name, name); @@ -61,8 +61,8 @@ int main(int argc, char *argv[]) int root_offset; int subnode1_offset, subnode2_offset; int subnode1_offset_p, subnode2_offset_p; - int subsubnode1_offset, subsubnode2_offset; - int subsubnode1_offset_p, subsubnode2_offset_p; + int subsubnode1_offset, subsubnode2_offset, subsubnode2_offset2; + int subsubnode1_offset_p, subsubnode2_offset_p, subsubnode2_offset2_p; test_init(argc, argv); fdt = load_blob_arg(argc, argv); @@ -74,11 +74,11 @@ int main(int argc, char *argv[]) else if (root_offset != 0) FAIL("fdt_path_offset(\"/\") returns incorrect offset %d", root_offset); - subnode1_offset = check_subnode(fdt, 0, "subnode1"); - subnode2_offset = check_subnode(fdt, 0, "subnode2"); + subnode1_offset = check_subnode(fdt, 0, "subnode@1"); + subnode2_offset = check_subnode(fdt, 0, "subnode@2"); - subnode1_offset_p = fdt_path_offset(fdt, "/subnode1"); - subnode2_offset_p = fdt_path_offset(fdt, "/subnode2"); + subnode1_offset_p = fdt_path_offset(fdt, "/subnode@1"); + subnode2_offset_p = fdt_path_offset(fdt, "/subnode@2"); if (subnode1_offset != subnode1_offset_p) FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)", @@ -89,10 +89,12 @@ int main(int argc, char *argv[]) subnode2_offset, subnode2_offset_p); subsubnode1_offset = check_subnode(fdt, subnode1_offset, "subsubnode"); - subsubnode2_offset = check_subnode(fdt, subnode2_offset, "subsubnode"); + subsubnode2_offset = check_subnode(fdt, subnode2_offset, "subsubnode@0"); + subsubnode2_offset2 = check_subnode(fdt, subnode2_offset, "subsubnode"); - subsubnode1_offset_p = fdt_path_offset(fdt, "/subnode1/subsubnode"); - subsubnode2_offset_p = fdt_path_offset(fdt, "/subnode2/subsubnode"); + subsubnode1_offset_p = fdt_path_offset(fdt, "/subnode@1/subsubnode"); + subsubnode2_offset_p = fdt_path_offset(fdt, "/subnode@2/subsubnode@0"); + subsubnode2_offset2_p = fdt_path_offset(fdt, "/subnode@2/subsubnode"); if (subsubnode1_offset != subsubnode1_offset_p) FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)", diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c index 3fb9307..099b3f4 100644 --- a/tests/rw_tree1.c +++ b/tests/rw_tree1.c @@ -72,14 +72,14 @@ int main(int argc, char *argv[]) CHECK(fdt_setprop_typed(fdt, 0, "prop-int", TEST_VALUE_1)); CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1)); - OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode1")); + OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@1")); CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_1)); OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode")); CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_1)); - OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode2")); + OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@2")); CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_2)); - OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode")); + OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode@0")); CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_2)); diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c index d4edfe4..eafce2c 100644 --- a/tests/subnode_offset.c +++ b/tests/subnode_offset.c @@ -48,7 +48,7 @@ int check_subnode(struct fdt_header *fdt, int parent, const char *name) if (tag != FDT_BEGIN_NODE) FAIL("Incorrect tag 0x%08x on property \"%s\"", tag, name); - if (!streq(nh->name, name)) + if (!nodename_eq(nh->name, name)) FAIL("Subnode name mismatch \"%s\" instead of \"%s\"", nh->name, name); @@ -59,13 +59,13 @@ int main(int argc, char *argv[]) { void *fdt; int subnode1_offset, subnode2_offset; - int subsubnode1_offset, subsubnode2_offset; + int subsubnode1_offset, subsubnode2_offset, subsubnode2_offset2; test_init(argc, argv); fdt = load_blob_arg(argc, argv); - subnode1_offset = check_subnode(fdt, 0, "subnode1"); - subnode2_offset = check_subnode(fdt, 0, "subnode2"); + subnode1_offset = check_subnode(fdt, 0, "subnode@1"); + subnode2_offset = check_subnode(fdt, 0, "subnode@2"); if (subnode1_offset == subnode2_offset) FAIL("Different subnodes have same offset"); @@ -74,10 +74,15 @@ int main(int argc, char *argv[]) check_property_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); subsubnode1_offset = check_subnode(fdt, subnode1_offset, "subsubnode"); - subsubnode2_offset = check_subnode(fdt, subnode2_offset, "subsubnode"); + subsubnode2_offset = check_subnode(fdt, subnode2_offset, "subsubnode@0"); + subsubnode2_offset2 = check_subnode(fdt, subnode2_offset, "subsubnode"); check_property_typed(fdt, subsubnode1_offset, "prop-int", TEST_VALUE_1); check_property_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); + check_property_typed(fdt, subsubnode2_offset2, "prop-int", TEST_VALUE_2); + + if (subsubnode2_offset != subsubnode2_offset2) + FAIL("Different offsets with and without unit address"); PASS(); } diff --git a/tests/supernode_atdepth_offset.c b/tests/supernode_atdepth_offset.c index 6736aca..39cade6 100644 --- a/tests/supernode_atdepth_offset.c +++ b/tests/supernode_atdepth_offset.c @@ -135,10 +135,10 @@ int main(int argc, char *argv[]) fdt = load_blob_arg(argc, argv); check_path(fdt, "/"); - check_path(fdt, "/subnode1"); - check_path(fdt, "/subnode2"); - check_path(fdt, "/subnode1/subsubnode"); - check_path(fdt, "/subnode2/subsubnode"); + check_path(fdt, "/subnode@1"); + check_path(fdt, "/subnode@2"); + check_path(fdt, "/subnode@1/subsubnode"); + check_path(fdt, "/subnode@2/subsubnode@0"); PASS(); } diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 7b54359..34bee4f 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -54,16 +54,16 @@ int main(int argc, char *argv[]) CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_property_string(fdt, "prop-str", TEST_STRING_1)); - CHECK(fdt_begin_node(fdt, "subnode1")); + CHECK(fdt_begin_node(fdt, "subnode@1")); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_begin_node(fdt, "subsubnode")); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_end_node(fdt)); CHECK(fdt_end_node(fdt)); - CHECK(fdt_begin_node(fdt, "subnode2")); + CHECK(fdt_begin_node(fdt, "subnode@2")); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_2)); - CHECK(fdt_begin_node(fdt, "subsubnode")); + CHECK(fdt_begin_node(fdt, "subsubnode@0")); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_2)); CHECK(fdt_end_node(fdt)); CHECK(fdt_end_node(fdt)); diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts index 5ddc208..30091f1 100644 --- a/tests/test_tree1.dts +++ b/tests/test_tree1.dts @@ -2,7 +2,7 @@ prop-int = ; prop-str = "hello world"; - subnode1 { + subnode@1 { prop-int = ; subsubnode { @@ -10,10 +10,10 @@ }; }; - subnode2 { + subnode@2 { prop-int = ; - subsubnode { + subsubnode@0 { prop-int = ; }; }; diff --git a/tests/tests.h b/tests/tests.h index ace7ba3..62716ce 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -126,6 +126,7 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name, }) #define check_getprop_string(fdt, nodeoffset, name, s) \ check_getprop((fdt), (nodeoffset), (name), strlen(s)+1, (s)) +int nodename_eq(const char *s1, const char *s2); //void *load_blob(const char *filename); void *load_blob_arg(int argc, char *argv[]); void save_blob(const char *filename, void *blob); diff --git a/tests/testutils.c b/tests/testutils.c index 82aebc5..68cc88a 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -125,6 +125,21 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name, return propval; } +int nodename_eq(const char *s1, const char *s2) +{ + int len = strlen(s2); + + len = strlen(s2); + if (strncmp(s1, s2, len) != 0) + return 0; + if (s1[len] == '\0') + return 1; + else if (!memchr(s2, '@', len) && (s1[len] == '@')) + return 1; + else + return 0; +} + #define CHUNKSIZE 128 void *load_blob(const char *filename) diff --git a/tests/trees.S b/tests/trees.S index 60e1b55..78c92d7 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -78,7 +78,7 @@ test_tree1_struct: PROP_INT(test_tree1, prop_int, TEST_VALUE_1) PROP_STR(test_tree1, prop_str, TEST_STRING_1) - BEGIN_NODE("subnode1") + BEGIN_NODE("subnode@1") PROP_INT(test_tree1, prop_int, TEST_VALUE_1) BEGIN_NODE("subsubnode") @@ -86,10 +86,10 @@ test_tree1_struct: END_NODE END_NODE - BEGIN_NODE("subnode2") + BEGIN_NODE("subnode@2") PROP_INT(test_tree1, prop_int, TEST_VALUE_2) - BEGIN_NODE("subsubnode") + BEGIN_NODE("subsubnode@0") PROP_INT(test_tree1, prop_int, TEST_VALUE_2) END_NODE END_NODE From ad9593f229362782b953da4b805df713e8468df0 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 4 Oct 2007 15:37:43 +1000 Subject: [PATCH 0106/1198] dtc: Refactor Makefiles This patch makes a number of Makefile cleanups and improvements: - We use more generic rules to invoke flex and bison, which is useful for some of the other changes. - We use the name dtc-lexer.lex.c for the flex output, instead of the default lex.yy.c. That means less potential for confusion if dtc is embedded into other projects (e.g. the kernel). - We separate out a Makefile.dtc designed for embedding into other projects, analagous to Makefile.libfdt. - Makefile.libfdt is cleaned up to be more useful based on some actual trial runs of embedding libfdt in the kernel bootwrapper. - Versioning related rules and variables are collected into one place in the Makefile. Signed-off-by: David Gibson --- Makefile | 202 ++++++++++++++++++++++------------------- Makefile.dtc | 24 +++++ libfdt/Makefile.libfdt | 19 ++-- 3 files changed, 139 insertions(+), 106 deletions(-) create mode 100644 Makefile.dtc diff --git a/Makefile b/Makefile index e1f8987..84f0efe 100644 --- a/Makefile +++ b/Makefile @@ -15,40 +15,12 @@ EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = -DTC_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) -VERSION_FILE = version_gen.h - -CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ - else if [ -x /bin/bash ]; then echo /bin/bash; \ - else echo sh; fi ; fi) - -nullstring := -space := $(nullstring) # end of line - -localver_config = $(subst $(space),, $(string) \ - $(patsubst "%",%,$(CONFIG_LOCALVERSION))) - -localver_cmd = $(subst $(space),, $(string) \ - $(patsubst "%",%,$(LOCALVERSION))) - -localver_scm = $(shell $(CONFIG_SHELL) ./scripts/setlocalversion) -localver_full = $(localver_config)$(localver_cmd)$(localver_scm) - -dtc_version = $(DTC_VERSION)$(localver_full) - -# -# Contents of the generated version file. -# -define filechk_version - (echo "#define DTC_VERSION \"DTC $(dtc_version)\""; ) -endef - - CPPFLAGS = -I libfdt CFLAGS = -Wall -g -Os LDFLAGS = -Llibfdt BISON = bison +LEX = flex INSTALL = /usr/bin/install DESTDIR = @@ -77,70 +49,6 @@ endif all: dtc ftdump libfdt tests -# -# Rules for dtc proper -# -DTC_PROGS = dtc ftdump -DTC_OBJS = dtc.o flattree.o fstree.o data.o livetree.o \ - srcpos.o treesource.o \ - dtc-parser.tab.o lex.yy.o -DTC_DEPFILES = $(DTC_OBJS:%.o=%.d) - -BIN += dtc ftdump - -dtc-parser.tab.c dtc-parser.tab.h dtc-parser.output: dtc-parser.y - @$(VECHO) BISON $@ - @$(VECHO) ---- Expect 2 s/r and 2 r/r. ---- - $(BISON) -d $< - -$(VERSION_FILE): Makefile FORCE - $(call filechk,version) - -lex.yy.c: dtc-lexer.l - @$(VECHO) LEX $@ - $(LEX) $< - -dtc: $(DTC_OBJS) - -ftdump: ftdump.o - -ifneq ($(DEPTARGETS),) --include $(DTC_DEPFILES) -endif - -# -# Rules for libfdt -# -LIBFDT_PREFIX = libfdt/ -include libfdt/Makefile.libfdt - -.PHONY: libfdt -libfdt: $(LIBFDT_LIB) - -libfdt_clean: - @$(VECHO) CLEAN "(libfdt)" - rm -f $(LIBFDT_CLEANFILES) - -ifneq ($(DEPTARGETS),) --include $(LIBFDT_DEPFILES) -endif - -# -# Testsuite rules -# -TESTS_PREFIX=tests/ -include tests/Makefile.tests - -STD_CLEANFILES = *~ *.o *.d *.a *.i *.s core a.out -GEN_CLEANFILES = $(VERSION_FILE) - -clean: libfdt_clean tests_clean - @$(VECHO) CLEAN - rm -f $(STD_CLEANFILES) - rm -f $(GEN_CLEANFILES) - rm -f *.tab.[ch] lex.yy.c *.output vgcore.* - rm -f $(BIN) - install: all @$(VECHO) INSTALL $(INSTALL) -d $(DESTDIR)$(BINDIR) @@ -150,6 +58,36 @@ install: all $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) $(INSTALL) -m 644 $(LIBFDT_INCLUDES) $(DESTDIR)$(INCLUDEDIR) +# +# Rules for versioning +# + +DTC_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) +VERSION_FILE = version_gen.h + +CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ + else if [ -x /bin/bash ]; then echo /bin/bash; \ + else echo sh; fi ; fi) + +nullstring := +space := $(nullstring) # end of line + +localver_config = $(subst $(space),, $(string) \ + $(patsubst "%",%,$(CONFIG_LOCALVERSION))) + +localver_cmd = $(subst $(space),, $(string) \ + $(patsubst "%",%,$(LOCALVERSION))) + +localver_scm = $(shell $(CONFIG_SHELL) ./scripts/setlocalversion) +localver_full = $(localver_config)$(localver_cmd)$(localver_scm) + +dtc_version = $(DTC_VERSION)$(localver_full) + +# Contents of the generated version file. +define filechk_version + (echo "#define DTC_VERSION \"DTC $(dtc_version)\""; ) +endef + define filechk set -e; \ echo ' CHK $@'; \ @@ -163,6 +101,75 @@ define filechk fi; endef +$(VERSION_FILE): Makefile FORCE + $(call filechk,version) + +# +# Rules for dtc proper +# +include Makefile.dtc + +BIN += dtc + +# This stops make from generating the lex and bison output during +# auto-dependency computation, but throwing them away as an +# intermediate target and building them again "for real" +.SECONDARY: $(DTC_GEN_SRCS) + +dtc: $(DTC_OBJS) + +ifneq ($(DEPTARGETS),) +-include $(DTC_OBJS:%.o=%.d) +endif +# +# Rules for ftdump +# +BIN += ftdump + +ftdump: ftdump.o + +ifneq ($(DEPTARGETS),) +-include ftdump.d +endif +# +# Rules for libfdt +# +LIBFDT_objdir = libfdt +LIBFDT_srcdir = libfdt +include libfdt/Makefile.libfdt + +.PHONY: libfdt +libfdt: $(LIBFDT_LIB) + +$(LIBFDT_LIB): $(addprefix libfdt/,$(LIBFDT_OBJS)) + +libfdt_clean: + @$(VECHO) CLEAN "(libfdt)" + rm -f $(addprefix libfdt/,$(STD_CLEANFILES)) + rm -f $(addprefix libfdt/,$(LIBFDT_CLEANFILES)) + +ifneq ($(DEPTARGETS),) +-include $(LIBFDT_OBJS:%.o=$(LIBFDT_objdir)/%.d) +endif + +# +# Testsuite rules +# +TESTS_PREFIX=tests/ +include tests/Makefile.tests + +# +# Clean rules +# +STD_CLEANFILES = *~ *.o *.d *.a *.i *.s core a.out vgcore.* \ + *.tab.[ch] *.lex.c *.output + +clean: libfdt_clean tests_clean + @$(VECHO) CLEAN + rm -f $(STD_CLEANFILES) $(DTC_CLEANFILES) + rm -f $(VERSION_FILE) + rm -f $(BIN) + # # Generic compile rules # @@ -179,6 +186,7 @@ endef $(CC) $(CPPFLAGS) $(AFLAGS) -D__ASSEMBLY__ -o $@ -c $< %.d: %.c + @$(VECHO) DEP $< $(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@ %.i: %.c @@ -193,4 +201,12 @@ endef @$(VECHO) AR $@ $(AR) $(ARFLAGS) $@ $^ +%.lex.c: %.l + @$(VECHO) LEX $@ + $(LEX) -o $@ $< + +%.tab.c %.tab.h %.output: %.y + @$(VECHO) BISON $@ + $(BISON) -d $< + FORCE: diff --git a/Makefile.dtc b/Makefile.dtc new file mode 100644 index 0000000..c843ee2 --- /dev/null +++ b/Makefile.dtc @@ -0,0 +1,24 @@ +# Makefile.dtc +# +# This is not a complete Makefile of itself. Instead, it is designed to +# be easily embeddable into other systems of Makefiles. +# +DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c +DTC_EXTRA = dtc.h srcpos.h +DTC_LEXFILES = dtc-lexer.l +DTC_BISONFILES = dtc-parser.y + +DTC_LEX_SRCS = $(DTC_LEXFILES:%.l=%.lex.c) +DTC_BISON_SRCS = $(DTC_BISONFILES:%.y=%.tab.c) +DTC_BISON_INCLUDES = $(DTC_BISONFILES:%.y=%.tab.h) + +DTC_GEN_SRCS = $(DTC_LEX_SRCS) $(DTC_BISON_SRCS) +DTC_GEN_ALL = $(DTC_GEN_SRCS) $(DTC_BISON_INCLUDES) +DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o) + +DTC_CLEANFILES = $(DTC_GEN_ALL) + +# We assume the containing Makefile system can do auto-dependencies for most +# things, but we supply the dependencies on generated header files explicitly + +$(addprefix $(DTC_objdir)/,$(DTC_GEN_SRCS:%.c=%.o)): $(addprefix $(DTC_objdir)/,$(DTC_BISON_INCLUDES)) diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index 3be2b21..82f9c6a 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -3,19 +3,12 @@ # This is not a complete Makefile of itself. Instead, it is designed to # be easily embeddable into other systems of Makefiles. # -LIBFDT_OBJS_L = fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o fdt_strerror.o -LIBFDT_OBJS = $(LIBFDT_OBJS_L:%=$(LIBFDT_PREFIX)%) +LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c +LIBFDT_INCLUDES = fdt.h libfdt.h +LIBFDT_EXTRA = libfdt_internal.h +LIBFDT_LIB = libfdt/libfdt.a -LIBFDT_LIB_L = libfdt.a -LIBFDT_LIB = $(LIBFDT_LIB_L:%=$(LIBFDT_PREFIX)%) +LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) -LIBFDT_INCLUDES_L = fdt.h libfdt.h -LIBFDT_INCLUDES = $(LIBFDT_INCLUDES_L:%=$(LIBFDT_PREFIX)%) +$(LIBFDT_objdir)/$(LIBFDT_LIB): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) -LIBFDT_CLEANFILES_L = *~ *.o *.d *.a $(LIBFDT_LIB) \ - *.i *.s a.out core -LIBFDT_CLEANFILES = $(LIBFDT_CLEANFILES_L:%=$(LIBFDT_PREFIX)%) - -$(LIBFDT_LIB): $(LIBFDT_OBJS) - -LIBFDT_DEPFILES = $(LIBFDT_OBJS:%.o=%.d) From fd1bf3a5ae46962528ef89a824261a88830758a2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 10 Oct 2007 17:12:12 +1000 Subject: [PATCH 0107/1198] libfdt: Add functions to get/add/delete memory reservemap entries This patch adds functions to libfdt for accessing the memory reservation map section of a device tree blob. fdt_num_mem_rsv() retreives the number of reservation entries in a dtb, and fdt_get_mem_rsv() retreives a specific reservation entry. fdt_add_mem_rsv() adds a new entry, and fdt_del_mem_rsv() removes a specific numbered entry. Testcases for these new functions are also included. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 17 +++++++++++++++ libfdt/fdt_rw.c | 47 ++++++++++++++++++++++++++++++++++++++++ libfdt/libfdt.h | 6 +++++ libfdt/libfdt_internal.h | 12 ++++++++++ tests/Makefile.tests | 3 ++- tests/run_tests.sh | 1 + tests/rw_tree1.c | 3 +++ tests/sw_tree1.c | 3 +++ tests/test_tree1.dts | 3 +++ tests/testdata.h | 11 ++++++++++ tests/tests.h | 2 ++ tests/testutils.c | 15 +++++++++++++ tests/trees.S | 11 ++++++++-- 13 files changed, 131 insertions(+), 3 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 8dab7a8..a5a15e3 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -87,6 +87,23 @@ char *fdt_string(const void *fdt, int stroffset) return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset; } +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) +{ + CHECK_HEADER(fdt); + *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); + *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); + return 0; +} + +int fdt_num_mem_rsv(const void *fdt) +{ + int i = 0; + + while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) + i++; + return i; +} + int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, const char *name, int namelen) { diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 6e4c808..85b6281 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -101,6 +101,19 @@ static int _blob_splice(void *fdt, void *p, int oldlen, int newlen) return 0; } +static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, + int oldn, int newn) +{ + int delta = (newn - oldn) * sizeof(*p); + int err; + err = _blob_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); + if (err) + return err; + fdt_set_header(fdt, off_dt_struct, fdt_off_dt_struct(fdt) + delta); + fdt_set_header(fdt, off_dt_strings, fdt_off_dt_strings(fdt) + delta); + return 0; +} + static int _blob_splice_struct(void *fdt, void *p, int oldlen, int newlen) { @@ -149,6 +162,40 @@ static int _find_add_string(void *fdt, const char *s) return (new - strtab); } +int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) +{ + struct fdt_reserve_entry *re; + int err; + + if ((err = rw_check_header(fdt))) + return err; + + re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); + err = _blob_splice_mem_rsv(fdt, re, 0, 1); + if (err) + return err; + + re->address = cpu_to_fdt64(address); + re->size = cpu_to_fdt64(size); + return 0; +} + +int fdt_del_mem_rsv(void *fdt, int n) +{ + struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); + int err; + + if ((err = rw_check_header(fdt))) + return err; + if (n >= fdt_num_mem_rsv(fdt)) + return -FDT_ERR_NOTFOUND; + + err = _blob_splice_mem_rsv(fdt, re, 1, 0); + if (err) + return err; + return 0; +} + static int _resize_property(void *fdt, int nodeoffset, const char *name, int len, struct fdt_property **prop) { diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index c059bdc..468e45f 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -112,6 +112,9 @@ int fdt_move(const void *fdt, void *buf, int bufsize); /* Read-only functions */ char *fdt_string(const void *fdt, int stroffset); +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); +int fdt_num_mem_rsv(const void *fdt); + int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, const char *name, int namelen); int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); @@ -183,6 +186,9 @@ int fdt_finish(void *fdt); int fdt_open_into(void *fdt, void *buf, int bufsize); int fdt_pack(void *fdt); +int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); +int fdt_del_mem_rsv(void *fdt, int n); + int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len); #define fdt_setprop_typed(fdt, nodeoffset, name, val) \ diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index a1a548d..d2d5e6a 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -73,6 +73,18 @@ static inline void *_fdt_offset_ptr_w(void *fdt, int offset) return (void *)_fdt_offset_ptr(fdt, offset); } +static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) +{ + const struct fdt_reserve_entry *rsv_table = + fdt + fdt_off_mem_rsvmap(fdt); + + return rsv_table + n; +} +static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) +{ + return (void *)_fdt_mem_rsv(fdt, n); +} + #define SW_MAGIC (~FDT_MAGIC) #endif /* _LIBFDT_INTERNAL_H */ diff --git a/tests/Makefile.tests b/tests/Makefile.tests index e97e903..c84b63d 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -1,4 +1,5 @@ -LIB_TESTS_L = root_node find_property subnode_offset path_offset \ +LIB_TESTS_L = get_mem_rsv \ + root_node find_property subnode_offset path_offset \ get_name getprop get_path supernode_atdepth_offset parent_offset \ node_offset_by_prop_value \ notfound \ diff --git a/tests/run_tests.sh b/tests/run_tests.sh index b51bd8f..2a5e486 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -31,6 +31,7 @@ tree1_tests () { TREE=$1 # Read-only tests + run_test get_mem_rsv $TREE run_test root_node $TREE run_test find_property $TREE run_test subnode_offset $TREE diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c index 099b3f4..7835362 100644 --- a/tests/rw_tree1.c +++ b/tests/rw_tree1.c @@ -69,6 +69,9 @@ int main(int argc, char *argv[]) CHECK(fdt_open_into(fdt, fdt, SPACE)); + CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_1, TEST_SIZE_1)); + CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2)); + CHECK(fdt_setprop_typed(fdt, 0, "prop-int", TEST_VALUE_1)); CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1)); diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 34bee4f..d4b960e 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -49,7 +49,10 @@ int main(int argc, char *argv[]) fdt = xmalloc(SPACE); CHECK(fdt_create(fdt, SPACE)); + CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1)); + CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_2, TEST_SIZE_2)); CHECK(fdt_finish_reservemap(fdt)); + CHECK(fdt_begin_node(fdt, "")); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_property_string(fdt, "prop-str", TEST_STRING_1)); diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts index 30091f1..212ffa7 100644 --- a/tests/test_tree1.dts +++ b/tests/test_tree1.dts @@ -1,3 +1,6 @@ +/memreserve/ deadbeef00000000-deadbeef000fffff; +/memreserve/ abcd1234 00001234; + / { prop-int = ; prop-str = "hello world"; diff --git a/tests/testdata.h b/tests/testdata.h index 15a4a35..3d08ff7 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -9,6 +9,17 @@ | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000)) #endif +#ifdef __ASSEMBLY__ +#define ASM_CONST_LL(x) (x) +#else +#define ASM_CONST_LL(x) (x##ULL) +#endif + +#define TEST_ADDR_1 ASM_CONST_LL(0xdeadbeef00000000) +#define TEST_SIZE_1 ASM_CONST_LL(0x100000) +#define TEST_ADDR_2 ASM_CONST_LL(0xabcd1234) +#define TEST_SIZE_2 ASM_CONST_LL(0x1234) + #define TEST_VALUE_1 cell_to_fdt(0xdeadbeef) #define TEST_VALUE_2 cell_to_fdt(0xabcd1234) diff --git a/tests/tests.h b/tests/tests.h index 62716ce..97f15d8 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -108,6 +108,8 @@ static inline void *xrealloc(void *p, size_t size) return p; } +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); #define check_property_typed(fdt, nodeoffset, name, val) \ diff --git a/tests/testutils.c b/tests/testutils.c index 68cc88a..6d6112b 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -69,6 +69,21 @@ void test_init(int argc, char *argv[]) test_name, getpid()); } +void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size) +{ + int err; + uint64_t addr_v, size_v; + + err = fdt_get_mem_rsv(fdt, n, &addr_v, &size_v); + if (err < 0) + FAIL("fdt_get_mem_rsv(%d): %s", n, fdt_strerror(err)); + if ((addr_v != addr) || (size_v != size)) + FAIL("fdt_get_mem_rsv() returned (0x%llx,0x%llx) " + "instead of (0x%llx,0x%llx)", + (unsigned long long)addr_v, (unsigned long long)size_v, + (unsigned long long)addr, (unsigned long long)size); +} + void check_property(void *fdt, int nodeoffset, const char *name, int len, const void *val) { diff --git a/tests/trees.S b/tests/trees.S index 78c92d7..bb662a6 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -37,6 +37,11 @@ tree: \ FDTQUAD(addr) ; \ FDTQUAD(len) ; +#define EMPTY_RSVMAP(tree) \ + .balign 8 ; \ +tree##_rsvmap: ; \ + RSVMAP_ENTRY(0, 0) + #define PROPHDR(tree, name, len) \ FDTLONG(FDT_PROP) ; \ FDTLONG(len) ; \ @@ -70,7 +75,10 @@ tree##_##name: \ TREE_HDR(test_tree1) + .balign 8 test_tree1_rsvmap: + RSVMAP_ENTRY(TEST_ADDR_1, TEST_SIZE_1) + RSVMAP_ENTRY(TEST_ADDR_2, TEST_SIZE_2) RSVMAP_ENTRY(0, 0) test_tree1_struct: @@ -103,8 +111,7 @@ test_tree1_strings: test_tree1_end: TREE_HDR(truncated_property) -truncated_property_rsvmap: - RSVMAP_ENTRY(0, 0) + EMPTY_RSVMAP(truncated_property) truncated_property_struct: BEGIN_NODE("") From 6f8b7710c9e866d6880cf060127bdbdc932bc6a6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 16 Oct 2007 13:50:34 +1000 Subject: [PATCH 0108/1198] libfdt: libfdt_env.h must be included first libfdt.h currently includes fdt.h, then libfdt_env.h. This is incorrect, because depending on the environment into which libfdt is embedded, libfdt_env.h may be needed to define datatypes used in fdt.h. This patch corrects the problem. 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 468e45f..8b7d501 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -51,8 +51,8 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include +#include #define FDT_FIRST_SUPPORTED_VERSION 0x10 #define FDT_LAST_SUPPORTED_VERSION 0x11 From 9e32930ebcacfcf7cb7c1c2b8e776eb3957cf6cb Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Tue, 16 Oct 2007 07:35:38 -0500 Subject: [PATCH 0109/1198] Restore warning message about bison expected output. It was dropped in ad9593f229362782b953da4b805df713e8468df0. Signed-off-by: Jon Loeliger --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 84f0efe..d7d1af5 100644 --- a/Makefile +++ b/Makefile @@ -207,6 +207,7 @@ clean: libfdt_clean tests_clean %.tab.c %.tab.h %.output: %.y @$(VECHO) BISON $@ + @$(VECHO) ---- Expect 2 s/r and 2 r/r. ---- $(BISON) -d $< FORCE: From 121acdec91f269b3efb4b5ac45820f0d1a3b37a1 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 16 Oct 2007 13:53:20 +1000 Subject: [PATCH 0110/1198] dtc: Don't delete *.test.dtb between testgroups The dtc/libfdt testsuite creates a number of .dtb files during its run. To ensure a clean test run, these are currently deleted before each group of tests. This is, in fact, a mistake, since if something goes wrong in the first group of tests, deleting the .dtb at the beginning of the second group of tests makes it harder to figure out what the problem was. This patch changes the script to only delete the files once, before the whole test run. Signed-off-by: David Gibson --- tests/run_tests.sh | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 2a5e486..6bc20ea 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -60,9 +60,6 @@ tree1_tests_rw () { } libfdt_tests () { - # Make sure we don't have stale blobs lying around - rm -f *.test.dtb - tree1_tests test_tree1.dtb # Sequential write tests @@ -102,9 +99,6 @@ libfdt_tests () { } dtc_tests () { - # Make sure we don't have stale blobs lying around - rm -f *.test.dtb - run_test dtc.sh -f -I dts -O dtb -o dtc_tree1.test.dtb test_tree1.dts tree1_tests dtc_tree1.test.dtb tree1_tests_rw dtc_tree1.test.dtb @@ -125,6 +119,9 @@ if [ -z "$TESTSETS" ]; then TESTSETS="libfdt dtc" fi +# Make sure we don't have stale blobs lying around +rm -f *.test.dtb + for set in $TESTSETS; do case $set in "libfdt") From 333542fabf8720b881e992a5abca32ef4bcb841a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 16 Oct 2007 13:58:25 +1000 Subject: [PATCH 0111/1198] libfdt: Add functions for handling the "compatible" property This patch adds functions for dealing with the compatible property. fdt_node_check_compatible() can be used to determine whether a node is compatible with a given string and fdt_node_offset_by_compatible() locates nodes with a given compatible string. Testcases for these functions are also included. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 83 +++++++++++++++++++++++++++++ libfdt/libfdt.h | 5 ++ tests/Makefile.tests | 1 + tests/node_offset_by_compatible.c | 86 +++++++++++++++++++++++++++++++ tests/run_tests.sh | 2 + tests/rw_tree1.c | 7 ++- tests/sw_tree1.c | 7 +++ tests/test_tree1.dts | 4 ++ tests/trees.S | 5 ++ 9 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 tests/node_offset_by_compatible.c diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index a5a15e3..49f2653 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -477,3 +477,86 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, return -FDT_ERR_NOTFOUND; } + +int _stringlist_contains(const void *strlist, int listlen, const char *str) +{ + int len = strlen(str); + const void *p; + + while (listlen >= len) { + if (memcmp(str, strlist, len+1) == 0) + return 1; + p = memchr(strlist, '\0', listlen); + if (!p) + return 0; /* malformed strlist.. */ + listlen -= (p-strlist) + 1; + strlist = p + 1; + } + return 0; +} + +int fdt_node_check_compatible(const void *fdt, int nodeoffset, + const char *compatible) +{ + const void *prop; + int len; + + prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); + if (!prop) + return len; + if (_stringlist_contains(prop, len, compatible)) + return 0; + else + return 1; +} + +int fdt_node_offset_by_compatible(const void *fdt, int startoffset, + const char *compatible) +{ + uint32_t tag; + int offset, nextoffset; + int err; + + CHECK_HEADER(fdt); + + if (startoffset >= 0) { + tag = _fdt_next_tag(fdt, startoffset, &nextoffset); + if (tag != FDT_BEGIN_NODE) + return -FDT_ERR_BADOFFSET; + } else { + nextoffset = 0; + } + + /* FIXME: The algorithm here is pretty horrible: we scan each + * property of a node in fdt_node_check_compatible(), then if + * that didn't find what we want, we scan over them again + * making our way to the next node. Still it's the easiest to + * implement approach; performance can come later. */ + do { + offset = nextoffset; + tag = _fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_BEGIN_NODE: + err = fdt_node_check_compatible(fdt, offset, + compatible); + if ((err < 0) + && (err != -FDT_ERR_NOTFOUND)) + return err; + else if (err == 0) + return offset; + break; + + case FDT_PROP: + case FDT_END: + case FDT_END_NODE: + case FDT_NOP: + break; + + default: + return -FDT_ERR_BADSTRUCTURE; + } + } while (tag != FDT_END); + + return -FDT_ERR_NOTFOUND; +} diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 8b7d501..9bb0fe3 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -153,6 +153,11 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, const char *propname, const void *propval, int proplen); +int fdt_node_check_compatible(const void *fdt, int nodeoffset, + const char *compatible); +int fdt_node_offset_by_compatible(const void *fdt, int startoffset, + const char *compatible); + /* Write-in-place functions */ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len); diff --git a/tests/Makefile.tests b/tests/Makefile.tests index c84b63d..3c3305b 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -2,6 +2,7 @@ LIB_TESTS_L = get_mem_rsv \ root_node find_property subnode_offset path_offset \ get_name getprop get_path supernode_atdepth_offset parent_offset \ node_offset_by_prop_value \ + node_check_compatible node_offset_by_compatible \ notfound \ setprop_inplace nop_property nop_node \ sw_tree1 \ diff --git a/tests/node_offset_by_compatible.c b/tests/node_offset_by_compatible.c new file mode 100644 index 0000000..02e9874 --- /dev/null +++ b/tests/node_offset_by_compatible.c @@ -0,0 +1,86 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_node_offset_by_compatible() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void check_search(void *fdt, const char *compat, ...) +{ + va_list ap; + int offset = -1, target; + + va_start(ap, compat); + do { + target = va_arg(ap, int); + verbose_printf("Searching (target = %d): %d ->", + target, offset); + offset = fdt_node_offset_by_compatible(fdt, offset, compat); + verbose_printf("%d\n", offset); + + if (offset != target) + FAIL("fdt_node_offset_by_compatible(%s) returns %d " + "instead of %d", compat, offset, target); + } while (target >= 0); + + va_end(ap); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + int subnode1_offset, subnode2_offset; + int subsubnode1_offset, subsubnode2_offset; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + subnode1_offset = fdt_path_offset(fdt, "/subnode@1"); + subnode2_offset = fdt_path_offset(fdt, "/subnode@2"); + subsubnode1_offset = fdt_path_offset(fdt, "/subnode@1/subsubnode"); + subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode@0"); + + if ((subnode1_offset < 0) || (subnode2_offset < 0) + || (subsubnode1_offset < 0) || (subsubnode2_offset < 0)) + FAIL("Can't find required nodes"); + + check_search(fdt, "test_tree1", 0, -FDT_ERR_NOTFOUND); + check_search(fdt, "subnode1", subnode1_offset, -FDT_ERR_NOTFOUND); + check_search(fdt, "subsubnode1", subsubnode1_offset, -FDT_ERR_NOTFOUND); + check_search(fdt, "subsubnode2", subsubnode2_offset, -FDT_ERR_NOTFOUND); + /* Eek.. HACK to make this work whatever the order in the + * example tree */ + if (subsubnode1_offset < subsubnode2_offset) + check_search(fdt, "subsubnode", subsubnode1_offset, + subsubnode2_offset, -FDT_ERR_NOTFOUND); + else + check_search(fdt, "subsubnode", subsubnode2_offset, + subsubnode1_offset, -FDT_ERR_NOTFOUND); + check_search(fdt, "nothing-like-this", -FDT_ERR_NOTFOUND); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 6bc20ea..0c2142f 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -42,6 +42,8 @@ tree1_tests () { run_test supernode_atdepth_offset $TREE run_test parent_offset $TREE run_test node_offset_by_prop_value $TREE + run_test node_check_compatible $TREE + run_test node_offset_by_compatible $TREE run_test notfound $TREE # Write-in-place tests diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c index 7835362..d063947 100644 --- a/tests/rw_tree1.c +++ b/tests/rw_tree1.c @@ -72,18 +72,23 @@ int main(int argc, char *argv[]) CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_1, TEST_SIZE_1)); CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2)); + CHECK(fdt_setprop_string(fdt, 0, "compatible", "test_tree1")); CHECK(fdt_setprop_typed(fdt, 0, "prop-int", TEST_VALUE_1)); CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1)); OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@1")); + CHECK(fdt_setprop_string(fdt, offset, "compatible", "subnode1")); CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_1)); OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode")); + CHECK(fdt_setprop(fdt, offset, "compatible", + "subsubnode1\0subsubnode", 23)); CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_1)); OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@2")); CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_2)); OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode@0")); - + CHECK(fdt_setprop(fdt, offset, "compatible", + "subsubnode2\0subsubnode", 23)); CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_2)); CHECK(fdt_pack(fdt)); diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index d4b960e..8784868 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -54,12 +54,17 @@ int main(int argc, char *argv[]) CHECK(fdt_finish_reservemap(fdt)); CHECK(fdt_begin_node(fdt, "")); + CHECK(fdt_property_string(fdt, "compatible", "test_tree1")); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_property_string(fdt, "prop-str", TEST_STRING_1)); CHECK(fdt_begin_node(fdt, "subnode@1")); + CHECK(fdt_property_string(fdt, "compatible", "subnode1")); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_begin_node(fdt, "subsubnode")); + CHECK(fdt_property(fdt, "compatible", "subsubnode1\0subsubnode", + 23)); + CHECK(fdt_property_string(fdt, "compatible", "subsubnode1\0")); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_end_node(fdt)); CHECK(fdt_end_node(fdt)); @@ -67,6 +72,8 @@ int main(int argc, char *argv[]) CHECK(fdt_begin_node(fdt, "subnode@2")); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_2)); CHECK(fdt_begin_node(fdt, "subsubnode@0")); + CHECK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode", + 23)); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_2)); CHECK(fdt_end_node(fdt)); CHECK(fdt_end_node(fdt)); diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts index 212ffa7..c5f8da3 100644 --- a/tests/test_tree1.dts +++ b/tests/test_tree1.dts @@ -2,13 +2,16 @@ /memreserve/ abcd1234 00001234; / { + compatible = "test_tree1"; prop-int = ; prop-str = "hello world"; subnode@1 { + compatible = "subnode1"; prop-int = ; subsubnode { + compatible = "subsubnode1", "subsubnode"; prop-int = ; }; }; @@ -17,6 +20,7 @@ prop-int = ; subsubnode@0 { + compatible = "subsubnode2", "subsubnode"; prop-int = ; }; }; diff --git a/tests/trees.S b/tests/trees.S index bb662a6..c0fbaf6 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -83,13 +83,16 @@ test_tree1_rsvmap: test_tree1_struct: BEGIN_NODE("") + PROP_STR(test_tree1, compatible, "test_tree1") PROP_INT(test_tree1, prop_int, TEST_VALUE_1) PROP_STR(test_tree1, prop_str, TEST_STRING_1) BEGIN_NODE("subnode@1") + PROP_STR(test_tree1, compatible, "subnode1") PROP_INT(test_tree1, prop_int, TEST_VALUE_1) BEGIN_NODE("subsubnode") + PROP_STR(test_tree1, compatible, "subsubnode1\0subsubnode") PROP_INT(test_tree1, prop_int, TEST_VALUE_1) END_NODE END_NODE @@ -98,6 +101,7 @@ test_tree1_struct: PROP_INT(test_tree1, prop_int, TEST_VALUE_2) BEGIN_NODE("subsubnode@0") + PROP_STR(test_tree1, compatible, "subsubnode2\0subsubnode") PROP_INT(test_tree1, prop_int, TEST_VALUE_2) END_NODE END_NODE @@ -106,6 +110,7 @@ test_tree1_struct: FDTLONG(FDT_END) test_tree1_strings: + STRING(test_tree1, compatible, "compatible") STRING(test_tree1, prop_int, "prop-int") STRING(test_tree1, prop_str, "prop-str") test_tree1_end: From a756c12bea9e39acbed483d9008852f3a371e4a4 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 16 Oct 2007 16:42:02 +1000 Subject: [PATCH 0112/1198] dtc: Improve support for string escapes dtc supports the use of C-style escapes (\n, \t and so forth) in string property definitions via the data_copy_escape_string() function. However, while it supports the most common escape characters, it doesn't support the full set that C does, which is a potential gotcha. Worse, a bug in the lexer means that while data_copy_escape_string() can handle the \" escape, a string with such an escape won't lex correctly. This patch fixes both problems, extending data_copy_escape_string() to support the missing escapes, and fixing the regex for strings in the lexer to handle internal escaped quotes. This also adds a testcase for string escape functionality. Signed-off-by: David Gibson --- data.c | 12 ++++++++++++ dtc-lexer.l | 2 +- tests/Makefile.tests | 3 ++- tests/escapes.dts | 4 ++++ tests/run_tests.sh | 3 +++ tests/string_escapes.c | 42 ++++++++++++++++++++++++++++++++++++++++++ tests/testdata.h | 1 + 7 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 tests/escapes.dts create mode 100644 tests/string_escapes.c diff --git a/data.c b/data.c index 1836f08..b8c79c1 100644 --- a/data.c +++ b/data.c @@ -150,12 +150,24 @@ struct data data_copy_escape_string(char *s, int len) c = s[i++]; assert(c); switch (c) { + case 'a': + q[d.len++] = '\a'; + break; + case 'b': + q[d.len++] = '\b'; + break; case 't': q[d.len++] = '\t'; break; case 'n': q[d.len++] = '\n'; break; + case 'v': + q[d.len++] = '\v'; + break; + case 'f': + q[d.len++] = '\f'; + break; case 'r': q[d.len++] = '\r'; break; diff --git a/dtc-lexer.l b/dtc-lexer.l index 08ed106..278a96e 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -69,7 +69,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } } -\"[^"]*\" { +\"([^\\"]|\\.)*\" { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("String: %s\n", yytext); diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 3c3305b..78afc8d 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -7,7 +7,8 @@ LIB_TESTS_L = get_mem_rsv \ setprop_inplace nop_property nop_node \ sw_tree1 \ move_and_save \ - open_pack rw_tree1 setprop del_property del_node + open_pack rw_tree1 setprop del_property del_node \ + string_escapes LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property diff --git a/tests/escapes.dts b/tests/escapes.dts new file mode 100644 index 0000000..236fe13 --- /dev/null +++ b/tests/escapes.dts @@ -0,0 +1,4 @@ +/ { + compatible = "test_string_escapes"; + escape-str = "nastystring: \a\b\t\n\v\f\r\\\"\xff"; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 0c2142f..e048b8f 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -104,6 +104,9 @@ dtc_tests () { run_test dtc.sh -f -I dts -O dtb -o dtc_tree1.test.dtb test_tree1.dts tree1_tests dtc_tree1.test.dtb tree1_tests_rw dtc_tree1.test.dtb + + run_test dtc.sh -f -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts + run_test string_escapes dtc_escapes.test.dtb } while getopts "vdt:" ARG ; do diff --git a/tests/string_escapes.c b/tests/string_escapes.c new file mode 100644 index 0000000..0238502 --- /dev/null +++ b/tests/string_escapes.c @@ -0,0 +1,42 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for string escapes in dtc + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_getprop(fdt, 0, "escape-str", + strlen(TEST_STRING_2)+1, TEST_STRING_2); + + PASS(); +} diff --git a/tests/testdata.h b/tests/testdata.h index 3d08ff7..525177f 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -24,6 +24,7 @@ #define TEST_VALUE_2 cell_to_fdt(0xabcd1234) #define TEST_STRING_1 "hello world" +#define TEST_STRING_2 "nastystring: \a\b\t\n\v\f\r\\\"\xff" #ifndef __ASSEMBLY__ extern struct fdt_header _test_tree1; From 32b6bd349087019d2915f350e9f3f0e64ec69e73 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 17 Oct 2007 11:23:57 +1000 Subject: [PATCH 0113/1198] dtc: Restore missing code for testcases Recent commits 333542fabf8720b881e992a5abca32ef4bcb841a and fd1bf3a5ae46962528ef89a824261a88830758a2 added new testcases to dtc. However, although the testcases were added to the Makefile and run_tests.sh, one of the .c files for the testcase was omitted from the patch in each case. This patch restores the missing testcase code. Signed-off-by: David Gibson --- tests/get_mem_rsv.c | 49 +++++++++++++++++++++++++++ tests/node_check_compatible.c | 62 +++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 tests/get_mem_rsv.c create mode 100644 tests/node_check_compatible.c diff --git a/tests/get_mem_rsv.c b/tests/get_mem_rsv.c new file mode 100644 index 0000000..554c788 --- /dev/null +++ b/tests/get_mem_rsv.c @@ -0,0 +1,49 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_get_mem_rsv() and fdt_num_mem_rsv() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + void *fdt; + int rc; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + rc = fdt_num_mem_rsv(fdt); + if (rc < 0) + FAIL("fdt_num_mem_rsv(): %s", fdt_strerror(rc)); + if (rc != 2) + FAIL("fdt_num_mem_rsv() returned %d instead of 2", rc); + + check_mem_rsv(fdt, 0, TEST_ADDR_1, TEST_SIZE_1); + check_mem_rsv(fdt, 1, TEST_ADDR_2, TEST_SIZE_2); + PASS(); +} diff --git a/tests/node_check_compatible.c b/tests/node_check_compatible.c new file mode 100644 index 0000000..04b6b40 --- /dev/null +++ b/tests/node_check_compatible.c @@ -0,0 +1,62 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_node_check_compatible() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void check_compatible(const void *fdt, const char *path, const char *compat) +{ + int offset, err; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(offset)); + + err = fdt_node_check_compatible(fdt, offset, compat); + if (err < 0) + FAIL("fdt_node_check_compatible(%s): %s", path, + fdt_strerror(err)); + if (err != 0) + FAIL("%s is not compatible with \"%s\"", path, compat); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_compatible(fdt, "/", "test_tree1"); + check_compatible(fdt, "/subnode@1/subsubnode", "subsubnode1"); + check_compatible(fdt, "/subnode@1/subsubnode", "subsubnode"); + check_compatible(fdt, "/subnode@2/subsubnode", "subsubnode2"); + check_compatible(fdt, "/subnode@2/subsubnode", "subsubnode"); + + PASS(); +} From 5a98ddd10af0113d80e08946f9ba5dbc99174402 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 17 Oct 2007 12:39:10 +1000 Subject: [PATCH 0114/1198] dtc: Improve -Odts output This patch makes improvements to the way properties are printed when in dtc is producing dts output. - Characters which need escaping are now properly handled when printing properties as strings - The heuristics for what format to use for a property are improved so that 'compatible' properties will be displayed as expected. - escapes.dts is altered to better demonstrate the changes, and the string_escapes testcase is adjusted accordingly. Signed-off-by: David Gibson --- tests/escapes.dts | 3 +- tests/string_escapes.c | 2 + tests/testdata.h | 3 +- treesource.c | 124 ++++++++++++++++++++++++++++++++--------- 4 files changed, 103 insertions(+), 29 deletions(-) diff --git a/tests/escapes.dts b/tests/escapes.dts index 236fe13..f1b8dbc 100644 --- a/tests/escapes.dts +++ b/tests/escapes.dts @@ -1,4 +1,5 @@ / { compatible = "test_string_escapes"; - escape-str = "nastystring: \a\b\t\n\v\f\r\\\"\xff"; + escape-str = "nastystring: \a\b\t\n\v\f\r\\\""; + escape-str-2 = "\xde\xad\xbe\xef"; }; diff --git a/tests/string_escapes.c b/tests/string_escapes.c index 0238502..30eb6a8 100644 --- a/tests/string_escapes.c +++ b/tests/string_escapes.c @@ -37,6 +37,8 @@ int main(int argc, char *argv[]) check_getprop(fdt, 0, "escape-str", strlen(TEST_STRING_2)+1, TEST_STRING_2); + check_getprop(fdt, 0, "escape-str-2", + strlen(TEST_STRING_3)+1, TEST_STRING_3); PASS(); } diff --git a/tests/testdata.h b/tests/testdata.h index 525177f..94f3dee 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -24,7 +24,8 @@ #define TEST_VALUE_2 cell_to_fdt(0xabcd1234) #define TEST_STRING_1 "hello world" -#define TEST_STRING_2 "nastystring: \a\b\t\n\v\f\r\\\"\xff" +#define TEST_STRING_2 "nastystring: \a\b\t\n\v\f\r\\\"" +#define TEST_STRING_3 "\xde\xad\xbe\xef" #ifndef __ASSEMBLY__ extern struct fdt_header _test_tree1; diff --git a/treesource.c b/treesource.c index a04c173..f62041f 100644 --- a/treesource.c +++ b/treesource.c @@ -56,22 +56,31 @@ enum proptype { PROP_BYTES, }; +int isstring(char c) +{ + return (isprint(c) + || (c == '\0') + || strchr("\a\b\t\n\v\f\r", c)); +} + static enum proptype guess_type(struct property *prop) { int len = prop->val.len; char *p = prop->val.val; - int nnoprint = 0; + int nnotstring = 0, nnul = 0; int i; if (len == 0) return PROP_EMPTY; for (i = 0; i < len; i++) { - if (! isprint(p[i])) - nnoprint++; + if (! isstring(p[i])) + nnotstring++; + if (p[i] == '\0') + nnul++; } - if ((nnoprint == 1) && (p[len-1] == '\0')) + if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))) return PROP_STRING; else if ((len % sizeof(cell_t)) == 0) return PROP_CELLS; @@ -79,6 +88,87 @@ static enum proptype guess_type(struct property *prop) return PROP_BYTES; } +static void write_propval_string(FILE *f, struct data val) +{ + char *str = val.val; + int i; + + assert(str[val.len-1] == '\0'); + + fprintf(f, " = \""); + for (i = 0; i < (val.len-1); i++) { + char c = str[i]; + + switch (c) { + case '\a': + fprintf(f, "\\a"); + break; + case '\b': + fprintf(f, "\\b"); + break; + case '\t': + fprintf(f, "\\t"); + break; + case '\n': + fprintf(f, "\\n"); + break; + case '\v': + fprintf(f, "\\v"); + break; + case '\f': + fprintf(f, "\\f"); + break; + case '\r': + fprintf(f, "\\r"); + break; + case '\\': + fprintf(f, "\\\\"); + break; + case '\"': + fprintf(f, "\\\""); + break; + case '\0': + fprintf(f, "\", \""); + break; + default: + if (isprint(c)) + fprintf(f, "%c", c); + else + fprintf(f, "\\x%02hhx", c); + } + } + fprintf(f, "\";\n"); +} + +static void write_propval_cells(FILE *f, struct data val) +{ + void *propend = val.val + val.len; + cell_t *cp = (cell_t *)val.val; + + fprintf(f, " = <"); + for (;;) { + fprintf(f, "%x", be32_to_cpu(*cp++)); + if ((void *)cp >= propend) + break; + fprintf(f, " "); + } + fprintf(f, ">;\n"); +} + +static void write_propval_bytes(FILE *f, struct data val) +{ + void *propend = val.val + val.len; + char *bp = val.val; + + fprintf(f, " = ["); + for (;;) { + fprintf(f, "%02hhx", *bp++); + if ((void *)bp >= propend) + break; + fprintf(f, " "); + } + fprintf(f, "];\n"); +} static void write_tree_source_node(FILE *f, struct node *tree, int level) { @@ -92,15 +182,11 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) fprintf(f, "/ {\n"); for_each_property(tree, prop) { - cell_t *cp; - char *bp; - void *propend; enum proptype type; write_prefix(f, level); fprintf(f, "\t%s", prop->name); type = guess_type(prop); - propend = prop->val.val + prop->val.len; switch (type) { case PROP_EMPTY: @@ -108,31 +194,15 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) break; case PROP_STRING: - fprintf(f, " = \"%s\";\n", (char *)prop->val.val); + write_propval_string(f, prop->val); break; case PROP_CELLS: - fprintf(f, " = <"); - cp = (cell_t *)prop->val.val; - for (;;) { - fprintf(f, "%x", be32_to_cpu(*cp++)); - if ((void *)cp >= propend) - break; - fprintf(f, " "); - } - fprintf(f, ">;\n"); + write_propval_cells(f, prop->val); break; case PROP_BYTES: - fprintf(f, " = ["); - bp = prop->val.val; - for (;;) { - fprintf(f, "%02hhx", *bp++); - if ((void *)bp >= propend) - break; - fprintf(f, " "); - } - fprintf(f, "];\n"); + write_propval_bytes(f, prop->val); break; } } From 11d530202172f1705c9e1e01e6de1642df94479d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 18 Oct 2007 12:10:42 +1000 Subject: [PATCH 0115/1198] libfdt: Make fdt_string() return a const pointer Currently, fdt_string() returns a (non-const) char *, despite taking a const void *fdt. This is inconsistent with all the other read-only functions which all return const pointers into the blob. This patch fixes that. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 2 +- libfdt/libfdt.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 49f2653..ebd3d01 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -82,7 +82,7 @@ static int nodename_eq(const void *fdt, int offset, return 0; } -char *fdt_string(const void *fdt, int stroffset) +const char *fdt_string(const void *fdt, int stroffset) { return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset; } diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 9bb0fe3..8d15155 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -110,7 +110,7 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) int fdt_move(const void *fdt, void *buf, int bufsize); /* Read-only functions */ -char *fdt_string(const void *fdt, int stroffset); +const char *fdt_string(const void *fdt, int stroffset); int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); int fdt_num_mem_rsv(const void *fdt); From d7649da4b9bfa4e8ed762d765cdb95db06b13399 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 18 Oct 2007 14:14:09 +1000 Subject: [PATCH 0116/1198] dtc: Make helper macros in trees.S more flexible This patch makes the helper macros in trees.S use separate labels for the end of each dt subblock, rather than using only start labels. This means that the macros can now be used to create trees with the subblocks in non-standard orders. In addition, it adds a bunch of extra ; after lines of asm code in macros, making them safe to use in nested macros. Signed-off-by: David Gibson --- tests/trees.S | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/tests/trees.S b/tests/trees.S index c0fbaf6..42a9f7a 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -5,7 +5,7 @@ .byte ((val) >> 24) & 0xff ; \ .byte ((val) >> 16) & 0xff ; \ .byte ((val) >> 8) & 0xff ; \ - .byte (val) & 0xff + .byte (val) & 0xff ; #define FDTQUAD(val) \ .byte ((val) >> 56) & 0xff ; \ @@ -15,10 +15,10 @@ .byte ((val) >> 24) & 0xff ; \ .byte ((val) >> 16) & 0xff ; \ .byte ((val) >> 8) & 0xff ; \ - .byte (val) & 0xff + .byte (val) & 0xff ; #define TREE_HDR(tree) \ - .balign 4 ; \ + .balign 8 ; \ .globl _##tree ; \ _##tree: \ tree: \ @@ -30,17 +30,18 @@ tree: \ FDTLONG(0x11) ; \ FDTLONG(0x10) ; \ FDTLONG(0) ; \ - FDTLONG(tree##_end - tree##_strings) ; \ - FDTLONG(tree##_strings - tree##_struct) ; + FDTLONG(tree##_strings_end - tree##_strings) ; \ + FDTLONG(tree##_struct_end - tree##_struct) ; #define RSVMAP_ENTRY(addr, len) \ FDTQUAD(addr) ; \ - FDTQUAD(len) ; + FDTQUAD(len) ; \ #define EMPTY_RSVMAP(tree) \ .balign 8 ; \ tree##_rsvmap: ; \ - RSVMAP_ENTRY(0, 0) + RSVMAP_ENTRY(0, 0) \ +tree##_rsvmap_end: ; #define PROPHDR(tree, name, len) \ FDTLONG(FDT_PROP) ; \ @@ -50,26 +51,26 @@ tree##_rsvmap: ; \ #define PROP_INT(tree, name, val) \ PROPHDR(tree, name, 4) \ /* For ease of testing the property values go in native-endian */ \ - .long val + .long val ; #define PROP_STR(tree, name, str) \ PROPHDR(tree, name, 55f - 54f) \ 54: \ .string str ; \ 55: \ - .balign 4 + .balign 4 ; #define BEGIN_NODE(name) \ FDTLONG(FDT_BEGIN_NODE) ; \ .string name ; \ - .balign 4 + .balign 4 ; #define END_NODE \ FDTLONG(FDT_END_NODE) ; #define STRING(tree, name, str) \ -tree##_##name: \ - .string str +tree##_##name: ; \ + .string str ; .data @@ -80,6 +81,7 @@ test_tree1_rsvmap: RSVMAP_ENTRY(TEST_ADDR_1, TEST_SIZE_1) RSVMAP_ENTRY(TEST_ADDR_2, TEST_SIZE_2) RSVMAP_ENTRY(0, 0) +test_tree1_rsvmap_end: test_tree1_struct: BEGIN_NODE("") @@ -108,13 +110,16 @@ test_tree1_struct: END_NODE 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_str, "prop-str") +test_tree1_strings_end: test_tree1_end: + TREE_HDR(truncated_property) EMPTY_RSVMAP(truncated_property) @@ -122,7 +127,10 @@ truncated_property_struct: BEGIN_NODE("") 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") +truncated_property_strings_end: + truncated_property_end: From 394e47208df7e3b22c089745695f41966d100f3e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 18 Oct 2007 14:17:25 +1000 Subject: [PATCH 0117/1198] libfdt: Add missing RW_CHECK_HEADER to fdt_del_node() fdt_del_node(), unlike most of the rw functions does not check the fdt's header with RW_CHECK_HEADER. However, it could make a mess of things if the conditions in RW_CHECK_HEADER aren't met. So, this patch adds the omitted check. Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 85b6281..ff74e3c 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -329,6 +329,8 @@ int fdt_del_node(void *fdt, int nodeoffset) { int endoffset; + RW_CHECK_HEADER(fdt); + endoffset = _fdt_node_end_offset(fdt, nodeoffset); if (endoffset < 0) return endoffset; From 169f0b183d45b87ba6dfc194792aee6170ffb54d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 18 Oct 2007 17:22:30 +1000 Subject: [PATCH 0118/1198] dtc: Disable semantic checks by default At present, dtc makes a lot of semantic checks on the device tree by default, and will refuse to produce output if they fail. This means people tend to need -f to force output despite failing semantic checks rather a lot. This patch splits the device tree checks into structural checks (no bad or duplicate names or phandles) and semantic checks (everything else). By default, only the structural checks are performed, and are fatal. -f will force output even with structural errors (using this in -Idts mode would essentially always be a bad idea, but it might be useful in -Idtb mode for examining a malformed dtb). Semantic checks are only performed if the new -c command line option is supplied, and are always warnings only. Semantic checks will never be performed on a tree with structural errors. This patch is only a stopgap before implementing proper fine-grained error/warning handling, but it should at least get rid of the far-too-frequent need for -f for the time being. This patch removes the -f from the dtc testcases now that it's no longer necessary. Signed-off-by: David Gibson --- dtc.c | 31 +++- dtc.h | 4 + livetree.c | 370 +++++++++++++++++++++++---------------------- tests/run_tests.sh | 4 +- 4 files changed, 217 insertions(+), 192 deletions(-) diff --git a/dtc.c b/dtc.c index 76a6dfe..bbef829 100644 --- a/dtc.c +++ b/dtc.c @@ -112,19 +112,20 @@ int main(int argc, char *argv[]) char *inform = "dts"; char *outform = "dts"; char *outname = "-"; - int force = 0; + int force = 0, check = 0; char *arg; int opt; FILE *inf = NULL; FILE *outf = NULL; int outversion = DEFAULT_FDT_VERSION; int boot_cpuid_phys = 0xfeedbeef; + int structure_ok; quiet = 0; reservenum = 0; minsize = 0; - while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:fqb:v")) != EOF) { + while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:fcqb:v")) != EOF) { switch (opt) { case 'I': inform = optarg; @@ -147,6 +148,9 @@ int main(int argc, char *argv[]) case 'f': force = 1; break; + case 'c': + check = 1; + break; case 'q': quiet++; break; @@ -189,12 +193,25 @@ int main(int argc, char *argv[]) if (! bi || ! bi->dt) die("Couldn't read input tree\n"); - if (! check_device_tree(bi->dt, outversion, boot_cpuid_phys)) { - if ((force) && (quiet < 3)) - fprintf(stderr, "Input tree has errors, output forced\n"); - if (! force) { - fprintf(stderr, "Input tree has errors, not writing output (use -f to force output)\n"); + structure_ok = check_structure(bi->dt); + if (!structure_ok) { + if (!force) { + fprintf(stderr, "ERROR: Input tree has structural errors, aborting (use -f to force output)\n"); exit(1); + } else if (quiet < 3) { + fprintf(stderr, "Warning: Input tree has structural errors, output forced\n"); + } + } + + fixup_references(bi->dt); + + if (check) { + if (!structure_ok) { + fprintf(stderr, "Warning: Skipping semantic checks due to structural errors\n"); + } else { + if (!check_semantics(bi->dt, outversion, + boot_cpuid_phys)) + fprintf(stderr, "Warning: Input tree has semantic errors\n"); } } diff --git a/dtc.h b/dtc.h index 09dec54..77494af 100644 --- a/dtc.h +++ b/dtc.h @@ -188,6 +188,10 @@ struct node *chain_node(struct node *first, struct node *list); void add_property(struct node *node, struct property *prop); void add_child(struct node *parent, struct node *child); +int check_structure(struct node *dt); +void fixup_references(struct node *dt); +int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys); + int check_device_tree(struct node *dt, int outversion, int boot_cpuid_phys); /* Boot info (tree plus memreserve information */ diff --git a/livetree.c b/livetree.c index 3b6542f..aa81d12 100644 --- a/livetree.c +++ b/livetree.c @@ -149,6 +149,18 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list, return list; } +struct boot_info *build_boot_info(struct reserve_info *reservelist, + struct node *tree) +{ + struct boot_info *bi; + + bi = xmalloc(sizeof(*bi)); + bi->reservelist = reservelist; + bi->dt = tree; + + return bi; +} + /* * Tree accessor functions */ @@ -248,13 +260,178 @@ static struct node *get_node_by_phandle(struct node *tree, cell_t phandle) return NULL; } +static cell_t get_node_phandle(struct node *root, struct node *node) +{ + static cell_t phandle = 1; /* FIXME: ick, static local */ + + if ((node->phandle != 0) && (node->phandle != -1)) + return node->phandle; + + assert(! get_property(node, "linux,phandle")); + + while (get_node_by_phandle(root, phandle)) + phandle++; + + node->phandle = phandle; + add_property(node, + build_property("linux,phandle", + data_append_cell(empty_data, phandle), + NULL)); + + return node->phandle; +} + /* - * Tree checking functions + * Structural check functions */ #define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__) #define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__) +#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0) + +static int check_names(struct node *tree) +{ + struct node *child, *child2; + struct property *prop, *prop2; + int len = strlen(tree->name); + int ok = 1; + + if (len == 0 && tree->parent) + DO_ERR("Empty, non-root nodename at %s\n", tree->fullpath); + + if (len > MAX_NODENAME_LEN) + WARNMSG("Overlength nodename at %s\n", tree->fullpath); + + for_each_property(tree, prop) { + /* check for duplicates */ + /* FIXME: do this more efficiently */ + for (prop2 = prop->next; prop2; prop2 = prop2->next) { + if (streq(prop->name, prop2->name)) { + DO_ERR("Duplicate propertyname %s in node %s\n", + prop->name, tree->fullpath); + } + } + + /* check name length */ + if (strlen(prop->name) > MAX_PROPNAME_LEN) + WARNMSG("Property name %s is too long in %s\n", + prop->name, tree->fullpath); + } + + for_each_child(tree, child) { + /* Check for duplicates */ + + for (child2 = child->next_sibling; + child2; + child2 = child2->next_sibling) { + if (streq(child->name, child2->name)) + DO_ERR("Duplicate node name %s\n", + child->fullpath); + } + if (! check_names(child)) + ok = 0; + } + + return ok; +} + +static int check_phandles(struct node *root, struct node *node) +{ + struct property *prop; + struct node *child, *other; + cell_t phandle; + int ok = 1; + + prop = get_property(node, "linux,phandle"); + if (prop) { + phandle = propval_cell(prop); + if ((phandle == 0) || (phandle == -1)) { + DO_ERR("%s has invalid linux,phandle %x\n", + node->fullpath, phandle); + } else { + other = get_node_by_phandle(root, phandle); + if (other) + DO_ERR("%s has duplicated phandle %x (seen before at %s)\n", + node->fullpath, phandle, other->fullpath); + + node->phandle = phandle; + } + } + + for_each_child(node, child) + ok = ok && check_phandles(root, child); + + return 1; +} + +int check_structure(struct node *dt) +{ + int ok = 1; + + ok = ok && check_names(dt); + ok = ok && check_phandles(dt, dt); + + return ok; +} + +/* + * Reference fixup functions + */ + +static void apply_fixup(struct node *root, struct property *prop, + struct fixup *f) +{ + struct node *refnode; + cell_t phandle; + + if (f->ref[0] == '/') { + /* Reference to full path */ + refnode = get_node_by_path(root, f->ref); + if (! refnode) + die("Reference to non-existent node \"%s\"\n", f->ref); + } else { + refnode = get_node_by_label(root, f->ref); + if (! refnode) + die("Reference to non-existent node label \"%s\"\n", f->ref); + } + + phandle = get_node_phandle(root, refnode); + + assert(f->offset + sizeof(cell_t) <= prop->val.len); + + *((cell_t *)(prop->val.val + f->offset)) = cpu_to_be32(phandle); +} + +static void fixup_phandles(struct node *root, struct node *node) +{ + struct property *prop; + struct node *child; + + for_each_property(node, prop) { + struct fixup *f = prop->val.refs; + + while (f) { + apply_fixup(root, prop, f); + prop->val.refs = f->next; + fixup_free(f); + f = prop->val.refs; + } + } + + for_each_child(node, child) + fixup_phandles(root, child); +} + +void fixup_references(struct node *dt) +{ + fixup_phandles(dt, dt); +} + +/* + * Semantic check functions + */ + static int must_be_one_cell(struct property *prop, struct node *node) { if (prop->val.len != sizeof(cell_t)) { @@ -315,82 +492,24 @@ static struct { {"device_type", must_be_string}, }; -#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0) - static int check_properties(struct node *node) { - struct property *prop, *prop2; + struct property *prop; + struct node *child; + int i; int ok = 1; - for_each_property(node, prop) { - int i; - - /* check for duplicates */ - /* FIXME: do this more efficiently */ - for (prop2 = prop->next; prop2; prop2 = prop2->next) { - if (streq(prop->name, prop2->name)) { - DO_ERR("Duplicate propertyname %s in node %s\n", - prop->name, node->fullpath); - } - } - - /* check name length */ - if (strlen(prop->name) > MAX_PROPNAME_LEN) - WARNMSG("Property name %s is too long in %s\n", - prop->name, node->fullpath); - - /* check this property */ - for (i = 0; i < ARRAY_SIZE(prop_checker_table); i++) { + for_each_property(node, prop) + for (i = 0; i < ARRAY_SIZE(prop_checker_table); i++) if (streq(prop->name, prop_checker_table[i].propname)) if (! prop_checker_table[i].check_fn(prop, node)) { ok = 0; break; } - } - } - return ok; -} - -static int check_node_name(struct node *node) -{ - int ok = 1; - int len = strlen(node->name); - - if (len == 0 && node->parent) - DO_ERR("Empty, non-root nodename at %s\n", node->fullpath); - - if (len > MAX_NODENAME_LEN) - DO_ERR("Overlength nodename at %s\n", node->fullpath); - - - return ok; -} - -static int check_structure(struct node *tree) -{ - struct node *child, *child2; - int ok = 1; - - if (! check_node_name(tree)) - ok = 0; - - if (! check_properties(tree)) - ok = 0; - - for_each_child(tree, child) { - /* Check for duplicates */ - - for (child2 = child->next_sibling; - child2; - child2 = child2->next_sibling) { - if (streq(child->name, child2->name)) - DO_ERR("Duplicate node name %s\n", - child->fullpath); - } - if (! check_structure(child)) + for_each_child(node, child) + if (! check_properties(child)) ok = 0; - } return ok; } @@ -638,115 +757,12 @@ static int check_addr_size_reg(struct node *node, return ok; } -static int check_phandles(struct node *root, struct node *node) -{ - struct property *prop; - struct node *child, *other; - cell_t phandle; - int ok = 1; - - prop = get_property(node, "linux,phandle"); - if (prop) { - phandle = propval_cell(prop); - if ((phandle == 0) || (phandle == -1)) { - DO_ERR("%s has invalid linux,phandle %x\n", - node->fullpath, phandle); - } else { - other = get_node_by_phandle(root, phandle); - if (other) - DO_ERR("%s has duplicated phandle %x (seen before at %s)\n", - node->fullpath, phandle, other->fullpath); - - node->phandle = phandle; - } - } - - for_each_child(node, child) - ok = ok && check_phandles(root, child); - - return 1; -} - -static cell_t get_node_phandle(struct node *root, struct node *node) -{ - static cell_t phandle = 1; /* FIXME: ick, static local */ - - if ((node->phandle != 0) && (node->phandle != -1)) - return node->phandle; - - assert(! get_property(node, "linux,phandle")); - - while (get_node_by_phandle(root, phandle)) - phandle++; - - node->phandle = phandle; - add_property(node, - build_property("linux,phandle", - data_append_cell(empty_data, phandle), - NULL)); - - return node->phandle; -} - -static void apply_fixup(struct node *root, struct property *prop, - struct fixup *f) -{ - struct node *refnode; - cell_t phandle; - - if (f->ref[0] == '/') { - /* Reference to full path */ - refnode = get_node_by_path(root, f->ref); - if (! refnode) - die("Reference to non-existent node \"%s\"\n", f->ref); - } else { - refnode = get_node_by_label(root, f->ref); - if (! refnode) - die("Reference to non-existent node label \"%s\"\n", f->ref); - } - - phandle = get_node_phandle(root, refnode); - - assert(f->offset + sizeof(cell_t) <= prop->val.len); - - *((cell_t *)(prop->val.val + f->offset)) = cpu_to_be32(phandle); -} - -static void fixup_phandles(struct node *root, struct node *node) -{ - struct property *prop; - struct node *child; - - for_each_property(node, prop) { - struct fixup *f = prop->val.refs; - - while (f) { - apply_fixup(root, prop, f); - prop->val.refs = f->next; - fixup_free(f); - f = prop->val.refs; - } - } - - for_each_child(node, child) - fixup_phandles(root, child); -} - -int check_device_tree(struct node *dt, int outversion, int boot_cpuid_phys) +int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys) { int ok = 1; - if (! check_structure(dt)) - return 0; - + ok = ok && check_properties(dt); ok = ok && check_addr_size_reg(dt, -1, -1); - ok = ok && check_phandles(dt, dt); - - fixup_phandles(dt, dt); - - if (! ok) - return 0; - ok = ok && check_root(dt); ok = ok && check_cpus(dt, outversion, boot_cpuid_phys); ok = ok && check_memory(dt); @@ -756,15 +772,3 @@ int check_device_tree(struct node *dt, int outversion, int boot_cpuid_phys) return 1; } - -struct boot_info *build_boot_info(struct reserve_info *reservelist, - struct node *tree) -{ - struct boot_info *bi; - - bi = xmalloc(sizeof(*bi)); - bi->reservelist = reservelist; - bi->dt = tree; - - return bi; -} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index e048b8f..9d8892d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -101,11 +101,11 @@ libfdt_tests () { } dtc_tests () { - run_test dtc.sh -f -I dts -O dtb -o dtc_tree1.test.dtb test_tree1.dts + run_test dtc.sh -I dts -O dtb -o dtc_tree1.test.dtb test_tree1.dts tree1_tests dtc_tree1.test.dtb tree1_tests_rw dtc_tree1.test.dtb - run_test dtc.sh -f -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts + run_test dtc.sh -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts run_test string_escapes dtc_escapes.test.dtb } From e321e51036932badbdc7eb3fbade7f325e9f9204 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 22 Oct 2007 14:09:23 +1000 Subject: [PATCH 0119/1198] dtc: data.c doesn't need to include dtc-parser.tab.h Presumably we used this #include once, but it's certainly not necessary now. Signed-off-by: David Gibson --- data.c | 1 - 1 file changed, 1 deletion(-) diff --git a/data.c b/data.c index b8c79c1..b6cd00e 100644 --- a/data.c +++ b/data.c @@ -19,7 +19,6 @@ */ #include "dtc.h" -#include "dtc-parser.tab.h" void fixup_free(struct fixup *f) { From 30807ca1ce48ac578ec5f00c47065c875c530608 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Thu, 18 Oct 2007 09:42:16 -0500 Subject: [PATCH 0120/1198] Reformat grammar rules to not mix language syntax and yacc syntax. Use consistent indenting on all rule actions. Signed-off-by: Jon Loeliger Acked-by: David Gibson --- dtc-parser.y | 152 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 118 insertions(+), 34 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 54fd787..4698793 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -79,103 +79,187 @@ extern struct boot_info *the_boot_info; %% -sourcefile: memreserves devicetree { +sourcefile: + memreserves devicetree + { the_boot_info = build_boot_info($1, $2); } ; -memreserves: memreserve memreserves { +memreserves: + memreserve memreserves + { $$ = chain_reserve_entry($1, $2); } - | /* empty */ { + | /* empty */ + { $$ = NULL; } ; -memreserve: label DT_MEMRESERVE DT_ADDR DT_ADDR ';' { +memreserve: + label DT_MEMRESERVE DT_ADDR DT_ADDR ';' + { $$ = build_reserve_entry($3, $4, $1); } - | label DT_MEMRESERVE DT_ADDR '-' DT_ADDR ';' { + | label DT_MEMRESERVE DT_ADDR '-' DT_ADDR ';' + { $$ = build_reserve_entry($3, $5 - $3 + 1, $1); } ; -devicetree: '/' nodedef { +devicetree: + '/' nodedef + { $$ = name_node($2, "", NULL); } ; -nodedef: '{' proplist subnodes '}' ';' { +nodedef: + '{' proplist subnodes '}' ';' + { $$ = build_node($2, $3); } ; -proplist: propdef proplist { +proplist: + propdef proplist + { $$ = chain_property($1, $2); } - | /* empty */ { + | /* empty */ + { $$ = NULL; } ; -propdef: label DT_PROPNAME '=' propdata ';' { +propdef: + label DT_PROPNAME '=' propdata ';' + { $$ = build_property($2, $4, $1); } - | label DT_PROPNAME ';' { + | label DT_PROPNAME ';' + { $$ = build_property($2, empty_data, $1); } ; -propdata: propdataprefix DT_STRING { $$ = data_merge($1, $2); } - | propdataprefix '<' celllist '>' { - $$ = data_merge(data_append_align($1, sizeof(cell_t)), $3); +propdata: + propdataprefix DT_STRING + { + $$ = data_merge($1, $2); + } + | propdataprefix '<' celllist '>' + { + $$ = data_merge(data_append_align($1, + sizeof(cell_t)), $3); + } + | propdataprefix '[' bytestring ']' + { + $$ = data_merge($1, $3); + } + | propdata DT_LABEL + { + $$ = data_add_label($1, $2); } - | propdataprefix '[' bytestring ']' { $$ = data_merge($1, $3); } - | propdata DT_LABEL { $$ = data_add_label($1, $2); } ; -propdataprefix: propdata ',' { $$ = $1; } - | propdataprefix DT_LABEL { $$ = data_add_label($1, $2); } - | /* empty */ { $$ = empty_data; } +propdataprefix: + propdata ',' + { + $$ = $1; + } + | propdataprefix DT_LABEL + { + $$ = data_add_label($1, $2); + } + | /* empty */ + { + $$ = empty_data; + } ; opt_cell_base: /* empty */ - { $$ = 16; } + { + $$ = 16; + } | DT_BASE ; -celllist: celllist opt_cell_base DT_CELL { +celllist: + celllist opt_cell_base DT_CELL + { $$ = data_append_cell($1, cell_from_string($3, $2)); } - | celllist DT_REF { + | celllist DT_REF + { $$ = data_append_cell(data_add_fixup($1, $2), -1); } - | celllist DT_LABEL { $$ = data_add_label($1, $2); } - | /* empty */ { $$ = empty_data; } + | celllist DT_LABEL + { + $$ = data_add_label($1, $2); + } + | /* empty */ + { + $$ = empty_data; + } ; -bytestring: bytestring DT_BYTE { $$ = data_append_byte($1, $2); } - | bytestring DT_LABEL { $$ = data_add_label($1, $2); } - | /* empty */ { $$ = empty_data; } +bytestring: + bytestring DT_BYTE + { + $$ = data_append_byte($1, $2); + } + | bytestring DT_LABEL + { + $$ = data_add_label($1, $2); + } + | /* empty */ + { + $$ = empty_data; + } ; -subnodes: subnode subnodes { +subnodes: + subnode subnodes + { $$ = chain_node($1, $2); } - | /* empty */ { $$ = NULL; } + | /* empty */ + { + $$ = NULL; + } ; -subnode: label nodename nodedef { $$ = name_node($3, $2, $1); } +subnode: + label nodename nodedef + { + $$ = name_node($3, $2, $1); + } ; -nodename: DT_NODENAME { $$ = $1; } - | DT_PROPNAME { $$ = $1; } +nodename: + DT_NODENAME + { + $$ = $1; + } + | DT_PROPNAME + { + $$ = $1; + } ; -label: DT_LABEL { $$ = $1; } - | /* empty */ { $$ = NULL; } +label: + DT_LABEL + { + $$ = $1; + } + | /* empty */ + { + $$ = NULL; + } ; %% From 5641289a4647db43c0fdccee25da020ca04d03ad Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Tue, 23 Oct 2007 09:28:54 -0500 Subject: [PATCH 0121/1198] DTC: Minor grammar rule shuffle. I like to see the basis cases established early in the rule sets, so place "empty" reduction first. Purely cosmetic. Signed-off-by: Jon Loeliger Acked-by: David Gibson --- dtc-parser.y | 70 ++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 4698793..8e6ed64 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -87,14 +87,14 @@ sourcefile: ; memreserves: - memreserve memreserves - { - $$ = chain_reserve_entry($1, $2); - } - | /* empty */ + /* empty */ { $$ = NULL; } + | memreserve memreserves + { + $$ = chain_reserve_entry($1, $2); + } ; memreserve: @@ -123,14 +123,14 @@ nodedef: ; proplist: - propdef proplist - { - $$ = chain_property($1, $2); - } - | /* empty */ + /* empty */ { $$ = NULL; } + | propdef proplist + { + $$ = chain_property($1, $2); + } ; propdef: @@ -165,7 +165,11 @@ propdata: ; propdataprefix: - propdata ',' + /* empty */ + { + $$ = empty_data; + } + | propdata ',' { $$ = $1; } @@ -173,10 +177,6 @@ propdataprefix: { $$ = data_add_label($1, $2); } - | /* empty */ - { - $$ = empty_data; - } ; opt_cell_base: @@ -188,7 +188,11 @@ opt_cell_base: ; celllist: - celllist opt_cell_base DT_CELL + /* empty */ + { + $$ = empty_data; + } + | celllist opt_cell_base DT_CELL { $$ = data_append_cell($1, cell_from_string($3, $2)); @@ -201,14 +205,14 @@ celllist: { $$ = data_add_label($1, $2); } - | /* empty */ - { - $$ = empty_data; - } ; bytestring: - bytestring DT_BYTE + /* empty */ + { + $$ = empty_data; + } + | bytestring DT_BYTE { $$ = data_append_byte($1, $2); } @@ -216,21 +220,17 @@ bytestring: { $$ = data_add_label($1, $2); } - | /* empty */ - { - $$ = empty_data; - } ; subnodes: - subnode subnodes - { - $$ = chain_node($1, $2); - } - | /* empty */ + /* empty */ { $$ = NULL; } + | subnode subnodes + { + $$ = chain_node($1, $2); + } ; subnode: @@ -252,14 +252,14 @@ nodename: ; label: - DT_LABEL - { - $$ = $1; - } - | /* empty */ + /* empty */ { $$ = NULL; } + | DT_LABEL + { + $$ = $1; + } ; %% From 7dfba39a23c6d18efbfe40b699106c13e03a4658 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Mon, 22 Oct 2007 16:37:31 -0500 Subject: [PATCH 0122/1198] DTC: Remove an unneeded %token definition. Signed-off-by: Jon Loeliger Acked-by: David Gibson --- dtc-parser.y | 1 - 1 file changed, 1 deletion(-) diff --git a/dtc-parser.y b/dtc-parser.y index 8e6ed64..33cf540 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -56,7 +56,6 @@ extern struct boot_info *the_boot_info; %token DT_CELL %token DT_BYTE %token DT_STRING -%token DT_UNIT %token DT_LABEL %token DT_REF From afa8c2e1d755f1f963e3ebe1fed01e49f6b16515 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Thu, 18 Oct 2007 09:49:45 -0500 Subject: [PATCH 0123/1198] Appease the printf() format $Gods with a correct type. Signed-off-by: Jon Loeliger --- tests/get_name.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/get_name.c b/tests/get_name.c index 2481741..22003b4 100644 --- a/tests/get_name.c +++ b/tests/get_name.c @@ -54,7 +54,7 @@ void check_name(void *fdt, const char *path) path, getname, checkname); if (len != strlen(getname)) - FAIL("fdt_get_name(%s) returned length %d instead of %d", + FAIL("fdt_get_name(%s) returned length %d instead of %zd", path, len, strlen(getname)); /* Now check that it doesn't break if we omit len */ From 2d50f8f9dd504f2a7b7662edd47419ad0e4c21a5 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Thu, 18 Oct 2007 09:46:52 -0500 Subject: [PATCH 0124/1198] Quiet a bogus "May be used uninitialized" warning. Signed-off-by: Jon Loeliger --- flattree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flattree.c b/flattree.c index a26e71b..5889900 100644 --- a/flattree.c +++ b/flattree.c @@ -136,7 +136,7 @@ static void asm_emit_cell(void *e, cell_t val) static void asm_emit_string(void *e, char *str, int len) { FILE *f = e; - char c; + char c = 0; if (len != 0) { /* XXX: ewww */ From 96b5fad3a12697b8f2a50dbca944bd44c6f4eec8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 24 Oct 2007 10:28:52 +1000 Subject: [PATCH 0125/1198] libfdt: Rename and publish _fdt_check_header() It's potentially useful for users of libfdt to sanity check a device tree (or, rather, a blob of data which may or may not be a device tree) before processing it in more detail with libfdt. This patch renames the libfdt internal function _fdt_check_header() to fdt_check_header() and makes it a published function, so it can now be used for this purpose. Signed-off-by: David Gibson --- libfdt/fdt.c | 4 ++-- libfdt/fdt_ro.c | 6 +++--- libfdt/fdt_rw.c | 2 +- libfdt/libfdt.h | 29 +++++++++++++++++------------ libfdt/libfdt_internal.h | 1 - 5 files changed, 23 insertions(+), 19 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index a29f1b0..2911b42 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -55,7 +55,7 @@ #include "libfdt_internal.h" -int _fdt_check_header(const void *fdt) +int fdt_check_header(const void *fdt) { if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ @@ -143,7 +143,7 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) int fdt_move(const void *fdt, void *buf, int bufsize) { - int err = _fdt_check_header(fdt); + int err = fdt_check_header(fdt); if (err) return err; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index ebd3d01..f39785f 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -58,7 +58,7 @@ #define CHECK_HEADER(fdt) \ { \ int err; \ - if ((err = _fdt_check_header(fdt)) != 0) \ + if ((err = fdt_check_header(fdt)) != 0) \ return err; \ } @@ -193,7 +193,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) const struct fdt_node_header *nh; int err; - if ((err = _fdt_check_header(fdt)) != 0) + if ((err = fdt_check_header(fdt)) != 0) goto fail; err = -FDT_ERR_BADOFFSET; @@ -222,7 +222,7 @@ const struct fdt_property *fdt_get_property(const void *fdt, int offset, nextoffset; int err; - if ((err = _fdt_check_header(fdt)) != 0) + if ((err = fdt_check_header(fdt)) != 0) goto fail; err = -FDT_ERR_BADOFFSET; diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index ff74e3c..bb7a2b7 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -59,7 +59,7 @@ static int rw_check_header(void *fdt) { int err; - if ((err = _fdt_check_header(fdt))) + if ((err = fdt_check_header(fdt))) return err; if (fdt_version(fdt) < 0x11) return -FDT_ERR_BADVERSION; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 8d15155..e43c0f1 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -79,6 +79,22 @@ #define FDT_ERR_MAX 12 +/* Low-level functions (you probably don't need these) */ + +const void *fdt_offset_ptr(const void *fdt, int offset, int checklen); +static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) +{ + return (void *)fdt_offset_ptr(fdt, offset, checklen); +} + + +#define fdt_offset_ptr_typed(fdt, offset, var) \ + ((typeof(var))(fdt_offset_ptr((fdt), (offset), sizeof(*(var))))) +#define fdt_offset_ptr_typed_w(fdt, offset, var) \ + ((typeof(var))(fdt_offset_ptr_w((fdt), (offset), sizeof(*(var))))) + +/* General functions */ + #define fdt_get_header(fdt, field) \ (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) #define fdt_magic(fdt) (fdt_get_header(fdt, magic)) @@ -95,18 +111,7 @@ #define fdt_set_header(fdt, field, val) \ ((struct fdt_header *)(fdt))->field = cpu_to_fdt32(val) -const void *fdt_offset_ptr(const void *fdt, int offset, int checklen); -static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) -{ - return (void *)fdt_offset_ptr(fdt, offset, checklen); -} - - -#define fdt_offset_ptr_typed(fdt, offset, var) \ - ((typeof(var))(fdt_offset_ptr((fdt), (offset), sizeof(*(var))))) -#define fdt_offset_ptr_typed_w(fdt, offset, var) \ - ((typeof(var))(fdt_offset_ptr_w((fdt), (offset), sizeof(*(var))))) - +int fdt_check_header(const void *fdt); int fdt_move(const void *fdt, void *buf, int bufsize); /* Read-only functions */ diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index d2d5e6a..1e60936 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -58,7 +58,6 @@ #define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) #define streq(p, q) (strcmp((p), (q)) == 0) -int _fdt_check_header(const void *fdt); uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset); const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); int _fdt_node_end_offset(void *fdt, int nodeoffset); From 3c44c87bdeacc66f46c55090d765a9766475ee50 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 24 Oct 2007 11:06:09 +1000 Subject: [PATCH 0126/1198] libfdt: Rename and publish _fdt_next_tag() Although it's a low-level function that shouldn't normally be needed, there are circumstances where it's useful for users of libfdt to use the _fdt_next_tag() function. Therefore, this patch renames it to fdt_next_tag() and publishes it in libfdt.h. In addition, this patch adds a new testcase using fdt_next_tag(), dtbs_equal_ordered. This testcase tests for structural equality of two dtbs, including the order of properties and subnodes, but ignoring NOP tags, the order of the dtb sections and the layout of strings in the strings block. This will be useful for testing other dtc functionality in the future. Signed-off-by: David Gibson --- libfdt/fdt.c | 2 +- libfdt/fdt_ro.c | 22 +++--- libfdt/fdt_rw.c | 6 +- libfdt/fdt_sw.c | 2 +- libfdt/fdt_wip.c | 4 +- libfdt/libfdt.h | 3 +- tests/Makefile.tests | 2 +- tests/dtbs_equal_ordered.c | 139 +++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 1 + tests/tests.h | 2 +- 10 files changed, 162 insertions(+), 21 deletions(-) create mode 100644 tests/dtbs_equal_ordered.c diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 2911b42..586a361 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -90,7 +90,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, int len) return p; } -uint32_t _fdt_next_tag(const void *fdt, int offset, int *nextoffset) +uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset) { const uint32_t *tagp, *lenp; uint32_t tag; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index f39785f..f6f0225 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -113,13 +113,13 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, CHECK_HEADER(fdt); - tag = _fdt_next_tag(fdt, parentoffset, &nextoffset); + tag = fdt_next_tag(fdt, parentoffset, &nextoffset); if (tag != FDT_BEGIN_NODE) return -FDT_ERR_BADOFFSET; do { offset = nextoffset; - tag = _fdt_next_tag(fdt, offset, &nextoffset); + tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_END: @@ -229,14 +229,14 @@ const struct fdt_property *fdt_get_property(const void *fdt, if (nodeoffset % FDT_TAGSIZE) goto fail; - tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); + tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); if (tag != FDT_BEGIN_NODE) goto fail; do { offset = nextoffset; - tag = _fdt_next_tag(fdt, offset, &nextoffset); + tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_END: err = -FDT_ERR_TRUNCATED; @@ -302,7 +302,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) CHECK_HEADER(fdt); - tag = _fdt_next_tag(fdt, 0, &nextoffset); + tag = fdt_next_tag(fdt, 0, &nextoffset); if (tag != FDT_BEGIN_NODE) return -FDT_ERR_BADSTRUCTURE; @@ -313,7 +313,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) while (nextoffset <= nodeoffset) { offset = nextoffset; - tag = _fdt_next_tag(fdt, offset, &nextoffset); + tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_END: return -FDT_ERR_BADOFFSET; @@ -374,7 +374,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, do { offset = nextoffset; - tag = _fdt_next_tag(fdt, offset, &nextoffset); + tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_END: return -FDT_ERR_BADOFFSET; @@ -439,7 +439,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, CHECK_HEADER(fdt); if (startoffset >= 0) { - tag = _fdt_next_tag(fdt, startoffset, &nextoffset); + tag = fdt_next_tag(fdt, startoffset, &nextoffset); if (tag != FDT_BEGIN_NODE) return -FDT_ERR_BADOFFSET; } else { @@ -453,7 +453,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, * approach; performance can come later. */ do { offset = nextoffset; - tag = _fdt_next_tag(fdt, offset, &nextoffset); + tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_BEGIN_NODE: @@ -520,7 +520,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, CHECK_HEADER(fdt); if (startoffset >= 0) { - tag = _fdt_next_tag(fdt, startoffset, &nextoffset); + tag = fdt_next_tag(fdt, startoffset, &nextoffset); if (tag != FDT_BEGIN_NODE) return -FDT_ERR_BADOFFSET; } else { @@ -534,7 +534,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, * implement approach; performance can come later. */ do { offset = nextoffset; - tag = _fdt_next_tag(fdt, offset, &nextoffset); + tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_BEGIN_NODE: diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index bb7a2b7..485b39d 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -224,7 +224,7 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len, int namestroff; int err; - tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); + tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); if (tag != FDT_BEGIN_NODE) return -FDT_ERR_BADOFFSET; @@ -298,10 +298,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 */ + fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ do { offset = nextoffset; - tag = _fdt_next_tag(fdt, offset, &nextoffset); + tag = fdt_next_tag(fdt, offset, &nextoffset); } while (tag == FDT_PROP); nh = _fdt_offset_ptr_w(fdt, offset); diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 25f85d7..d7391b8 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -235,7 +235,7 @@ int fdt_finish(void *fdt) /* Walk the structure, correcting string offsets */ offset = 0; - while ((tag = _fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { + while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { if (tag == FDT_PROP) { struct fdt_property *prop = fdt_offset_ptr_w(fdt, offset, sizeof(*prop)); diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c index 78d530c..88e24b8 100644 --- a/libfdt/fdt_wip.c +++ b/libfdt/fdt_wip.c @@ -100,12 +100,12 @@ int _fdt_node_end_offset(void *fdt, int nodeoffset) uint32_t tag; int offset, nextoffset; - tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); + tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); if (tag != FDT_BEGIN_NODE) return -FDT_ERR_BADOFFSET; do { offset = nextoffset; - tag = _fdt_next_tag(fdt, offset, &nextoffset); + tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_END: diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index e43c0f1..885ae00 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -93,8 +93,9 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) #define fdt_offset_ptr_typed_w(fdt, offset, var) \ ((typeof(var))(fdt_offset_ptr_w((fdt), (offset), sizeof(*(var))))) -/* General functions */ +uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); +/* General functions */ #define fdt_get_header(fdt, field) \ (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) #define fdt_magic(fdt) (fdt_get_header(fdt, magic)) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 78afc8d..c212f02 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -8,7 +8,7 @@ LIB_TESTS_L = get_mem_rsv \ sw_tree1 \ move_and_save \ open_pack rw_tree1 setprop del_property del_node \ - string_escapes + string_escapes dtbs_equal_ordered LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property diff --git a/tests/dtbs_equal_ordered.c b/tests/dtbs_equal_ordered.c new file mode 100644 index 0000000..d72124f --- /dev/null +++ b/tests/dtbs_equal_ordered.c @@ -0,0 +1,139 @@ +/* + * libfdt - Flat Device Tree manipulation + * Tests if two given dtbs are structurally equal (including order) + * Copyright (C) 2007 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void compare_mem_rsv(const void *fdt1, const void *fdt2) +{ + int i; + uint64_t addr1, size1, addr2, size2; + int err; + + if (fdt_num_mem_rsv(fdt1) != fdt_num_mem_rsv(fdt2)) + FAIL("Trees have different number of reserve entries"); + for (i = 0; i < fdt_num_mem_rsv(fdt1); i++) { + err = fdt_get_mem_rsv(fdt1, i, &addr1, &size1); + if (err) + FAIL("fdt_get_mem_rsv(fdt1, %d, ...): %s", i, + fdt_strerror(err)); + err = fdt_get_mem_rsv(fdt2, i, &addr2, &size2); + if (err) + FAIL("fdt_get_mem_rsv(fdt2, %d, ...): %s", i, + fdt_strerror(err)); + if ((addr1 != addr2) || (size1 != size2)) + FAIL("Mismatch in reserve entry %d: " + "(0x%llx, 0x%llx) != (0x%llx, 0x%llx)", i, + addr1, size1, addr2, size2); + } +} + +void compare_structure(const void *fdt1, const void *fdt2) +{ + int nextoffset1 = 0, nextoffset2 = 0; + int offset1, offset2; + uint32_t tag1, tag2; + const char *name1, *name2; + int err; + const struct fdt_property *prop1, *prop2; + int len1, len2; + + while (1) { + do { + offset1 = nextoffset1; + tag1 = fdt_next_tag(fdt1, offset1, &nextoffset1); + } while (tag1 == FDT_NOP); + do { + offset2 = nextoffset2; + tag2 = fdt_next_tag(fdt2, offset2, &nextoffset2); + } while (tag2 == FDT_NOP); + + if (tag1 != tag2) + FAIL("Tag mismatch (%d != %d) at (%d, %d)", + tag1, tag2, offset1, offset2); + + switch (tag1) { + case FDT_BEGIN_NODE: + name1 = fdt_get_name(fdt1, offset1, &err); + if (!name1) + FAIL("fdt_get_name(fdt1, %d, ..): %s", + offset1, fdt_strerror(err)); + name2 = fdt_get_name(fdt2, offset2, NULL); + if (!name2) + FAIL("fdt_get_name(fdt2, %d, ..): %s", + offset2, fdt_strerror(err)); + if (!streq(name1, name2)) + FAIL("Name mismatch (\"%s\" != \"%s\") at (%d, %d)", + name1, name2, offset1, offset2); + break; + + case FDT_PROP: + prop1 = fdt_offset_ptr_typed(fdt1, offset1, prop1); + if (!prop1) + FAIL("Could get fdt1 property at %d", offset1); + prop2 = fdt_offset_ptr_typed(fdt2, offset2, prop2); + if (!prop2) + FAIL("Could get fdt2 property at %d", offset2); + + name1 = fdt_string(fdt1, fdt32_to_cpu(prop1->nameoff)); + name2 = fdt_string(fdt2, fdt32_to_cpu(prop2->nameoff)); + if (!streq(name1, name2)) + FAIL("Property name mismatch \"%s\" != \"%s\" " + "at (%d, %d)", name1, name2, offset1, offset2); + len1 = fdt32_to_cpu(prop1->len); + len2 = fdt32_to_cpu(prop2->len); + if (len1 != len2) + FAIL("Property length mismatch %u != %u " + "at (%d, %d)", len1, len2, offset1, offset2); + + if (memcmp(prop1->data, prop2->data, len1) != 0) + FAIL("Property value mismatch at (%d, %d)", + offset1, offset2); + break; + + case FDT_END: + return; + } + } +} + +int main(int argc, char *argv[]) +{ + void *fdt1, *fdt2; + + test_init(argc, argv); + if (argc != 3) + CONFIG("Usage: %s ", argv[0]); + fdt1 = load_blob(argv[1]); + fdt2 = load_blob(argv[2]); + + compare_mem_rsv(fdt1, fdt2); + compare_structure(fdt1, fdt2); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 9d8892d..b661bc8 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -104,6 +104,7 @@ dtc_tests () { run_test dtc.sh -I dts -O dtb -o dtc_tree1.test.dtb test_tree1.dts tree1_tests dtc_tree1.test.dtb tree1_tests_rw dtc_tree1.test.dtb + run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb run_test dtc.sh -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts run_test string_escapes dtc_escapes.test.dtb diff --git a/tests/tests.h b/tests/tests.h index 97f15d8..0029a84 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -129,7 +129,7 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name, #define check_getprop_string(fdt, nodeoffset, name, s) \ check_getprop((fdt), (nodeoffset), (name), strlen(s)+1, (s)) int nodename_eq(const char *s1, const char *s2); -//void *load_blob(const char *filename); +void *load_blob(const char *filename); void *load_blob_arg(int argc, char *argv[]); void save_blob(const char *filename, void *blob); From cec0c384effbdd0f87a483ebc4936c0f98ee11f0 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 24 Oct 2007 17:10:58 +1000 Subject: [PATCH 0127/1198] libfdt: Add some documenting comments in libfdt.h This patch adds some internal documentation in libfdt.h, in the form of comments on the error codes and some functions. Only a couple of functions are covered so far, leaving the documentation still woefully inadequate, but hey, it's a start. Signed-off-by: David Gibson --- libfdt/libfdt.h | 144 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 136 insertions(+), 8 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 885ae00..228b4ce 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -59,27 +59,64 @@ /* Error codes: informative error codes */ #define FDT_ERR_NOTFOUND 1 + /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ #define FDT_ERR_EXISTS 2 + /* FDT_ERR_EXISTS: Attemped to create a node or property which + * already exists */ #define FDT_ERR_NOSPACE 3 + /* FDT_ERR_NOSPACE: Operation needed to expand the device + * tree, but its buffer did not have sufficient space to + * contain the expanded tree. Use fdt_open_into() to move the + * device tree to a buffer with more space. */ /* Error codes: codes for bad parameters */ #define FDT_ERR_BADOFFSET 4 + /* FDT_ERR_BADOFFSET: Function was passed a structure block + * offset which is out-of-bounds, or which points to an + * unsuitable part of the structure for the operation. */ #define FDT_ERR_BADPATH 5 + /* FDT_ERR_BADPATH: Function was passed a badly formatted path + * (e.g. missing a leading / for a function which requires an + * absolute path) */ #define FDT_ERR_BADSTATE 6 + /* FDT_ERR_BADSTATE: Function was passed an incomplete device + * tree created by the sequential-write functions, which is + * not sufficiently complete for the requested operation. */ /* Error codes: codes for bad device tree blobs */ #define FDT_ERR_TRUNCATED 7 + /* FDT_ERR_TRUNCATED: Structure block of the given device tree + * ends without an FDT_END tag. */ #define FDT_ERR_BADMAGIC 8 + /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a + * device tree at all - it is missing the flattened device + * tree magic number. */ #define FDT_ERR_BADVERSION 9 + /* FDT_ERR_BADVERSION: Given device tree has a version which + * can't be handled by the requested operation. For + * read-write functions, this may mean that fdt_open_into() is + * required to convert the tree to the expected version. */ #define FDT_ERR_BADSTRUCTURE 10 + /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt + * structure block or other serious error (e.g. misnested + * nodes, or subnodes preceding properties). */ #define FDT_ERR_BADLAYOUT 11 + /* FDT_ERR_BADLAYOUT: For read-write functions, the given + * device tree has it's sub-blocks in an order that the + * function can't handle (memory reserve map, then structure, + * then strings). Use fdt_open_into() to reorganize the tree + * into a form suitable for the read-write operations. */ /* "Can't happen" error indicating a bug in libfdt */ #define FDT_ERR_INTERNAL 12 + /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. + * Indicates a bug in libfdt itself. */ #define FDT_ERR_MAX 12 -/* Low-level functions (you probably don't need these) */ +/**********************************************************************/ +/* Low-level functions (you probably don't need these) */ +/**********************************************************************/ const void *fdt_offset_ptr(const void *fdt, int offset, int checklen); static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) @@ -95,7 +132,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); -/* General functions */ +/**********************************************************************/ +/* General functions */ +/**********************************************************************/ + #define fdt_get_header(fdt, field) \ (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) #define fdt_magic(fdt) (fdt_get_header(fdt, magic)) @@ -112,15 +152,91 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); #define fdt_set_header(fdt, field, val) \ ((struct fdt_header *)(fdt))->field = cpu_to_fdt32(val) +/** + * fdt_check_header - sanity check a device tree or possible device tree + * @fdt: pointer to data which might be a flattened device tree + * + * fdt_check_header() checks that the given buffer contains what + * appears to be a flattened device tree with sane information in its + * header. + * + * returns: + * 0, if the buffer appears to contain a valid device tree + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings, as above + */ int fdt_check_header(const void *fdt); + +/** + * fdt_move - move a device tree around in memory + * @fdt: pointer to the device tree to move + * @buf: pointer to memory where the device is to be moved + * @bufsize: size of the memory space at buf + * + * fdt_move() relocates, if possible, the device tree blob located at + * fdt to the buffer at buf of size bufsize. The buffer may overlap + * with the existing device tree blob at fdt. Therefore, + * fdt_move(fdt, fdt, fdt_totalsize(fdt)) + * should always succeed. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ int fdt_move(const void *fdt, void *buf, int bufsize); -/* Read-only functions */ +/**********************************************************************/ +/* Read-only functions */ +/**********************************************************************/ + +/** + * fdt_string - retreive a string from the strings block of a device tree + * @fdt: pointer to the device tree blob + * @stroffset: offset of the string within the strings block (native endian) + * + * fdt_string() retrieves a pointer to a single string from the + * strings block of the device tree blob at fdt. + * + * returns: + * a pointer to the string, on success + * NULL, if stroffset is out of bounds + */ const char *fdt_string(const void *fdt, int stroffset); -int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); +/** + * fdt_num_mem_rsv - retreive the number of memory reserve map entries + * @fdt: pointer to the device tree blob + * + * Returns the number of entries in the device tree blob's memory + * reservation map. This does not include the terminating 0,0 entry + * or any other (0,0) entries reserved for expansion. + * + * returns: + * the number of entries + */ int fdt_num_mem_rsv(const void *fdt); +/** + * fdt_get_mem_rsv - retreive one memory reserve map entry + * @fdt: pointer to the device tree blob + * @address, @size: pointers to 64-bit variables + * + * 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. + * + * returns: + * 0, on success + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); + int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, const char *name, int namelen); int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); @@ -164,7 +280,10 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible); -/* Write-in-place functions */ +/**********************************************************************/ +/* Write-in-place functions */ +/**********************************************************************/ + int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len); @@ -177,7 +296,10 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, int fdt_nop_property(void *fdt, int nodeoffset, const char *name); int fdt_nop_node(void *fdt, int nodeoffset); -/* Sequential-write functions */ +/**********************************************************************/ +/* Sequential write functions */ +/**********************************************************************/ + int fdt_create(void *buf, int bufsize); int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); int fdt_finish_reservemap(void *fdt); @@ -193,7 +315,10 @@ int fdt_property(void *fdt, const char *name, const void *val, int len); int fdt_end_node(void *fdt); int fdt_finish(void *fdt); -/* Read-write functions */ +/**********************************************************************/ +/* Read-write functions */ +/**********************************************************************/ + int fdt_open_into(void *fdt, void *buf, int bufsize); int fdt_pack(void *fdt); @@ -215,7 +340,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, int fdt_add_subnode(void *fdt, int parentoffset, const char *name); int fdt_del_node(void *fdt, int nodeoffset); -/* Extra functions */ +/**********************************************************************/ +/* Debugging / informational functions */ +/**********************************************************************/ + const char *fdt_strerror(int errval); #endif /* _LIBFDT_H */ From 57f99b7b3f8f21d4e685a50665951e9bcaad80b7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 25 Oct 2007 11:27:31 +1000 Subject: [PATCH 0128/1198] libfdt: Documentation (patch the second) Add documentation for another handful of libfdt functions to libfdt.h Signed-off-by: David Gibson --- libfdt/libfdt.h | 80 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 228b4ce..bd3bf3c 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -237,13 +237,91 @@ int fdt_num_mem_rsv(const void *fdt); */ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); +/** + * fdt_subnode_offset_namelen - find a subnode based on substring + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * @namelen: number of characters of name to consider + * + * Identical to fdt_subnode_offset(), but only examine the first + * 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. + */ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, const char *name, int namelen); +/** + * fdt_subnode_offset - find a subnode of a given node + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * + * fdt_subnode_offset() finds a subnode of the node at structure block + * offset parentoffset with the given name. name may include a unit + * address, in which case fdt_subnode_offset() will find the subnode + * with that unit address, or the unit address may be omitted, in + * which case fdt_subnode_offset() will find an arbitrary subnode + * whose name excluding unit address matches the given name. + * + * returns: + * structure block offset of the requested 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 + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); +/** + * fdt_path_offset - find a tree node by its full path + * @fdt: pointer to the device tree blob + * @path: full path of the node to locate + * + * fdt_path_offset() finds a node of a given path in the device tree. + * Each path component may omit the unit address portion, but the + * results of this are undefined if any such path component is + * ambiguous (that is if there are multiple nodes at the relevant + * level matching the given component, differentiated only by unit + * address). + * + * 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_NOTFOUND, if the requested node does not exist + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ int fdt_path_offset(const void *fdt, const char *path); -const char *fdt_get_name(const void *fdt, int nodeoffset, int *baselen); +/** + * fdt_get_name - retreive the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of the starting node + * @len: pointer to an intger variable (will be overwritten) or NULL + * + * fdt_get_name() retrieves the name (including unit address) of the + * device tree node at structure block offset nodeoffset. If len is + * non-NULL, the length of this name is also returned, in the integer + * pointed to by len. + * + * returns: + * pointer to the node's name, on success + * *len contains the length of that name (>=0) + * NULL, on error + * *len contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +const char *fdt_get_name(const void *fdt, int nodeoffset, int *len); const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, const char *name, int *lenp); From 9b91134ba3043deb7689bcee06b78a596647c626 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 25 Oct 2007 14:29:38 +1000 Subject: [PATCH 0129/1198] libfdt: Remove un-const-safe fdt_set_header macro The fdt_set_header() macro casts an arbitrary pointer into (struct fdt_header *) to set fdt header fields. While we need to change the type, so that we can use this macro on the usual (void *) used to represent a device tree blob, the current macro also casts away any const on the input pointer, which loses an important check. This patch replaces the fdt_set_header() macro with a set of inline functions, one for each header field which do a similar thing, but which won't silently remove const from a given pointer. This approach is also more in keeping with the individual accessor macros we use for reading fdt header fields. Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 14 +++++++------- libfdt/fdt_sw.c | 28 ++++++++++++++-------------- libfdt/libfdt.h | 19 +++++++++++++++++-- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 485b39d..23547a5 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -109,8 +109,8 @@ static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, err = _blob_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); if (err) return err; - fdt_set_header(fdt, off_dt_struct, fdt_off_dt_struct(fdt) + delta); - fdt_set_header(fdt, off_dt_strings, fdt_off_dt_strings(fdt) + delta); + fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); return 0; } @@ -123,8 +123,8 @@ static int _blob_splice_struct(void *fdt, void *p, if ((err = _blob_splice(fdt, p, oldlen, newlen))) return err; - fdt_set_header(fdt, size_dt_struct, fdt_size_dt_struct(fdt) + delta); - fdt_set_header(fdt, off_dt_strings, fdt_off_dt_strings(fdt) + delta); + fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); return 0; } @@ -136,7 +136,7 @@ static int _blob_splice_string(void *fdt, int newlen) if ((err = _blob_splice(fdt, p, 0, newlen))) return err; - fdt_set_header(fdt, size_dt_strings, fdt_size_dt_strings(fdt) + newlen); + fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); return 0; } @@ -349,7 +349,7 @@ int fdt_open_into(void *fdt, void *buf, int bufsize) fdt = buf; - fdt_set_header(fdt, totalsize, bufsize); + fdt_set_totalsize(fdt, bufsize); /* FIXME: re-order if necessary */ @@ -369,6 +369,6 @@ int fdt_pack(void *fdt) return err; /* FIXME: pack components */ - fdt_set_header(fdt, totalsize, _blob_data_size(fdt)); + fdt_set_totalsize(fdt, _blob_data_size(fdt)); return 0; } diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index d7391b8..dda2de3 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -73,7 +73,7 @@ static void *grab_space(void *fdt, int len) if ((offset + len < offset) || (offset + len > spaceleft)) return NULL; - fdt_set_header(fdt, size_dt_struct, offset + len); + fdt_set_size_dt_struct(fdt, offset + len); return fdt_offset_ptr_w(fdt, offset, len); } @@ -86,15 +86,15 @@ int fdt_create(void *buf, int bufsize) memset(buf, 0, bufsize); - fdt_set_header(fdt, magic, SW_MAGIC); - fdt_set_header(fdt, version, FDT_LAST_SUPPORTED_VERSION); - fdt_set_header(fdt, last_comp_version, FDT_FIRST_SUPPORTED_VERSION); - fdt_set_header(fdt, totalsize, bufsize); + fdt_set_magic(fdt, SW_MAGIC); + fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); + fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); + fdt_set_totalsize(fdt, bufsize); - fdt_set_header(fdt, off_mem_rsvmap, ALIGN(sizeof(struct fdt_header), - sizeof(struct fdt_reserve_entry))); - fdt_set_header(fdt, off_dt_struct, fdt_off_mem_rsvmap(fdt)); - fdt_set_header(fdt, off_dt_strings, bufsize); + fdt_set_off_mem_rsvmap(fdt, ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry))); + fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); + fdt_set_off_dt_strings(fdt, bufsize); return 0; } @@ -118,7 +118,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) re->address = cpu_to_fdt64(addr); re->size = cpu_to_fdt64(size); - fdt_set_header(fdt, off_dt_struct, offset + sizeof(*re)); + fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); return 0; } @@ -181,7 +181,7 @@ static int find_add_string(void *fdt, const char *s) return 0; /* no more room :( */ memcpy(strtab + offset, s, len); - fdt_set_header(fdt, size_dt_strings, strtabsize + len); + fdt_set_size_dt_strings(fdt, strtabsize + len); return offset; } @@ -231,7 +231,7 @@ int fdt_finish(void *fdt) oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); - fdt_set_header(fdt, off_dt_strings, newstroffset); + fdt_set_off_dt_strings(fdt, newstroffset); /* Walk the structure, correcting string offsets */ offset = 0; @@ -252,7 +252,7 @@ int fdt_finish(void *fdt) } /* Finally, adjust the header */ - fdt_set_header(fdt, totalsize, newstroffset + fdt_size_dt_strings(fdt)); - fdt_set_header(fdt, magic, FDT_MAGIC); + fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); + fdt_set_magic(fdt, FDT_MAGIC); return 0; } diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index bd3bf3c..5710bb3 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -149,8 +149,23 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); #define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) #define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) -#define fdt_set_header(fdt, field, val) \ - ((struct fdt_header *)(fdt))->field = cpu_to_fdt32(val) +#define __fdt_set_hdr(name) \ + static inline void fdt_set_##name(void *fdt, uint32_t val) \ + { \ + struct fdt_header *fdth = 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); +#undef __fdt_set_hdr /** * fdt_check_header - sanity check a device tree or possible device tree From 3bef796b449320cefb8e52838ca90163df698722 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 25 Oct 2007 15:05:58 +1000 Subject: [PATCH 0130/1198] libfdt: Test on trees with different block layouts At present, all the example dtbs we use in the testsuite are version 17 and have reservation map, then structure block then strings block (the natural ordering based on alignment constraints). However, all libfdt's read-only and in-place write functions should also work on v16 trees, and on trees with other layouts. This patch adds a testcase / utility function to rearrange the blocks of a dtb and/or regress a v17 tree to v16, and uses it to run tests on trees with different layouts and versions. Signed-off-by: David Gibson --- tests/Makefile.tests | 2 +- tests/mangle-layout.c | 166 ++++++++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 11 +++ 3 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 tests/mangle-layout.c diff --git a/tests/Makefile.tests b/tests/Makefile.tests index c212f02..68324e9 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -6,7 +6,7 @@ LIB_TESTS_L = get_mem_rsv \ notfound \ setprop_inplace nop_property nop_node \ sw_tree1 \ - move_and_save \ + move_and_save mangle-layout \ open_pack rw_tree1 setprop del_property del_node \ string_escapes dtbs_equal_ordered LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c new file mode 100644 index 0000000..a20af00 --- /dev/null +++ b/tests/mangle-layout.c @@ -0,0 +1,166 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase/tool for rearranging blocks of a dtb + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +struct bufstate { + void *buf; + int size; +}; + +void expand_buf(struct bufstate *buf, int newsize) +{ + buf->buf = realloc(buf->buf, newsize); + if (!buf->buf) + CONFIG("Allocation failure"); + buf->size = newsize; +} + +void new_header(struct bufstate *buf, int version, const void *fdt) +{ + int hdrsize; + + if (version == 16) + hdrsize = FDT_V16_SIZE; + else if (version == 17) + hdrsize = FDT_V17_SIZE; + else + CONFIG("Bad version %d", version); + + expand_buf(buf, hdrsize); + memset(buf->buf, 0, hdrsize); + + fdt_set_magic(buf->buf, FDT_MAGIC); + fdt_set_version(buf->buf, version); + fdt_set_last_comp_version(buf->buf, 16); + fdt_set_boot_cpuid_phys(buf->buf, fdt_boot_cpuid_phys(fdt)); +} + +void add_block(struct bufstate *buf, int version, char block, const void *fdt) +{ + int align, size; + const void *src; + int offset; + + switch (block) { + case 'm': + /* Memory reserve map */ + align = 8; + src = fdt + fdt_off_mem_rsvmap(fdt); + size = (fdt_num_mem_rsv(fdt) + 1) + * sizeof(struct fdt_reserve_entry); + break; + + case 't': + /* Structure block */ + align = 4; + src = fdt + fdt_off_dt_struct(fdt); + size = fdt_size_dt_struct(fdt); + break; + + case 's': + /* Strings block */ + align = 1; + src = fdt + fdt_off_dt_strings(fdt); + size = fdt_size_dt_strings(fdt); + break; + default: + CONFIG("Bad block '%c'", block); + } + + offset = ALIGN(buf->size, align); + fprintf(stderr, "Moving block %c from %p, to offset %d, size %d\n", + block, src, offset, size); + + expand_buf(buf, offset+size); + + memcpy(buf->buf + offset, src, size); + + switch (block) { + case 'm': + fdt_set_off_mem_rsvmap(buf->buf, offset); + break; + + case 't': + fdt_set_off_dt_struct(buf->buf, offset); + if (version >= 17) + fdt_set_size_dt_struct(buf->buf, size); + break; + + case 's': + fdt_set_off_dt_strings(buf->buf, offset); + fdt_set_size_dt_strings(buf->buf, size); + break; + } +} + +int main(int argc, char *argv[]) +{ + void *fdt; + int version; + const char *blockorder; + struct bufstate buf = {NULL, 0}; + int err; + const char *inname; + char outname[PATH_MAX]; + + test_init(argc, argv); + if (argc != 4) + CONFIG("Usage: %s ", argv[0]); + + inname = argv[1]; + fdt = load_blob(argv[1]); + version = atoi(argv[2]); + blockorder = argv[3]; + sprintf(outname, "v%d.%s.%s", version, blockorder, inname); + + if ((version != 16) && (version != 17)) + CONFIG("Version must be 16 or 17"); + + if (fdt_version(fdt) < 17) + CONFIG("Input tree must be v17"); + + new_header(&buf, version, fdt); + + while (*blockorder) { + add_block(&buf, version, *blockorder, fdt); + blockorder++; + } + + fdt_set_totalsize(buf.buf, buf.size); + + err = fdt_check_header(buf.buf); + if (err) + FAIL("Output tree fails check: %s", fdt_strerror(err)); + + save_blob(outname, buf.buf); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index b661bc8..25bacbf 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -78,6 +78,17 @@ libfdt_tests () { tree1_tests deshunted.$tree done + # v16 and alternate layout tests + for tree in test_tree1.dtb; do + for version in 17 16; do + for layout in mts mst tms tsm smt stm; do + run_test mangle-layout $tree $version $layout + tree1_tests v$version.$layout.$tree + run_test dtbs_equal_ordered $tree v$version.$layout.$tree + done + done + done + # Read-write tests for tree in test_tree1.dtb sw_tree1.test.dtb; do rm -f opened.$tree repacked.$tree From 7b3fb789d2cd5fed818f439d0c7aed44b9860fab Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Mon, 22 Oct 2007 16:09:56 -0500 Subject: [PATCH 0131/1198] DTC: Remove the need for the GLR Parser. Previously, there were a few shift/reduce and reduce/reduce errors in the grammar that were being handled by the not-so-popular GLR Parser technique. Flip a right-recursive stack-abusing rule into a left-recursive stack-friendly rule and clear up three messes in one shot: No more conflicts, no need for the GLR parser, and friendlier stackness. Compensate by reversing the property list on the node. Signed-off-by: Jon Loeliger --- Makefile | 1 - dtc-parser.y | 5 ++--- dtc.h | 1 + livetree.c | 17 ++++++++++++++++- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index d7d1af5..84f0efe 100644 --- a/Makefile +++ b/Makefile @@ -207,7 +207,6 @@ clean: libfdt_clean tests_clean %.tab.c %.tab.h %.output: %.y @$(VECHO) BISON $@ - @$(VECHO) ---- Expect 2 s/r and 2 r/r. ---- $(BISON) -d $< FORCE: diff --git a/dtc-parser.y b/dtc-parser.y index 33cf540..61ed250 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -18,7 +18,6 @@ * USA */ -%glr-parser %locations %{ @@ -126,9 +125,9 @@ proplist: { $$ = NULL; } - | propdef proplist + | proplist propdef { - $$ = chain_property($1, $2); + $$ = chain_property($2, $1); } ; diff --git a/dtc.h b/dtc.h index 77494af..1fc6523 100644 --- a/dtc.h +++ b/dtc.h @@ -180,6 +180,7 @@ struct node { struct property *build_property(char *name, struct data val, char *label); struct property *chain_property(struct property *first, struct property *list); +struct property *reverse_properties(struct property *first); struct node *build_node(struct property *proplist, struct node *children); struct node *name_node(struct node *node, char *name, char *label); diff --git a/livetree.c b/livetree.c index aa81d12..c480b36 100644 --- a/livetree.c +++ b/livetree.c @@ -46,6 +46,21 @@ struct property *chain_property(struct property *first, struct property *list) return first; } +struct property *reverse_properties(struct property *first) +{ + struct property *p = first; + struct property *head = NULL; + struct property *next; + + while (p) { + next = p->next; + p->next = head; + head = p; + p = next; + } + return head; +} + struct node *build_node(struct property *proplist, struct node *children) { struct node *new = xmalloc(sizeof(*new)); @@ -53,7 +68,7 @@ struct node *build_node(struct property *proplist, struct node *children) memset(new, 0, sizeof(*new)); - new->proplist = proplist; + new->proplist = reverse_properties(proplist); new->children = children; for_each_child(new, child) { From 7e14259791129d42527553461349b261d9e48bd8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 30 Oct 2007 13:17:15 +1100 Subject: [PATCH 0132/1198] dtc: Remove leftover debugging printf() from mangle-layout The mangle-layout testcase/utility had a leftover debugging printf(). This patch removes it. Signed-off-by: David Gibson --- tests/mangle-layout.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c index a20af00..efd6aab 100644 --- a/tests/mangle-layout.c +++ b/tests/mangle-layout.c @@ -96,8 +96,6 @@ void add_block(struct bufstate *buf, int version, char block, const void *fdt) } offset = ALIGN(buf->size, align); - fprintf(stderr, "Moving block %c from %p, to offset %d, size %d\n", - block, src, offset, size); expand_buf(buf, offset+size); From 4a5df5c026c96f36326d4037a0658d38193e2ca1 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 30 Oct 2007 13:22:12 +1100 Subject: [PATCH 0133/1198] libfdt: Correctly handle versions > 17 If future dtb version > 17 are defined, that are still backwards compatible with v16, libfdt will of course be able to read and understand them. However, when modifying such a tree, it can't guarantee that it won't clobber additional structure from the new version which it doesn't know about. Therefore, before making modifications to a tree of version >17, we must change it's version to be exactly 17. 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 23547a5..78231d0 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -61,7 +61,7 @@ static int rw_check_header(void *fdt) if ((err = fdt_check_header(fdt))) return err; - if (fdt_version(fdt) < 0x11) + if (fdt_version(fdt) < 17) return -FDT_ERR_BADVERSION; if (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8)) return -FDT_ERR_BADLAYOUT; @@ -74,6 +74,9 @@ static int rw_check_header(void *fdt) if (fdt_totalsize(fdt) < (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))) return -FDT_ERR_BADLAYOUT; + if (fdt_version(fdt) > 17) + fdt_set_version(fdt, 17); + return 0; } From a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 1 Nov 2007 11:37:31 +1100 Subject: [PATCH 0134/1198] libfdt: Handle v16 and re-ordered trees for r/w Currently all the read/write functions in libfdt require that the given tree be v17, and further, that the tree has the memory reservation block, structure block and strings block stored in that physical order. This patch eases these constraints, by making fdt_open_int() reorder the blocks, and/or convert the tree to v17, so that it will then be ready for the other read-write functions. It also extends fdt_pack() to actually remove any gaps between blocks that might be present. Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 108 +++++++++++++++++++++++++++++++++++-------- libfdt/libfdt.h | 2 +- tests/del_node.c | 2 + tests/del_property.c | 2 + tests/run_tests.sh | 29 +++++++----- tests/tests.h | 1 + tests/testutils.c | 18 ++++++++ 7 files changed, 130 insertions(+), 32 deletions(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 78231d0..dfe5628 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -55,6 +55,18 @@ #include "libfdt_internal.h" +static int _blocks_misordered(const void *fdt, + int mem_rsv_size, int struct_size) +{ + return (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8)) + || (fdt_off_dt_struct(fdt) < + (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) + || (fdt_off_dt_strings(fdt) < + (fdt_off_dt_struct(fdt) + struct_size)) + || (fdt_totalsize(fdt) < + (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); +} + static int rw_check_header(void *fdt) { int err; @@ -63,16 +75,8 @@ static int rw_check_header(void *fdt) return err; if (fdt_version(fdt) < 17) return -FDT_ERR_BADVERSION; - if (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8)) - return -FDT_ERR_BADLAYOUT; - if (fdt_off_dt_struct(fdt) < - (fdt_off_mem_rsvmap(fdt) + sizeof(struct fdt_reserve_entry))) - return -FDT_ERR_BADLAYOUT; - if (fdt_off_dt_strings(fdt) < - (fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt))) - return -FDT_ERR_BADLAYOUT; - if (fdt_totalsize(fdt) < - (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))) + if (_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), + fdt_size_dt_struct(fdt))) return -FDT_ERR_BADLAYOUT; if (fdt_version(fdt) > 17) fdt_set_version(fdt, 17); @@ -342,36 +346,102 @@ int fdt_del_node(void *fdt, int nodeoffset) endoffset - nodeoffset, 0); } -int fdt_open_into(void *fdt, void *buf, int bufsize) +static void _packblocks(const void *fdt, void *buf, + int mem_rsv_size, int struct_size) +{ + int mem_rsv_off, struct_off, strings_off; + + mem_rsv_off = ALIGN(sizeof(struct fdt_header), 8); + struct_off = mem_rsv_off + mem_rsv_size; + strings_off = struct_off + struct_size; + + memmove(buf + mem_rsv_off, fdt + fdt_off_mem_rsvmap(fdt), mem_rsv_size); + fdt_set_off_mem_rsvmap(buf, mem_rsv_off); + + memcpy(buf + struct_off, fdt + fdt_off_dt_struct(fdt), struct_size); + fdt_set_off_dt_struct(buf, struct_off); + fdt_set_size_dt_struct(buf, struct_size); + + memcpy(buf + strings_off, fdt + fdt_off_dt_strings(fdt), + fdt_size_dt_strings(fdt)); + fdt_set_off_dt_strings(buf, strings_off); + fdt_set_size_dt_strings(buf, fdt_size_dt_strings(fdt)); +} + +int fdt_open_into(const void *fdt, void *buf, int bufsize) { int err; + int mem_rsv_size, struct_size; + int newsize; + void *tmp; - err = fdt_move(fdt, buf, bufsize); + err = fdt_check_header(fdt); if (err) return err; - fdt = buf; + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) + * sizeof(struct fdt_reserve_entry); - fdt_set_totalsize(fdt, bufsize); + if (fdt_version(fdt) >= 17) { + struct_size = fdt_size_dt_struct(fdt); + } else { + struct_size = 0; + while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) + ; + } - /* FIXME: re-order if necessary */ + if (!_blocks_misordered(fdt, mem_rsv_size, struct_size)) { + /* no further work necessary */ + err = fdt_move(fdt, buf, bufsize); + if (err) + return err; + fdt_set_version(buf, 17); + fdt_set_size_dt_struct(buf, struct_size); + fdt_set_totalsize(buf, bufsize); + return 0; + } - err = rw_check_header(fdt); - if (err) - return err; + /* Need to reorder */ + newsize = ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size + + struct_size + fdt_size_dt_strings(fdt); + + if (bufsize < newsize) + return -FDT_ERR_NOSPACE; + + if (((buf + newsize) <= fdt) + || (buf >= (fdt + fdt_totalsize(fdt)))) { + tmp = buf; + } else { + tmp = (void *)fdt + fdt_totalsize(fdt); + if ((tmp + newsize) > (buf + bufsize)) + return -FDT_ERR_NOSPACE; + } + + _packblocks(fdt, tmp, mem_rsv_size, struct_size); + memmove(buf, tmp, newsize); + + fdt_set_magic(buf, FDT_MAGIC); + fdt_set_totalsize(buf, bufsize); + fdt_set_version(buf, 17); + fdt_set_last_comp_version(buf, 16); + fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); return 0; } int fdt_pack(void *fdt) { + int mem_rsv_size; int err; err = rw_check_header(fdt); if (err) return err; - /* FIXME: pack components */ + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) + * sizeof(struct fdt_reserve_entry); + _packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); fdt_set_totalsize(fdt, _blob_data_size(fdt)); + return 0; } diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 5710bb3..4ef65bc 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -412,7 +412,7 @@ int fdt_finish(void *fdt); /* Read-write functions */ /**********************************************************************/ -int fdt_open_into(void *fdt, void *buf, int bufsize); +int fdt_open_into(const void *fdt, void *buf, int bufsize); int fdt_pack(void *fdt); int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); diff --git a/tests/del_node.c b/tests/del_node.c index 51b12b2..fad777e 100644 --- a/tests/del_node.c +++ b/tests/del_node.c @@ -40,6 +40,8 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); + fdt = open_blob_rw(fdt); + oldsize = fdt_totalsize(fdt); subnode1_offset = fdt_path_offset(fdt, "/subnode@1"); diff --git a/tests/del_property.c b/tests/del_property.c index 35dc932..2c412c3 100644 --- a/tests/del_property.c +++ b/tests/del_property.c @@ -41,6 +41,8 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); + fdt = open_blob_rw(fdt); + oldsize = fdt_totalsize(fdt); intp = check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 25bacbf..8fcc44a 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -61,6 +61,8 @@ tree1_tests_rw () { run_test del_node $TREE } +ALL_LAYOUTS="mts mst tms tsm smt stm" + libfdt_tests () { tree1_tests test_tree1.dtb @@ -81,7 +83,7 @@ libfdt_tests () { # v16 and alternate layout tests for tree in test_tree1.dtb; do for version in 17 16; do - for layout in mts mst tms tsm smt stm; do + for layout in $ALL_LAYOUTS; do run_test mangle-layout $tree $version $layout tree1_tests v$version.$layout.$tree run_test dtbs_equal_ordered $tree v$version.$layout.$tree @@ -90,18 +92,21 @@ libfdt_tests () { done # Read-write tests - for tree in test_tree1.dtb sw_tree1.test.dtb; do - rm -f opened.$tree repacked.$tree - run_test open_pack $tree - tree1_tests opened.$tree - tree1_tests repacked.$tree - done + for basetree in test_tree1.dtb; do + for version in 17 16; do + for layout in $ALL_LAYOUTS; do + tree=v$version.$layout.$basetree + rm -f opened.$tree repacked.$tree + run_test open_pack $tree + tree1_tests $tree + tree1_tests opened.$tree + tree1_tests repacked.$tree - for tree in test_tree1.dtb sw_tree1.test.dtb; do - tree1_tests_rw $tree - tree1_tests_rw moved.$tree - tree1_tests_rw shunted.$tree - tree1_tests_rw deshunted.$tree + tree1_tests_rw $tree + tree1_tests_rw opened.$tree + tree1_tests_rw repacked.$tree + done + done done run_test rw_tree1 tree1_tests rw_tree1.test.dtb diff --git a/tests/tests.h b/tests/tests.h index 0029a84..f6dcd15 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -132,5 +132,6 @@ int nodename_eq(const char *s1, const char *s2); 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); #endif /* _TESTS_H */ diff --git a/tests/testutils.c b/tests/testutils.c index 6d6112b..338e3bd 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -220,3 +220,21 @@ void save_blob(const char *filename, void *fdt) offset += ret; } } + +void *open_blob_rw(void *blob) +{ + int err; + void *buf = blob; + + 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); + } + if (err) + FAIL("fdt_open_into(): %s", fdt_strerror(err)); + return buf; +} From 2f1ccc36f478d0cdb55666eb62ae6a338751be9c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 1 Nov 2007 16:49:26 +1100 Subject: [PATCH 0135/1198] dtc: Move tree checking code to checks.c This patch moves the dtc code for checking the device tree its processing into a new checks.c. The tree accessor functions from livetree.c which the checks use are exported and added to dtc.h. Another small step towards a flexible checking architecture. Signed-off-by: David Gibson --- Makefile.dtc | 3 +- checks.c | 460 +++++++++++++++++++++++++++++++++++++++++++++++++++ dtc.h | 15 +- livetree.c | 449 +------------------------------------------------ 4 files changed, 478 insertions(+), 449 deletions(-) create mode 100644 checks.c diff --git a/Makefile.dtc b/Makefile.dtc index c843ee2..d607fdb 100644 --- a/Makefile.dtc +++ b/Makefile.dtc @@ -3,7 +3,8 @@ # This is not a complete Makefile of itself. Instead, it is designed to # be easily embeddable into other systems of Makefiles. # -DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c +DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \ + checks.c DTC_EXTRA = dtc.h srcpos.h DTC_LEXFILES = dtc-lexer.l DTC_BISONFILES = dtc-parser.y diff --git a/checks.c b/checks.c new file mode 100644 index 0000000..f0e7505 --- /dev/null +++ b/checks.c @@ -0,0 +1,460 @@ +/* + * (C) Copyright David Gibson , IBM Corporation. 2007. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "dtc.h" + +/* + * Structural check functions + */ + +#define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__) +#define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__) + +#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0) + +static int check_names(struct node *tree) +{ + struct node *child, *child2; + struct property *prop, *prop2; + int len = strlen(tree->name); + int ok = 1; + + if (len == 0 && tree->parent) + DO_ERR("Empty, non-root nodename at %s\n", tree->fullpath); + + if (len > MAX_NODENAME_LEN) + WARNMSG("Overlength nodename at %s\n", tree->fullpath); + + for_each_property(tree, prop) { + /* check for duplicates */ + /* FIXME: do this more efficiently */ + for (prop2 = prop->next; prop2; prop2 = prop2->next) { + if (streq(prop->name, prop2->name)) { + DO_ERR("Duplicate propertyname %s in node %s\n", + prop->name, tree->fullpath); + } + } + + /* check name length */ + if (strlen(prop->name) > MAX_PROPNAME_LEN) + WARNMSG("Property name %s is too long in %s\n", + prop->name, tree->fullpath); + } + + for_each_child(tree, child) { + /* Check for duplicates */ + + for (child2 = child->next_sibling; + child2; + child2 = child2->next_sibling) { + if (streq(child->name, child2->name)) + DO_ERR("Duplicate node name %s\n", + child->fullpath); + } + if (! check_names(child)) + ok = 0; + } + + return ok; +} + +static int check_phandles(struct node *root, struct node *node) +{ + struct property *prop; + struct node *child, *other; + cell_t phandle; + int ok = 1; + + prop = get_property(node, "linux,phandle"); + if (prop) { + phandle = propval_cell(prop); + if ((phandle == 0) || (phandle == -1)) { + DO_ERR("%s has invalid linux,phandle %x\n", + node->fullpath, phandle); + } else { + other = get_node_by_phandle(root, phandle); + if (other) + DO_ERR("%s has duplicated phandle %x (seen before at %s)\n", + node->fullpath, phandle, other->fullpath); + + node->phandle = phandle; + } + } + + for_each_child(node, child) + ok = ok && check_phandles(root, child); + + return 1; +} + +int check_structure(struct node *dt) +{ + int ok = 1; + + ok = ok && check_names(dt); + ok = ok && check_phandles(dt, dt); + + return ok; +} + +/* + * Semantic check functions + */ + +static int must_be_one_cell(struct property *prop, struct node *node) +{ + if (prop->val.len != sizeof(cell_t)) { + ERRMSG("\"%s\" property in %s has the wrong length (should be 1 cell)\n", + prop->name, node->fullpath); + return 0; + } + + return 1; +} + +static int must_be_cells(struct property *prop, struct node *node) +{ + if ((prop->val.len % sizeof(cell_t)) != 0) { + ERRMSG("\"%s\" property in %s is not a multiple of cell size\n", + prop->name, node->fullpath); + return 0; + } + + return 1; +} + +static int must_be_string(struct property *prop, struct node *node) +{ + if (! data_is_one_string(prop->val)) { + ERRMSG("\"%s\" property in %s is not a string\n", + prop->name, node->fullpath); + return 0; + } + + return 1; +} + +static int name_prop_check(struct property *prop, struct node *node) +{ + if ((prop->val.len != node->basenamelen+1) + || !strneq(prop->val.val, node->name, node->basenamelen)) { + ERRMSG("name property \"%s\" does not match node basename in %s\n", + prop->val.val, + node->fullpath); + return 0; + } + + return 1; +} + +static struct { + char *propname; + int (*check_fn)(struct property *prop, struct node *node); +} prop_checker_table[] = { + {"name", must_be_string}, + {"name", name_prop_check}, + {"linux,phandle", must_be_one_cell}, + {"#address-cells", must_be_one_cell}, + {"#size-cells", must_be_one_cell}, + {"reg", must_be_cells}, + {"model", must_be_string}, + {"device_type", must_be_string}, +}; + +static int check_properties(struct node *node) +{ + struct property *prop; + struct node *child; + int i; + int ok = 1; + + for_each_property(node, prop) + for (i = 0; i < ARRAY_SIZE(prop_checker_table); i++) + if (streq(prop->name, prop_checker_table[i].propname)) + if (! prop_checker_table[i].check_fn(prop, node)) { + ok = 0; + break; + } + + for_each_child(node, child) + if (! check_properties(child)) + ok = 0; + + return ok; +} + +#define CHECK_HAVE(node, propname) \ + do { \ + if (! (prop = get_property((node), (propname)))) \ + DO_ERR("Missing \"%s\" property in %s\n", (propname), \ + (node)->fullpath); \ + } while (0); + +#define CHECK_HAVE_WARN(node, propname) \ + do { \ + if (! (prop = get_property((node), (propname)))) \ + WARNMSG("%s has no \"%s\" property\n", \ + (node)->fullpath, (propname)); \ + } while (0) + +#define CHECK_HAVE_STRING(node, propname) \ + do { \ + CHECK_HAVE((node), (propname)); \ + if (prop && !data_is_one_string(prop->val)) \ + DO_ERR("\"%s\" property in %s is not a string\n", \ + (propname), (node)->fullpath); \ + } while (0) + +#define CHECK_HAVE_STREQ(node, propname, value) \ + do { \ + CHECK_HAVE_STRING((node), (propname)); \ + if (prop && !streq(prop->val.val, (value))) \ + DO_ERR("%s has wrong %s, %s (should be %s\n", \ + (node)->fullpath, (propname), \ + prop->val.val, (value)); \ + } while (0) + +#define CHECK_HAVE_ONECELL(node, propname) \ + do { \ + CHECK_HAVE((node), (propname)); \ + if (prop && (prop->val.len != sizeof(cell_t))) \ + DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \ + } while (0) + +#define CHECK_HAVE_WARN_ONECELL(node, propname) \ + do { \ + CHECK_HAVE_WARN((node), (propname)); \ + if (prop && (prop->val.len != sizeof(cell_t))) \ + DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \ + } while (0) + +#define CHECK_HAVE_WARN_PHANDLE(xnode, propname, root) \ + do { \ + struct node *ref; \ + CHECK_HAVE_WARN_ONECELL((xnode), (propname)); \ + if (prop) {\ + cell_t phandle = propval_cell(prop); \ + if ((phandle == 0) || (phandle == -1)) { \ + DO_ERR("\"%s\" property in %s contains an invalid phandle %x\n", (propname), (xnode)->fullpath, phandle); \ + } else { \ + ref = get_node_by_phandle((root), propval_cell(prop)); \ + if (! ref) \ + DO_ERR("\"%s\" property in %s refers to non-existant phandle %x\n", (propname), (xnode)->fullpath, propval_cell(prop)); \ + } \ + } \ + } while (0) + +#define CHECK_HAVE_WARN_STRING(node, propname) \ + do { \ + CHECK_HAVE_WARN((node), (propname)); \ + if (prop && !data_is_one_string(prop->val)) \ + DO_ERR("\"%s\" property in %s is not a string\n", \ + (propname), (node)->fullpath); \ + } while (0) + +static int check_root(struct node *root) +{ + struct property *prop; + int ok = 1; + + CHECK_HAVE_STRING(root, "model"); + + CHECK_HAVE(root, "#address-cells"); + CHECK_HAVE(root, "#size-cells"); + + CHECK_HAVE_WARN(root, "compatible"); + + return ok; +} + +static int check_cpus(struct node *root, int outversion, int boot_cpuid_phys) +{ + struct node *cpus, *cpu; + struct property *prop; + struct node *bootcpu = NULL; + int ok = 1; + + cpus = get_subnode(root, "cpus"); + if (! cpus) { + ERRMSG("Missing /cpus node\n"); + return 0; + } + + CHECK_HAVE_WARN(cpus, "#address-cells"); + CHECK_HAVE_WARN(cpus, "#size-cells"); + + for_each_child(cpus, cpu) { + CHECK_HAVE_STREQ(cpu, "device_type", "cpu"); + + if (cpu->addr_cells != 1) + DO_ERR("%s has bad #address-cells value %d (should be 1)\n", + cpu->fullpath, cpu->addr_cells); + if (cpu->size_cells != 0) + DO_ERR("%s has bad #size-cells value %d (should be 0)\n", + cpu->fullpath, cpu->size_cells); + + CHECK_HAVE_ONECELL(cpu, "reg"); + if (prop) { + cell_t unitnum; + char *eptr; + + unitnum = strtol(get_unitname(cpu), &eptr, 16); + if (*eptr) { + WARNMSG("%s has bad format unit name %s (should be CPU number\n", + cpu->fullpath, get_unitname(cpu)); + } else if (unitnum != propval_cell(prop)) { + WARNMSG("%s unit name \"%s\" does not match \"reg\" property <%x>\n", + cpu->fullpath, get_unitname(cpu), + propval_cell(prop)); + } + } + +/* CHECK_HAVE_ONECELL(cpu, "d-cache-line-size"); */ +/* CHECK_HAVE_ONECELL(cpu, "i-cache-line-size"); */ + CHECK_HAVE_ONECELL(cpu, "d-cache-size"); + CHECK_HAVE_ONECELL(cpu, "i-cache-size"); + + CHECK_HAVE_WARN_ONECELL(cpu, "clock-frequency"); + CHECK_HAVE_WARN_ONECELL(cpu, "timebase-frequency"); + + prop = get_property(cpu, "linux,boot-cpu"); + if (prop) { + if (prop->val.len) + WARNMSG("\"linux,boot-cpu\" property in %s is non-empty\n", + cpu->fullpath); + if (bootcpu) + DO_ERR("Multiple boot cpus (%s and %s)\n", + bootcpu->fullpath, cpu->fullpath); + else + bootcpu = cpu; + } + } + + if (outversion < 2) { + if (! bootcpu) + WARNMSG("No cpu has \"linux,boot-cpu\" property\n"); + } else { + if (bootcpu) + WARNMSG("\"linux,boot-cpu\" property is deprecated in blob version 2 or higher\n"); + if (boot_cpuid_phys == 0xfeedbeef) + WARNMSG("physical boot CPU not set. Use -b option to set\n"); + } + + return ok; +} + +static int check_memory(struct node *root) +{ + struct node *mem; + struct property *prop; + int nnodes = 0; + int ok = 1; + + for_each_child(root, mem) { + if (! strneq(mem->name, "memory", mem->basenamelen)) + continue; + + nnodes++; + + CHECK_HAVE_STREQ(mem, "device_type", "memory"); + CHECK_HAVE(mem, "reg"); + } + + if (nnodes == 0) { + ERRMSG("No memory nodes\n"); + return 0; + } + + return ok; +} + +static int check_chosen(struct node *root) +{ + struct node *chosen; + struct property *prop; + int ok = 1; + + chosen = get_subnode(root, "chosen"); + if (!chosen) + return ok; + + /* give warning for obsolete interrupt-controller property */ + do { + if ((prop = get_property(chosen, "interrupt-controller")) != NULL) { + WARNMSG("%s has obsolete \"%s\" property\n", + chosen->fullpath, "interrupt-controller"); + } + } while (0); + + return ok; +} + +static int check_addr_size_reg(struct node *node, + int p_addr_cells, int p_size_cells) +{ + int addr_cells = p_addr_cells; + int size_cells = p_size_cells; + struct property *prop; + struct node *child; + int ok = 1; + + node->addr_cells = addr_cells; + node->size_cells = size_cells; + + prop = get_property(node, "reg"); + if (prop) { + int len = prop->val.len / 4; + + if ((len % (addr_cells+size_cells)) != 0) + DO_ERR("\"reg\" property in %s has invalid length (%d) for given #address-cells (%d) and #size-cells (%d)\n", + node->fullpath, prop->val.len, + addr_cells, size_cells); + } + + prop = get_property(node, "#address-cells"); + if (prop) + addr_cells = propval_cell(prop); + + prop = get_property(node, "#size-cells"); + if (prop) + size_cells = propval_cell(prop); + + for_each_child(node, child) { + ok = ok && check_addr_size_reg(child, addr_cells, size_cells); + } + + return ok; +} + +int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys) +{ + int ok = 1; + + ok = ok && check_properties(dt); + ok = ok && check_addr_size_reg(dt, -1, -1); + ok = ok && check_root(dt); + ok = ok && check_cpus(dt, outversion, boot_cpuid_phys); + ok = ok && check_memory(dt); + ok = ok && check_chosen(dt); + if (! ok) + return 0; + + return 1; +} diff --git a/dtc.h b/dtc.h index 1fc6523..d080153 100644 --- a/dtc.h +++ b/dtc.h @@ -189,11 +189,13 @@ struct node *chain_node(struct node *first, struct node *list); void add_property(struct node *node, struct property *prop); void add_child(struct node *parent, struct node *child); -int check_structure(struct node *dt); -void fixup_references(struct node *dt); -int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys); +char *get_unitname(struct node *node); +struct property *get_property(struct node *node, char *propname); +cell_t propval_cell(struct property *prop); +struct node *get_subnode(struct node *node, char *nodename); +struct node *get_node_by_phandle(struct node *tree, cell_t phandle); -int check_device_tree(struct node *dt, int outversion, int boot_cpuid_phys); +void fixup_references(struct node *dt); /* Boot info (tree plus memreserve information */ @@ -220,6 +222,11 @@ struct boot_info { struct boot_info *build_boot_info(struct reserve_info *reservelist, struct node *tree); +/* Checks */ + +int check_structure(struct node *dt); +int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys); + /* Flattened trees */ void dt_to_blob(FILE *f, struct boot_info *bi, int version, diff --git a/livetree.c b/livetree.c index c480b36..cdd1ab5 100644 --- a/livetree.c +++ b/livetree.c @@ -180,7 +180,7 @@ struct boot_info *build_boot_info(struct reserve_info *reservelist, * Tree accessor functions */ -static char *get_unitname(struct node *node) +char *get_unitname(struct node *node) { if (node->name[node->basenamelen] == '\0') return ""; @@ -188,7 +188,7 @@ static char *get_unitname(struct node *node) return node->name + node->basenamelen + 1; } -static struct property *get_property(struct node *node, char *propname) +struct property *get_property(struct node *node, char *propname) { struct property *prop; @@ -199,13 +199,13 @@ static struct property *get_property(struct node *node, char *propname) return NULL; } -static cell_t propval_cell(struct property *prop) +cell_t propval_cell(struct property *prop) { assert(prop->val.len == sizeof(cell_t)); return be32_to_cpu(*((cell_t *)prop->val.val)); } -static struct node *get_subnode(struct node *node, char *nodename) +struct node *get_subnode(struct node *node, char *nodename) { struct node *child; @@ -257,7 +257,7 @@ static struct node *get_node_by_label(struct node *tree, const char *label) return NULL; } -static struct node *get_node_by_phandle(struct node *tree, cell_t phandle) +struct node *get_node_by_phandle(struct node *tree, cell_t phandle) { struct node *child, *node; @@ -296,100 +296,6 @@ static cell_t get_node_phandle(struct node *root, struct node *node) return node->phandle; } -/* - * Structural check functions - */ - -#define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__) -#define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__) - -#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0) - -static int check_names(struct node *tree) -{ - struct node *child, *child2; - struct property *prop, *prop2; - int len = strlen(tree->name); - int ok = 1; - - if (len == 0 && tree->parent) - DO_ERR("Empty, non-root nodename at %s\n", tree->fullpath); - - if (len > MAX_NODENAME_LEN) - WARNMSG("Overlength nodename at %s\n", tree->fullpath); - - for_each_property(tree, prop) { - /* check for duplicates */ - /* FIXME: do this more efficiently */ - for (prop2 = prop->next; prop2; prop2 = prop2->next) { - if (streq(prop->name, prop2->name)) { - DO_ERR("Duplicate propertyname %s in node %s\n", - prop->name, tree->fullpath); - } - } - - /* check name length */ - if (strlen(prop->name) > MAX_PROPNAME_LEN) - WARNMSG("Property name %s is too long in %s\n", - prop->name, tree->fullpath); - } - - for_each_child(tree, child) { - /* Check for duplicates */ - - for (child2 = child->next_sibling; - child2; - child2 = child2->next_sibling) { - if (streq(child->name, child2->name)) - DO_ERR("Duplicate node name %s\n", - child->fullpath); - } - if (! check_names(child)) - ok = 0; - } - - return ok; -} - -static int check_phandles(struct node *root, struct node *node) -{ - struct property *prop; - struct node *child, *other; - cell_t phandle; - int ok = 1; - - prop = get_property(node, "linux,phandle"); - if (prop) { - phandle = propval_cell(prop); - if ((phandle == 0) || (phandle == -1)) { - DO_ERR("%s has invalid linux,phandle %x\n", - node->fullpath, phandle); - } else { - other = get_node_by_phandle(root, phandle); - if (other) - DO_ERR("%s has duplicated phandle %x (seen before at %s)\n", - node->fullpath, phandle, other->fullpath); - - node->phandle = phandle; - } - } - - for_each_child(node, child) - ok = ok && check_phandles(root, child); - - return 1; -} - -int check_structure(struct node *dt) -{ - int ok = 1; - - ok = ok && check_names(dt); - ok = ok && check_phandles(dt, dt); - - return ok; -} - /* * Reference fixup functions */ @@ -442,348 +348,3 @@ void fixup_references(struct node *dt) { fixup_phandles(dt, dt); } - -/* - * Semantic check functions - */ - -static int must_be_one_cell(struct property *prop, struct node *node) -{ - if (prop->val.len != sizeof(cell_t)) { - ERRMSG("\"%s\" property in %s has the wrong length (should be 1 cell)\n", - prop->name, node->fullpath); - return 0; - } - - return 1; -} - -static int must_be_cells(struct property *prop, struct node *node) -{ - if ((prop->val.len % sizeof(cell_t)) != 0) { - ERRMSG("\"%s\" property in %s is not a multiple of cell size\n", - prop->name, node->fullpath); - return 0; - } - - return 1; -} - -static int must_be_string(struct property *prop, struct node *node) -{ - if (! data_is_one_string(prop->val)) { - ERRMSG("\"%s\" property in %s is not a string\n", - prop->name, node->fullpath); - return 0; - } - - return 1; -} - -static int name_prop_check(struct property *prop, struct node *node) -{ - if ((prop->val.len != node->basenamelen+1) - || !strneq(prop->val.val, node->name, node->basenamelen)) { - ERRMSG("name property \"%s\" does not match node basename in %s\n", - prop->val.val, - node->fullpath); - return 0; - } - - return 1; -} - -static struct { - char *propname; - int (*check_fn)(struct property *prop, struct node *node); -} prop_checker_table[] = { - {"name", must_be_string}, - {"name", name_prop_check}, - {"linux,phandle", must_be_one_cell}, - {"#address-cells", must_be_one_cell}, - {"#size-cells", must_be_one_cell}, - {"reg", must_be_cells}, - {"model", must_be_string}, - {"device_type", must_be_string}, -}; - -static int check_properties(struct node *node) -{ - struct property *prop; - struct node *child; - int i; - int ok = 1; - - for_each_property(node, prop) - for (i = 0; i < ARRAY_SIZE(prop_checker_table); i++) - if (streq(prop->name, prop_checker_table[i].propname)) - if (! prop_checker_table[i].check_fn(prop, node)) { - ok = 0; - break; - } - - for_each_child(node, child) - if (! check_properties(child)) - ok = 0; - - return ok; -} - -#define CHECK_HAVE(node, propname) \ - do { \ - if (! (prop = get_property((node), (propname)))) \ - DO_ERR("Missing \"%s\" property in %s\n", (propname), \ - (node)->fullpath); \ - } while (0); - -#define CHECK_HAVE_WARN(node, propname) \ - do { \ - if (! (prop = get_property((node), (propname)))) \ - WARNMSG("%s has no \"%s\" property\n", \ - (node)->fullpath, (propname)); \ - } while (0) - -#define CHECK_HAVE_STRING(node, propname) \ - do { \ - CHECK_HAVE((node), (propname)); \ - if (prop && !data_is_one_string(prop->val)) \ - DO_ERR("\"%s\" property in %s is not a string\n", \ - (propname), (node)->fullpath); \ - } while (0) - -#define CHECK_HAVE_STREQ(node, propname, value) \ - do { \ - CHECK_HAVE_STRING((node), (propname)); \ - if (prop && !streq(prop->val.val, (value))) \ - DO_ERR("%s has wrong %s, %s (should be %s\n", \ - (node)->fullpath, (propname), \ - prop->val.val, (value)); \ - } while (0) - -#define CHECK_HAVE_ONECELL(node, propname) \ - do { \ - CHECK_HAVE((node), (propname)); \ - if (prop && (prop->val.len != sizeof(cell_t))) \ - DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \ - } while (0) - -#define CHECK_HAVE_WARN_ONECELL(node, propname) \ - do { \ - CHECK_HAVE_WARN((node), (propname)); \ - if (prop && (prop->val.len != sizeof(cell_t))) \ - DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \ - } while (0) - -#define CHECK_HAVE_WARN_PHANDLE(xnode, propname, root) \ - do { \ - struct node *ref; \ - CHECK_HAVE_WARN_ONECELL((xnode), (propname)); \ - if (prop) {\ - cell_t phandle = propval_cell(prop); \ - if ((phandle == 0) || (phandle == -1)) { \ - DO_ERR("\"%s\" property in %s contains an invalid phandle %x\n", (propname), (xnode)->fullpath, phandle); \ - } else { \ - ref = get_node_by_phandle((root), propval_cell(prop)); \ - if (! ref) \ - DO_ERR("\"%s\" property in %s refers to non-existant phandle %x\n", (propname), (xnode)->fullpath, propval_cell(prop)); \ - } \ - } \ - } while (0) - -#define CHECK_HAVE_WARN_STRING(node, propname) \ - do { \ - CHECK_HAVE_WARN((node), (propname)); \ - if (prop && !data_is_one_string(prop->val)) \ - DO_ERR("\"%s\" property in %s is not a string\n", \ - (propname), (node)->fullpath); \ - } while (0) - -static int check_root(struct node *root) -{ - struct property *prop; - int ok = 1; - - CHECK_HAVE_STRING(root, "model"); - - CHECK_HAVE(root, "#address-cells"); - CHECK_HAVE(root, "#size-cells"); - - CHECK_HAVE_WARN(root, "compatible"); - - return ok; -} - -static int check_cpus(struct node *root, int outversion, int boot_cpuid_phys) -{ - struct node *cpus, *cpu; - struct property *prop; - struct node *bootcpu = NULL; - int ok = 1; - - cpus = get_subnode(root, "cpus"); - if (! cpus) { - ERRMSG("Missing /cpus node\n"); - return 0; - } - - CHECK_HAVE_WARN(cpus, "#address-cells"); - CHECK_HAVE_WARN(cpus, "#size-cells"); - - for_each_child(cpus, cpu) { - CHECK_HAVE_STREQ(cpu, "device_type", "cpu"); - - if (cpu->addr_cells != 1) - DO_ERR("%s has bad #address-cells value %d (should be 1)\n", - cpu->fullpath, cpu->addr_cells); - if (cpu->size_cells != 0) - DO_ERR("%s has bad #size-cells value %d (should be 0)\n", - cpu->fullpath, cpu->size_cells); - - CHECK_HAVE_ONECELL(cpu, "reg"); - if (prop) { - cell_t unitnum; - char *eptr; - - unitnum = strtol(get_unitname(cpu), &eptr, 16); - if (*eptr) { - WARNMSG("%s has bad format unit name %s (should be CPU number\n", - cpu->fullpath, get_unitname(cpu)); - } else if (unitnum != propval_cell(prop)) { - WARNMSG("%s unit name \"%s\" does not match \"reg\" property <%x>\n", - cpu->fullpath, get_unitname(cpu), - propval_cell(prop)); - } - } - -/* CHECK_HAVE_ONECELL(cpu, "d-cache-line-size"); */ -/* CHECK_HAVE_ONECELL(cpu, "i-cache-line-size"); */ - CHECK_HAVE_ONECELL(cpu, "d-cache-size"); - CHECK_HAVE_ONECELL(cpu, "i-cache-size"); - - CHECK_HAVE_WARN_ONECELL(cpu, "clock-frequency"); - CHECK_HAVE_WARN_ONECELL(cpu, "timebase-frequency"); - - prop = get_property(cpu, "linux,boot-cpu"); - if (prop) { - if (prop->val.len) - WARNMSG("\"linux,boot-cpu\" property in %s is non-empty\n", - cpu->fullpath); - if (bootcpu) - DO_ERR("Multiple boot cpus (%s and %s)\n", - bootcpu->fullpath, cpu->fullpath); - else - bootcpu = cpu; - } - } - - if (outversion < 2) { - if (! bootcpu) - WARNMSG("No cpu has \"linux,boot-cpu\" property\n"); - } else { - if (bootcpu) - WARNMSG("\"linux,boot-cpu\" property is deprecated in blob version 2 or higher\n"); - if (boot_cpuid_phys == 0xfeedbeef) - WARNMSG("physical boot CPU not set. Use -b option to set\n"); - } - - return ok; -} - -static int check_memory(struct node *root) -{ - struct node *mem; - struct property *prop; - int nnodes = 0; - int ok = 1; - - for_each_child(root, mem) { - if (! strneq(mem->name, "memory", mem->basenamelen)) - continue; - - nnodes++; - - CHECK_HAVE_STREQ(mem, "device_type", "memory"); - CHECK_HAVE(mem, "reg"); - } - - if (nnodes == 0) { - ERRMSG("No memory nodes\n"); - return 0; - } - - return ok; -} - -static int check_chosen(struct node *root) -{ - struct node *chosen; - struct property *prop; - int ok = 1; - - chosen = get_subnode(root, "chosen"); - if (!chosen) - return ok; - - /* give warning for obsolete interrupt-controller property */ - do { - if ((prop = get_property(chosen, "interrupt-controller")) != NULL) { - WARNMSG("%s has obsolete \"%s\" property\n", - chosen->fullpath, "interrupt-controller"); - } - } while (0); - - return ok; -} - -static int check_addr_size_reg(struct node *node, - int p_addr_cells, int p_size_cells) -{ - int addr_cells = p_addr_cells; - int size_cells = p_size_cells; - struct property *prop; - struct node *child; - int ok = 1; - - node->addr_cells = addr_cells; - node->size_cells = size_cells; - - prop = get_property(node, "reg"); - if (prop) { - int len = prop->val.len / 4; - - if ((len % (addr_cells+size_cells)) != 0) - DO_ERR("\"reg\" property in %s has invalid length (%d) for given #address-cells (%d) and #size-cells (%d)\n", - node->fullpath, prop->val.len, - addr_cells, size_cells); - } - - prop = get_property(node, "#address-cells"); - if (prop) - addr_cells = propval_cell(prop); - - prop = get_property(node, "#size-cells"); - if (prop) - size_cells = propval_cell(prop); - - for_each_child(node, child) { - ok = ok && check_addr_size_reg(child, addr_cells, size_cells); - } - - return ok; -} - -int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys) -{ - int ok = 1; - - ok = ok && check_properties(dt); - ok = ok && check_addr_size_reg(dt, -1, -1); - ok = ok && check_root(dt); - ok = ok && check_cpus(dt, outversion, boot_cpuid_phys); - ok = ok && check_memory(dt); - ok = ok && check_chosen(dt); - if (! ok) - return 0; - - return 1; -} From bf141b96cda8affecf7404198f72c08c8c2c542e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 2 Nov 2007 15:15:17 +1100 Subject: [PATCH 0136/1198] dtc: Don't include libfdt in global LDFLAGS Remove the uneccessary LDFLAGS from the top-level makefile. It only added libfdt/ to the link path. dtc doesn't need libfdt at all, and the testcases which do, already link libfdt.a by explicit path. Signed-off-by: David Gibson --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 84f0efe..5e1f05d 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,6 @@ CONFIG_LOCALVERSION = CPPFLAGS = -I libfdt CFLAGS = -Wall -g -Os -LDFLAGS = -Llibfdt BISON = bison LEX = flex From 02563ad023122ac2dbd6de6169eaf4b911ddcc7e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 2 Nov 2007 16:10:30 +1100 Subject: [PATCH 0137/1198] dtc: Make -Idts -Odts preserve node/property labels This patch changes -Odts mode output so that labels on properties, nodes and memreserve entries in input source are preserved in the output. Preserving labels within property values is trickier - another patch coming later. Signed-off-by: David Gibson --- treesource.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/treesource.c b/treesource.c index f62041f..376ebc8 100644 --- a/treesource.c +++ b/treesource.c @@ -176,6 +176,8 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) struct node *child; write_prefix(f, level); + if (tree->label) + fprintf(f, "%s: ", tree->label); if (tree->name && (*tree->name)) fprintf(f, "%s {\n", tree->name); else @@ -184,8 +186,10 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) for_each_property(tree, prop) { enum proptype type; - write_prefix(f, level); - fprintf(f, "\t%s", prop->name); + write_prefix(f, level+1); + if (prop->label) + fprintf(f, "%s: ", prop->label); + fprintf(f, "%s", prop->name); type = guess_type(prop); switch (type) { @@ -220,6 +224,8 @@ void dt_to_source(FILE *f, struct boot_info *bi) struct reserve_info *re; for (re = bi->reservelist; re; re = re->next) { + if (re->label) + fprintf(f, "%s: ", re->label); fprintf(f, "/memreserve/\t%016llx-%016llx;\n", (unsigned long long)re->re.address, (unsigned long long)(re->re.address + re->re.size - 1)); From f7497dc6be43769abb9119d7bed8fb08f4eecff6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 2 Nov 2007 16:54:26 +1100 Subject: [PATCH 0138/1198] dtc: Don't force alignment of cell list data At present, defining a property as, say: foo = [abcd], ; Will cause dtc to insert 2 bytes of zeros between the abcd and the ffffffff, to align the cell form data. Doing so seemed like a good idea at the time, but I don't believe there are any users who actually rely on this behaviour. Segher claims that OF has some defined bindings which include properties an unaligned subsection of which is interpreted as 32-bit ints (i.e. like cell data). Worse, this alignment will cause nothing but pain when we add expression support to dtc (when celldata is included in a larger bytestring expession, we won't know the size of the preceding chunk of the expression until it's evaluated, so we would have to carry alignment fixup information right through the expression evaluation process). Therefore, this patch kills off this alignment behaviour. Signed-off-by: David Gibson --- dtc-parser.y | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 61ed250..4853794 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -149,8 +149,7 @@ propdata: } | propdataprefix '<' celllist '>' { - $$ = data_merge(data_append_align($1, - sizeof(cell_t)), $3); + $$ = data_merge($1, $3); } | propdataprefix '[' bytestring ']' { From e0f2989809aa79aab0f4c827e199b6671b941f48 Mon Sep 17 00:00:00 2001 From: Emil Medve Date: Fri, 2 Nov 2007 10:26:15 -0500 Subject: [PATCH 0139/1198] dtc: Fix the install target /usr/bin/install: cannot stat `fdt.h': No such file or directory /usr/bin/install: cannot stat `libfdt.h': No such file or directory Signed-off-by: Emil Medve Acked-by: David Gibson --- Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 5e1f05d..4d4b98e 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,7 @@ install: all $(INSTALL) -d $(DESTDIR)$(LIBDIR) $(INSTALL) -m 644 $(LIBFDT_LIB) $(DESTDIR)$(LIBDIR) $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) - $(INSTALL) -m 644 $(LIBFDT_INCLUDES) $(DESTDIR)$(INCLUDEDIR) + $(INSTALL) -m 644 $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES)) $(DESTDIR)$(INCLUDEDIR) # # Rules for versioning @@ -135,17 +135,17 @@ endif # LIBFDT_objdir = libfdt LIBFDT_srcdir = libfdt -include libfdt/Makefile.libfdt +include $(LIBFDT_srcdir)/Makefile.libfdt .PHONY: libfdt libfdt: $(LIBFDT_LIB) -$(LIBFDT_LIB): $(addprefix libfdt/,$(LIBFDT_OBJS)) +$(LIBFDT_LIB): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) libfdt_clean: @$(VECHO) CLEAN "(libfdt)" - rm -f $(addprefix libfdt/,$(STD_CLEANFILES)) - rm -f $(addprefix libfdt/,$(LIBFDT_CLEANFILES)) + rm -f $(addprefix $(LIBFDT_objdir)/,$(STD_CLEANFILES)) + rm -f $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_CLEANFILES)) ifneq ($(DEPTARGETS),) -include $(LIBFDT_OBJS:%.o=$(LIBFDT_objdir)/%.d) From 2ec634d24bf00b103da895b57c7f1bcac1446112 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 5 Nov 2007 14:29:18 +1100 Subject: [PATCH 0140/1198] libfdt: Add more documentation (patch the third) libfdt: Add more documentation (patch the third) This patch adds documentation in libfdt.h for a few more libfdt functions. It also makes a slight update to the documentation of fdt_get_name(). Signed-off-by: David Gibson --- libfdt/libfdt.h | 92 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 85 insertions(+), 7 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 4ef65bc..f6e43b5 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -319,28 +319,54 @@ int fdt_path_offset(const void *fdt, const char *path); * fdt_get_name - retreive the name of a given node * @fdt: pointer to the device tree blob * @nodeoffset: structure block offset of the starting node - * @len: pointer to an intger variable (will be overwritten) or NULL + * @lenp: pointer to an integer variable (will be overwritten) or NULL * * fdt_get_name() retrieves the name (including unit address) of the - * device tree node at structure block offset nodeoffset. If len is + * device tree node at structure block offset nodeoffset. If lenp is * non-NULL, the length of this name is also returned, in the integer - * pointed to by len. + * pointed to by lenp. * * returns: * pointer to the node's name, on success - * *len contains the length of that name (>=0) + * If lenp is non-NULL, *lenp contains the length of that name (>=0) * NULL, on error - * *len contains an error code (<0): + * if lenp is non-NULL *lenp contains an error code (<0): * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, standard meanings */ -const char *fdt_get_name(const void *fdt, int nodeoffset, int *len); +const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); +/** + * fdt_get_property - find a given property in a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_property() retrieves a pointer to the fdt_property + * structure within the device tree blob corresponding to the property + * named 'name' of the node at offset nodeoffset. If lenp is + * non-NULL, the length of the property value also returned, in the + * integer pointed to by lenp. + * + * returns: + * pointer to the structure representing the property + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_NOTFOUND, node does not have named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, const char *name, int *lenp); - static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, const char *name, int *lenp) @@ -349,6 +375,33 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, name, lenp); } +/** + * fdt_getprop - retrieve the value of a given property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @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 + * pointer to within the device blob itself, not a copy of the value). + * If lenp is non-NULL, the length of the property value also + * returned, in the integer pointed to by lenp. + * + * returns: + * pointer to the property's value + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_NOTFOUND, node does not have named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp); static inline void *fdt_getprop_w(void *fdt, int nodeoffset, @@ -357,6 +410,31 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset, return (void *)fdt_getprop(fdt, nodeoffset, name, lenp); } +/** + * fdt_get_path - determine the full path of a node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose path to find + * @buf: character buffer to contain the returned path (will be overwritten) + * @buflen: size of the character buffer at buf + * + * fdt_get_path() computes the full path of the node at offset + * nodeoffset, and records that path in the buffer at buf. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * 0, on success + * buf contains the absolute path of the node at + * nodeoffset, as a NUL-terminated string. + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) + * characters and will not fit in the given buffer. + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, From 9d3af7ab624eee7a611bd115b7ea17d5f88bb1f5 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 5 Nov 2007 14:29:37 +1100 Subject: [PATCH 0141/1198] libfdt: Add more documentation (patch the fourth) This patch documents a few more functions in libfdt.h. It also makes a slight update to the description of the FDT_ERR_INTERNAL error code. Signed-off-by: David Gibson --- libfdt/libfdt.h | 75 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index f6e43b5..8a664bb 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -110,7 +110,8 @@ /* "Can't happen" error indicating a bug in libfdt */ #define FDT_ERR_INTERNAL 12 /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. - * Indicates a bug in libfdt itself. */ + * Should never be returned, if it is, it indicates a bug in + * libfdt itself. */ #define FDT_ERR_MAX 12 @@ -437,9 +438,81 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset, */ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); +/** + * fdt_supernode_atdepth_offset - find a specific ancestor of a node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * @supernodedepth: depth of the ancestor to find + * @nodedepth: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_supernode_atdepth_offset() finds an ancestor of the given node + * at a specific depth from the root (where the root itself has depth + * 0, its immediate subnodes depth 1 and so forth). So + * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); + * will always return 0, the offset of the root node. If the node at + * nodeoffset has depth D, then: + * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); + * will return nodeoffset itself. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + + * structure block offset of the node at node offset's ancestor + * of depth supernodedepth (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag +* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int supernodedepth, int *nodedepth); + +/** + * fdt_node_depth - find the depth of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * + * fdt_node_depth() finds the depth of a given node. The root node + * has depth 0, its immediate subnodes depth 1 and so forth. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * depth of the node at nodeoffset (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ int fdt_node_depth(const void *fdt, int nodeoffset); + +/** + * fdt_parent_offset - find the parent of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * + * fdt_parent_offset() locates the parent node of a given node (that + * is, it finds the offset of the node which contains the node at + * nodeoffset as a subnode). + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset, *twice*. + * + * returns: + * stucture block offset of the parent of the node at nodeoffset + * (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ int fdt_parent_offset(const void *fdt, int nodeoffset); int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, From d79d4e280f008a02b4da030b32189b5efbff7d89 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 6 Nov 2007 10:42:45 +1100 Subject: [PATCH 0142/1198] libfdt: Fix sw_tree1 testcase There is a bug in the sw_tree1 testcase / utility which puts two "compatible" properties in one node in the output tree. This patch fixes the bug, and also adds a new test checking that the sw_tree1 output is equal to test_tree1.dtb as its supposed to be, which should catch future errors of this type. Signed-off-by: David Gibson --- tests/run_tests.sh | 1 + tests/sw_tree1.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 8fcc44a..278008b 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -70,6 +70,7 @@ libfdt_tests () { run_test sw_tree1 tree1_tests sw_tree1.test.dtb tree1_tests unfinished_tree1.test.dtb + run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb # fdt_move tests for tree in test_tree1.dtb sw_tree1.test.dtb unfinished_tree1.test.dtb; do diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 8784868..68551c3 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -64,7 +64,6 @@ int main(int argc, char *argv[]) CHECK(fdt_begin_node(fdt, "subsubnode")); CHECK(fdt_property(fdt, "compatible", "subsubnode1\0subsubnode", 23)); - CHECK(fdt_property_string(fdt, "compatible", "subsubnode1\0")); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_end_node(fdt)); CHECK(fdt_end_node(fdt)); From ed01ae41e2cbbbd26c9efd495b833ba9eb1e062a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 7 Nov 2007 10:21:20 +1100 Subject: [PATCH 0143/1198] dtc: Refactor printing of property values in -Odts mode Currently the main recursive tree printing function, write_tree_source_node(), calls guess_type() to apply heuristics to see how to print a property value, then calls the appropriate write_propval_*() function to print it. However, future heuristics for handling internal labels and the like don't work well this way. Therefore, this patch refactors things to have write_tree_source_node() call a new write_propval() function, which incorporates the heurstic logic from guess_type() and also calls the right function to do the actual printing. No behavioural change. Signed-off-by: David Gibson --- treesource.c | 97 ++++++++++++++++++++-------------------------------- 1 file changed, 38 insertions(+), 59 deletions(-) diff --git a/treesource.c b/treesource.c index 376ebc8..0a4367a 100644 --- a/treesource.c +++ b/treesource.c @@ -49,13 +49,6 @@ static void write_prefix(FILE *f, int level) fputc('\t', f); } -enum proptype { - PROP_EMPTY, - PROP_STRING, - PROP_CELLS, - PROP_BYTES, -}; - int isstring(char c) { return (isprint(c) @@ -63,31 +56,6 @@ int isstring(char c) || strchr("\a\b\t\n\v\f\r", c)); } -static enum proptype guess_type(struct property *prop) -{ - int len = prop->val.len; - char *p = prop->val.val; - int nnotstring = 0, nnul = 0; - int i; - - if (len == 0) - return PROP_EMPTY; - - for (i = 0; i < len; i++) { - if (! isstring(p[i])) - nnotstring++; - if (p[i] == '\0') - nnul++; - } - - if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))) - return PROP_STRING; - else if ((len % sizeof(cell_t)) == 0) - return PROP_CELLS; - else - return PROP_BYTES; -} - static void write_propval_string(FILE *f, struct data val) { char *str = val.val; @@ -95,7 +63,7 @@ static void write_propval_string(FILE *f, struct data val) assert(str[val.len-1] == '\0'); - fprintf(f, " = \""); + fprintf(f, "\""); for (i = 0; i < (val.len-1); i++) { char c = str[i]; @@ -137,7 +105,7 @@ static void write_propval_string(FILE *f, struct data val) fprintf(f, "\\x%02hhx", c); } } - fprintf(f, "\";\n"); + fprintf(f, "\""); } static void write_propval_cells(FILE *f, struct data val) @@ -145,14 +113,14 @@ static void write_propval_cells(FILE *f, struct data val) void *propend = val.val + val.len; cell_t *cp = (cell_t *)val.val; - fprintf(f, " = <"); + fprintf(f, "<"); for (;;) { fprintf(f, "%x", be32_to_cpu(*cp++)); if ((void *)cp >= propend) break; fprintf(f, " "); } - fprintf(f, ">;\n"); + fprintf(f, ">"); } static void write_propval_bytes(FILE *f, struct data val) @@ -160,14 +128,45 @@ static void write_propval_bytes(FILE *f, struct data val) void *propend = val.val + val.len; char *bp = val.val; - fprintf(f, " = ["); + fprintf(f, "["); for (;;) { fprintf(f, "%02hhx", *bp++); if ((void *)bp >= propend) break; fprintf(f, " "); } - fprintf(f, "];\n"); + fprintf(f, "]"); +} + +static void write_propval(FILE *f, struct property *prop) +{ + int len = prop->val.len; + char *p = prop->val.val; + int nnotstring = 0, nnul = 0; + int i; + + if (len == 0) { + fprintf(f, ";\n"); + return; + } + + for (i = 0; i < len; i++) { + if (! isstring(p[i])) + nnotstring++; + if (p[i] == '\0') + nnul++; + } + + fprintf(f, " = "); + + if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))) { + write_propval_string(f, prop->val); + } else if (((len % sizeof(cell_t)) == 0)) { + write_propval_cells(f, prop->val); + } else { + write_propval_bytes(f, prop->val); + } + fprintf(f, ";\n"); } static void write_tree_source_node(FILE *f, struct node *tree, int level) @@ -184,31 +183,11 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) fprintf(f, "/ {\n"); for_each_property(tree, prop) { - enum proptype type; - write_prefix(f, level+1); if (prop->label) fprintf(f, "%s: ", prop->label); fprintf(f, "%s", prop->name); - type = guess_type(prop); - - switch (type) { - case PROP_EMPTY: - fprintf(f, ";\n"); - break; - - case PROP_STRING: - write_propval_string(f, prop->val); - break; - - case PROP_CELLS: - write_propval_cells(f, prop->val); - break; - - case PROP_BYTES: - write_propval_bytes(f, prop->val); - break; - } + write_propval(f, prop); } for_each_child(tree, child) { fprintf(f, "\n"); From d3ea6e5f96e8b6fb74607b9061836f2bdd57b0af Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 7 Nov 2007 10:22:25 +1100 Subject: [PATCH 0144/1198] dtc: Make -Idts -Odts preserve property-internal labels This patch changes -Odts mode output so that labels within property values in the input are preserved in the output. Applied on top of the earlier patch to preserve node and property labels in -Odts mode, this means that dtc in -Idts -Odts mode will transfer all labels in the input to the output. Signed-off-by: David Gibson --- tests/label01.dts | 7 ++--- treesource.c | 66 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/tests/label01.dts b/tests/label01.dts index ad1f1e4..372b17a 100644 --- a/tests/label01.dts +++ b/tests/label01.dts @@ -36,10 +36,11 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff; }; node: randomnode { - prop: string = data: "\xff\0stuffstuff\t\t\t\n\n\n" data_end: ; - blob = [byte: 0a 0b 0c 0d de ea ad be ef byte_end: ]; - ref = < cell: &/memory@0 cell_end: >; + prop: string = str: "foo", str_mid: "stuffstuff\t\t\t\n\n\n" str_end: ; + blob = [byte: 0a 0b 0c 0d byte_mid: de ea ad be ef byte_end: ]; + ref = < cell: &/memory@0 0 cell_mid: ffffffff cell_end: >; mixed = "abc", pre: [1234] post: , gap: < aligned: a b c>; + tricky1 = [61 lt1: 62 63 00]; subnode: child { }; /* subnode_end: is auto-generated by node emit */ diff --git a/treesource.c b/treesource.c index 0a4367a..0752280 100644 --- a/treesource.c +++ b/treesource.c @@ -60,13 +60,24 @@ static void write_propval_string(FILE *f, struct data val) { char *str = val.val; int i; + int newchunk = 1; + struct fixup *l = val.labels; assert(str[val.len-1] == '\0'); - fprintf(f, "\""); for (i = 0; i < (val.len-1); i++) { char c = str[i]; + if (newchunk) { + while (l && (l->offset <= i)) { + assert(l->offset == i); + fprintf(f, "%s: ", l->ref); + l = l->next; + } + fprintf(f, "\""); + newchunk = 0; + } + switch (c) { case '\a': fprintf(f, "\\a"); @@ -96,7 +107,8 @@ static void write_propval_string(FILE *f, struct data val) fprintf(f, "\\\""); break; case '\0': - fprintf(f, "\", \""); + fprintf(f, "\", "); + newchunk = 1; break; default: if (isprint(c)) @@ -106,20 +118,41 @@ static void write_propval_string(FILE *f, struct data val) } } fprintf(f, "\""); + + /* Wrap up any labels at the end of the value */ + while (l) { + assert (l->offset == val.len); + fprintf(f, " %s:", l->ref); + l = l->next; + } } static void write_propval_cells(FILE *f, struct data val) { void *propend = val.val + val.len; cell_t *cp = (cell_t *)val.val; + struct fixup *l = val.labels; fprintf(f, "<"); for (;;) { + while (l && (l->offset <= ((char *)cp - val.val))) { + assert(l->offset == ((char *)cp - val.val)); + fprintf(f, "%s: ", l->ref); + l = l->next; + } + fprintf(f, "%x", be32_to_cpu(*cp++)); if ((void *)cp >= propend) break; fprintf(f, " "); } + + /* Wrap up any labels at the end of the value */ + while (l) { + assert (l->offset == val.len); + fprintf(f, " %s:", l->ref); + l = l->next; + } fprintf(f, ">"); } @@ -127,14 +160,27 @@ static void write_propval_bytes(FILE *f, struct data val) { void *propend = val.val + val.len; char *bp = val.val; + struct fixup *l = val.labels; fprintf(f, "["); for (;;) { + while (l && (l->offset == (bp-val.val))) { + fprintf(f, "%s: ", l->ref); + l = l->next; + } + fprintf(f, "%02hhx", *bp++); if ((void *)bp >= propend) break; fprintf(f, " "); } + + /* Wrap up any labels at the end of the value */ + while (l) { + assert (l->offset == val.len); + fprintf(f, " %s:", l->ref); + l = l->next; + } fprintf(f, "]"); } @@ -142,7 +188,9 @@ static void write_propval(FILE *f, struct property *prop) { int len = prop->val.len; char *p = prop->val.val; + struct fixup *l; int nnotstring = 0, nnul = 0; + int nnotstringlbl = 0, nnotcelllbl = 0; int i; if (len == 0) { @@ -157,15 +205,23 @@ static void write_propval(FILE *f, struct property *prop) nnul++; } - fprintf(f, " = "); + for (l = prop->val.labels; l; l = l->next) { + if ((l->offset > 0) && (prop->val.val[l->offset - 1] != '\0')) + nnotstringlbl++; + if ((l->offset % sizeof(cell_t)) != 0) + nnotcelllbl++; + } - if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))) { + fprintf(f, " = "); + if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) + && (nnotstringlbl == 0)) { write_propval_string(f, prop->val); - } else if (((len % sizeof(cell_t)) == 0)) { + } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { write_propval_cells(f, prop->val); } else { write_propval_bytes(f, prop->val); } + fprintf(f, ";\n"); } From b433db0fc74bc7b4c04fcfb014bfaac0f5f29a14 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 7 Nov 2007 10:34:06 +1100 Subject: [PATCH 0145/1198] dtc: Add testcases exercising -Odts mode This patch adds a batch of testcases exercising dtc's -Odts mode. Specifically it checks that using dtc to convert dtb->dts->dtb preserves the original dtb for a number of example dtb files. Signed-off-by: David Gibson --- tests/Makefile.tests | 2 +- tests/run_tests.sh | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 68324e9..8ee0e5d 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -23,7 +23,7 @@ TESTS_TARGETS = $(TESTS) $(TESTS_TREES) TESTS_DEPFILES = $(TESTS:%=%.d) $(TESTS_PREFIX)testutils.d -TESTS_CLEANFILES_L = *.output vgcore.* *.dtb +TESTS_CLEANFILES_L = *.output vgcore.* *.dtb *.test.dts TESTS_CLEANFILES = $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) BIN += $(TESTS) $(TESTS_PREFIX)dumptrees diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 278008b..5cf849b 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -82,7 +82,7 @@ libfdt_tests () { done # v16 and alternate layout tests - for tree in test_tree1.dtb; do + for tree in test_tree1.dtb sw_tree1.test.dtb; do for version in 17 16; do for layout in $ALL_LAYOUTS; do run_test mangle-layout $tree $version $layout @@ -93,7 +93,7 @@ libfdt_tests () { done # Read-write tests - for basetree in test_tree1.dtb; do + for basetree in test_tree1.dtb sw_tree1.test.dtb; do for version in 17 16; do for layout in $ALL_LAYOUTS; do tree=v$version.$layout.$basetree @@ -125,6 +125,13 @@ dtc_tests () { run_test dtc.sh -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts run_test string_escapes dtc_escapes.test.dtb + + # Check -Odts mode preserve all dtb information + for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb ; do + run_test dtc.sh -I dtb -O dts -o odts_$tree.test.dts $tree + run_test dtc.sh -I dts -O dtb -o odts_$tree.test.dtb odts_$tree.test.dts + run_test dtbs_equal_ordered $tree odts_$tree.test.dtb + done } while getopts "vdt:" ARG ; do @@ -143,7 +150,7 @@ if [ -z "$TESTSETS" ]; then fi # Make sure we don't have stale blobs lying around -rm -f *.test.dtb +rm -f *.test.dtb *.test.dts for set in $TESTSETS; do case $set in From 9409bd96a56b914baf5bfa802bc6a56fff5698e6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 7 Nov 2007 10:58:22 +1100 Subject: [PATCH 0146/1198] dtc: Better exercise dtc base and bytestring features This patch alters the main testcase, and the dts file corresponding to it so that we at least trivially exercise dtc's bytestring and base conversion features. Signed-off-by: David Gibson --- tests/test_tree1.dts | 10 +++++----- tests/testdata.h | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts index c5f8da3..ac920df 100644 --- a/tests/test_tree1.dts +++ b/tests/test_tree1.dts @@ -1,5 +1,5 @@ /memreserve/ deadbeef00000000-deadbeef000fffff; -/memreserve/ abcd1234 00001234; +/memreserve/ 75bcd15 1000; / { compatible = "test_tree1"; @@ -8,20 +8,20 @@ subnode@1 { compatible = "subnode1"; - prop-int = ; + prop-int = [deadbeef]; subsubnode { compatible = "subsubnode1", "subsubnode"; - prop-int = ; + prop-int = ; }; }; subnode@2 { - prop-int = ; + prop-int = ; subsubnode@0 { compatible = "subsubnode2", "subsubnode"; - prop-int = ; + prop-int = ; }; }; }; diff --git a/tests/testdata.h b/tests/testdata.h index 94f3dee..027d972 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -17,11 +17,11 @@ #define TEST_ADDR_1 ASM_CONST_LL(0xdeadbeef00000000) #define TEST_SIZE_1 ASM_CONST_LL(0x100000) -#define TEST_ADDR_2 ASM_CONST_LL(0xabcd1234) -#define TEST_SIZE_2 ASM_CONST_LL(0x1234) +#define TEST_ADDR_2 ASM_CONST_LL(123456789) +#define TEST_SIZE_2 ASM_CONST_LL(010000) #define TEST_VALUE_1 cell_to_fdt(0xdeadbeef) -#define TEST_VALUE_2 cell_to_fdt(0xabcd1234) +#define TEST_VALUE_2 cell_to_fdt(123456789) #define TEST_STRING_1 "hello world" #define TEST_STRING_2 "nastystring: \a\b\t\n\v\f\r\\\"" From 53acf491e9d576519f97b62984762498f9453cb4 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 7 Nov 2007 11:54:14 +1100 Subject: [PATCH 0147/1198] libfdt: Add more documentation (path the fifth) This patch documents a few more functions in libfdt.h. All the read-only functions are now documented. Signed-off-by: David Gibson --- libfdt/libfdt.h | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 8a664bb..220431a 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -515,12 +515,107 @@ int fdt_node_depth(const void *fdt, int nodeoffset); */ int fdt_parent_offset(const void *fdt, int nodeoffset); +/** + * fdt_node_offset_by_prop_value - find nodes with a given property value + * @fdt: pointer to the device tree blob + * @startoffset: only find nodes after this offset + * @propname: property name to check + * @propval: property value to search for + * @proplen: length of the value in propval + * + * fdt_node_offset_by_prop_value() returns the offset of the first + * node after startoffset, which has a property named propname whose + * value is of length proplen and has value equal to propval; or if + * startoffset is -1, the very first such node in the tree. + * + * To iterate through all nodes matching the criterion, the following + * idiom can be used: + * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, + * propval, proplen); + * while (offset != -FDT_ERR_NOTFOUND) { + * // other code here + * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, + * propval, proplen); + * } + * + * Note the -1 in the first call to the function, if 0 is used here + * instead, the function will never locate the root node, even if it + * matches the criterion. + * + * returns: + * structure block offset of the located node (>= 0, >startoffset), + * on success + * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the + * tree after startoffset + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, const char *propname, const void *propval, int proplen); +/** + * 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, + * it returns non-zero otherwise, or on error. + * + * returns: + * 0, if the node has a 'compatible' property listing the given string + * 1, if the node has a 'compatible' property, but it does not list + * the given string + * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property + * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible); + +/** + * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value + * @fdt: pointer to the device tree blob + * @startoffset: only find nodes after this offset + * @compatible: 'compatible' string to match against + * + * fdt_node_offset_by_compatible() returns the offset of the first + * node after startoffset, which has a 'compatible' property which + * lists the given compatible string; or if startoffset is -1, the + * very first such node in the tree. + * + * To iterate through all nodes matching the criterion, the following + * idiom can be used: + * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); + * while (offset != -FDT_ERR_NOTFOUND) { + * // other code here + * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); + * } + * + * Note the -1 in the first call to the function, if 0 is used here + * instead, the function will never locate the root node, even if it + * matches the criterion. + * + * returns: + * structure block offset of the located node (>= 0, >startoffset), + * on success + * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the + * tree after startoffset + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible); From 9ed27a2aac6f7bbbb16d48854763a6d79f6a9857 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 7 Nov 2007 11:16:19 +1100 Subject: [PATCH 0148/1198] dtc: Simplify lexing/parsing of literals vs. node/property names The current scheme of having CELLDATA and MEMRESERVE states to recognize hex literals instead of node or property names is arse-backwards. The patch switches things around so that literals are lexed in normal states, and property/node names are only recognized in the special PROPNODENAME state, which is only entered after a { or a ;, and is left as soon as we scan a property/node name or a keyword. Signed-off-by: David Gibson Signed-off-by: Jon Loeliger --- dtc-lexer.l | 109 ++++++++++++-------------------------------- dtc-parser.y | 124 +++++++++++++++++++++++---------------------------- 2 files changed, 85 insertions(+), 148 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 278a96e..677abe4 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -21,9 +21,8 @@ %option noyywrap nounput yylineno %x INCLUDE -%x CELLDATA %x BYTESTRING -%x MEMRESERVE +%x PROPNODENAME PROPCHAR [a-zA-Z0-9,._+*#?-] UNITCHAR [0-9a-f,] @@ -51,7 +50,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) %% -"/include/" BEGIN(INCLUDE); +<*>"/include/" BEGIN(INCLUDE); \"[^"\n]*\" { yytext[strlen(yytext) - 1] = 0; @@ -63,13 +62,13 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) } -<> { +<*><> { if (!pop_input_file()) { yyterminate(); } } -\"([^\\"]|\\.)*\" { +<*>\"([^\\"]|\\.)*\" { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("String: %s\n", yytext); @@ -79,45 +78,24 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) return DT_STRING; } -"/memreserve/" { +<*>"/memreserve/" { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Keyword: /memreserve/\n"); - BEGIN(MEMRESERVE); - return DT_MEMRESERVE; - } - -[0-9a-fA-F]+ { - yylloc.filenum = srcpos_filenum; - yylloc.first_line = yylineno; - if (yyleng > 2*sizeof(yylval.addr)) { - fprintf(stderr, "Address value %s too large\n", - yytext); - } - yylval.addr = (u64) strtoull(yytext, NULL, 16); - DPRINT("Addr: %llx\n", - (unsigned long long)yylval.addr); - return DT_ADDR; - } - -";" { - yylloc.filenum = srcpos_filenum; - yylloc.first_line = yylineno; - DPRINT("/MEMRESERVE\n"); BEGIN(INITIAL); - return ';'; + return DT_MEMRESERVE; } <*>[a-zA-Z_][a-zA-Z0-9_]*: { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Label: %s\n", yytext); - yylval.str = strdup(yytext); - yylval.str[yyleng-1] = '\0'; + yylval.labelref = strdup(yytext); + yylval.labelref[yyleng-1] = '\0'; return DT_LABEL; } -[bodh]# { +[bodh]# { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; if (*yytext == 'b') @@ -132,27 +110,19 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) return DT_BASE; } -[0-9a-fA-F]+ { +[0-9a-fA-F]+ { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; - yylval.str = strdup(yytext); - DPRINT("Cell: '%s'\n", yylval.str); - return DT_CELL; + yylval.literal = strdup(yytext); + DPRINT("Literal: '%s'\n", yylval.literal); + return DT_LITERAL; } -">" { - yylloc.filenum = srcpos_filenum; - yylloc.first_line = yylineno; - DPRINT("/CELLDATA\n"); - BEGIN(INITIAL); - return '>'; - } - -\&{REFCHAR}* { +\&{REFCHAR}* { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Ref: %s\n", yytext+1); - yylval.str = strdup(yytext+1); + yylval.labelref = strdup(yytext+1); return DT_REF; } @@ -172,30 +142,13 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) return ']'; } -, { /* Technically this is a valid property name, - but we'd rather use it as punctuation, so detect it - here in preference */ +{PROPCHAR}+(@{UNITCHAR}+)? { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; - DPRINT("Char (propname like): %c (\\x%02x)\n", yytext[0], - (unsigned)yytext[0]); - return yytext[0]; - } - -{PROPCHAR}+ { - yylloc.filenum = srcpos_filenum; - yylloc.first_line = yylineno; - DPRINT("PropName: %s\n", yytext); - yylval.str = strdup(yytext); - return DT_PROPNAME; - } - -{PROPCHAR}+(@{UNITCHAR}+)? { - yylloc.filenum = srcpos_filenum; - yylloc.first_line = yylineno; - DPRINT("NodeName: %s\n", yytext); - yylval.str = strdup(yytext); - return DT_NODENAME; + DPRINT("PropNodeName: %s\n", yytext); + yylval.propnodename = strdup(yytext); + BEGIN(INITIAL); + return DT_PROPNODENAME; } @@ -213,21 +166,17 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) <*>. { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; - switch (yytext[0]) { - case '<': - DPRINT("CELLDATA\n"); - BEGIN(CELLDATA); - break; - case '[': - DPRINT("BYTESTRING\n"); - BEGIN(BYTESTRING); - break; - default: - + if (yytext[0] == '[') { + DPRINT("\n"); + BEGIN(BYTESTRING); + } + if ((yytext[0] == '{') + || (yytext[0] == ';')) { + DPRINT("\n"); + BEGIN(PROPNODENAME); + } DPRINT("Char: %c (\\x%02x)\n", yytext[0], (unsigned)yytext[0]); - break; - } return yytext[0]; } diff --git a/dtc-parser.y b/dtc-parser.y index 4853794..5ac3db7 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -25,45 +25,46 @@ #include "srcpos.h" int yylex(void); -cell_t cell_from_string(char *s, unsigned int base); +unsigned long long eval_literal(const char *s, int base, int bits); extern struct boot_info *the_boot_info; %} %union { - cell_t cval; + char *propnodename; + char *literal; + char *labelref; unsigned int cbase; u8 byte; - char *str; struct data data; + + u64 addr; + cell_t cell; struct property *prop; struct property *proplist; struct node *node; struct node *nodelist; - int datalen; - int hexlen; - u64 addr; struct reserve_info *re; } %token DT_MEMRESERVE -%token DT_ADDR -%token DT_PROPNAME -%token DT_NODENAME +%token DT_PROPNODENAME +%token DT_LITERAL %token DT_BASE -%token DT_CELL %token DT_BYTE %token DT_STRING -%token DT_LABEL -%token DT_REF +%token DT_LABEL +%token DT_REF %type propdata %type propdataprefix %type memreserve %type memreserves -%type opt_cell_base +%type addr %type celllist +%type cellbase +%type cellval %type bytestring %type propdef %type proplist @@ -72,8 +73,7 @@ extern struct boot_info *the_boot_info; %type nodedef %type subnode %type subnodes -%type label -%type nodename +%type label %% @@ -96,16 +96,23 @@ memreserves: ; memreserve: - label DT_MEMRESERVE DT_ADDR DT_ADDR ';' + label DT_MEMRESERVE addr addr ';' { $$ = build_reserve_entry($3, $4, $1); } - | label DT_MEMRESERVE DT_ADDR '-' DT_ADDR ';' + | label DT_MEMRESERVE addr '-' addr ';' { $$ = build_reserve_entry($3, $5 - $3 + 1, $1); } ; +addr: + DT_LITERAL + { + $$ = eval_literal($1, 16, 64); + } + ; + devicetree: '/' nodedef { @@ -132,11 +139,11 @@ proplist: ; propdef: - label DT_PROPNAME '=' propdata ';' + label DT_PROPNODENAME '=' propdata ';' { $$ = build_property($2, $4, $1); } - | label DT_PROPNAME ';' + | label DT_PROPNODENAME ';' { $$ = build_property($2, empty_data, $1); } @@ -176,23 +183,14 @@ propdataprefix: } ; -opt_cell_base: - /* empty */ - { - $$ = 16; - } - | DT_BASE - ; - celllist: /* empty */ { $$ = empty_data; } - | celllist opt_cell_base DT_CELL + | celllist cellval { - $$ = data_append_cell($1, - cell_from_string($3, $2)); + $$ = data_append_cell($1, $2); } | celllist DT_REF { @@ -204,6 +202,21 @@ celllist: } ; +cellbase: + /* empty */ + { + $$ = 16; + } + | DT_BASE + ; + +cellval: + cellbase DT_LITERAL + { + $$ = eval_literal($2, $1, 32); + } + ; + bytestring: /* empty */ { @@ -231,23 +244,12 @@ subnodes: ; subnode: - label nodename nodedef + label DT_PROPNODENAME nodedef { $$ = name_node($3, $2, $1); } ; -nodename: - DT_NODENAME - { - $$ = $1; - } - | DT_PROPNAME - { - $$ = $1; - } - ; - label: /* empty */ { @@ -272,33 +274,19 @@ void yyerror (char const *s) fname, yylloc.first_line, s); } - -/* - * Convert a string representation of a numeric cell - * in the given base into a cell. - * - * FIXME: should these specification errors be fatal instead? - */ - -cell_t cell_from_string(char *s, unsigned int base) +unsigned long long eval_literal(const char *s, int base, int bits) { - cell_t c; + unsigned long long val; char *e; - c = strtoul(s, &e, base); - if (*e) { - fprintf(stderr, - "Line %d: Invalid cell value '%s' : " - "%c is not a base %d digit; %d assumed\n", - yylloc.first_line, s, *e, base, c); - } - - if (errno == EINVAL || errno == ERANGE) { - fprintf(stderr, - "Line %d: Invalid cell value '%s'; %d assumed\n", - yylloc.first_line, s, c); - errno = 0; - } - - return c; + errno = 0; + val = strtoull(s, &e, base); + if (*e) + yyerror("bad characters in literal"); + else if ((errno == ERANGE) + || ((bits < 64) && (val >= (1ULL << bits)))) + yyerror("literal out of range"); + else if (errno != 0) + yyerror("bad literal"); + return val; } From 9138db565adeb2fbba3181fb589f1c9a3f818dde Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 7 Nov 2007 11:17:17 +1100 Subject: [PATCH 0149/1198] dtc: Switch dtc to C-style literals dtc: Switch dtc to C-style literals This patch introduces a new version of dts file, distinguished from older files by starting with the special token /dts-v1/. dts files in the new version take C-style literals instead of the old bare hex or OF-style base notation. In addition, the "range" for of memreserve entries (/memreserve/ f0000-fffff) is no longer recognized in the new format. Signed-off-by: David Gibson Signed-off-by: Jon Loeliger --- dtc-lexer.l | 40 +++++++++++++++++++++++++++++++-------- dtc-parser.y | 38 +++++++++++++++++++++++++++++++++++-- tests/run_tests.sh | 4 ++++ tests/test_tree1.dts | 14 ++++++++------ tests/test_tree1_dts0.dts | 27 ++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 16 deletions(-) create mode 100644 tests/test_tree1_dts0.dts diff --git a/dtc-lexer.l b/dtc-lexer.l index 677abe4..eec6527 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -23,6 +23,7 @@ %x INCLUDE %x BYTESTRING %x PROPNODENAME +%s V1 PROPCHAR [a-zA-Z0-9,._+*#?-] UNITCHAR [0-9a-f,] @@ -44,12 +45,18 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) #define DPRINT(fmt, ...) do { } while (0) #endif +static int dts_version; /* = 0 */ - +#define BEGIN_DEFAULT() if (dts_version == 0) { \ + DPRINT("\n"); \ + BEGIN(INITIAL); \ + } else { \ + DPRINT("\n"); \ + BEGIN(V1); \ + } %} %% - <*>"/include/" BEGIN(INCLUDE); \"[^"\n]*\" { @@ -58,7 +65,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) /* Some unrecoverable error.*/ exit(1); } - BEGIN(INITIAL); + BEGIN_DEFAULT(); } @@ -78,11 +85,20 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) return DT_STRING; } +<*>"/dts-v1/" { + yylloc.filenum = srcpos_filenum; + yylloc.first_line = yylineno; + DPRINT("Keyword: /dts-v1/\n"); + dts_version = 1; + BEGIN_DEFAULT(); + return DT_V1; + } + <*>"/memreserve/" { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Keyword: /memreserve/\n"); - BEGIN(INITIAL); + BEGIN_DEFAULT(); return DT_MEMRESERVE; } @@ -95,7 +111,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) return DT_LABEL; } -[bodh]# { +[bodh]# { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; if (*yytext == 'b') @@ -110,7 +126,15 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) return DT_BASE; } -[0-9a-fA-F]+ { +[0-9a-fA-F]+ { + yylloc.filenum = srcpos_filenum; + yylloc.first_line = yylineno; + yylval.literal = strdup(yytext); + DPRINT("Literal: '%s'\n", yylval.literal); + return DT_LEGACYLITERAL; + } + +[0-9]+|0[xX][0-9a-fA-F]+ { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; yylval.literal = strdup(yytext); @@ -138,7 +162,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("/BYTESTRING\n"); - BEGIN(INITIAL); + BEGIN_DEFAULT(); return ']'; } @@ -147,7 +171,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) yylloc.first_line = yylineno; DPRINT("PropNodeName: %s\n", yytext); yylval.propnodename = strdup(yytext); - BEGIN(INITIAL); + BEGIN_DEFAULT(); return DT_PROPNODENAME; } diff --git a/dtc-parser.y b/dtc-parser.y index 5ac3db7..d998bfe 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -48,9 +48,11 @@ extern struct boot_info *the_boot_info; struct reserve_info *re; } +%token DT_V1 %token DT_MEMRESERVE %token DT_PROPNODENAME %token DT_LITERAL +%token DT_LEGACYLITERAL %token DT_BASE %token DT_BYTE %token DT_STRING @@ -61,6 +63,8 @@ extern struct boot_info *the_boot_info; %type propdataprefix %type memreserve %type memreserves +%type v0_memreserve +%type v0_memreserves %type addr %type celllist %type cellbase @@ -78,7 +82,11 @@ extern struct boot_info *the_boot_info; %% sourcefile: - memreserves devicetree + DT_V1 ';' memreserves devicetree + { + the_boot_info = build_boot_info($3, $4); + } + | v0_memreserves devicetree { the_boot_info = build_boot_info($1, $2); } @@ -100,6 +108,24 @@ memreserve: { $$ = build_reserve_entry($3, $4, $1); } + ; + +v0_memreserves: + /* empty */ + { + $$ = NULL; + } + | v0_memreserve v0_memreserves + { + $$ = chain_reserve_entry($1, $2); + }; + ; + +v0_memreserve: + memreserve + { + $$ = $1; + } | label DT_MEMRESERVE addr '-' addr ';' { $$ = build_reserve_entry($3, $5 - $3 + 1, $1); @@ -108,6 +134,10 @@ memreserve: addr: DT_LITERAL + { + $$ = eval_literal($1, 0, 64); + } + | DT_LEGACYLITERAL { $$ = eval_literal($1, 16, 64); } @@ -211,7 +241,11 @@ cellbase: ; cellval: - cellbase DT_LITERAL + DT_LITERAL + { + $$ = eval_literal($1, 0, 32); + } + | cellbase DT_LEGACYLITERAL { $$ = eval_literal($2, $1, 32); } diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 5cf849b..713e296 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -123,6 +123,10 @@ dtc_tests () { tree1_tests_rw dtc_tree1.test.dtb run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb + run_test dtc.sh -I dts -O dtb -o dtc_tree1_dts0.test.dtb test_tree1_dts0.dts + tree1_tests dtc_tree1_dts0.test.dtb + tree1_tests_rw dtc_tree1_dts0.test.dtb + run_test dtc.sh -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts run_test string_escapes dtc_escapes.test.dtb diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts index ac920df..d5942fb 100644 --- a/tests/test_tree1.dts +++ b/tests/test_tree1.dts @@ -1,9 +1,11 @@ -/memreserve/ deadbeef00000000-deadbeef000fffff; -/memreserve/ 75bcd15 1000; +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; / { compatible = "test_tree1"; - prop-int = ; + prop-int = <0xdeadbeef>; prop-str = "hello world"; subnode@1 { @@ -12,16 +14,16 @@ subsubnode { compatible = "subsubnode1", "subsubnode"; - prop-int = ; + prop-int = <0xdeadbeef>; }; }; subnode@2 { - prop-int = ; + prop-int = <123456789>; subsubnode@0 { compatible = "subsubnode2", "subsubnode"; - prop-int = ; + prop-int = <0726746425>; }; }; }; diff --git a/tests/test_tree1_dts0.dts b/tests/test_tree1_dts0.dts new file mode 100644 index 0000000..ac920df --- /dev/null +++ b/tests/test_tree1_dts0.dts @@ -0,0 +1,27 @@ +/memreserve/ deadbeef00000000-deadbeef000fffff; +/memreserve/ 75bcd15 1000; + +/ { + compatible = "test_tree1"; + prop-int = ; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = ; + }; + }; + + subnode@2 { + prop-int = ; + + subsubnode@0 { + compatible = "subsubnode2", "subsubnode"; + prop-int = ; + }; + }; +}; From 91967acabdfbff8b44fd3a19f432bc6e690df8cc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 7 Nov 2007 11:17:37 +1100 Subject: [PATCH 0150/1198] dtc: -Odts produces v1 output This patch alters the -Odts mode output so that it uses dts-v1 format. This means that dtc -Idts -Odts used on a v0 dts file will convert that file to v1. Signed-off-by: David Gibson Signed-off-by: Jon Loeliger --- treesource.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/treesource.c b/treesource.c index 0752280..df3df7e 100644 --- a/treesource.c +++ b/treesource.c @@ -141,7 +141,7 @@ static void write_propval_cells(FILE *f, struct data val) l = l->next; } - fprintf(f, "%x", be32_to_cpu(*cp++)); + fprintf(f, "0x%x", be32_to_cpu(*cp++)); if ((void *)cp >= propend) break; fprintf(f, " "); @@ -258,12 +258,14 @@ void dt_to_source(FILE *f, struct boot_info *bi) { struct reserve_info *re; + fprintf(f, "/dts-v1/;\n\n"); + for (re = bi->reservelist; re; re = re->next) { if (re->label) fprintf(f, "%s: ", re->label); - fprintf(f, "/memreserve/\t%016llx-%016llx;\n", + fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", (unsigned long long)re->re.address, - (unsigned long long)(re->re.address + re->re.size - 1)); + (unsigned long long)re->re.size); } write_tree_source_node(f, bi->dt, 0); From f6588bc32fd46d63da6058f37ce799ab948c3513 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 13 Nov 2007 09:52:58 +1100 Subject: [PATCH 0151/1198] dtc: Add missing dependencies for tests At present, the Makefiles will not rebuild trees.o or the dtb files derived from it if testdata.h is updated. This is incorrect, and is because of missing dependency information. This patch fixes the problem by making sure that dependency information is generated from trees.S and dumptrees.c. Signed-off-by: David Gibson --- Makefile | 4 ++++ tests/Makefile.tests | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4d4b98e..9f9bee0 100644 --- a/Makefile +++ b/Makefile @@ -188,6 +188,10 @@ clean: libfdt_clean tests_clean @$(VECHO) DEP $< $(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@ +%.d: %.S + @$(VECHO) DEP $< + $(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@ + %.i: %.c @$(VECHO) CPP $@ $(CC) $(CPPFLAGS) -E $< > $@ diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 8ee0e5d..ec589aa 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -21,7 +21,8 @@ TESTS_TREES = $(TESTS_TREES_L:%=$(TESTS_PREFIX)%) TESTS_TARGETS = $(TESTS) $(TESTS_TREES) -TESTS_DEPFILES = $(TESTS:%=%.d) $(TESTS_PREFIX)testutils.d +TESTS_DEPFILES = $(TESTS:%=%.d) \ + $(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d) TESTS_CLEANFILES_L = *.output vgcore.* *.dtb *.test.dts TESTS_CLEANFILES = $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) From 7346858f8139cb143269bbc728b77072074ae997 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 13 Nov 2007 09:59:38 +1100 Subject: [PATCH 0152/1198] libfdt: Add phandle related functions This patch adds fdt_get_phandle() and fdt_node_offset_by_phandle() functions to libfdt. fdt_get_phandle() will retreive the phandle value of a given node, and fdt_node_offset_by_phandle() will locate a node given a phandle. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 21 +++++++++++ libfdt/libfdt.h | 54 +++++++++++++++++++++++----- tests/Makefile.tests | 5 +-- tests/get_phandle.c | 58 ++++++++++++++++++++++++++++++ tests/node_offset_by_phandle.c | 64 ++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 6 ++++ tests/rw_tree1.c | 4 +++ tests/sw_tree1.c | 2 ++ tests/test_tree1.dts | 2 ++ tests/test_tree1_dts0.dts | 2 ++ tests/testdata.h | 3 ++ tests/trees.S | 3 ++ 12 files changed, 214 insertions(+), 10 deletions(-) create mode 100644 tests/get_phandle.c create mode 100644 tests/node_offset_by_phandle.c diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index f6f0225..ef082be 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -293,6 +293,18 @@ const void *fdt_getprop(const void *fdt, int nodeoffset, return prop->data; } +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) +{ + const uint32_t *php; + int len; + + php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); + if (!php || (len != sizeof(*php))) + return 0; + + return fdt32_to_cpu(*php); +} + int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) { uint32_t tag; @@ -478,6 +490,15 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, return -FDT_ERR_NOTFOUND; } +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) +{ + if ((phandle == 0) || (phandle == -1)) + return -FDT_ERR_BADPHANDLE; + phandle = cpu_to_fdt32(phandle); + return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle", + &phandle, sizeof(phandle)); +} + int _stringlist_contains(const void *strlist, int listlen, const char *str) { int len = strlen(str); diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 220431a..d2f8320 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -78,29 +78,32 @@ /* FDT_ERR_BADPATH: Function was passed a badly formatted path * (e.g. missing a leading / for a function which requires an * absolute path) */ -#define FDT_ERR_BADSTATE 6 +#define FDT_ERR_BADPHANDLE 6 + /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle + * value. phandle values of 0 and -1 are not permitted. */ +#define FDT_ERR_BADSTATE 7 /* FDT_ERR_BADSTATE: Function was passed an incomplete device * tree created by the sequential-write functions, which is * not sufficiently complete for the requested operation. */ /* Error codes: codes for bad device tree blobs */ -#define FDT_ERR_TRUNCATED 7 +#define FDT_ERR_TRUNCATED 8 /* FDT_ERR_TRUNCATED: Structure block of the given device tree * ends without an FDT_END tag. */ -#define FDT_ERR_BADMAGIC 8 +#define FDT_ERR_BADMAGIC 9 /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a * device tree at all - it is missing the flattened device * tree magic number. */ -#define FDT_ERR_BADVERSION 9 +#define FDT_ERR_BADVERSION 10 /* FDT_ERR_BADVERSION: Given device tree has a version which * can't be handled by the requested operation. For * read-write functions, this may mean that fdt_open_into() is * required to convert the tree to the expected version. */ -#define FDT_ERR_BADSTRUCTURE 10 +#define FDT_ERR_BADSTRUCTURE 11 /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt * structure block or other serious error (e.g. misnested * nodes, or subnodes preceding properties). */ -#define FDT_ERR_BADLAYOUT 11 +#define FDT_ERR_BADLAYOUT 12 /* FDT_ERR_BADLAYOUT: For read-write functions, the given * device tree has it's sub-blocks in an order that the * function can't handle (memory reserve map, then structure, @@ -108,12 +111,12 @@ * into a form suitable for the read-write operations. */ /* "Can't happen" error indicating a bug in libfdt */ -#define FDT_ERR_INTERNAL 12 +#define FDT_ERR_INTERNAL 13 /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. * Should never be returned, if it is, it indicates a bug in * libfdt itself. */ -#define FDT_ERR_MAX 12 +#define FDT_ERR_MAX 13 /**********************************************************************/ /* Low-level functions (you probably don't need these) */ @@ -411,6 +414,20 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset, return (void *)fdt_getprop(fdt, nodeoffset, name, lenp); } +/** + * fdt_get_phandle - retreive the phandle of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of the node + * + * fdt_get_phandle() retrieves the phandle of the device tree node at + * structure block offset nodeoffset. + * + * returns: + * the phandle of the node at nodeoffset, on succes (!= 0, != -1) + * 0, if the node has no phandle, or another error occurs + */ +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); + /** * fdt_get_path - determine the full path of a node * @fdt: pointer to the device tree blob @@ -557,6 +574,27 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, const char *propname, const void *propval, int proplen); +/** + * fdt_node_offset_by_phandle - find the node with a given phandle + * @fdt: pointer to the device tree blob + * @phandle: phandle value + * + * fdt_node_offset_by_prop_value() returns the offset of the node + * which has the given phandle value. If there is more than one node + * in the tree with the given phandle (an invalid tree), results are + * undefined. + * + * returns: + * structure block offset of the located node (>= 0), on success + * -FDT_ERR_NOTFOUND, no node with that phandle exists + * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); + /** * fdt_node_check_compatible: check a node's compatible property * @fdt: pointer to the device tree blob diff --git a/tests/Makefile.tests b/tests/Makefile.tests index ec589aa..4e1b1e9 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -1,7 +1,8 @@ LIB_TESTS_L = get_mem_rsv \ root_node find_property subnode_offset path_offset \ - get_name getprop get_path supernode_atdepth_offset parent_offset \ - node_offset_by_prop_value \ + get_name getprop get_phandle \ + get_path supernode_atdepth_offset parent_offset \ + node_offset_by_prop_value node_offset_by_phandle \ node_check_compatible node_offset_by_compatible \ notfound \ setprop_inplace nop_property nop_node \ diff --git a/tests/get_phandle.c b/tests/get_phandle.c new file mode 100644 index 0000000..f7650b8 --- /dev/null +++ b/tests/get_phandle.c @@ -0,0 +1,58 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_get_phandle() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void check_phandle(void *fdt, const char *path, uint32_t checkhandle) +{ + int offset; + uint32_t phandle; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("Couldn't find %s", path); + + phandle = fdt_get_phandle(fdt, offset); + if (phandle != checkhandle) + FAIL("fdt_get_phandle(%s) returned 0x%x instead of 0x%x\n", + path, phandle, checkhandle); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_phandle(fdt, "/", 0); + check_phandle(fdt, "/subnode@2", PHANDLE_1); + check_phandle(fdt, "/subnode@2/subsubnode@0", PHANDLE_2); + + PASS(); +} diff --git a/tests/node_offset_by_phandle.c b/tests/node_offset_by_phandle.c new file mode 100644 index 0000000..e9fd939 --- /dev/null +++ b/tests/node_offset_by_phandle.c @@ -0,0 +1,64 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_node_offset_by_phandle() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void check_search(void *fdt, uint32_t phandle, int target) +{ + int offset; + + offset = fdt_node_offset_by_phandle(fdt, phandle); + + if (offset != target) + FAIL("fdt_node_offset_by_phandle(0x%x) returns %d " + "instead of %d", phandle, offset, target); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + int subnode2_offset, subsubnode2_offset; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + subnode2_offset = fdt_path_offset(fdt, "/subnode@2"); + subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode@0"); + + if ((subnode2_offset < 0) || (subsubnode2_offset < 0)) + FAIL("Can't find required nodes"); + + check_search(fdt, PHANDLE_1, subnode2_offset); + check_search(fdt, PHANDLE_2, subsubnode2_offset); + check_search(fdt, ~PHANDLE_1, -FDT_ERR_NOTFOUND); + check_search(fdt, 0, -FDT_ERR_BADPHANDLE); + check_search(fdt, -1, -FDT_ERR_BADPHANDLE); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 713e296..9ae2a12 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -38,10 +38,12 @@ tree1_tests () { run_test path_offset $TREE run_test get_name $TREE run_test getprop $TREE + run_test get_phandle $TREE run_test get_path $TREE run_test supernode_atdepth_offset $TREE run_test parent_offset $TREE run_test node_offset_by_prop_value $TREE + run_test node_offset_by_phandle $TREE run_test node_check_compatible $TREE run_test node_offset_by_compatible $TREE run_test notfound $TREE @@ -130,12 +132,16 @@ dtc_tests () { run_test dtc.sh -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts run_test string_escapes dtc_escapes.test.dtb + run_test dtc.sh -I dts -O dtb -o dtc_references.test.dtb references.dts + run_test references dtc_references.test.dtb + # Check -Odts mode preserve all dtb information for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb ; do run_test dtc.sh -I dtb -O dts -o odts_$tree.test.dts $tree run_test dtc.sh -I dts -O dtb -o odts_$tree.test.dtb odts_$tree.test.dts run_test dtbs_equal_ordered $tree odts_$tree.test.dtb done + } while getopts "vdt:" ARG ; do diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c index d063947..71f7b98 100644 --- a/tests/rw_tree1.c +++ b/tests/rw_tree1.c @@ -85,8 +85,12 @@ int main(int argc, char *argv[]) CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_1)); OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@2")); + CHECK(fdt_setprop_typed(fdt, offset, "linux,phandle", + cpu_to_fdt32(PHANDLE_1))); CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_2)); OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode@0")); + CHECK(fdt_setprop_typed(fdt, offset, "linux,phandle", + cpu_to_fdt32(PHANDLE_2))); CHECK(fdt_setprop(fdt, offset, "compatible", "subsubnode2\0subsubnode", 23)); CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_2)); diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 68551c3..215d515 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -69,8 +69,10 @@ int main(int argc, char *argv[]) CHECK(fdt_end_node(fdt)); CHECK(fdt_begin_node(fdt, "subnode@2")); + CHECK(fdt_property_typed(fdt, "linux,phandle", cpu_to_fdt32(PHANDLE_1))); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_2)); CHECK(fdt_begin_node(fdt, "subsubnode@0")); + CHECK(fdt_property_typed(fdt, "linux,phandle", cpu_to_fdt32(PHANDLE_2))); CHECK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode", 23)); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_2)); diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts index d5942fb..27602af 100644 --- a/tests/test_tree1.dts +++ b/tests/test_tree1.dts @@ -19,9 +19,11 @@ }; subnode@2 { + linux,phandle = <0x2000>; prop-int = <123456789>; subsubnode@0 { + linux,phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; }; diff --git a/tests/test_tree1_dts0.dts b/tests/test_tree1_dts0.dts index ac920df..bc65819 100644 --- a/tests/test_tree1_dts0.dts +++ b/tests/test_tree1_dts0.dts @@ -17,9 +17,11 @@ }; subnode@2 { + linux,phandle = <2000>; prop-int = ; subsubnode@0 { + linux,phandle = <2001>; compatible = "subsubnode2", "subsubnode"; prop-int = ; }; diff --git a/tests/testdata.h b/tests/testdata.h index 027d972..130026f 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -23,6 +23,9 @@ #define TEST_VALUE_1 cell_to_fdt(0xdeadbeef) #define TEST_VALUE_2 cell_to_fdt(123456789) +#define PHANDLE_1 0x2000 +#define PHANDLE_2 0x2001 + #define TEST_STRING_1 "hello world" #define TEST_STRING_2 "nastystring: \a\b\t\n\v\f\r\\\"" #define TEST_STRING_3 "\xde\xad\xbe\xef" diff --git a/tests/trees.S b/tests/trees.S index 42a9f7a..8ecae27 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -100,9 +100,11 @@ test_tree1_struct: END_NODE BEGIN_NODE("subnode@2") + PROP_INT(test_tree1, phandle, cell_to_fdt(PHANDLE_1)) PROP_INT(test_tree1, prop_int, TEST_VALUE_2) BEGIN_NODE("subsubnode@0") + PROP_INT(test_tree1, phandle, cell_to_fdt(PHANDLE_2)) PROP_STR(test_tree1, compatible, "subsubnode2\0subsubnode") PROP_INT(test_tree1, prop_int, TEST_VALUE_2) END_NODE @@ -116,6 +118,7 @@ test_tree1_strings: STRING(test_tree1, compatible, "compatible") STRING(test_tree1, prop_int, "prop-int") STRING(test_tree1, prop_str, "prop-str") + STRING(test_tree1, phandle, "linux,phandle") test_tree1_strings_end: test_tree1_end: From 682576d85bd159fc25ef99ab35a997fda172592e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 13 Nov 2007 10:02:29 +1100 Subject: [PATCH 0153/1198] dtc: Add testcase for dtc references This patch adds a testcase for dtc's reference-to-phandle functionality. Signed-off-by: David Gibson --- tests/Makefile.tests | 3 +- tests/references.c | 100 +++++++++++++++++++++++++++++++++++++++++++ tests/references.dts | 23 ++++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 tests/references.c create mode 100644 tests/references.dts diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 4e1b1e9..5f0e668 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -9,7 +9,8 @@ LIB_TESTS_L = get_mem_rsv \ sw_tree1 \ move_and_save mangle-layout \ open_pack rw_tree1 setprop del_property del_node \ - string_escapes dtbs_equal_ordered + string_escapes references \ + dtbs_equal_ordered LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property diff --git a/tests/references.c b/tests/references.c new file mode 100644 index 0000000..affc1d7 --- /dev/null +++ b/tests/references.c @@ -0,0 +1,100 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for phandle references in dtc + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void check_ref(const void *fdt, int node, uint32_t checkref) +{ + const uint32_t *p; + uint32_t ref; + int len; + + p = fdt_getprop(fdt, node, "ref", &len); + if (!p) + FAIL("fdt_getprop(%d, \"ref\"): %s", node, fdt_strerror(len)); + if (len != sizeof(*p)) + FAIL("'ref' in node at %d has wrong size (%d instead of %d)", + node, len, sizeof(*p)); + ref = fdt32_to_cpu(*p); + if (ref != checkref) + FAIL("'ref' in node at %d has value 0x%x instead of 0x%x", + node, ref, checkref); + + p = fdt_getprop(fdt, node, "lref", &len); + if (!p) + FAIL("fdt_getprop(%d, \"lref\"): %s", node, fdt_strerror(len)); + if (len != sizeof(*p)) + FAIL("'lref' in node at %d has wrong size (%d instead of %d)", + node, len, sizeof(*p)); + ref = fdt32_to_cpu(*p); + if (ref != checkref) + FAIL("'lref' in node at %d has value 0x%x instead of 0x%x", + node, ref, checkref); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + int n1, n2, n3, n4; + uint32_t h1, h2, h4; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + n1 = fdt_path_offset(fdt, "/node1"); + if (n1 < 0) + FAIL("fdt_path_offset(/node1): %s", fdt_strerror(n1)); + n2 = fdt_path_offset(fdt, "/node2"); + if (n2 < 0) + FAIL("fdt_path_offset(/node2): %s", fdt_strerror(n2)); + n3 = fdt_path_offset(fdt, "/node3"); + if (n3 < 0) + FAIL("fdt_path_offset(/node3): %s", fdt_strerror(n3)); + n4 = fdt_path_offset(fdt, "/node4"); + if (n4 < 0) + FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4)); + + h1 = fdt_get_phandle(fdt, n1); + h2 = fdt_get_phandle(fdt, n2); + h4 = fdt_get_phandle(fdt, n4); + + if (h1 != 0x2000) + FAIL("/node1 has wrong phandle, 0x%x instead of 0x%x", + h1, 0x2000); + if (h2 != 0x1) + FAIL("/node2 has wrong phandle, 0x%x instead of 0x%x", + h2, 0x1); + if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0)) + FAIL("/node4 has bad phandle, 0x%x", h4); + + check_ref(fdt, n1, h2); + check_ref(fdt, n2, h1); + check_ref(fdt, n3, h4); + + PASS(); +} diff --git a/tests/references.dts b/tests/references.dts new file mode 100644 index 0000000..fc032f8 --- /dev/null +++ b/tests/references.dts @@ -0,0 +1,23 @@ +/dts-v1/; + +/ { + /* Explicit phandles */ + n1: node1 { + linux,phandle = <0x2000>; + ref = <&/node2>; /* reference precedes target */ + lref = <&n2>; + }; + n2: node2 { + linux,phandle = <0x1>; + ref = <&/node1>; /* reference after target */ + lref = <&n1>; + }; + + /* Implicit phandles */ + n3: node3 { + ref = <&/node4>; + lref = <&n4>; + }; + n4: node4 { + }; +}; From 9521dc5ecc66c158cd6853cabba2c29f545780f6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 20 Nov 2007 13:35:46 +1100 Subject: [PATCH 0154/1198] libfdt: Abolish _typed() variants, add _cell() variants In a number of places through libfdt and its tests, we have *_typed() macro variants on functions which use gcc's typeof and statement expression extensions to allow passing literals where the underlying function takes a buffer and size. These seemed like a good idea at the time, but in fact they have some problems. They use typeof and statement expressions, extensions I'd prefer to avoid for portability. Plus, they have potential gotchas - although they'll deal with the size of the thing passed, they won't deal with other representation issues (like endianness) and results could be very strange if the type of the expression passed isn't what you think it is. In fact, the only users of these _typed() macros were when the value passed is a single cell (32-bit integer). Therefore, this patch removes all these _typed() macros and replaces them with explicit _cell() variants which handle a single 32-bit integer, and which also perform endian convesions as appropriate. With this in place, it now becomes easy to use standardized big-endian representation for integer valued properties in the testcases, regardless of the platform we're running on. We therefore do that, which has the additional advantage that all the example trees created during a test run are now byte-for-byte identical regardless of platform. Signed-off-by: David Gibson --- libfdt/libfdt.h | 33 ++++++++++++++++--------------- tests/del_node.c | 10 +++++----- tests/del_property.c | 2 +- tests/find_property.c | 2 +- tests/getprop.c | 2 +- tests/node_offset_by_prop_value.c | 14 ++++++------- tests/nop_node.c | 10 +++++----- tests/nop_property.c | 2 +- tests/rw_tree1.c | 16 +++++++-------- tests/setprop.c | 2 +- tests/setprop_inplace.c | 6 +++--- tests/subnode_offset.c | 10 +++++----- tests/sw_tree1.c | 14 ++++++------- tests/testdata.h | 4 ++-- tests/tests.h | 8 ++++---- tests/trees.S | 7 +++---- 16 files changed, 70 insertions(+), 72 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index d2f8320..a61e50d 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -663,12 +663,12 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len); - -#define fdt_setprop_inplace_typed(fdt, nodeoffset, name, val) \ - ({ \ - typeof(val) x = val; \ - fdt_setprop_inplace(fdt, nodeoffset, name, &x, sizeof(x)); \ - }) +static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + val = cpu_to_fdt32(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); +} int fdt_nop_property(void *fdt, int nodeoffset, const char *name); int fdt_nop_node(void *fdt, int nodeoffset); @@ -682,11 +682,11 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); int fdt_finish_reservemap(void *fdt); int fdt_begin_node(void *fdt, const char *name); int fdt_property(void *fdt, const char *name, const void *val, int len); -#define fdt_property_typed(fdt, name, val) \ - ({ \ - typeof(val) x = (val); \ - fdt_property((fdt), (name), &x, sizeof(x)); \ - }) +static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) +{ + val = cpu_to_fdt32(val); + return fdt_property(fdt, name, &val, sizeof(val)); +} #define fdt_property_string(fdt, name, str) \ fdt_property(fdt, name, str, strlen(str)+1) int fdt_end_node(void *fdt); @@ -704,11 +704,12 @@ int fdt_del_mem_rsv(void *fdt, int n); int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len); -#define fdt_setprop_typed(fdt, nodeoffset, name, val) \ - ({ \ - typeof(val) x = (val); \ - fdt_setprop((fdt), (nodeoffset), (name), &x, sizeof(x)); \ - }) +static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, + uint32_t val) +{ + val = cpu_to_fdt32(val); + return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); +} #define fdt_setprop_string(fdt, nodeoffset, name, str) \ fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) int fdt_delprop(void *fdt, int nodeoffset, const char *name); diff --git a/tests/del_node.c b/tests/del_node.c index fad777e..afad502 100644 --- a/tests/del_node.c +++ b/tests/del_node.c @@ -48,19 +48,19 @@ int main(int argc, char *argv[]) if (subnode1_offset < 0) FAIL("Couldn't find \"/subnode@1\": %s", fdt_strerror(subnode1_offset)); - check_getprop_typed(fdt, subnode1_offset, "prop-int", TEST_VALUE_1); + check_getprop_cell(fdt, subnode1_offset, "prop-int", TEST_VALUE_1); subnode2_offset = fdt_path_offset(fdt, "/subnode@2"); if (subnode2_offset < 0) FAIL("Couldn't find \"/subnode@2\": %s", fdt_strerror(subnode2_offset)); - check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); + check_getprop_cell(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode"); if (subsubnode2_offset < 0) FAIL("Couldn't find \"/subnode@2/subsubnode\": %s", fdt_strerror(subsubnode2_offset)); - check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); + check_getprop_cell(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); err = fdt_del_node(fdt, subnode1_offset); if (err) @@ -76,13 +76,13 @@ int main(int argc, char *argv[]) if (subnode2_offset < 0) FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(subnode2_offset)); - check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); + check_getprop_cell(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode"); if (subsubnode2_offset < 0) FAIL("Couldn't find \"/subnode@2/subsubnode\": %s", fdt_strerror(subsubnode2_offset)); - check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); + check_getprop_cell(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); err = fdt_del_node(fdt, subnode2_offset); if (err) diff --git a/tests/del_property.c b/tests/del_property.c index 2c412c3..449eca6 100644 --- a/tests/del_property.c +++ b/tests/del_property.c @@ -45,7 +45,7 @@ int main(int argc, char *argv[]) oldsize = fdt_totalsize(fdt); - intp = check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); + intp = check_getprop_cell(fdt, 0, "prop-int", TEST_VALUE_1); verbose_printf("int value was 0x%08x\n", *intp); err = fdt_delprop(fdt, 0, "prop-int"); diff --git a/tests/find_property.c b/tests/find_property.c index ced14ae..74a6965 100644 --- a/tests/find_property.c +++ b/tests/find_property.c @@ -35,7 +35,7 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); - check_property_typed(fdt, 0, "prop-int", TEST_VALUE_1); + check_property_cell(fdt, 0, "prop-int", TEST_VALUE_1); check_property(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1); PASS(); diff --git a/tests/getprop.c b/tests/getprop.c index f124951..239856e 100644 --- a/tests/getprop.c +++ b/tests/getprop.c @@ -36,7 +36,7 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); - check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); + check_getprop_cell(fdt, 0, "prop-int", TEST_VALUE_1); check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1); PASS(); diff --git a/tests/node_offset_by_prop_value.c b/tests/node_offset_by_prop_value.c index 651bc05..c55110a 100644 --- a/tests/node_offset_by_prop_value.c +++ b/tests/node_offset_by_prop_value.c @@ -67,9 +67,9 @@ void check_search_str(void *fdt, const char *propname, const char *propval, ...) va_end(ap); } -#define check_search_val(fdt, propname, propval, ...) \ +#define check_search_cell(fdt, propname, propval, ...) \ { \ - typeof(propval) val = (propval); \ + uint32_t val = cpu_to_fdt32(propval); \ check_search((fdt), (propname), &val, sizeof(val), \ ##__VA_ARGS__); \ } @@ -92,17 +92,17 @@ int main(int argc, char *argv[]) || (subsubnode1_offset < 0) || (subsubnode2_offset < 0)) FAIL("Can't find required nodes"); - check_search_val(fdt, "prop-int", TEST_VALUE_1, 0, subnode1_offset, - subsubnode1_offset, -FDT_ERR_NOTFOUND); + check_search_cell(fdt, "prop-int", TEST_VALUE_1, 0, subnode1_offset, + subsubnode1_offset, -FDT_ERR_NOTFOUND); - check_search_val(fdt, "prop-int", TEST_VALUE_2, subnode2_offset, - subsubnode2_offset, -FDT_ERR_NOTFOUND); + check_search_cell(fdt, "prop-int", TEST_VALUE_2, subnode2_offset, + subsubnode2_offset, -FDT_ERR_NOTFOUND); check_search_str(fdt, "prop-str", TEST_STRING_1, 0, -FDT_ERR_NOTFOUND); check_search_str(fdt, "prop-str", "no such string", -FDT_ERR_NOTFOUND); - check_search_val(fdt, "prop-int", TEST_VALUE_1+1, -FDT_ERR_NOTFOUND); + check_search_cell(fdt, "prop-int", TEST_VALUE_1+1, -FDT_ERR_NOTFOUND); check_search(fdt, "no-such-prop", NULL, 0, -FDT_ERR_NOTFOUND); diff --git a/tests/nop_node.c b/tests/nop_node.c index ab487a4..ea3a18f 100644 --- a/tests/nop_node.c +++ b/tests/nop_node.c @@ -43,19 +43,19 @@ int main(int argc, char *argv[]) if (subnode1_offset < 0) FAIL("Couldn't find \"/subnode1\": %s", fdt_strerror(subnode1_offset)); - check_getprop_typed(fdt, subnode1_offset, "prop-int", TEST_VALUE_1); + check_getprop_cell(fdt, subnode1_offset, "prop-int", TEST_VALUE_1); subnode2_offset = fdt_path_offset(fdt, "/subnode@2"); if (subnode2_offset < 0) FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(subnode2_offset)); - check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); + check_getprop_cell(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode"); if (subsubnode2_offset < 0) FAIL("Couldn't find \"/subnode@2/subsubnode\": %s", fdt_strerror(subsubnode2_offset)); - check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); + check_getprop_cell(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); err = fdt_nop_node(fdt, subnode1_offset); if (err) @@ -71,13 +71,13 @@ int main(int argc, char *argv[]) if (subnode2_offset < 0) FAIL("Couldn't find \"/subnode2\": %s", fdt_strerror(subnode2_offset)); - check_getprop_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); + check_getprop_cell(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode"); if (subsubnode2_offset < 0) FAIL("Couldn't find \"/subnode@2/subsubnode\": %s", fdt_strerror(subsubnode2_offset)); - check_getprop_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); + check_getprop_cell(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); err = fdt_nop_node(fdt, subnode2_offset); if (err) diff --git a/tests/nop_property.c b/tests/nop_property.c index 02371ac..e6ef4d9 100644 --- a/tests/nop_property.c +++ b/tests/nop_property.c @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); - intp = check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); + intp = check_getprop_cell(fdt, 0, "prop-int", TEST_VALUE_1); verbose_printf("int value was 0x%08x\n", *intp); err = fdt_nop_property(fdt, 0, "prop-int"); diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c index 71f7b98..8f335c9 100644 --- a/tests/rw_tree1.c +++ b/tests/rw_tree1.c @@ -73,27 +73,25 @@ int main(int argc, char *argv[]) CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2)); CHECK(fdt_setprop_string(fdt, 0, "compatible", "test_tree1")); - CHECK(fdt_setprop_typed(fdt, 0, "prop-int", TEST_VALUE_1)); + CHECK(fdt_setprop_cell(fdt, 0, "prop-int", TEST_VALUE_1)); CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1)); OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@1")); CHECK(fdt_setprop_string(fdt, offset, "compatible", "subnode1")); - CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_1)); + CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_1)); OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode")); CHECK(fdt_setprop(fdt, offset, "compatible", "subsubnode1\0subsubnode", 23)); - CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_1)); + CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_1)); OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@2")); - CHECK(fdt_setprop_typed(fdt, offset, "linux,phandle", - cpu_to_fdt32(PHANDLE_1))); - CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_2)); + CHECK(fdt_setprop_cell(fdt, offset, "linux,phandle", PHANDLE_1)); + CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_2)); OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode@0")); - CHECK(fdt_setprop_typed(fdt, offset, "linux,phandle", - cpu_to_fdt32(PHANDLE_2))); + CHECK(fdt_setprop_cell(fdt, offset, "linux,phandle", PHANDLE_2)); CHECK(fdt_setprop(fdt, offset, "compatible", "subsubnode2\0subsubnode", 23)); - CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_2)); + CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_2)); CHECK(fdt_pack(fdt)); diff --git a/tests/setprop.c b/tests/setprop.c index d771954..386b87b 100644 --- a/tests/setprop.c +++ b/tests/setprop.c @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) fdt = buf; - intp = check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); + intp = check_getprop_cell(fdt, 0, "prop-int", TEST_VALUE_1); verbose_printf("Old int value was 0x%08x\n", *intp); err = fdt_setprop_string(fdt, 0, "prop-int", NEW_STRING); diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c index 590dfeb..aa0cd96 100644 --- a/tests/setprop_inplace.c +++ b/tests/setprop_inplace.c @@ -42,14 +42,14 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob_arg(argc, argv); - intp = check_getprop_typed(fdt, 0, "prop-int", TEST_VALUE_1); + intp = check_getprop_cell(fdt, 0, "prop-int", TEST_VALUE_1); verbose_printf("Old int value was 0x%08x\n", *intp); - err = fdt_setprop_inplace_typed(fdt, 0, "prop-int", ~TEST_VALUE_1); + err = fdt_setprop_inplace_cell(fdt, 0, "prop-int", ~TEST_VALUE_1); if (err) FAIL("Failed to set \"prop-int\" to 0x08%x: %s", ~TEST_VALUE_1, fdt_strerror(err)); - intp = check_getprop_typed(fdt, 0, "prop-int", ~TEST_VALUE_1); + intp = check_getprop_cell(fdt, 0, "prop-int", ~TEST_VALUE_1); verbose_printf("New int value is 0x%08x\n", *intp); strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c index eafce2c..f5b88e1 100644 --- a/tests/subnode_offset.c +++ b/tests/subnode_offset.c @@ -70,16 +70,16 @@ int main(int argc, char *argv[]) if (subnode1_offset == subnode2_offset) FAIL("Different subnodes have same offset"); - check_property_typed(fdt, subnode1_offset, "prop-int", TEST_VALUE_1); - check_property_typed(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); + check_property_cell(fdt, subnode1_offset, "prop-int", TEST_VALUE_1); + check_property_cell(fdt, subnode2_offset, "prop-int", TEST_VALUE_2); subsubnode1_offset = check_subnode(fdt, subnode1_offset, "subsubnode"); subsubnode2_offset = check_subnode(fdt, subnode2_offset, "subsubnode@0"); subsubnode2_offset2 = check_subnode(fdt, subnode2_offset, "subsubnode"); - check_property_typed(fdt, subsubnode1_offset, "prop-int", TEST_VALUE_1); - check_property_typed(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); - check_property_typed(fdt, subsubnode2_offset2, "prop-int", TEST_VALUE_2); + check_property_cell(fdt, subsubnode1_offset, "prop-int", TEST_VALUE_1); + check_property_cell(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2); + check_property_cell(fdt, subsubnode2_offset2, "prop-int", TEST_VALUE_2); if (subsubnode2_offset != subsubnode2_offset2) FAIL("Different offsets with and without unit address"); diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 215d515..2a94b63 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -55,27 +55,27 @@ int main(int argc, char *argv[]) CHECK(fdt_begin_node(fdt, "")); CHECK(fdt_property_string(fdt, "compatible", "test_tree1")); - CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); + CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_property_string(fdt, "prop-str", TEST_STRING_1)); CHECK(fdt_begin_node(fdt, "subnode@1")); CHECK(fdt_property_string(fdt, "compatible", "subnode1")); - CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); + CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_begin_node(fdt, "subsubnode")); CHECK(fdt_property(fdt, "compatible", "subsubnode1\0subsubnode", 23)); - CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_1)); + CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_end_node(fdt)); CHECK(fdt_end_node(fdt)); CHECK(fdt_begin_node(fdt, "subnode@2")); - CHECK(fdt_property_typed(fdt, "linux,phandle", cpu_to_fdt32(PHANDLE_1))); - CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_2)); + CHECK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_1)); + CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2)); CHECK(fdt_begin_node(fdt, "subsubnode@0")); - CHECK(fdt_property_typed(fdt, "linux,phandle", cpu_to_fdt32(PHANDLE_2))); + CHECK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_2)); CHECK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode", 23)); - CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_2)); + CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2)); CHECK(fdt_end_node(fdt)); CHECK(fdt_end_node(fdt)); diff --git a/tests/testdata.h b/tests/testdata.h index 130026f..0f7f2fa 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -20,8 +20,8 @@ #define TEST_ADDR_2 ASM_CONST_LL(123456789) #define TEST_SIZE_2 ASM_CONST_LL(010000) -#define TEST_VALUE_1 cell_to_fdt(0xdeadbeef) -#define TEST_VALUE_2 cell_to_fdt(123456789) +#define TEST_VALUE_1 0xdeadbeef +#define TEST_VALUE_2 123456789 #define PHANDLE_1 0x2000 #define PHANDLE_2 0x2001 diff --git a/tests/tests.h b/tests/tests.h index f6dcd15..c273f3c 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -112,18 +112,18 @@ 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); -#define check_property_typed(fdt, nodeoffset, name, val) \ +#define check_property_cell(fdt, nodeoffset, name, val) \ ({ \ - typeof(val) x = val; \ + uint32_t x = cpu_to_fdt32(val); \ check_property(fdt, nodeoffset, name, sizeof(x), &x); \ }) const void *check_getprop(void *fdt, int nodeoffset, const char *name, int len, const void *val); -#define check_getprop_typed(fdt, nodeoffset, name, val) \ +#define check_getprop_cell(fdt, nodeoffset, name, val) \ ({ \ - typeof(val) x = val; \ + uint32_t x = cpu_to_fdt32(val); \ check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \ }) #define check_getprop_string(fdt, nodeoffset, name, s) \ diff --git a/tests/trees.S b/tests/trees.S index 8ecae27..e3c5d47 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -50,8 +50,7 @@ tree##_rsvmap_end: ; #define PROP_INT(tree, name, val) \ PROPHDR(tree, name, 4) \ - /* For ease of testing the property values go in native-endian */ \ - .long val ; + FDTLONG(val) ; #define PROP_STR(tree, name, str) \ PROPHDR(tree, name, 55f - 54f) \ @@ -100,11 +99,11 @@ test_tree1_struct: END_NODE BEGIN_NODE("subnode@2") - PROP_INT(test_tree1, phandle, cell_to_fdt(PHANDLE_1)) + PROP_INT(test_tree1, phandle, PHANDLE_1) PROP_INT(test_tree1, prop_int, TEST_VALUE_2) BEGIN_NODE("subsubnode@0") - PROP_INT(test_tree1, phandle, cell_to_fdt(PHANDLE_2)) + 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 From 2cf86939aff2692098396e7f25ce299e7195fa12 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 19 Nov 2007 17:26:22 +1100 Subject: [PATCH 0155/1198] libfdt: Abolish fdt_offset_ptr_typed() The fdt_offset_ptr_typed() macro seemed like a good idea at the time. However, it's not actually used all that often, it can silently throw away const qualifications and it uses a gcc extension (typeof) which I'd prefer to avoid for portability. Therefore, this patch gets rid of it (and the fdt_offset_ptr_typed_w() variant which was never used at all). It also makes a few variables const in testcases, which always should have been const, but weren't caught before because of the aforementioned silent discards. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 2 +- libfdt/libfdt.h | 6 ------ tests/dtbs_equal_ordered.c | 4 ++-- tests/path_offset.c | 4 ++-- tests/root_node.c | 4 ++-- tests/subnode_offset.c | 4 ++-- 6 files changed, 9 insertions(+), 15 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index ef082be..12a37d5 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -249,7 +249,7 @@ const struct fdt_property *fdt_get_property(const void *fdt, case FDT_PROP: err = -FDT_ERR_BADSTRUCTURE; - prop = fdt_offset_ptr_typed(fdt, offset, prop); + prop = fdt_offset_ptr(fdt, offset, sizeof(*prop)); if (! prop) goto fail; namestroff = fdt32_to_cpu(prop->nameoff); diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index a61e50d..6b2fb92 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -128,12 +128,6 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) return (void *)fdt_offset_ptr(fdt, offset, checklen); } - -#define fdt_offset_ptr_typed(fdt, offset, var) \ - ((typeof(var))(fdt_offset_ptr((fdt), (offset), sizeof(*(var))))) -#define fdt_offset_ptr_typed_w(fdt, offset, var) \ - ((typeof(var))(fdt_offset_ptr_w((fdt), (offset), sizeof(*(var))))) - uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); /**********************************************************************/ diff --git a/tests/dtbs_equal_ordered.c b/tests/dtbs_equal_ordered.c index d72124f..0c30ad3 100644 --- a/tests/dtbs_equal_ordered.c +++ b/tests/dtbs_equal_ordered.c @@ -93,10 +93,10 @@ void compare_structure(const void *fdt1, const void *fdt2) break; case FDT_PROP: - prop1 = fdt_offset_ptr_typed(fdt1, offset1, prop1); + prop1 = fdt_offset_ptr(fdt1, offset1, sizeof(*prop1)); if (!prop1) FAIL("Could get fdt1 property at %d", offset1); - prop2 = fdt_offset_ptr_typed(fdt2, offset2, prop2); + prop2 = fdt_offset_ptr(fdt2, offset2, sizeof(*prop2)); if (!prop2) FAIL("Could get fdt2 property at %d", offset2); diff --git a/tests/path_offset.c b/tests/path_offset.c index 834bc93..4b014ac 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -31,7 +31,7 @@ int check_subnode(void *fdt, int parent, const char *name) { int offset; - struct fdt_node_header *nh; + const struct fdt_node_header *nh; uint32_t tag; verbose_printf("Checking subnode \"%s\" of %d...", name, parent); @@ -39,7 +39,7 @@ int check_subnode(void *fdt, int parent, const char *name) verbose_printf("offset %d...", offset); if (offset < 0) FAIL("fdt_subnode_offset(\"%s\"): %s", name, fdt_strerror(offset)); - nh = fdt_offset_ptr_typed(fdt, offset, nh); + nh = fdt_offset_ptr(fdt, offset, sizeof(*nh)); verbose_printf("pointer %p\n", nh); if (! nh) FAIL("NULL retrieving subnode \"%s\"", name); diff --git a/tests/root_node.c b/tests/root_node.c index fa2dc90..3f47829 100644 --- a/tests/root_node.c +++ b/tests/root_node.c @@ -32,12 +32,12 @@ int main(int argc, char *argv[]) { void *fdt; - struct fdt_node_header *nh; + const struct fdt_node_header *nh; test_init(argc, argv); fdt = load_blob_arg(argc, argv); - nh = fdt_offset_ptr_typed(fdt, 0, nh); + nh = fdt_offset_ptr(fdt, 0, sizeof(*nh)); if (! nh) FAIL("NULL retrieving root node"); diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c index f5b88e1..ac2f32e 100644 --- a/tests/subnode_offset.c +++ b/tests/subnode_offset.c @@ -31,7 +31,7 @@ int check_subnode(struct fdt_header *fdt, int parent, const char *name) { int offset; - struct fdt_node_header *nh; + const struct fdt_node_header *nh; uint32_t tag; verbose_printf("Checking subnode \"%s\" of %d...", name, parent); @@ -39,7 +39,7 @@ int check_subnode(struct fdt_header *fdt, int parent, const char *name) verbose_printf("offset %d...", offset); if (offset < 0) FAIL("fdt_subnode_offset(\"%s\"): %s", name, fdt_strerror(offset)); - nh = fdt_offset_ptr_typed(fdt, offset, nh); + nh = fdt_offset_ptr(fdt, offset, sizeof(*nh)); verbose_printf("pointer %p\n", nh); if (! nh) FAIL("NULL retrieving subnode \"%s\"", name); From 0d6ade254773aa4798fed1b2f1639ea2b8bdeb89 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 20 Nov 2007 16:24:23 +1100 Subject: [PATCH 0156/1198] dtc: Add testcases for tree checks This patch adds a group of testcases to check that dtc correctly rejects trees with various structural errors. To make things easier to test, we change dtc so that failing checks (as opposed to other errors) result in exit code 2. This patch also fixes an embarrasing bug uncovered by these new tests: check_phandles() worked out if the tree's phandles were valid, then throws that information away and returns success always. Signed-off-by: David Gibson --- checks.c | 2 +- dtc.c | 2 +- tests/dtc-checkfails.sh | 22 ++++++++++++++++++++++ tests/dtc.sh | 20 +------------------- tests/dup-nodename.dts | 8 ++++++++ tests/dup-phandle.dts | 10 ++++++++++ tests/dup-propname.dts | 6 ++++++ tests/minusone-phandle.dts | 7 +++++++ tests/run_tests.sh | 6 ++++++ tests/tests.sh | 21 +++++++++++++++++++++ tests/zero-phandle.dts | 7 +++++++ 11 files changed, 90 insertions(+), 21 deletions(-) create mode 100755 tests/dtc-checkfails.sh create mode 100644 tests/dup-nodename.dts create mode 100644 tests/dup-phandle.dts create mode 100644 tests/dup-propname.dts create mode 100644 tests/minusone-phandle.dts create mode 100644 tests/tests.sh create mode 100644 tests/zero-phandle.dts diff --git a/checks.c b/checks.c index f0e7505..0a34109 100644 --- a/checks.c +++ b/checks.c @@ -101,7 +101,7 @@ static int check_phandles(struct node *root, struct node *node) for_each_child(node, child) ok = ok && check_phandles(root, child); - return 1; + return ok; } int check_structure(struct node *dt) diff --git a/dtc.c b/dtc.c index bbef829..602b296 100644 --- a/dtc.c +++ b/dtc.c @@ -197,7 +197,7 @@ int main(int argc, char *argv[]) if (!structure_ok) { if (!force) { fprintf(stderr, "ERROR: Input tree has structural errors, aborting (use -f to force output)\n"); - exit(1); + exit(2); } else if (quiet < 3) { fprintf(stderr, "Warning: Input tree has structural errors, output forced\n"); } diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh new file mode 100755 index 0000000..0a45a0b --- /dev/null +++ b/tests/dtc-checkfails.sh @@ -0,0 +1,22 @@ +#! /bin/sh + +. tests.sh + +TMPFILE="tmp.out.$$" + +rm -f $TMPFILE + +verbose_run "$DTC" -o $TMPFILE "$@" +ret="$?" + +if [ -f $TMPFILE ]; then + FAIL "output file was created despite bad input" +fi + +if [ "$ret" = "2" ]; then + PASS +else + FAIL "dtc returned error code $ret instead of 2 (check failed)" +fi + +rm -f $TMPFILE diff --git a/tests/dtc.sh b/tests/dtc.sh index f704f55..c5a7324 100755 --- a/tests/dtc.sh +++ b/tests/dtc.sh @@ -1,24 +1,6 @@ #! /bin/sh -PASS () { - echo "PASS" - exit 0 -} - -FAIL () { - echo "FAIL" "$@" - exit 2 -} - -DTC=../dtc - -verbose_run () { - if [ -z "$QUIET_TEST" ]; then - "$@" - else - "$@" > /dev/null 2> /dev/null - fi -} +. tests.sh if verbose_run "$DTC" "$@"; then PASS diff --git a/tests/dup-nodename.dts b/tests/dup-nodename.dts new file mode 100644 index 0000000..2a3aa75 --- /dev/null +++ b/tests/dup-nodename.dts @@ -0,0 +1,8 @@ +/dts-v1/; + +/ { + node { + }; + node { + }; +}; diff --git a/tests/dup-phandle.dts b/tests/dup-phandle.dts new file mode 100644 index 0000000..c266c61 --- /dev/null +++ b/tests/dup-phandle.dts @@ -0,0 +1,10 @@ +/dts-v1/; + +/ { + node1 { + linux,phandle = <1>; + }; + node2 { + linux,phandle = <1>; + }; +}; diff --git a/tests/dup-propname.dts b/tests/dup-propname.dts new file mode 100644 index 0000000..8145f6e --- /dev/null +++ b/tests/dup-propname.dts @@ -0,0 +1,6 @@ +/dts-v1/; + +/ { + prop; + prop; +}; diff --git a/tests/minusone-phandle.dts b/tests/minusone-phandle.dts new file mode 100644 index 0000000..21d9986 --- /dev/null +++ b/tests/minusone-phandle.dts @@ -0,0 +1,7 @@ +/dts-v1/; + +/ { + node { + linux,phandle = <0xffffffff>; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 9ae2a12..2a41d43 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -142,6 +142,12 @@ dtc_tests () { run_test dtbs_equal_ordered $tree odts_$tree.test.dtb done + # Check some checks + run_test dtc-checkfails.sh -I dts -O dtb dup-nodename.dts + run_test dtc-checkfails.sh -I dts -O dtb dup-propname.dts + run_test dtc-checkfails.sh -I dts -O dtb dup-phandle.dts + run_test dtc-checkfails.sh -I dts -O dtb zero-phandle.dts + run_test dtc-checkfails.sh -I dts -O dtb minusone-phandle.dts } while getopts "vdt:" ARG ; do diff --git a/tests/tests.sh b/tests/tests.sh new file mode 100644 index 0000000..396b4cf --- /dev/null +++ b/tests/tests.sh @@ -0,0 +1,21 @@ +# Common functions for shell testcases + +PASS () { + echo "PASS" + exit 0 +} + +FAIL () { + echo "FAIL" "$@" + exit 2 +} + +DTC=../dtc + +verbose_run () { + if [ -z "$QUIET_TEST" ]; then + "$@" + else + "$@" > /dev/null 2> /dev/null + fi +} diff --git a/tests/zero-phandle.dts b/tests/zero-phandle.dts new file mode 100644 index 0000000..7997d98 --- /dev/null +++ b/tests/zero-phandle.dts @@ -0,0 +1,7 @@ +/dts-v1/; + +/ { + node { + linux,phandle = <0>; + }; +}; From b2e61bde9fa50428380f7d9e170781499fe462f1 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 20 Nov 2007 22:14:12 +1100 Subject: [PATCH 0157/1198] dtc: Don't use env(1) in testsuite The run_tests.sh script currently invokes the testcase binaries via env(1). This behaviour is inherited from the libhugetlbfs testsuite which uses this approach to easily set various configuration environment variables in testcases. We don't use that for dtc, and are unlikely to ever want to. Therefore this patch removes that technique, which substantially speeds up the testsuite. Signed-off-by: David Gibson --- tests/run_tests.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 2a41d43..1a3bcbf 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -2,8 +2,6 @@ export QUIET_TEST=1 -ENV=/usr/bin/env - tot_tests=0 tot_pass=0 tot_fail=0 @@ -13,7 +11,7 @@ tot_strange=0 run_test () { tot_tests=$[tot_tests + 1] echo -n "$@: " - if PATH=".:$PATH" $ENV "$@"; then + if "./$@"; then tot_pass=$[tot_pass + 1] else ret="$?" From 8eaf5e358366017aa2e846c5038d1aa19958314e Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Tue, 20 Nov 2007 09:14:03 -0600 Subject: [PATCH 0158/1198] Add a script that compares an "old" and "new" dtc results. Lots of room for improvement here. Command line options, etc. The script iterates over a hard-coded list of kernel DTS files. Signed-off-by: Jon Loeliger --- tests/test_kernel_dts | 86 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100755 tests/test_kernel_dts diff --git a/tests/test_kernel_dts b/tests/test_kernel_dts new file mode 100755 index 0000000..238f3f7 --- /dev/null +++ b/tests/test_kernel_dts @@ -0,0 +1,86 @@ +#!/usr/bin/perl + +my $dtc_old = "/home/jdl/FSL/dtc/dtc-old"; +my $dtc_new = "/home/jdl/FSL/dtc/dtc-new"; + +my $basic_options = "-b 0 -f -I dts -O dtb"; + +my $linux_dts_dir = "/usr/src/linux-2.6/arch/powerpc/boot/dts"; + +# Yeah, sure, we could, like, readdir() this instead... +my @boards = ( + "bamboo", + "ebony", + "ep88xc", + "holly", + "kilauea", + "kuroboxHD", + "kuroboxHG", + "lite5200", + "lite5200b", + "mpc7448hpc2", + "mpc8272ads", + "mpc8313erdb", + "mpc832x_mds", + "mpc832x_rdb", + "mpc8349emitx", + "mpc8349emitxgp", + "mpc834x_mds", + "mpc836x_mds", + "mpc8540ads", + "mpc8541cds", + "mpc8544ds", + "mpc8548cds", + "mpc8555cds", + "mpc8560ads", + "mpc8568mds", + "mpc8572ds", + "mpc8610_hpcd", + "mpc8641_hpcn", + "mpc866ads", # Feh. Bad node references... + "mpc885ads", + "pq2fads", + "prpmc2800", + "ps3", + "sequoia", + "walnut", +); + +foreach my $board (@boards) { + my $dts_file = "$linux_dts_dir/$board.dts"; + + my $old_dtb_file = "/tmp/$board.dtb.old"; + my $new_dtb_file = "/tmp/$board.dtb.new"; + + my $cmd_old = "$dtc_old $basic_options -o $old_dtb_file $dts_file"; + my $cmd_new = "$dtc_new $basic_options -o $new_dtb_file $dts_file"; + my $cmd_cmp = "cmp $old_dtb_file $new_dtb_file"; + + print "------------------------------------------------\n"; + print "OLD: $cmd_old\n"; + unlink($old_dtb_file) if (-f $old_dtb_file); + system("$cmd_old >& /dev/null"); + my $status = $?; + if ($status) { + print " FAILED to run old DTC on $board\n"; + } + + print "NEW: $cmd_new\n"; + unlink($new_dtb_file) if (-f $new_dtb_file); + system("$cmd_new >& /dev/null"); + $status = $?; + if ($status) { + print " FAILED to run new DTC on $board\n"; + } + + if (-f $old_dtb_file && -f $new_dtb_file) { + print "CMP: $cmd_cmp\n"; + system($cmd_cmp); + $status = $?; + if ($status) { + print " FAILED $board\n"; + } + } else { + printf " FAILED: Missing dtb file\n"; + } +} From 3ce53633871584ad93528fdf5cdcb939bb24ffc3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 21 Nov 2007 11:29:18 +1100 Subject: [PATCH 0159/1198] dtc: Remove some redundant testcases This patch removes a number of testcases from the testsuite that are extremely unlikely to find any bugs that won't be found by the other tests. This speeds up the testsuite. - Both loops across the various tree block layouts run the tree1_tests on the basic mangled tree. This is completely redundant, so remove the second copy. This removes 456 testcases. - We currently run tree1_tests on various trees manipulated by move_and_save. We replace those with just a dtbs_equal_ordered test to check that the manipulated tree is equal to the original. What we're testing here is that fdt_move() operates correctly - it's very unlikely it would succeed well enough for the ordered_equal test to succeed, but the tree1_tests would fail on the result. This removes 162 testcases. - Currently we re-ordered with mangle-layout both the basic test_tree1.dtb and sw_tree1.test.dtb. Since we've already checked that these dtbs are equivalent with dtbs_ordered_equal, it's very unlikely that the tests would fail on one but not the other. Therefore reduce this to only using test_tree1.dtb. This removes 828 testcases. Signed-off-by: David Gibson --- tests/run_tests.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 1a3bcbf..54d4504 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -76,13 +76,13 @@ libfdt_tests () { for tree in test_tree1.dtb sw_tree1.test.dtb unfinished_tree1.test.dtb; do rm -f moved.$tree shunted.$tree deshunted.$tree run_test move_and_save $tree - tree1_tests moved.$tree - tree1_tests shunted.$tree - tree1_tests deshunted.$tree + run_test dtbs_equal_ordered $tree moved.$tree + run_test dtbs_equal_ordered $tree shunted.$tree + run_test dtbs_equal_ordered $tree deshunted.$tree done # v16 and alternate layout tests - for tree in test_tree1.dtb sw_tree1.test.dtb; do + for tree in test_tree1.dtb; do for version in 17 16; do for layout in $ALL_LAYOUTS; do run_test mangle-layout $tree $version $layout @@ -93,13 +93,12 @@ libfdt_tests () { done # Read-write tests - for basetree in test_tree1.dtb sw_tree1.test.dtb; do + for basetree in test_tree1.dtb; do for version in 17 16; do for layout in $ALL_LAYOUTS; do tree=v$version.$layout.$basetree rm -f opened.$tree repacked.$tree run_test open_pack $tree - tree1_tests $tree tree1_tests opened.$tree tree1_tests repacked.$tree From 67b6b33b9b413a450a72135b5dc59c0a1e33e647 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 21 Nov 2007 11:56:14 +1100 Subject: [PATCH 0160/1198] dtc: Add valgrind support to testsuite This patch adds some options to the run_tests.sh script allowing it to run all the testcases under valgrind to check for pointer corruption bugs and memory leaks. Invoking "make checkm" will run the testsuite with valgrind. It include a mechanism for specifying valgrind errors to be suppressed on a per-testcase basis, and adds a couple of such suppression files for the mangle-layout and open_pack testcases which dump for use by other testcases a buffer which may contain uninitialized sections. We use suppressions rather than initializing the buffer so that valgrind will catch any internal access s to the uninitialized data, which would be a bug. The patch also fixes one genuine bug caught by valgrind - _packblocks() in fdt_rw.c was using memcpy() where it should have been using memmove(). At present the valgrinding won't do anything useful for testcases invoked via a shell script - which includes all the dtc testcases. I plan to fix that later. Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 6 +++--- tests/Makefile.tests | 5 ++++- tests/mangle-layout.supp | 7 +++++++ tests/open_pack.supp | 7 +++++++ tests/run_tests.sh | 22 ++++++++++++++++++++-- 5 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 tests/mangle-layout.supp create mode 100644 tests/open_pack.supp diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index dfe5628..6673f8e 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -358,12 +358,12 @@ static void _packblocks(const void *fdt, void *buf, memmove(buf + mem_rsv_off, fdt + fdt_off_mem_rsvmap(fdt), mem_rsv_size); fdt_set_off_mem_rsvmap(buf, mem_rsv_off); - memcpy(buf + struct_off, fdt + fdt_off_dt_struct(fdt), struct_size); + memmove(buf + struct_off, fdt + fdt_off_dt_struct(fdt), struct_size); fdt_set_off_dt_struct(buf, struct_off); fdt_set_size_dt_struct(buf, struct_size); - memcpy(buf + strings_off, fdt + fdt_off_dt_strings(fdt), - fdt_size_dt_strings(fdt)); + memmove(buf + strings_off, fdt + fdt_off_dt_strings(fdt), + fdt_size_dt_strings(fdt)); fdt_set_off_dt_strings(buf, strings_off); fdt_set_size_dt_strings(buf, fdt_size_dt_strings(fdt)); } diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 5f0e668..569bd9e 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -26,7 +26,7 @@ TESTS_TARGETS = $(TESTS) $(TESTS_TREES) TESTS_DEPFILES = $(TESTS:%=%.d) \ $(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d) -TESTS_CLEANFILES_L = *.output vgcore.* *.dtb *.test.dts +TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts TESTS_CLEANFILES = $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) BIN += $(TESTS) $(TESTS_PREFIX)dumptrees @@ -52,6 +52,9 @@ tests_clean: check: tests dtc cd $(TESTS_PREFIX); ./run_tests.sh +checkm: tests dtc + cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$ + checkv: tests dtc cd $(TESTS_PREFIX); ./run_tests.sh -v diff --git a/tests/mangle-layout.supp b/tests/mangle-layout.supp new file mode 100644 index 0000000..2cc8449 --- /dev/null +++ b/tests/mangle-layout.supp @@ -0,0 +1,7 @@ +{ + uninitialized alignment gaps can be dumped to output + Memcheck:Param + write(buf) + obj:/lib/ld-2.6.1.so + fun:main +} diff --git a/tests/open_pack.supp b/tests/open_pack.supp new file mode 100644 index 0000000..a38abc5 --- /dev/null +++ b/tests/open_pack.supp @@ -0,0 +1,7 @@ +{ + opened blob dumps uninitialized data + Memcheck:Param + write(buf) + obj:/lib/ld-2.6.1.so + fun:main +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 54d4504..6875c42 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -2,16 +2,26 @@ export QUIET_TEST=1 +export VALGRIND= +VGCODE=126 + tot_tests=0 tot_pass=0 tot_fail=0 tot_config=0 +tot_vg=0 tot_strange=0 run_test () { tot_tests=$[tot_tests + 1] echo -n "$@: " - if "./$@"; then + VGLOCAL="$VALGRIND" + if [ -n "$VALGRIND" ]; then + if [ -f $1.supp ]; then + VGLOCAL="$VGLOCAL --suppressions=$1.supp" + fi + fi + if $VGLOCAL "./$@"; then tot_pass=$[tot_pass + 1] else ret="$?" @@ -19,6 +29,8 @@ run_test () { tot_config=$[tot_config + 1] elif [ "$ret" == "2" ]; then tot_fail=$[tot_fail + 1] + elif [ "$ret" == "$VGCODE" ]; then + tot_vg=$[tot_vg + 1] else tot_strange=$[tot_strange + 1] fi @@ -147,7 +159,7 @@ dtc_tests () { run_test dtc-checkfails.sh -I dts -O dtb minusone-phandle.dts } -while getopts "vdt:" ARG ; do +while getopts "vt:m" ARG ; do case $ARG in "v") unset QUIET_TEST @@ -155,6 +167,9 @@ while getopts "vdt:" ARG ; do "t") TESTSETS=$OPTARG ;; + "m") + VALGRIND="valgrind --tool=memcheck -q --error-exitcode=$VGCODE" + ;; esac done @@ -181,6 +196,9 @@ echo -e "* Total testcases: $tot_tests" echo -e "* PASS: $tot_pass" echo -e "* FAIL: $tot_fail" echo -e "* Bad configuration: $tot_config" +if [ -n "$VALGRIND" ]; then + echo -e "* valgrind errors: $tot_vg" +fi echo -e "* Strange test result: $tot_strange" echo -e "**********" From b16a2bd89dbf109b9c8d1c9e047b9afa72af6d2f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 22 Nov 2007 14:38:07 +1100 Subject: [PATCH 0161/1198] dtc: Flexible tree checking infrastructure (v2) dtc: Flexible tree checking infrastructure Here, at last, is a substantial start on revising dtc's infrastructure for checking the tree; this is the rework I've been saying was necessary practically since dtc was first release. In the new model, we have a table of "check" structures, each with a name, references to checking functions, and status variables. Each check can (in principle) be individually switched off or on (as either a warning or error). Checks have a list of prerequisites, so if checks need to rely on results from earlier checks to make sense (or even to avoid crashing) they just need to list the relevant other checks there. For now, only the "structural" checks and the fixups for phandle references are converted to the new mechanism. The rather more involved semantic checks (which is where this new mechanism will really be useful) will have to be converted in future patches. At present, there's no user interface for turning on/off the checks - the -f option now forces output even if "error" level checks fail. Again, future patches will be needed to add the fine-grained control, but that should be quite straightforward with the infrastructure implemented here. Also adds a testcase for the handling of bad references, which catches a bug encountered while developing this patch. Signed-off-by: David Gibson --- checks.c | 367 ++++++++++++++++++++++++++--------- dtc.c | 12 +- dtc.h | 8 +- livetree.c | 67 ++----- tests/nonexist-label-ref.dts | 8 + tests/nonexist-node-ref.dts | 8 + tests/run_tests.sh | 2 + 7 files changed, 313 insertions(+), 159 deletions(-) create mode 100644 tests/nonexist-label-ref.dts create mode 100644 tests/nonexist-node-ref.dts diff --git a/checks.c b/checks.c index 0a34109..c8a099e 100644 --- a/checks.c +++ b/checks.c @@ -20,104 +20,293 @@ #include "dtc.h" +#ifdef TRACE_CHECKS +#define TRACE(c, ...) \ + do { \ + fprintf(stderr, "=== %s: ", (c)->name); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } while (0) +#else +#define TRACE(c, fmt, ...) do { } while (0) +#endif + +enum checklevel { + IGNORE = 0, + WARN = 1, + ERROR = 2, +}; + +enum checkstatus { + UNCHECKED = 0, + PREREQ, + PASSED, + FAILED, +}; + +struct check; + +typedef void (*tree_check_fn)(struct check *c, struct node *dt); +typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node); +typedef void (*prop_check_fn)(struct check *c, struct node *dt, + struct node *node, struct property *prop); + +struct check { + const char *name; + tree_check_fn tree_fn; + node_check_fn node_fn; + prop_check_fn prop_fn; + void *data; + enum checklevel level; + enum checkstatus status; + int inprogress; + int num_prereqs; + struct check **prereq; +}; + +#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \ + static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \ + static struct check nm = { \ + .name = #nm, \ + .tree_fn = (tfn), \ + .node_fn = (nfn), \ + .prop_fn = (pfn), \ + .data = (d), \ + .level = (lvl), \ + .status = UNCHECKED, \ + .num_prereqs = ARRAY_SIZE(nm##_prereqs), \ + .prereq = nm##_prereqs, \ + }; + +#define TREE_CHECK(nm, d, lvl, ...) \ + CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__) +#define NODE_CHECK(nm, d, lvl, ...) \ + CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__) +#define PROP_CHECK(nm, d, lvl, ...) \ + CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__) +#define BATCH_CHECK(nm, lvl, ...) \ + CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__) + +static inline void check_msg(struct check *c, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + if ((c->level < WARN) || (c->level <= quiet)) + return; /* Suppress message */ + + fprintf(stderr, "%s (%s): ", + (c->level == ERROR) ? "ERROR" : "Warning", c->name); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); +} + +#define FAIL(c, fmt, ...) \ + do { \ + TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \ + (c)->status = FAILED; \ + check_msg((c), fmt, __VA_ARGS__); \ + } while (0) + +static void check_nodes_props(struct check *c, struct node *dt, struct node *node) +{ + struct node *child; + struct property *prop; + + TRACE(c, "%s", node->fullpath); + if (c->node_fn) + c->node_fn(c, dt, node); + + if (c->prop_fn) + for_each_property(node, prop) { + TRACE(c, "%s\t'%s'", node->fullpath, prop->name); + c->prop_fn(c, dt, node, prop); + } + + for_each_child(node, child) + check_nodes_props(c, dt, child); +} + +static int run_check(struct check *c, struct node *dt) +{ + int error = 0; + int i; + + assert(!c->inprogress); + + if (c->status != UNCHECKED) + goto out; + + c->inprogress = 1; + + for (i = 0; i < c->num_prereqs; i++) { + struct check *prq = c->prereq[i]; + error |= run_check(prq, dt); + if (prq->status != PASSED) { + c->status = PREREQ; + check_msg(c, "Failed prerequisite '%s'", + c->prereq[i]->name); + } + } + + if (c->status != UNCHECKED) + goto out; + + if (c->node_fn || c->prop_fn) + check_nodes_props(c, dt, dt); + + if (c->tree_fn) + c->tree_fn(c, dt); + if (c->status == UNCHECKED) + c->status = PASSED; + + TRACE(c, "\tCompleted, status %d", c->status); + +out: + c->inprogress = 0; + if ((c->status != PASSED) && (c->level == ERROR)) + error = 1; + return error; +} + /* * Structural check functions */ +static void check_duplicate_node_names(struct check *c, struct node *dt, + struct node *node) +{ + struct node *child, *child2; + + for_each_child(node, child) + for (child2 = child->next_sibling; + child2; + child2 = child2->next_sibling) + if (streq(child->name, child2->name)) + FAIL(c, "Duplicate node name %s", + child->fullpath); +} +NODE_CHECK(duplicate_node_names, NULL, ERROR); + +static void check_duplicate_property_names(struct check *c, struct node *dt, + struct node *node) +{ + struct property *prop, *prop2; + + for_each_property(node, prop) + for (prop2 = prop->next; prop2; prop2 = prop2->next) + if (streq(prop->name, prop2->name)) + FAIL(c, "Duplicate property name %s in %s", + prop->name, node->fullpath); +} +NODE_CHECK(duplicate_property_names, NULL, ERROR); + +static void check_explicit_phandles(struct check *c, struct node *root, + struct node *node) +{ + struct property *prop; + struct node *other; + cell_t phandle; + + prop = get_property(node, "linux,phandle"); + if (! prop) + return; /* No phandle, that's fine */ + + if (prop->val.len != sizeof(cell_t)) { + FAIL(c, "%s has bad length (%d) linux,phandle property", + node->fullpath, prop->val.len); + return; + } + + phandle = propval_cell(prop); + if ((phandle == 0) || (phandle == -1)) { + FAIL(c, "%s has invalid linux,phandle value 0x%x", + node->fullpath, phandle); + return; + } + + other = get_node_by_phandle(root, phandle); + if (other) { + FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)", + node->fullpath, phandle, other->fullpath); + return; + } + + node->phandle = phandle; +} +NODE_CHECK(explicit_phandles, NULL, ERROR); + +/* + * Reference fixup functions + */ + +static void fixup_phandle_references(struct check *c, struct node *dt, + struct node *node, struct property *prop) +{ + struct fixup *f = prop->val.refs; + struct node *refnode; + cell_t phandle; + + while (f) { + assert(f->offset + sizeof(cell_t) <= prop->val.len); + + refnode = get_node_by_ref(dt, f->ref); + if (! refnode) { + FAIL(c, "Reference to non-existent node or label \"%s\"\n", + f->ref); + } else { + phandle = get_node_phandle(dt, refnode); + + *((cell_t *)(prop->val.val + f->offset)) = cpu_to_be32(phandle); + } + + prop->val.refs = f->next; + fixup_free(f); + f = prop->val.refs; + } +} +CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR, + &duplicate_node_names, &explicit_phandles); + +static struct check *check_table[] = { + &duplicate_node_names, &duplicate_property_names, + &explicit_phandles, + &phandle_references, +}; + +void process_checks(int force, struct node *dt) +{ + int i; + int error = 0; + + for (i = 0; i < ARRAY_SIZE(check_table); i++) { + struct check *c = check_table[i]; + + if (c->level != IGNORE) + error = error || run_check(c, dt); + } + + if (error) { + if (!force) { + fprintf(stderr, "ERROR: Input tree has errors, aborting " + "(use -f to force output)\n"); + exit(2); + } else if (quiet < 3) { + fprintf(stderr, "Warning: Input tree has errors, " + "output forced\n"); + } + } +} + +/* + * Semantic check functions + */ + #define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__) #define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__) #define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0) -static int check_names(struct node *tree) -{ - struct node *child, *child2; - struct property *prop, *prop2; - int len = strlen(tree->name); - int ok = 1; - - if (len == 0 && tree->parent) - DO_ERR("Empty, non-root nodename at %s\n", tree->fullpath); - - if (len > MAX_NODENAME_LEN) - WARNMSG("Overlength nodename at %s\n", tree->fullpath); - - for_each_property(tree, prop) { - /* check for duplicates */ - /* FIXME: do this more efficiently */ - for (prop2 = prop->next; prop2; prop2 = prop2->next) { - if (streq(prop->name, prop2->name)) { - DO_ERR("Duplicate propertyname %s in node %s\n", - prop->name, tree->fullpath); - } - } - - /* check name length */ - if (strlen(prop->name) > MAX_PROPNAME_LEN) - WARNMSG("Property name %s is too long in %s\n", - prop->name, tree->fullpath); - } - - for_each_child(tree, child) { - /* Check for duplicates */ - - for (child2 = child->next_sibling; - child2; - child2 = child2->next_sibling) { - if (streq(child->name, child2->name)) - DO_ERR("Duplicate node name %s\n", - child->fullpath); - } - if (! check_names(child)) - ok = 0; - } - - return ok; -} - -static int check_phandles(struct node *root, struct node *node) -{ - struct property *prop; - struct node *child, *other; - cell_t phandle; - int ok = 1; - - prop = get_property(node, "linux,phandle"); - if (prop) { - phandle = propval_cell(prop); - if ((phandle == 0) || (phandle == -1)) { - DO_ERR("%s has invalid linux,phandle %x\n", - node->fullpath, phandle); - } else { - other = get_node_by_phandle(root, phandle); - if (other) - DO_ERR("%s has duplicated phandle %x (seen before at %s)\n", - node->fullpath, phandle, other->fullpath); - - node->phandle = phandle; - } - } - - for_each_child(node, child) - ok = ok && check_phandles(root, child); - - return ok; -} - -int check_structure(struct node *dt) -{ - int ok = 1; - - ok = ok && check_names(dt); - ok = ok && check_phandles(dt, dt); - - return ok; -} - -/* - * Semantic check functions - */ - static int must_be_one_cell(struct property *prop, struct node *node) { if (prop->val.len != sizeof(cell_t)) { diff --git a/dtc.c b/dtc.c index 602b296..5b16e5d 100644 --- a/dtc.c +++ b/dtc.c @@ -193,17 +193,7 @@ int main(int argc, char *argv[]) if (! bi || ! bi->dt) die("Couldn't read input tree\n"); - structure_ok = check_structure(bi->dt); - if (!structure_ok) { - if (!force) { - fprintf(stderr, "ERROR: Input tree has structural errors, aborting (use -f to force output)\n"); - exit(2); - } else if (quiet < 3) { - fprintf(stderr, "Warning: Input tree has structural errors, output forced\n"); - } - } - - fixup_references(bi->dt); + process_checks(force, bi->dt); if (check) { if (!structure_ok) { diff --git a/dtc.h b/dtc.h index d080153..ac3657b 100644 --- a/dtc.h +++ b/dtc.h @@ -193,9 +193,11 @@ char *get_unitname(struct node *node); struct property *get_property(struct node *node, char *propname); cell_t propval_cell(struct property *prop); struct node *get_subnode(struct node *node, char *nodename); +struct node *get_node_by_path(struct node *tree, char *path); +struct node *get_node_by_label(struct node *tree, const char *label); struct node *get_node_by_phandle(struct node *tree, cell_t phandle); - -void fixup_references(struct node *dt); +struct node *get_node_by_ref(struct node *tree, char *ref); +cell_t get_node_phandle(struct node *root, struct node *node); /* Boot info (tree plus memreserve information */ @@ -224,7 +226,7 @@ struct boot_info *build_boot_info(struct reserve_info *reservelist, /* Checks */ -int check_structure(struct node *dt); +void process_checks(int force, struct node *dt); int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys); /* Flattened trees */ diff --git a/livetree.c b/livetree.c index cdd1ab5..6f71c30 100644 --- a/livetree.c +++ b/livetree.c @@ -216,7 +216,7 @@ struct node *get_subnode(struct node *node, char *nodename) return NULL; } -static struct node *get_node_by_path(struct node *tree, char *path) +struct node *get_node_by_path(struct node *tree, char *path) { char *p; struct node *child; @@ -239,7 +239,7 @@ static struct node *get_node_by_path(struct node *tree, char *path) return NULL; } -static struct node *get_node_by_label(struct node *tree, const char *label) +struct node *get_node_by_label(struct node *tree, const char *label) { struct node *child, *node; @@ -275,7 +275,15 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle) return NULL; } -static cell_t get_node_phandle(struct node *root, struct node *node) +struct node *get_node_by_ref(struct node *tree, char *ref) +{ + if (ref[0] == '/') + return get_node_by_path(tree, ref); + else + return get_node_by_label(tree, ref); +} + +cell_t get_node_phandle(struct node *root, struct node *node) { static cell_t phandle = 1; /* FIXME: ick, static local */ @@ -295,56 +303,3 @@ static cell_t get_node_phandle(struct node *root, struct node *node) return node->phandle; } - -/* - * Reference fixup functions - */ - -static void apply_fixup(struct node *root, struct property *prop, - struct fixup *f) -{ - struct node *refnode; - cell_t phandle; - - if (f->ref[0] == '/') { - /* Reference to full path */ - refnode = get_node_by_path(root, f->ref); - if (! refnode) - die("Reference to non-existent node \"%s\"\n", f->ref); - } else { - refnode = get_node_by_label(root, f->ref); - if (! refnode) - die("Reference to non-existent node label \"%s\"\n", f->ref); - } - - phandle = get_node_phandle(root, refnode); - - assert(f->offset + sizeof(cell_t) <= prop->val.len); - - *((cell_t *)(prop->val.val + f->offset)) = cpu_to_be32(phandle); -} - -static void fixup_phandles(struct node *root, struct node *node) -{ - struct property *prop; - struct node *child; - - for_each_property(node, prop) { - struct fixup *f = prop->val.refs; - - while (f) { - apply_fixup(root, prop, f); - prop->val.refs = f->next; - fixup_free(f); - f = prop->val.refs; - } - } - - for_each_child(node, child) - fixup_phandles(root, child); -} - -void fixup_references(struct node *dt) -{ - fixup_phandles(dt, dt); -} diff --git a/tests/nonexist-label-ref.dts b/tests/nonexist-label-ref.dts new file mode 100644 index 0000000..25927a1 --- /dev/null +++ b/tests/nonexist-label-ref.dts @@ -0,0 +1,8 @@ +/dts-v1/; + +/ { + ref = <&label>; + badref = <&nosuchlabel>; + label: node { + }; +}; diff --git a/tests/nonexist-node-ref.dts b/tests/nonexist-node-ref.dts new file mode 100644 index 0000000..fa35891 --- /dev/null +++ b/tests/nonexist-node-ref.dts @@ -0,0 +1,8 @@ +/dts-v1/; + +/ { + ref = < &/node >; + badref = < &/nosuchnode >; + label: node { + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 6875c42..a8f6e10 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -157,6 +157,8 @@ dtc_tests () { run_test dtc-checkfails.sh -I dts -O dtb dup-phandle.dts run_test dtc-checkfails.sh -I dts -O dtb zero-phandle.dts run_test dtc-checkfails.sh -I dts -O dtb minusone-phandle.dts + run_test dtc-checkfails.sh -I dts -O dtb nonexist-node-ref.dts + run_test dtc-checkfails.sh -I dts -O dtb nonexist-label-ref.dts } while getopts "vt:m" ARG ; do From dc941774e228779562379a221ddc489d289e8513 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 22 Nov 2007 14:39:23 +1100 Subject: [PATCH 0162/1198] dtc: Merge refs and labels into single "markers" list (v2) Currently, every 'data' object, used to represent property values, has two lists of fixup structures - one for labels and one for references. Sometimes we want to look at them separately, but other times we need to consider both types of fixup. I'm planning to implement string references, where a full path rather than a phandle is substituted into a property value. Adding yet another list of fixups for that would start to get silly. So, this patch merges the "refs" and "labels" lists into a single list of "markers", each of which has a type field indicating if it represents a label or a phandle reference. String references or any other new type of in-data marker will then just need a new type value - merging data blocks and other common manipulations will just work. While I was at it I made some cleanups to the handling of fixups which simplify things further. Signed-off-by: David Gibson --- checks.c | 20 ++++------ data.c | 101 ++++++++++++++------------------------------------- dtc-parser.y | 11 +++--- dtc.h | 24 ++++++++---- flattree.c | 11 +++--- treesource.c | 62 ++++++++++++++++--------------- 6 files changed, 97 insertions(+), 132 deletions(-) diff --git a/checks.c b/checks.c index c8a099e..cacb5b4 100644 --- a/checks.c +++ b/checks.c @@ -243,26 +243,22 @@ NODE_CHECK(explicit_phandles, NULL, ERROR); static void fixup_phandle_references(struct check *c, struct node *dt, struct node *node, struct property *prop) { - struct fixup *f = prop->val.refs; + struct marker *m = prop->val.markers; struct node *refnode; cell_t phandle; - while (f) { - assert(f->offset + sizeof(cell_t) <= prop->val.len); + for_each_marker_of_type(m, REF_PHANDLE) { + assert(m->offset + sizeof(cell_t) <= prop->val.len); - refnode = get_node_by_ref(dt, f->ref); + refnode = get_node_by_ref(dt, m->ref); if (! refnode) { FAIL(c, "Reference to non-existent node or label \"%s\"\n", - f->ref); - } else { - phandle = get_node_phandle(dt, refnode); - - *((cell_t *)(prop->val.val + f->offset)) = cpu_to_be32(phandle); + m->ref); + continue; } - prop->val.refs = f->next; - fixup_free(f); - f = prop->val.refs; + phandle = get_node_phandle(dt, refnode); + *((cell_t *)(prop->val.val + m->offset)) = cpu_to_be32(phandle); } } CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR, diff --git a/data.c b/data.c index b6cd00e..46cc081 100644 --- a/data.c +++ b/data.c @@ -20,28 +20,16 @@ #include "dtc.h" -void fixup_free(struct fixup *f) -{ - free(f->ref); - free(f); -} - void data_free(struct data d) { - struct fixup *f, *nf; + struct marker *m, *nm; - f = d.refs; - while (f) { - nf = f->next; - fixup_free(f); - f = nf; - } - - f = d.labels; - while (f) { - nf = f->next; - fixup_free(f); - f = nf; + m = d.markers; + while (m) { + nm = m->next; + free(m->ref); + free(m); + m = nm; } assert(!d.val || d.asize); @@ -214,37 +202,29 @@ struct data data_append_data(struct data d, void *p, int len) return d; } -void fixup_merge(struct fixup **fd, struct fixup **fd2, int d1_len) +struct data data_append_markers(struct data d, struct marker *m) { - struct fixup **ff; - struct fixup *f, *f2; - - /* Extract d2's fixups */ - f2 = *fd2; - *fd2 = NULL; - - /* Tack them onto d's list of fixups */ - ff = fd; - while (*ff) - ff = &((*ff)->next); - *ff = f2; - - /* And correct them for their new position */ - for (f = f2; f; f = f->next) - f->offset += d1_len; - + struct marker **mp = &d.markers; + /* Find the end of the markerlist */ + while (*mp) + mp = &((*mp)->next); + *mp = m; + return d; } struct data data_merge(struct data d1, struct data d2) { struct data d; + struct marker *m2 = d2.markers; - d = data_append_data(d1, d2.val, d2.len); + d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2); - fixup_merge(&d.refs, &d2.refs, d1.len); - fixup_merge(&d.labels, &d2.labels, d1.len); + /* Adjust for the length of d1 */ + for_each_marker(m2) + m2->offset += d1.len; + d2.markers = NULL; /* So data_free() doesn't clobber them */ data_free(d2); return d; @@ -294,42 +274,17 @@ struct data data_append_align(struct data d, int align) return data_append_zeroes(d, newlen - d.len); } -struct data data_add_fixup(struct data d, char *ref) +struct data data_add_marker(struct data d, enum markertype type, char *ref) { - struct fixup *f; - struct data nd; + struct marker *m; - f = xmalloc(sizeof(*f)); - f->offset = d.len; - f->ref = ref; - f->next = d.refs; + m = xmalloc(sizeof(*m)); + m->offset = d.len; + m->type = type; + m->ref = ref; + m->next = NULL; - nd = d; - nd.refs = f; - - return nd; -} - -struct data data_add_label(struct data d, char *label) -{ - struct fixup *f, **p; - struct data nd; - - f = xmalloc(sizeof(*f)); - f->offset = d.len; - f->ref = label; - - nd = d; - p = &nd.labels; - - /* adding to end keeps them sorted */ - while (*p) - p = &((*p)->next); - - f->next = *p; - *p = f; - - return nd; + return data_append_markers(d, m); } int data_is_one_string(struct data d) diff --git a/dtc-parser.y b/dtc-parser.y index d998bfe..2407af4 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -194,7 +194,7 @@ propdata: } | propdata DT_LABEL { - $$ = data_add_label($1, $2); + $$ = data_add_marker($1, LABEL, $2); } ; @@ -209,7 +209,7 @@ propdataprefix: } | propdataprefix DT_LABEL { - $$ = data_add_label($1, $2); + $$ = data_add_marker($1, LABEL, $2); } ; @@ -224,11 +224,12 @@ celllist: } | celllist DT_REF { - $$ = data_append_cell(data_add_fixup($1, $2), -1); + $$ = data_append_cell(data_add_marker($1, REF_PHANDLE, + $2), -1); } | celllist DT_LABEL { - $$ = data_add_label($1, $2); + $$ = data_add_marker($1, LABEL, $2); } ; @@ -262,7 +263,7 @@ bytestring: } | bytestring DT_LABEL { - $$ = data_add_label($1, $2); + $$ = data_add_marker($1, LABEL, $2); } ; diff --git a/dtc.h b/dtc.h index ac3657b..ad21e0d 100644 --- a/dtc.h +++ b/dtc.h @@ -101,23 +101,34 @@ typedef u32 cell_t; #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) /* Data blobs */ -struct fixup { +enum markertype { + REF_PHANDLE, + LABEL, +}; + +struct marker { + enum markertype type; int offset; char *ref; - struct fixup *next; + struct marker *next; }; struct data { int len; char *val; int asize; - struct fixup *refs; - struct fixup *labels; + struct marker *markers; }; + #define empty_data ((struct data){ /* all .members = 0 or NULL */ }) -void fixup_free(struct fixup *f); +#define for_each_marker(m) \ + for (; (m); (m) = (m)->next) +#define for_each_marker_of_type(m, t) \ + for_each_marker(m) \ + if ((m)->type == (t)) + void data_free(struct data d); struct data data_grow_for(struct data d, int xlen); @@ -135,8 +146,7 @@ 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_add_fixup(struct data d, char *ref); -struct data data_add_label(struct data d, char *label); +struct data data_add_marker(struct data d, enum markertype type, char *ref); int data_is_one_string(struct data d); diff --git a/flattree.c b/flattree.c index 5889900..c1032d1 100644 --- a/flattree.c +++ b/flattree.c @@ -162,12 +162,13 @@ static void asm_emit_data(void *e, struct data d) { FILE *f = e; int off = 0; - struct fixup *l; + struct marker *m; - l = d.labels; - while (l) { - emit_offset_label(f, l->ref, l->offset); - l = l->next; + m = d.markers; + while (m) { + if (m->type == LABEL) + emit_offset_label(f, m->ref, m->offset); + m = m->next; } while ((d.len - off) >= sizeof(u32)) { diff --git a/treesource.c b/treesource.c index df3df7e..202b8a7 100644 --- a/treesource.c +++ b/treesource.c @@ -61,7 +61,7 @@ static void write_propval_string(FILE *f, struct data val) char *str = val.val; int i; int newchunk = 1; - struct fixup *l = val.labels; + struct marker *m = val.markers; assert(str[val.len-1] == '\0'); @@ -69,10 +69,12 @@ static void write_propval_string(FILE *f, struct data val) char c = str[i]; if (newchunk) { - while (l && (l->offset <= i)) { - assert(l->offset == i); - fprintf(f, "%s: ", l->ref); - l = l->next; + while (m && (m->offset <= i)) { + if (m->type == LABEL) { + assert(m->offset == i); + fprintf(f, "%s: ", m->ref); + } + m = m->next; } fprintf(f, "\""); newchunk = 0; @@ -120,10 +122,9 @@ static void write_propval_string(FILE *f, struct data val) fprintf(f, "\""); /* Wrap up any labels at the end of the value */ - while (l) { - assert (l->offset == val.len); - fprintf(f, " %s:", l->ref); - l = l->next; + for_each_marker_of_type(m, LABEL) { + assert (m->offset == val.len); + fprintf(f, " %s:", m->ref); } } @@ -131,14 +132,16 @@ static void write_propval_cells(FILE *f, struct data val) { void *propend = val.val + val.len; cell_t *cp = (cell_t *)val.val; - struct fixup *l = val.labels; + struct marker *m = val.markers; fprintf(f, "<"); for (;;) { - while (l && (l->offset <= ((char *)cp - val.val))) { - assert(l->offset == ((char *)cp - val.val)); - fprintf(f, "%s: ", l->ref); - l = l->next; + while (m && (m->offset <= ((char *)cp - val.val))) { + if (m->type == LABEL) { + assert(m->offset == ((char *)cp - val.val)); + fprintf(f, "%s: ", m->ref); + } + m = m->next; } fprintf(f, "0x%x", be32_to_cpu(*cp++)); @@ -148,10 +151,9 @@ static void write_propval_cells(FILE *f, struct data val) } /* Wrap up any labels at the end of the value */ - while (l) { - assert (l->offset == val.len); - fprintf(f, " %s:", l->ref); - l = l->next; + for_each_marker_of_type(m, LABEL) { + assert (m->offset == val.len); + fprintf(f, " %s:", m->ref); } fprintf(f, ">"); } @@ -160,13 +162,14 @@ static void write_propval_bytes(FILE *f, struct data val) { void *propend = val.val + val.len; char *bp = val.val; - struct fixup *l = val.labels; + struct marker *m = val.markers; fprintf(f, "["); for (;;) { - while (l && (l->offset == (bp-val.val))) { - fprintf(f, "%s: ", l->ref); - l = l->next; + while (m && (m->offset == (bp-val.val))) { + if (m->type == LABEL) + fprintf(f, "%s: ", m->ref); + m = m->next; } fprintf(f, "%02hhx", *bp++); @@ -176,10 +179,9 @@ static void write_propval_bytes(FILE *f, struct data val) } /* Wrap up any labels at the end of the value */ - while (l) { - assert (l->offset == val.len); - fprintf(f, " %s:", l->ref); - l = l->next; + for_each_marker_of_type(m, LABEL) { + assert (m->offset == val.len); + fprintf(f, " %s:", m->ref); } fprintf(f, "]"); } @@ -188,7 +190,7 @@ static void write_propval(FILE *f, struct property *prop) { int len = prop->val.len; char *p = prop->val.val; - struct fixup *l; + struct marker *m = prop->val.markers; int nnotstring = 0, nnul = 0; int nnotstringlbl = 0, nnotcelllbl = 0; int i; @@ -205,10 +207,10 @@ static void write_propval(FILE *f, struct property *prop) nnul++; } - for (l = prop->val.labels; l; l = l->next) { - if ((l->offset > 0) && (prop->val.val[l->offset - 1] != '\0')) + for_each_marker_of_type(m, LABEL) { + if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0')) nnotstringlbl++; - if ((l->offset % sizeof(cell_t)) != 0) + if ((m->offset % sizeof(cell_t)) != 0) nnotcelllbl++; } From f29454eb7e615ef52a4e61f95248c32dc1f7625b Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 28 Nov 2007 09:39:08 -0600 Subject: [PATCH 0163/1198] Fix whitespace in libfdt/fdt.h Take from u-boot whitespace fixup of the file Signed-off-by: Kumar Gala --- libfdt/fdt.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/libfdt/fdt.h b/libfdt/fdt.h index e00559a..48ccfd9 100644 --- a/libfdt/fdt.h +++ b/libfdt/fdt.h @@ -4,22 +4,22 @@ #ifndef __ASSEMBLY__ struct fdt_header { - uint32_t magic; /* magic word FDT_MAGIC */ - uint32_t totalsize; /* total size of DT block */ - uint32_t off_dt_struct; /* offset to structure */ - uint32_t off_dt_strings; /* offset to strings */ - uint32_t off_mem_rsvmap; /* offset to memory reserve map */ - uint32_t version; /* format version */ - uint32_t last_comp_version; /* last compatible version */ + uint32_t magic; /* magic word FDT_MAGIC */ + uint32_t totalsize; /* total size of DT block */ + uint32_t off_dt_struct; /* offset to structure */ + uint32_t off_dt_strings; /* offset to strings */ + uint32_t off_mem_rsvmap; /* offset to memory reserve map */ + uint32_t version; /* format version */ + uint32_t last_comp_version; /* last compatible version */ - /* version 2 fields below */ - uint32_t boot_cpuid_phys; /* Which physical CPU id we're + /* version 2 fields below */ + uint32_t boot_cpuid_phys; /* Which physical CPU id we're booting on */ /* version 3 fields below */ - uint32_t size_dt_strings; /* size of the strings block */ + uint32_t size_dt_strings; /* size of the strings block */ /* version 17 fields below */ - uint32_t size_dt_struct; /* size of the structure block */ + uint32_t size_dt_struct; /* size of the structure block */ }; struct fdt_reserve_entry { @@ -41,12 +41,12 @@ struct fdt_property { #endif /* !__ASSEMBLY */ -#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ +#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ #define FDT_TAGSIZE sizeof(uint32_t) -#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ -#define FDT_END_NODE 0x2 /* End node */ -#define FDT_PROP 0x3 /* Property: name off, +#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ +#define FDT_END_NODE 0x2 /* End node */ +#define FDT_PROP 0x3 /* Property: name off, size, content */ #define FDT_NOP 0x4 /* nop */ #define FDT_END 0x9 From 7c44c2f9cb1cc2df7aacd13decfc4e64b73d1730 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 22 Nov 2007 17:10:07 +1100 Subject: [PATCH 0164/1198] dtc: Fix some lexical problems with references The recent change to the lexer to only recognize property and node names in the appropriate context removed a number of lexical warts in our language that would have gotten ugly as we add expression support and so forth. But there's one nasty one remaining: references can contain a full path, including the various problematic node name characters (',', '+' and '-', for example). This would cause trouble with expressions, and it also causes trouble with the patch I'm working on to allow expanding references to paths rather than phandles. This patch therefore reworks the lexer to mitigate these problems. - References to labels cause no problems. These are now recognized separately from references to full paths. No syntax change here. - References to full paths, including problematic characters are allowed by "quoting" the path with braces e.g. &{/pci@10000/somedevice@3,8000}. The braces protect any internal problematic characters from being confused with operators or whatever. - For compatibility with existing dts files, in v0 dts files we allow bare references to paths as before &/foo/bar/whatever - but *only* if the path contains no troublesome characters. Specifically only [a-zA-Z0-9_@/] are allowed. This is an incompatible change to the dts-v1 format, but since AFAIK no-one has yet switched to dts-v1 files, I think we can get away with it. Better to make the transition when people to convert to v1, and get rid of the problematic old syntax. Strictly speaking, it's also an incompatible change to the v0 format, since some path references that were allowed before are no longer allowed. I suspect no-one has been using the no-longer-supported forms (certainly none of the kernel dts files will cause trouble). We might need to think about this harder, though. Signed-off-by: David Gibson --- dtc-lexer.l | 31 ++++++++++++++++++++++++------- tests/nonexist-node-ref.dts | 4 ++-- tests/references.dts | 6 +++--- tests/references_dts0.dts | 21 +++++++++++++++++++++ tests/run_tests.sh | 3 +++ 5 files changed, 53 insertions(+), 12 deletions(-) create mode 100644 tests/references_dts0.dts diff --git a/dtc-lexer.l b/dtc-lexer.l index eec6527..109661d 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -25,12 +25,12 @@ %x PROPNODENAME %s V1 -PROPCHAR [a-zA-Z0-9,._+*#?-] -UNITCHAR [0-9a-f,] +PROPNODECHAR [a-zA-Z0-9,._+*#?@-] +PATHCHAR ({PROPNODECHAR}|[/]) +LEGACYPATHCHAR [a-zA-Z0-9_@/] +LABEL [a-zA-Z_][a-zA-Z0-9_]* WS [[:space:]] -REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) - %{ #include "dtc.h" #include "srcpos.h" @@ -102,7 +102,7 @@ static int dts_version; /* = 0 */ return DT_MEMRESERVE; } -<*>[a-zA-Z_][a-zA-Z0-9_]*: { +<*>{LABEL}: { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Label: %s\n", yytext); @@ -142,7 +142,24 @@ static int dts_version; /* = 0 */ return DT_LITERAL; } -\&{REFCHAR}* { +\&{LABEL} { /* label reference */ + yylloc.filenum = srcpos_filenum; + yylloc.first_line = yylineno; + DPRINT("Ref: %s\n", yytext+1); + yylval.labelref = strdup(yytext+1); + return DT_REF; + } + +"&{/"{PATHCHAR}+\} { /* new-style path reference */ + yylloc.filenum = srcpos_filenum; + yylloc.first_line = yylineno; + yytext[yyleng-1] = '\0'; + DPRINT("Ref: %s\n", yytext+2); + yylval.labelref = strdup(yytext+2); + return DT_REF; + } + +"&/"{LEGACYPATHCHAR}+ { /* old-style path reference */ yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Ref: %s\n", yytext+1); @@ -166,7 +183,7 @@ static int dts_version; /* = 0 */ return ']'; } -{PROPCHAR}+(@{UNITCHAR}+)? { +{PROPNODECHAR}+ { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("PropNodeName: %s\n", yytext); diff --git a/tests/nonexist-node-ref.dts b/tests/nonexist-node-ref.dts index fa35891..efd4140 100644 --- a/tests/nonexist-node-ref.dts +++ b/tests/nonexist-node-ref.dts @@ -1,8 +1,8 @@ /dts-v1/; / { - ref = < &/node >; - badref = < &/nosuchnode >; + ref = < &{/node} >; + badref = < &{/nosuchnode} >; label: node { }; }; diff --git a/tests/references.dts b/tests/references.dts index fc032f8..36b6f51 100644 --- a/tests/references.dts +++ b/tests/references.dts @@ -4,18 +4,18 @@ /* Explicit phandles */ n1: node1 { linux,phandle = <0x2000>; - ref = <&/node2>; /* reference precedes target */ + ref = <&{/node2}>; /* reference precedes target */ lref = <&n2>; }; n2: node2 { linux,phandle = <0x1>; - ref = <&/node1>; /* reference after target */ + ref = <&{/node1}>; /* reference after target */ lref = <&n1>; }; /* Implicit phandles */ n3: node3 { - ref = <&/node4>; + ref = <&{/node4}>; lref = <&n4>; }; n4: node4 { diff --git a/tests/references_dts0.dts b/tests/references_dts0.dts new file mode 100644 index 0000000..df82c23 --- /dev/null +++ b/tests/references_dts0.dts @@ -0,0 +1,21 @@ +/ { + /* Explicit phandles */ + n1: node1 { + linux,phandle = <2000>; + ref = <&/node2>; /* reference precedes target */ + lref = <&n2>; + }; + n2: node2 { + linux,phandle = <1>; + ref = <&/node1>; /* reference after target */ + lref = <&n1>; + }; + + /* Implicit phandles */ + n3: node3 { + ref = <&/node4>; + lref = <&n4>; + }; + n4: node4 { + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index a8f6e10..d8bedca 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -144,6 +144,9 @@ dtc_tests () { run_test dtc.sh -I dts -O dtb -o dtc_references.test.dtb references.dts run_test references dtc_references.test.dtb + run_test dtc.sh -I dts -O dtb -o dtc_references_dts0.test.dtb references_dts0.dts + run_test references dtc_references_dts0.test.dtb + # Check -Odts mode preserve all dtb information for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb ; do run_test dtc.sh -I dtb -O dts -o odts_$tree.test.dts $tree From 2b7dc8dce549ad72ad437b254bf756d7ba4c2a5a Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 28 Nov 2007 10:21:12 -0600 Subject: [PATCH 0165/1198] Add an option to pad the blob that is generated There are times when we need extra space in the blob and just want to have it added on w/o know the exact size to make it. The padding and min size options are mutually exclusive. Signed-off-by: Kumar Gala --- dtc.c | 14 +++++++++++++- dtc.h | 1 + flattree.c | 20 +++++++++++++------- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/dtc.c b/dtc.c index 5b16e5d..566c904 100644 --- a/dtc.c +++ b/dtc.c @@ -29,6 +29,7 @@ int quiet; /* Level of quietness */ int reservenum; /* Number of memory reservation slots */ int minsize; /* Minimum blob size */ +int padsize; /* Additional padding to blob */ char *join_path(char *path, char *name) { @@ -97,6 +98,8 @@ static void __attribute__ ((noreturn)) usage(void) fprintf(stderr, "\t\tMake space for reserve map entries (relevant for \n\t\tdtb and asm output only)\n"); fprintf(stderr, "\t-S \n"); fprintf(stderr, "\t\tMake the blob at least long (extra space)\n"); + fprintf(stderr, "\t-p \n"); + fprintf(stderr, "\t\tAdd padding to the blob of long (extra space)\n"); fprintf(stderr, "\t-b \n"); fprintf(stderr, "\t\tSet the physical boot cpu\n"); fprintf(stderr, "\t-f\n"); @@ -124,8 +127,9 @@ int main(int argc, char *argv[]) quiet = 0; reservenum = 0; minsize = 0; + padsize = 0; - while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:fcqb:v")) != EOF) { + while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:v")) != EOF) { switch (opt) { case 'I': inform = optarg; @@ -145,6 +149,9 @@ int main(int argc, char *argv[]) case 'S': minsize = strtol(optarg, NULL, 0); break; + case 'p': + padsize = strtol(optarg, NULL, 0); + break; case 'f': force = 1; break; @@ -173,6 +180,11 @@ int main(int argc, char *argv[]) else arg = argv[optind]; + /* minsize and padsize are mutually exclusive */ + if ((minsize) && (padsize)) { + die("Can't set both -p and -S\n"); + } + fprintf(stderr, "DTC: %s->%s on file \"%s\"\n", inform, outform, arg); diff --git a/dtc.h b/dtc.h index ad21e0d..ef91c4c 100644 --- a/dtc.h +++ b/dtc.h @@ -43,6 +43,7 @@ extern int quiet; /* Level of quietness */ extern int reservenum; /* Number of memory reservation slots */ extern int minsize; /* Minimum blob size */ +extern int padsize; /* Additional padding to blob */ static inline void __attribute__((noreturn)) die(char * str, ...) { diff --git a/flattree.c b/flattree.c index c1032d1..c860b63 100644 --- a/flattree.c +++ b/flattree.c @@ -367,7 +367,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, struct data dtbuf = empty_data; struct data strbuf = empty_data; struct fdt_header fdt; - int padlen; + int padlen = 0; for (i = 0; i < ARRAY_SIZE(version_table); i++) { if (version_table[i].version == version) @@ -388,16 +388,17 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, /* * If the user asked for more space than is used, adjust the totalsize. */ - padlen = minsize - be32_to_cpu(fdt.totalsize); - if (padlen > 0) { - fdt.totalsize = cpu_to_be32(minsize); - } else { - if ((minsize > 0) && (quiet < 1)) + if (minsize > 0) { + padlen = minsize - be32_to_cpu(fdt.totalsize); + if ((padlen < 0) && (quiet < 1)) fprintf(stderr, "Warning: blob size %d >= minimum size %d\n", be32_to_cpu(fdt.totalsize), minsize); } + if (padsize > 0) + padlen = padsize; + /* * Assemble the blob: start with the header, add with alignment * the reserve buffer, add the reserve map terminating zeroes, @@ -414,8 +415,10 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, * If the user asked for more space than is used, pad out the blob. */ if (padlen > 0) { + int tsize = be32_to_cpu(fdt.totalsize); + tsize += padlen; blob = data_append_zeroes(blob, padlen); - fdt.totalsize = cpu_to_be32(minsize); + fdt.totalsize = cpu_to_be32(tsize); } fwrite(blob.val, blob.len, 1, f); @@ -545,6 +548,9 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) fprintf(f, "\t.space\t%d - (_%s_blob_end - _%s_blob_start), 0\n", minsize, symprefix, symprefix); } + if (padsize > 0) { + fprintf(f, "\t.space\t%d, 0\n", padsize); + } emit_label(f, symprefix, "blob_abs_end"); data_free(strbuf); From 2d72816ccfdcfd8039ab0b8883f9eeac895984bb Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 4 Dec 2007 11:49:43 +1100 Subject: [PATCH 0166/1198] dtc: Fix uninitialized use of structure_ok My rework of the tree checking code introduced a potentially nasty bug - it uses the structure_ok variable uninitialized. This patch fixes the problem. It's a fairly ugly bandaid approach, but the ugly will disappear once future patches have folded the semantic checks into the new framework. Signed-off-by: David Gibson --- checks.c | 16 +++++++++++++++- dtc.c | 13 +------------ dtc.h | 4 ++-- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/checks.c b/checks.c index cacb5b4..83f1fae 100644 --- a/checks.c +++ b/checks.c @@ -270,8 +270,12 @@ static struct check *check_table[] = { &phandle_references, }; -void process_checks(int force, struct node *dt) +int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys); + +void process_checks(int force, struct boot_info *bi, + int checkflag, int outversion, int boot_cpuid_phys) { + struct node *dt = bi->dt; int i; int error = 0; @@ -292,6 +296,16 @@ void process_checks(int force, struct node *dt) "output forced\n"); } } + + if (checkflag) { + if (error) { + fprintf(stderr, "Warning: Skipping semantic checks due to structural errors\n"); + } else { + if (!check_semantics(bi->dt, outversion, + boot_cpuid_phys)) + fprintf(stderr, "Warning: Input tree has semantic errors\n"); + } + } } /* diff --git a/dtc.c b/dtc.c index 566c904..179c303 100644 --- a/dtc.c +++ b/dtc.c @@ -122,7 +122,6 @@ int main(int argc, char *argv[]) FILE *outf = NULL; int outversion = DEFAULT_FDT_VERSION; int boot_cpuid_phys = 0xfeedbeef; - int structure_ok; quiet = 0; reservenum = 0; @@ -205,17 +204,7 @@ int main(int argc, char *argv[]) if (! bi || ! bi->dt) die("Couldn't read input tree\n"); - process_checks(force, bi->dt); - - if (check) { - if (!structure_ok) { - fprintf(stderr, "Warning: Skipping semantic checks due to structural errors\n"); - } else { - if (!check_semantics(bi->dt, outversion, - boot_cpuid_phys)) - fprintf(stderr, "Warning: Input tree has semantic errors\n"); - } - } + process_checks(force, bi, check, outversion, boot_cpuid_phys); if (streq(outname, "-")) { outf = stdout; diff --git a/dtc.h b/dtc.h index ef91c4c..00a9431 100644 --- a/dtc.h +++ b/dtc.h @@ -237,8 +237,8 @@ struct boot_info *build_boot_info(struct reserve_info *reservelist, /* Checks */ -void process_checks(int force, struct node *dt); -int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys); +void process_checks(int force, struct boot_info *bi, + int checkflag, int outversion, int boot_cpuid_phys); /* Flattened trees */ From 92cb9a25b1a9117f4dacb0bce8c16b90b73b8698 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 4 Dec 2007 14:26:15 +1100 Subject: [PATCH 0167/1198] dtc: Add many const qualifications This adds 'const' qualifiers to many variables and functions. In particular it's now used for passing names to the tree accesor functions. Signed-off-by: David Gibson --- data.c | 12 ++++++------ dtc.c | 14 +++++++------- dtc.h | 24 ++++++++++++------------ flattree.c | 44 ++++++++++++++++++++++---------------------- fstree.c | 4 ++-- livetree.c | 12 ++++++------ treesource.c | 6 +++--- 7 files changed, 58 insertions(+), 58 deletions(-) diff --git a/data.c b/data.c index 46cc081..3c4ab87 100644 --- a/data.c +++ b/data.c @@ -64,7 +64,7 @@ struct data data_grow_for(struct data d, int xlen) return nd; } -struct data data_copy_mem(char *mem, int len) +struct data data_copy_mem(const char *mem, int len) { struct data d; @@ -76,7 +76,7 @@ struct data data_copy_mem(char *mem, int len) return d; } -static char get_oct_char(char *s, int *i) +static char get_oct_char(const char *s, int *i) { char x[4]; char *endx; @@ -98,7 +98,7 @@ static char get_oct_char(char *s, int *i) return val; } -static char get_hex_char(char *s, int *i) +static char get_hex_char(const char *s, int *i) { char x[3]; char *endx; @@ -117,7 +117,7 @@ static char get_hex_char(char *s, int *i) return val; } -struct data data_copy_escape_string(char *s, int len) +struct data data_copy_escape_string(const char *s, int len) { int i = 0; struct data d; @@ -194,7 +194,7 @@ struct data data_copy_file(FILE *f, size_t len) return d; } -struct data data_append_data(struct data d, void *p, int len) +struct data data_append_data(struct data d, const void *p, int len) { d = data_grow_for(d, len); memcpy(d.val + d.len, p, len); @@ -237,7 +237,7 @@ struct data data_append_cell(struct data d, cell_t word) return data_append_data(d, &beword, sizeof(beword)); } -struct data data_append_re(struct data d, struct fdt_reserve_entry *re) +struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) { struct fdt_reserve_entry bere; diff --git a/dtc.c b/dtc.c index 179c303..01131d7 100644 --- a/dtc.c +++ b/dtc.c @@ -31,7 +31,7 @@ int reservenum; /* Number of memory reservation slots */ int minsize; /* Minimum blob size */ int padsize; /* Additional padding to blob */ -char *join_path(char *path, char *name) +char *join_path(const char *path, const char *name) { int lenp = strlen(path); int lenn = strlen(name); @@ -55,10 +55,10 @@ char *join_path(char *path, char *name) return str; } -void fill_fullpaths(struct node *tree, char *prefix) +void fill_fullpaths(struct node *tree, const char *prefix) { struct node *child; - char *unit; + const char *unit; tree->fullpath = join_path(prefix, tree->name); @@ -112,11 +112,11 @@ static void __attribute__ ((noreturn)) usage(void) int main(int argc, char *argv[]) { struct boot_info *bi; - char *inform = "dts"; - char *outform = "dts"; - char *outname = "-"; + const char *inform = "dts"; + const char *outform = "dts"; + const char *outname = "-"; int force = 0, check = 0; - char *arg; + const char *arg; int opt; FILE *inf = NULL; FILE *outf = NULL; diff --git a/dtc.h b/dtc.h index 00a9431..330e274 100644 --- a/dtc.h +++ b/dtc.h @@ -134,14 +134,14 @@ void data_free(struct data d); struct data data_grow_for(struct data d, int xlen); -struct data data_copy_mem(char *mem, int len); -struct data data_copy_escape_string(char *s, int len); +struct data data_copy_mem(const char *mem, int len); +struct data data_copy_escape_string(const char *s, int len); struct data data_copy_file(FILE *f, size_t len); -struct data data_append_data(struct data d, void *p, int len); +struct data data_append_data(struct data d, const void *p, int len); struct data data_merge(struct data d1, struct data d2); struct data data_append_cell(struct data d, cell_t word); -struct data data_append_re(struct data d, struct fdt_reserve_entry *re); +struct data data_append_re(struct data d, const struct fdt_reserve_entry *re); struct data data_append_addr(struct data d, u64 addr); struct data data_append_byte(struct data d, uint8_t byte); struct data data_append_zeroes(struct data d, int len); @@ -200,14 +200,14 @@ struct node *chain_node(struct node *first, struct node *list); void add_property(struct node *node, struct property *prop); void add_child(struct node *parent, struct node *child); -char *get_unitname(struct node *node); -struct property *get_property(struct node *node, char *propname); +const char *get_unitname(struct node *node); +struct property *get_property(struct node *node, const char *propname); cell_t propval_cell(struct property *prop); -struct node *get_subnode(struct node *node, char *nodename); -struct node *get_node_by_path(struct node *tree, char *path); +struct node *get_subnode(struct node *node, const char *nodename); +struct node *get_node_by_path(struct node *tree, const char *path); struct node *get_node_by_label(struct node *tree, const char *label); struct node *get_node_by_phandle(struct node *tree, cell_t phandle); -struct node *get_node_by_ref(struct node *tree, char *ref); +struct node *get_node_by_ref(struct node *tree, const char *ref); cell_t get_node_phandle(struct node *root, struct node *node); /* Boot info (tree plus memreserve information */ @@ -256,11 +256,11 @@ struct boot_info *dt_from_source(const char *f); /* FS trees */ -struct boot_info *dt_from_fs(char *dirname); +struct boot_info *dt_from_fs(const char *dirname); /* misc */ -char *join_path(char *path, char *name); -void fill_fullpaths(struct node *tree, char *prefix); +char *join_path(const char *path, const char *name); +void fill_fullpaths(struct node *tree, const char *prefix); #endif /* _DTC_H */ diff --git a/flattree.c b/flattree.c index c860b63..35b11b1 100644 --- a/flattree.c +++ b/flattree.c @@ -51,9 +51,9 @@ struct emitter { void (*string)(void *, char *, int); void (*align)(void *, int); void (*data)(void *, struct data); - void (*beginnode)(void *, char *); - void (*endnode)(void *, char *); - void (*property)(void *, char *); + void (*beginnode)(void *, const char *); + void (*endnode)(void *, const char *); + void (*property)(void *, const char *); }; static void bin_emit_cell(void *e, cell_t val) @@ -88,17 +88,17 @@ static void bin_emit_data(void *e, struct data d) *dtbuf = data_append_data(*dtbuf, d.val, d.len); } -static void bin_emit_beginnode(void *e, char *label) +static void bin_emit_beginnode(void *e, const char *label) { bin_emit_cell(e, FDT_BEGIN_NODE); } -static void bin_emit_endnode(void *e, char *label) +static void bin_emit_endnode(void *e, const char *label) { bin_emit_cell(e, FDT_END_NODE); } -static void bin_emit_property(void *e, char *label) +static void bin_emit_property(void *e, const char *label) { bin_emit_cell(e, FDT_PROP); } @@ -113,14 +113,14 @@ static struct emitter bin_emitter = { .property = bin_emit_property, }; -static void emit_label(FILE *f, char *prefix, char *label) +static void emit_label(FILE *f, const char *prefix, const char *label) { fprintf(f, "\t.globl\t%s_%s\n", prefix, label); fprintf(f, "%s_%s:\n", prefix, label); fprintf(f, "_%s_%s:\n", prefix, label); } -static void emit_offset_label(FILE *f, char *label, int offset) +static void emit_offset_label(FILE *f, const char *label, int offset) { fprintf(f, "\t.globl\t%s\n", label); fprintf(f, "%s\t= . + %d\n", label, offset); @@ -191,7 +191,7 @@ static void asm_emit_data(void *e, struct data d) assert(off == d.len); } -static void asm_emit_beginnode(void *e, char *label) +static void asm_emit_beginnode(void *e, const char *label) { FILE *f = e; @@ -202,7 +202,7 @@ static void asm_emit_beginnode(void *e, char *label) fprintf(f, "\t.long\tFDT_BEGIN_NODE\n"); } -static void asm_emit_endnode(void *e, char *label) +static void asm_emit_endnode(void *e, const char *label) { FILE *f = e; @@ -213,7 +213,7 @@ static void asm_emit_endnode(void *e, char *label) } } -static void asm_emit_property(void *e, char *label) +static void asm_emit_property(void *e, const char *label) { FILE *f = e; @@ -234,7 +234,7 @@ static struct emitter asm_emitter = { .property = asm_emit_property, }; -static int stringtable_insert(struct data *d, char *str) +static int stringtable_insert(struct data *d, const char *str) { int i; @@ -435,7 +435,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, static void dump_stringtable_asm(FILE *f, struct data strbuf) { - char *p; + const char *p; int len; p = strbuf.val; @@ -453,7 +453,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) int i; struct data strbuf = empty_data; struct reserve_info *re; - char *symprefix = "dt"; + const char *symprefix = "dt"; for (i = 0; i < ARRAY_SIZE(version_table); i++) { if (version_table[i].version == version) @@ -600,7 +600,7 @@ static void flat_realign(struct inbuf *inb, int align) static char *flat_read_string(struct inbuf *inb) { int len = 0; - char *p = inb->ptr; + const char *p = inb->ptr; char *str; do { @@ -637,7 +637,7 @@ static struct data flat_read_data(struct inbuf *inb, int len) static char *flat_read_stringtable(struct inbuf *inb, int offset) { - char *p; + const char *p; p = inb->base + offset; while (1) { @@ -679,7 +679,7 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) { struct reserve_info *reservelist = NULL; struct reserve_info *new; - char *p; + const char *p; struct fdt_reserve_entry re; /* @@ -704,9 +704,9 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) } -static char *nodename_from_path(char *ppath, char *cpath) +static char *nodename_from_path(const char *ppath, const char *cpath) { - char *lslash; + const char *lslash; int plen; lslash = strrchr(cpath, '/'); @@ -730,9 +730,9 @@ static char *nodename_from_path(char *ppath, char *cpath) static const char PROPCHAR[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,._+*#?-"; static const char UNITCHAR[] = "0123456789abcdef,"; -static int check_node_name(char *name) +static int check_node_name(const char *name) { - char *atpos; + const char *atpos; int basenamelen; atpos = strrchr(name, '@'); @@ -754,7 +754,7 @@ static int check_node_name(char *name) static struct node *unflatten_tree(struct inbuf *dtbuf, struct inbuf *strbuf, - char *parent_path, int flags) + const char *parent_path, int flags) { struct node *node; u32 val; diff --git a/fstree.c b/fstree.c index 28fd94c..2a160a4 100644 --- a/fstree.c +++ b/fstree.c @@ -23,7 +23,7 @@ #include #include -static struct node *read_fstree(char *dirname) +static struct node *read_fstree(const char *dirname) { DIR *d; struct dirent *de; @@ -80,7 +80,7 @@ static struct node *read_fstree(char *dirname) return tree; } -struct boot_info *dt_from_fs(char *dirname) +struct boot_info *dt_from_fs(const char *dirname) { struct node *tree; diff --git a/livetree.c b/livetree.c index 6f71c30..6ba0846 100644 --- a/livetree.c +++ b/livetree.c @@ -180,7 +180,7 @@ struct boot_info *build_boot_info(struct reserve_info *reservelist, * Tree accessor functions */ -char *get_unitname(struct node *node) +const char *get_unitname(struct node *node) { if (node->name[node->basenamelen] == '\0') return ""; @@ -188,7 +188,7 @@ char *get_unitname(struct node *node) return node->name + node->basenamelen + 1; } -struct property *get_property(struct node *node, char *propname) +struct property *get_property(struct node *node, const char *propname) { struct property *prop; @@ -205,7 +205,7 @@ cell_t propval_cell(struct property *prop) return be32_to_cpu(*((cell_t *)prop->val.val)); } -struct node *get_subnode(struct node *node, char *nodename) +struct node *get_subnode(struct node *node, const char *nodename) { struct node *child; @@ -216,9 +216,9 @@ struct node *get_subnode(struct node *node, char *nodename) return NULL; } -struct node *get_node_by_path(struct node *tree, char *path) +struct node *get_node_by_path(struct node *tree, const char *path) { - char *p; + const char *p; struct node *child; if (!path || ! (*path)) @@ -275,7 +275,7 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle) return NULL; } -struct node *get_node_by_ref(struct node *tree, char *ref) +struct node *get_node_by_ref(struct node *tree, const char *ref) { if (ref[0] == '/') return get_node_by_path(tree, ref); diff --git a/treesource.c b/treesource.c index 202b8a7..a6a7767 100644 --- a/treesource.c +++ b/treesource.c @@ -58,7 +58,7 @@ int isstring(char c) static void write_propval_string(FILE *f, struct data val) { - char *str = val.val; + const char *str = val.val; int i; int newchunk = 1; struct marker *m = val.markers; @@ -161,7 +161,7 @@ static void write_propval_cells(FILE *f, struct data val) static void write_propval_bytes(FILE *f, struct data val) { void *propend = val.val + val.len; - char *bp = val.val; + const char *bp = val.val; struct marker *m = val.markers; fprintf(f, "["); @@ -189,7 +189,7 @@ static void write_propval_bytes(FILE *f, struct data val) static void write_propval(FILE *f, struct property *prop) { int len = prop->val.len; - char *p = prop->val.val; + const char *p = prop->val.val; struct marker *m = prop->val.markers; int nnotstring = 0, nnul = 0; int nnotstringlbl = 0, nnotcelllbl = 0; From 501e21cc6f1a7eca5954f5b0611d9853a7b9367e Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 4 Dec 2007 10:33:20 -0600 Subject: [PATCH 0168/1198] Print out the total size as part of ftdump Signed-off-by: Kumar Gala --- ftdump.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ftdump.c b/ftdump.c index 577c2cf..53343d7 100644 --- a/ftdump.c +++ b/ftdump.c @@ -87,6 +87,7 @@ static void dump_blob(void *blob) char *p_struct = blob + be32_to_cpu(bph->off_dt_struct); char *p_strings = blob + be32_to_cpu(bph->off_dt_strings); uint32_t version = be32_to_cpu(bph->version); + uint32_t totalsize = be32_to_cpu(bph->totalsize); uint32_t tag; char *p; char *s, *t; @@ -98,6 +99,7 @@ static void dump_blob(void *blob) shift = 4; printf("// Version 0x%x tree\n", version); + printf("// Totalsize 0x%x(%d)\n", totalsize, totalsize); for (i = 0; ; i++) { addr = be64_to_cpu(p_rsvmap[i].address); size = be64_to_cpu(p_rsvmap[i].size); From d06cda32f6428601b4b2278a0286aa2b7a172eb1 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 5 Dec 2007 09:34:53 +1100 Subject: [PATCH 0169/1198] dtc: Fix FAIL() macro varargs The way the checking subsystem FAIL() macro is currently implemented it must take at least one paramater after the format string. This patch corrects the problem. Signed-off-by: David Gibson --- checks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checks.c b/checks.c index 83f1fae..fea89df 100644 --- a/checks.c +++ b/checks.c @@ -101,11 +101,11 @@ static inline void check_msg(struct check *c, const char *fmt, ...) fprintf(stderr, "\n"); } -#define FAIL(c, fmt, ...) \ +#define FAIL(c, ...) \ do { \ TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \ (c)->status = FAILED; \ - check_msg((c), fmt, __VA_ARGS__); \ + check_msg((c), __VA_ARGS__); \ } while (0) static void check_nodes_props(struct check *c, struct node *dt, struct node *node) From 459c955cca6adfa393b9279ee595c60e199dbffe Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 5 Dec 2007 09:40:23 +1100 Subject: [PATCH 0170/1198] dtc: Convert "name" property checking to new infrastructure This patch removes the old-style checking code for the "name" property - i.e. verifying that the "name" property, if present, matches the node name. It replaces it with a pair of more-or-less equivalent checks in the new checking framework. This also promotes this check to a "structural" check, or at least an error-rather-than-warning test, since the structural/semantic distinction doesn't really apply in the new framework. A testcase for the check is also added. Signed-off-by: David Gibson --- checks.c | 54 ++++++++++++++++++++++++++----------- tests/bad-name-property.dts | 7 +++++ tests/run_tests.sh | 1 + 3 files changed, 47 insertions(+), 15 deletions(-) create mode 100644 tests/bad-name-property.dts diff --git a/checks.c b/checks.c index fea89df..22f1b2a 100644 --- a/checks.c +++ b/checks.c @@ -169,6 +169,27 @@ out: return error; } +/* + * Utility check functions + */ + +static void check_is_string(struct check *c, struct node *root, + struct node *node) +{ + struct property *prop; + char *propname = c->data; + + prop = get_property(node, propname); + if (!prop) + return; /* Not present, assumed ok */ + + if (!data_is_one_string(prop->val)) + FAIL(c, "\"%s\" property in %s is not a string", + propname, node->fullpath); +} +#define CHECK_IS_STRING(nm, propname, lvl) \ + CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl)) + /* * Structural check functions */ @@ -236,6 +257,23 @@ static void check_explicit_phandles(struct check *c, struct node *root, } NODE_CHECK(explicit_phandles, NULL, ERROR); +static void check_name_properties(struct check *c, struct node *root, + struct node *node) +{ + struct property *prop; + + prop = get_property(node, "name"); + if (!prop) + return; /* No name property, that's fine */ + + if ((prop->val.len != node->basenamelen+1) + || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) + FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead" + " of base node name)", node->fullpath, prop->val.val); +} +CHECK_IS_STRING(name_is_string, "name", ERROR); +NODE_CHECK(name_properties, NULL, ERROR, &name_is_string); + /* * Reference fixup functions */ @@ -266,6 +304,7 @@ CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR, static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, + &name_is_string, &name_properties, &explicit_phandles, &phandle_references, }; @@ -350,25 +389,10 @@ static int must_be_string(struct property *prop, struct node *node) return 1; } -static int name_prop_check(struct property *prop, struct node *node) -{ - if ((prop->val.len != node->basenamelen+1) - || !strneq(prop->val.val, node->name, node->basenamelen)) { - ERRMSG("name property \"%s\" does not match node basename in %s\n", - prop->val.val, - node->fullpath); - return 0; - } - - return 1; -} - static struct { char *propname; int (*check_fn)(struct property *prop, struct node *node); } prop_checker_table[] = { - {"name", must_be_string}, - {"name", name_prop_check}, {"linux,phandle", must_be_one_cell}, {"#address-cells", must_be_one_cell}, {"#size-cells", must_be_one_cell}, diff --git a/tests/bad-name-property.dts b/tests/bad-name-property.dts new file mode 100644 index 0000000..4fde4be --- /dev/null +++ b/tests/bad-name-property.dts @@ -0,0 +1,7 @@ +/dts-v1/; + +/ { + node@0 { + name = "badthing"; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index d8bedca..9d32337 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -162,6 +162,7 @@ dtc_tests () { run_test dtc-checkfails.sh -I dts -O dtb minusone-phandle.dts run_test dtc-checkfails.sh -I dts -O dtb nonexist-node-ref.dts run_test dtc-checkfails.sh -I dts -O dtb nonexist-label-ref.dts + run_test dtc-checkfails.sh -I dts -O dtb bad-name-property.dts } while getopts "vt:m" ARG ; do From 2b67c632df15ab57e5bf1a59f23cbcac8cda6acd Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 5 Dec 2007 09:50:25 +1100 Subject: [PATCH 0171/1198] dtc: Trivial lexer cleanups This patch applies a couple of tiny cleanups to the lexer. The not-very-useful 'WS' named pattern is removed, and the debugging printf() for single character tokens is moved to the top of the action, which results in less confusing output when LEXDEBUG is switched on (because it goes before the printf()s for possible resulting lexer state changes). Signed-off-by: David Gibson --- dtc-lexer.l | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 109661d..3c4b798 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -29,7 +29,6 @@ PROPNODECHAR [a-zA-Z0-9,._+*#?@-] PATHCHAR ({PROPNODECHAR}|[/]) LEGACYPATHCHAR [a-zA-Z0-9_@/] LABEL [a-zA-Z_][a-zA-Z0-9_]* -WS [[:space:]] %{ #include "dtc.h" @@ -193,7 +192,7 @@ static int dts_version; /* = 0 */ } -<*>{WS}+ /* eat whitespace */ +<*>[[:space:]]+ /* eat whitespace */ <*>"/*"([^*]|\*+[^*/])*\*+"/" { yylloc.filenum = srcpos_filenum; @@ -207,6 +206,8 @@ static int dts_version; /* = 0 */ <*>. { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; + DPRINT("Char: %c (\\x%02x)\n", yytext[0], + (unsigned)yytext[0]); if (yytext[0] == '[') { DPRINT("\n"); BEGIN(BYTESTRING); @@ -216,9 +217,6 @@ static int dts_version; /* = 0 */ DPRINT("\n"); BEGIN(PROPNODENAME); } - DPRINT("Char: %c (\\x%02x)\n", yytext[0], - (unsigned)yytext[0]); - return yytext[0]; } From c048102f5bcafb9a316bd7532fe3958c99af6b74 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 5 Dec 2007 10:27:04 +1100 Subject: [PATCH 0172/1198] dtc: Generate useful error message for properties after subnodes On several occasions, I've accidentally put properties after subnodes in a dts file. I've then spent ages thinking that the resulting syntax error was because of something else. This patch arranges for this specific syntax error to generate a more specific and useful error message. Signed-off-by: David Gibson --- dtc-parser.y | 5 +++++ tests/prop-after-subnode.dts | 9 +++++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/prop-after-subnode.dts diff --git a/dtc-parser.y b/dtc-parser.y index 2407af4..43182fd 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -276,6 +276,11 @@ subnodes: { $$ = chain_node($1, $2); } + | subnode propdef + { + yyerror("syntax error: properties must precede subnodes\n"); + YYERROR; + } ; subnode: diff --git a/tests/prop-after-subnode.dts b/tests/prop-after-subnode.dts new file mode 100644 index 0000000..6dd0b66 --- /dev/null +++ b/tests/prop-after-subnode.dts @@ -0,0 +1,9 @@ +/dts-v1/; + +/ { + node1 { + }; + prop; + node2 { + }; +}; From 80c72a81cffdfde0965853d1ea834352b3e91f89 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 4 Dec 2007 17:36:08 -0600 Subject: [PATCH 0173/1198] Fix padding options "Add an option to pad the blob that is generated" broke the padding support. We were updating the fdt header after writing it. Signed-off-by: Kumar Gala --- flattree.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/flattree.c b/flattree.c index 35b11b1..a7cfb84 100644 --- a/flattree.c +++ b/flattree.c @@ -399,6 +399,12 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, if (padsize > 0) padlen = padsize; + if (padlen > 0) { + int tsize = be32_to_cpu(fdt.totalsize); + tsize += padlen; + fdt.totalsize = cpu_to_be32(tsize); + } + /* * Assemble the blob: start with the header, add with alignment * the reserve buffer, add the reserve map terminating zeroes, @@ -414,12 +420,8 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, /* * If the user asked for more space than is used, pad out the blob. */ - if (padlen > 0) { - int tsize = be32_to_cpu(fdt.totalsize); - tsize += padlen; + if (padlen > 0) blob = data_append_zeroes(blob, padlen); - fdt.totalsize = cpu_to_be32(tsize); - } fwrite(blob.val, blob.len, 1, f); From efbbef8e4f86f8043760f1e48b25ab2795ba3524 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 5 Dec 2007 10:43:50 +1100 Subject: [PATCH 0174/1198] dtc: Implement path references This patch extends dtc syntax to allow references (&label, or &{/full/path}) directly within property definitions, rather than inside a cell list. Such references are expanded to the full path of the referenced node, as a string, instead of to a phandle as references within cell lists are evaluated. A testcase is also included. Signed-off-by: David Gibson --- checks.c | 27 ++++++++++++- data.c | 15 +++++++ dtc-parser.y | 4 ++ dtc.h | 3 ++ tests/Makefile.tests | 2 +- tests/path-references.c | 83 +++++++++++++++++++++++++++++++++++++++ tests/path-references.dts | 14 +++++++ tests/run_tests.sh | 3 ++ 8 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 tests/path-references.c create mode 100644 tests/path-references.dts diff --git a/checks.c b/checks.c index 22f1b2a..59b23b8 100644 --- a/checks.c +++ b/checks.c @@ -302,11 +302,36 @@ static void fixup_phandle_references(struct check *c, struct node *dt, CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR, &duplicate_node_names, &explicit_phandles); +static void fixup_path_references(struct check *c, struct node *dt, + struct node *node, struct property *prop) +{ + struct marker *m = prop->val.markers; + struct node *refnode; + char *path; + + for_each_marker_of_type(m, REF_PATH) { + assert(m->offset <= prop->val.len); + + refnode = get_node_by_ref(dt, m->ref); + if (!refnode) { + FAIL(c, "Reference to non-existent node or label \"%s\"\n", + m->ref); + continue; + } + + path = refnode->fullpath; + prop->val = data_insert_at_marker(prop->val, m, path, + strlen(path) + 1); + } +} +CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR, + &duplicate_node_names); + static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &name_is_string, &name_properties, &explicit_phandles, - &phandle_references, + &phandle_references, &path_references, }; int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys); diff --git a/data.c b/data.c index 3c4ab87..a94718c 100644 --- a/data.c +++ b/data.c @@ -202,6 +202,21 @@ struct data data_append_data(struct data d, const void *p, int len) return d; } +struct data data_insert_at_marker(struct data d, struct marker *m, + const void *p, int len) +{ + d = data_grow_for(d, len); + memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset); + memcpy(d.val + m->offset, p, len); + d.len += len; + + /* Adjust all markers after the one we're inserting at */ + m = m->next; + for_each_marker(m) + m->offset += len; + return d; +} + struct data data_append_markers(struct data d, struct marker *m) { struct marker **mp = &d.markers; diff --git a/dtc-parser.y b/dtc-parser.y index 43182fd..002ea7f 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -192,6 +192,10 @@ propdata: { $$ = data_merge($1, $3); } + | propdataprefix DT_REF + { + $$ = data_add_marker($1, REF_PATH, $2); + } | propdata DT_LABEL { $$ = data_add_marker($1, LABEL, $2); diff --git a/dtc.h b/dtc.h index 330e274..6528177 100644 --- a/dtc.h +++ b/dtc.h @@ -104,6 +104,7 @@ typedef u32 cell_t; /* Data blobs */ enum markertype { REF_PHANDLE, + REF_PATH, LABEL, }; @@ -139,6 +140,8 @@ struct data data_copy_escape_string(const char *s, int len); struct data data_copy_file(FILE *f, size_t len); struct data data_append_data(struct data d, const void *p, int len); +struct data data_insert_at_marker(struct data d, struct marker *m, + const void *p, int len); struct data data_merge(struct data d1, struct data d2); struct data data_append_cell(struct data d, cell_t word); struct data data_append_re(struct data d, const struct fdt_reserve_entry *re); diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 569bd9e..ff87eaa 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -9,7 +9,7 @@ LIB_TESTS_L = get_mem_rsv \ sw_tree1 \ move_and_save mangle-layout \ open_pack rw_tree1 setprop del_property del_node \ - string_escapes references \ + string_escapes references path-references \ dtbs_equal_ordered LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) diff --git a/tests/path-references.c b/tests/path-references.c new file mode 100644 index 0000000..b96c5b2 --- /dev/null +++ b/tests/path-references.c @@ -0,0 +1,83 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for string references in dtc + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void check_ref(const void *fdt, int node, const char *checkpath) +{ + const char *p; + int len; + + p = fdt_getprop(fdt, node, "ref", &len); + if (!p) + FAIL("fdt_getprop(%d, \"ref\"): %s", node, fdt_strerror(len)); + if (!streq(p, checkpath)) + FAIL("'ref' in node at %d has value \"%s\" instead of \"%s\"", + node, p, checkpath); + + p = fdt_getprop(fdt, node, "lref", &len); + if (!p) + FAIL("fdt_getprop(%d, \"lref\"): %s", node, fdt_strerror(len)); + if (!streq(p, checkpath)) + FAIL("'lref' in node at %d has value \"%s\" instead of \"%s\"", + node, p, checkpath); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + const char *p; + int len, multilen; + int n1, n2; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + n1 = fdt_path_offset(fdt, "/node1"); + if (n1 < 0) + FAIL("fdt_path_offset(/node1): %s", fdt_strerror(n1)); + n2 = fdt_path_offset(fdt, "/node2"); + if (n2 < 0) + FAIL("fdt_path_offset(/node2): %s", fdt_strerror(n2)); + + check_ref(fdt, n1, "/node2"); + check_ref(fdt, n2, "/node1"); + + /* Check multiple reference */ + multilen = strlen("/node1") + strlen("/node2") + 2; + p = fdt_getprop(fdt, 0, "multiref", &len); + if (!p) + FAIL("fdt_getprop(0, \"multiref\"): %s", fdt_strerror(len)); + if (len != multilen) + FAIL("multiref has wrong length, %d instead of %d", + len, multilen); + if ((!streq(p, "/node1") || !streq(p + strlen("/node1") + 1, "/node2"))) + FAIL("multiref has wrong value"); + + PASS(); +} diff --git a/tests/path-references.dts b/tests/path-references.dts new file mode 100644 index 0000000..91e7ef7 --- /dev/null +++ b/tests/path-references.dts @@ -0,0 +1,14 @@ +/dts-v1/; + +/ { + /* Check multiple references case */ + multiref = &n1 , &n2; + n1: node1 { + ref = &{/node2}; /* reference precedes target */ + lref = &n2; + }; + n2: node2 { + ref = &{/node1}; /* reference after target */ + lref = &n1; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 9d32337..4a70b4a 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -147,6 +147,9 @@ dtc_tests () { run_test dtc.sh -I dts -O dtb -o dtc_references_dts0.test.dtb references_dts0.dts run_test references dtc_references_dts0.test.dtb + run_test dtc.sh -I dts -O dtb -o dtc_path-references.test.dtb path-references.dts + run_test path-references dtc_path-references.test.dtb + # Check -Odts mode preserve all dtb information for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb ; do run_test dtc.sh -I dtb -O dts -o odts_$tree.test.dts $tree From d6060bd231b9cf5d22af4b850438b32016da4af8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 6 Dec 2007 13:07:50 +1100 Subject: [PATCH 0175/1198] dtc: Remove space from flex command line Author: Geoff Levand Apparently some versions of flex don't correctly parse the -o parameter, if there's a space between the -o and its argument. So, this patch removes it. Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9f9bee0..bcb143f 100644 --- a/Makefile +++ b/Makefile @@ -206,7 +206,7 @@ clean: libfdt_clean tests_clean %.lex.c: %.l @$(VECHO) LEX $@ - $(LEX) -o $@ $< + $(LEX) -o$@ $< %.tab.c %.tab.h %.output: %.y @$(VECHO) BISON $@ From 5ba0086bfd0fa6ab25f7ce1870417301a26c104f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 6 Dec 2007 16:56:55 +1100 Subject: [PATCH 0176/1198] dtc: More detailed testing of tree checks This patch modifies the dtc-checkfails.sh testcase wrapper so that instead of testing just that dtc fails with a particular error code on the sample input, it scans dtc's stderr output looking for a message that dtc failed a specific check or checks. This has several advantages: - It means we more precisely check dtc's checking behaviour - It means we can check for generation of warnings using the same script - It means we can test cases where dtc should generate multiple errors or warnings from different checks Signed-off-by: David Gibson --- tests/Makefile.tests | 2 +- tests/dtc-checkfails.sh | 30 ++++++++++++++++++------------ tests/run_tests.sh | 16 ++++++++-------- tests/tests.sh | 11 +++++++++++ 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index ff87eaa..8d17b89 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -26,7 +26,7 @@ TESTS_TARGETS = $(TESTS) $(TESTS_TREES) TESTS_DEPFILES = $(TESTS:%=%.d) \ $(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d) -TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts +TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts tmp.* TESTS_CLEANFILES = $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) BIN += $(TESTS) $(TESTS_PREFIX)dumptrees diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh index 0a45a0b..cca4119 100755 --- a/tests/dtc-checkfails.sh +++ b/tests/dtc-checkfails.sh @@ -2,21 +2,27 @@ . tests.sh -TMPFILE="tmp.out.$$" +for x; do + shift + if [ "$x" = "--" ]; then + break; + fi + CHECKS="$CHECKS $x" +done -rm -f $TMPFILE +LOG="tmp.log.$$" -verbose_run "$DTC" -o $TMPFILE "$@" +rm -f $TMPFILE $LOG + +verbose_run_log "$LOG" "$DTC" -o /dev/null "$@" ret="$?" -if [ -f $TMPFILE ]; then - FAIL "output file was created despite bad input" -fi +for c in $CHECKS; do + if ! grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then + FAIL "Failed to trigger check \"%c\"" + fi +done -if [ "$ret" = "2" ]; then - PASS -else - FAIL "dtc returned error code $ret instead of 2 (check failed)" -fi +rm -f $LOG -rm -f $TMPFILE +PASS diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 4a70b4a..e044bd2 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -158,14 +158,14 @@ dtc_tests () { done # Check some checks - run_test dtc-checkfails.sh -I dts -O dtb dup-nodename.dts - run_test dtc-checkfails.sh -I dts -O dtb dup-propname.dts - run_test dtc-checkfails.sh -I dts -O dtb dup-phandle.dts - run_test dtc-checkfails.sh -I dts -O dtb zero-phandle.dts - run_test dtc-checkfails.sh -I dts -O dtb minusone-phandle.dts - run_test dtc-checkfails.sh -I dts -O dtb nonexist-node-ref.dts - run_test dtc-checkfails.sh -I dts -O dtb nonexist-label-ref.dts - run_test dtc-checkfails.sh -I dts -O dtb bad-name-property.dts + run_test dtc-checkfails.sh duplicate_node_names -- -I dts -O dtb dup-nodename.dts + run_test dtc-checkfails.sh duplicate_property_names -- -I dts -O dtb dup-propname.dts + run_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb dup-phandle.dts + run_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb zero-phandle.dts + run_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb minusone-phandle.dts + run_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-node-ref.dts + run_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-label-ref.dts + run_test dtc-checkfails.sh name_properties -- -I dts -O dtb bad-name-property.dts } while getopts "vt:m" ARG ; do diff --git a/tests/tests.sh b/tests/tests.sh index 396b4cf..28b3fb1 100644 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -19,3 +19,14 @@ verbose_run () { "$@" > /dev/null 2> /dev/null fi } + +verbose_run_log () { + LOG="$1" + shift + "$@" &> "$LOG" + ret=$? + if [ -z "$QUIET_TEST" ]; then + cat "$LOG" >&2 + fi + return $ret +} From c21acabc40ff1edf8c01f4452c79eaf338b4c13e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 6 Dec 2007 16:59:45 +1100 Subject: [PATCH 0177/1198] dtc: Migrate "one cell" checks to new framework This patch converts to the new tree checking framework those checks which verify that certain properties (#address-cells and #size-cells) are exactly one cell in size, when present. We also drop the old-style check for "linux,phandle" being one cell, since that is already implied in the the existing new-style checks on the linux,phandle property. Signed-off-by: David Gibson --- checks.c | 40 ++++++++++++++++++++++++++-------------- tests/bad-ncells.dts | 7 +++++++ tests/run_tests.sh | 2 ++ 3 files changed, 35 insertions(+), 14 deletions(-) create mode 100644 tests/bad-ncells.dts diff --git a/checks.c b/checks.c index 59b23b8..5f76ff2 100644 --- a/checks.c +++ b/checks.c @@ -190,6 +190,23 @@ static void check_is_string(struct check *c, struct node *root, #define CHECK_IS_STRING(nm, propname, lvl) \ CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl)) +static void check_is_cell(struct check *c, struct node *root, + struct node *node) +{ + struct property *prop; + char *propname = c->data; + + prop = get_property(node, propname); + if (!prop) + return; /* Not present, assumed ok */ + + if (prop->val.len != sizeof(cell_t)) + FAIL(c, "\"%s\" property in %s is not a single cell", + propname, node->fullpath); +} +#define CHECK_IS_CELL(nm, propname, lvl) \ + CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl)) + /* * Structural check functions */ @@ -327,11 +344,20 @@ static void fixup_path_references(struct check *c, struct node *dt, CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR, &duplicate_node_names); +/* + * Semantic checks + */ +CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN); +CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN); +CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN); + static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &name_is_string, &name_properties, &explicit_phandles, &phandle_references, &path_references, + + &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell, }; int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys); @@ -381,17 +407,6 @@ void process_checks(int force, struct boot_info *bi, #define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0) -static int must_be_one_cell(struct property *prop, struct node *node) -{ - if (prop->val.len != sizeof(cell_t)) { - ERRMSG("\"%s\" property in %s has the wrong length (should be 1 cell)\n", - prop->name, node->fullpath); - return 0; - } - - return 1; -} - static int must_be_cells(struct property *prop, struct node *node) { if ((prop->val.len % sizeof(cell_t)) != 0) { @@ -418,9 +433,6 @@ static struct { char *propname; int (*check_fn)(struct property *prop, struct node *node); } prop_checker_table[] = { - {"linux,phandle", must_be_one_cell}, - {"#address-cells", must_be_one_cell}, - {"#size-cells", must_be_one_cell}, {"reg", must_be_cells}, {"model", must_be_string}, {"device_type", must_be_string}, diff --git a/tests/bad-ncells.dts b/tests/bad-ncells.dts new file mode 100644 index 0000000..636198c --- /dev/null +++ b/tests/bad-ncells.dts @@ -0,0 +1,7 @@ +/dts-v1/; + +/ { + #address-cells = "badthing"; + #size-cells = "badthing"; + #interrupt-cells = "badthing"; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index e044bd2..9e0af51 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -166,6 +166,8 @@ dtc_tests () { run_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-node-ref.dts run_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-label-ref.dts run_test dtc-checkfails.sh name_properties -- -I dts -O dtb bad-name-property.dts + + run_test dtc-checkfails.sh address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell -- -I dts -O dtb bad-ncells.dts } while getopts "vt:m" ARG ; do From faf037f0ef294412a3bb04be4032bf2f008a5945 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 6 Dec 2007 17:01:07 +1100 Subject: [PATCH 0178/1198] dtc: Migrate "string property" checks to new framework This patch converts to the new tree checking framework those checks which verify that certain properties (device_type, model) have a string value, when present. Signed-off-by: David Gibson --- checks.c | 18 +++++------------- tests/bad-string-props.dts | 7 +++++++ tests/run_tests.sh | 2 ++ 3 files changed, 14 insertions(+), 13 deletions(-) create mode 100644 tests/bad-string-props.dts diff --git a/checks.c b/checks.c index 5f76ff2..f9a9a0e 100644 --- a/checks.c +++ b/checks.c @@ -351,6 +351,10 @@ CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN); CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN); CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN); +CHECK_IS_STRING(device_type_is_string, "device_type", WARN); +CHECK_IS_STRING(model_is_string, "model", WARN); +CHECK_IS_STRING(status_is_string, "status", WARN); + static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &name_is_string, &name_properties, @@ -358,6 +362,7 @@ static struct check *check_table[] = { &phandle_references, &path_references, &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell, + &device_type_is_string, &model_is_string, &status_is_string, }; int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys); @@ -418,24 +423,11 @@ static int must_be_cells(struct property *prop, struct node *node) return 1; } -static int must_be_string(struct property *prop, struct node *node) -{ - if (! data_is_one_string(prop->val)) { - ERRMSG("\"%s\" property in %s is not a string\n", - prop->name, node->fullpath); - return 0; - } - - return 1; -} - static struct { char *propname; int (*check_fn)(struct property *prop, struct node *node); } prop_checker_table[] = { {"reg", must_be_cells}, - {"model", must_be_string}, - {"device_type", must_be_string}, }; static int check_properties(struct node *node) diff --git a/tests/bad-string-props.dts b/tests/bad-string-props.dts new file mode 100644 index 0000000..396f820 --- /dev/null +++ b/tests/bad-string-props.dts @@ -0,0 +1,7 @@ +/dts-v1/; + +/ { + device_type = <0xdeadbeef>; + model = <0xdeadbeef>; + status = <0xdeadbeef>; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 9e0af51..c0003a2 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -168,6 +168,8 @@ dtc_tests () { run_test dtc-checkfails.sh name_properties -- -I dts -O dtb bad-name-property.dts run_test dtc-checkfails.sh address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell -- -I dts -O dtb bad-ncells.dts + run_test dtc-checkfails.sh device_type_is_string model_is_string status_is_string -- -I dts -O dtb bad-string-props.dts + } while getopts "vt:m" ARG ; do From e110920707ecedd7f1f4426dd4240d51c5ce0dd0 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 6 Dec 2007 17:04:04 +1100 Subject: [PATCH 0179/1198] dtc: Remove obsolete check_properties() function After the last couple of patches converting various old-style semantic checks to the new framework, the only thing that the old-style check_properties() function still checks is that the size of "reg" properties is a multiple of the cell size. This patch removes check_properties() and all related code and data. The check on the size of reg properties is folded into the existing check for the format of "reg" properties (still old-style for the time being). Signed-off-by: David Gibson --- checks.c | 48 +++--------------------------------------------- 1 file changed, 3 insertions(+), 45 deletions(-) diff --git a/checks.c b/checks.c index f9a9a0e..8ce7411 100644 --- a/checks.c +++ b/checks.c @@ -412,46 +412,6 @@ void process_checks(int force, struct boot_info *bi, #define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0) -static int must_be_cells(struct property *prop, struct node *node) -{ - if ((prop->val.len % sizeof(cell_t)) != 0) { - ERRMSG("\"%s\" property in %s is not a multiple of cell size\n", - prop->name, node->fullpath); - return 0; - } - - return 1; -} - -static struct { - char *propname; - int (*check_fn)(struct property *prop, struct node *node); -} prop_checker_table[] = { - {"reg", must_be_cells}, -}; - -static int check_properties(struct node *node) -{ - struct property *prop; - struct node *child; - int i; - int ok = 1; - - for_each_property(node, prop) - for (i = 0; i < ARRAY_SIZE(prop_checker_table); i++) - if (streq(prop->name, prop_checker_table[i].propname)) - if (! prop_checker_table[i].check_fn(prop, node)) { - ok = 0; - break; - } - - for_each_child(node, child) - if (! check_properties(child)) - ok = 0; - - return ok; -} - #define CHECK_HAVE(node, propname) \ do { \ if (! (prop = get_property((node), (propname)))) \ @@ -672,10 +632,9 @@ static int check_addr_size_reg(struct node *node, prop = get_property(node, "reg"); if (prop) { - int len = prop->val.len / 4; - - if ((len % (addr_cells+size_cells)) != 0) - DO_ERR("\"reg\" property in %s has invalid length (%d) for given #address-cells (%d) and #size-cells (%d)\n", + int reg_entry_len = (addr_cells + size_cells) * sizeof(cell_t); + if ((prop->val.len % reg_entry_len) != 0) + DO_ERR("\"reg\" property in %s has invalid length (%d bytes) for given #address-cells (%d) and #size-cells (%d)\n", node->fullpath, prop->val.len, addr_cells, size_cells); } @@ -699,7 +658,6 @@ int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys) { int ok = 1; - ok = ok && check_properties(dt); ok = ok && check_addr_size_reg(dt, -1, -1); ok = ok && check_root(dt); ok = ok && check_cpus(dt, outversion, boot_cpuid_phys); From 7e089d9473989bc6dadfdfa81fa3fc029abf26db Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 7 Dec 2007 14:05:55 +1100 Subject: [PATCH 0180/1198] dtc: Convert #address-cells and #size-cells related checks This patch converts checks related to #address-cells and #size-cells to the new framework. Specifically, it reimplements the check that "reg" properties have a valid size based on the relevant #address-cells and #size-cells values. The new implementation uses the correct default value, unlike the old-style check which assumed the values were inherited by default. It also implements a new, similar test for "ranges" properties. Finally, since relying on the default values of these variables is considered not-good-practice these days, it implements a "style" check which will give a warning if the tree ever relies on the default values (that is if any node with either "reg" or "ranges" appears under a parent which has no #address-cells or #size-cells property). --- checks.c | 181 ++++++++++++++++++++++++++---------- tests/bad-empty-ranges.dts | 11 +++ tests/bad-reg-ranges.dts | 12 +++ tests/default-addr-size.dts | 7 ++ tests/run_tests.sh | 4 +- 5 files changed, 164 insertions(+), 51 deletions(-) create mode 100644 tests/bad-empty-ranges.dts create mode 100644 tests/bad-reg-ranges.dts create mode 100644 tests/default-addr-size.dts diff --git a/checks.c b/checks.c index 8ce7411..e27ab30 100644 --- a/checks.c +++ b/checks.c @@ -355,6 +355,127 @@ CHECK_IS_STRING(device_type_is_string, "device_type", WARN); CHECK_IS_STRING(model_is_string, "model", WARN); CHECK_IS_STRING(status_is_string, "status", WARN); +static void fixup_addr_size_cells(struct check *c, struct node *dt, + struct node *node) +{ + struct property *prop; + + node->addr_cells = -1; + node->size_cells = -1; + + prop = get_property(node, "#address-cells"); + if (prop) + node->addr_cells = propval_cell(prop); + + prop = get_property(node, "#size-cells"); + if (prop) + node->size_cells = propval_cell(prop); +} +CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN, + &address_cells_is_cell, &size_cells_is_cell); + +#define node_addr_cells(n) \ + (((n)->addr_cells == -1) ? 2 : (n)->addr_cells) +#define node_size_cells(n) \ + (((n)->size_cells == -1) ? 1 : (n)->size_cells) + +static void check_reg_format(struct check *c, struct node *dt, + struct node *node) +{ + struct property *prop; + int addr_cells, size_cells, entrylen; + + prop = get_property(node, "reg"); + if (!prop) + return; /* No "reg", that's fine */ + + if (!node->parent) { + FAIL(c, "Root node has a \"reg\" property"); + return; + } + + if (prop->val.len == 0) + FAIL(c, "\"reg\" property in %s is empty", node->fullpath); + + addr_cells = node_addr_cells(node->parent); + size_cells = node_size_cells(node->parent); + entrylen = (addr_cells + size_cells) * sizeof(cell_t); + + if ((prop->val.len % entrylen) != 0) + FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) " + "(#address-cells == %d, #size-cells == %d)", + node->fullpath, prop->val.len, addr_cells, size_cells); +} +NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells); + +static void check_ranges_format(struct check *c, struct node *dt, + struct node *node) +{ + struct property *prop; + int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen; + + prop = get_property(node, "ranges"); + if (!prop) + return; + + if (!node->parent) { + FAIL(c, "Root node has a \"ranges\" property"); + return; + } + + p_addr_cells = node_addr_cells(node->parent); + p_size_cells = node_size_cells(node->parent); + c_addr_cells = node_addr_cells(node); + c_size_cells = node_size_cells(node); + entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t); + + if (prop->val.len == 0) { + if (p_addr_cells != c_addr_cells) + FAIL(c, "%s has empty \"ranges\" property but its " + "#address-cells (%d) differs from %s (%d)", + node->fullpath, c_addr_cells, node->parent->fullpath, + p_addr_cells); + if (p_size_cells != c_size_cells) + FAIL(c, "%s has empty \"ranges\" property but its " + "#size-cells (%d) differs from %s (%d)", + node->fullpath, c_size_cells, node->parent->fullpath, + p_size_cells); + } else if ((prop->val.len % entrylen) != 0) { + FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) " + "(parent #address-cells == %d, child #address-cells == %d, " + "#size-cells == %d)", node->fullpath, prop->val.len, + p_addr_cells, c_addr_cells, c_size_cells); + } +} +NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells); + +/* + * Style checks + */ +static void check_avoid_default_addr_size(struct check *c, struct node *dt, + struct node *node) +{ + struct property *reg, *ranges; + + if (!node->parent) + return; /* Ignore root node */ + + reg = get_property(node, "reg"); + ranges = get_property(node, "ranges"); + + if (!reg && !ranges) + return; + + if ((node->parent->addr_cells == -1)) + FAIL(c, "Relying on default #address-cells value for %s", + node->fullpath); + + if ((node->parent->size_cells == -1)) + FAIL(c, "Relying on default #size-cells value for %s", + node->fullpath); +} +NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells); + static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &name_is_string, &name_properties, @@ -363,6 +484,10 @@ static struct check *check_table[] = { &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell, &device_type_is_string, &model_is_string, &status_is_string, + + &addr_size_cells, ®_format, &ranges_format, + + &avoid_default_addr_size, }; int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys); @@ -487,10 +612,6 @@ static int check_root(struct node *root) int ok = 1; CHECK_HAVE_STRING(root, "model"); - - CHECK_HAVE(root, "#address-cells"); - CHECK_HAVE(root, "#size-cells"); - CHECK_HAVE_WARN(root, "compatible"); return ok; @@ -509,19 +630,16 @@ static int check_cpus(struct node *root, int outversion, int boot_cpuid_phys) return 0; } - CHECK_HAVE_WARN(cpus, "#address-cells"); - CHECK_HAVE_WARN(cpus, "#size-cells"); + if (cpus->addr_cells != 1) + DO_ERR("%s has bad #address-cells value %d (should be 1)\n", + cpus->fullpath, cpus->addr_cells); + if (cpus->size_cells != 0) + DO_ERR("%s has bad #size-cells value %d (should be 0)\n", + cpus->fullpath, cpus->size_cells); for_each_child(cpus, cpu) { CHECK_HAVE_STREQ(cpu, "device_type", "cpu"); - if (cpu->addr_cells != 1) - DO_ERR("%s has bad #address-cells value %d (should be 1)\n", - cpu->fullpath, cpu->addr_cells); - if (cpu->size_cells != 0) - DO_ERR("%s has bad #size-cells value %d (should be 0)\n", - cpu->fullpath, cpu->size_cells); - CHECK_HAVE_ONECELL(cpu, "reg"); if (prop) { cell_t unitnum; @@ -618,47 +736,10 @@ static int check_chosen(struct node *root) return ok; } -static int check_addr_size_reg(struct node *node, - int p_addr_cells, int p_size_cells) -{ - int addr_cells = p_addr_cells; - int size_cells = p_size_cells; - struct property *prop; - struct node *child; - int ok = 1; - - node->addr_cells = addr_cells; - node->size_cells = size_cells; - - prop = get_property(node, "reg"); - if (prop) { - int reg_entry_len = (addr_cells + size_cells) * sizeof(cell_t); - if ((prop->val.len % reg_entry_len) != 0) - DO_ERR("\"reg\" property in %s has invalid length (%d bytes) for given #address-cells (%d) and #size-cells (%d)\n", - node->fullpath, prop->val.len, - addr_cells, size_cells); - } - - prop = get_property(node, "#address-cells"); - if (prop) - addr_cells = propval_cell(prop); - - prop = get_property(node, "#size-cells"); - if (prop) - size_cells = propval_cell(prop); - - for_each_child(node, child) { - ok = ok && check_addr_size_reg(child, addr_cells, size_cells); - } - - return ok; -} - int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys) { int ok = 1; - ok = ok && check_addr_size_reg(dt, -1, -1); ok = ok && check_root(dt); ok = ok && check_cpus(dt, outversion, boot_cpuid_phys); ok = ok && check_memory(dt); diff --git a/tests/bad-empty-ranges.dts b/tests/bad-empty-ranges.dts new file mode 100644 index 0000000..2be7bc8 --- /dev/null +++ b/tests/bad-empty-ranges.dts @@ -0,0 +1,11 @@ +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; + node { + #address-cells = <1>; + #size-cells = <1>; + ranges; + }; +}; diff --git a/tests/bad-reg-ranges.dts b/tests/bad-reg-ranges.dts new file mode 100644 index 0000000..77419f5 --- /dev/null +++ b/tests/bad-reg-ranges.dts @@ -0,0 +1,12 @@ +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; + node { + reg = <0 0>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0>; + }; +}; diff --git a/tests/default-addr-size.dts b/tests/default-addr-size.dts new file mode 100644 index 0000000..e964a55 --- /dev/null +++ b/tests/default-addr-size.dts @@ -0,0 +1,7 @@ +/dts-v1/; + +/ { + node { + reg = <0 0 0>; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c0003a2..2ded0e7 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -169,7 +169,9 @@ dtc_tests () { run_test dtc-checkfails.sh address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell -- -I dts -O dtb bad-ncells.dts run_test dtc-checkfails.sh device_type_is_string model_is_string status_is_string -- -I dts -O dtb bad-string-props.dts - + run_test dtc-checkfails.sh reg_format ranges_format -- -I dts -O dtb bad-reg-ranges.dts + run_test dtc-checkfails.sh ranges_format -- -I dts -O dtb bad-empty-ranges.dts + run_test dtc-checkfails.sh avoid_default_addr_size -- -I dts -O dtb default-addr-size.dts } while getopts "vt:m" ARG ; do From e4ffc1443d23d57babde8413f53e001e84610c4f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 7 Dec 2007 14:06:11 +1100 Subject: [PATCH 0181/1198] dtc: Convert check for obsolete /chosen property This converts the test for the obsolete "interrupt-controller" property in /chosen to the new framework. That was the only thing left in the old-style check_chosen() function, so that function is removed, too. Signed-off-by: David Gibson --- checks.c | 40 +++++++++---------- .../obsolete-chosen-interrupt-controller.dts | 13 ++++++ tests/run_tests.sh | 1 + 3 files changed, 32 insertions(+), 22 deletions(-) create mode 100644 tests/obsolete-chosen-interrupt-controller.dts diff --git a/checks.c b/checks.c index e27ab30..6325ee9 100644 --- a/checks.c +++ b/checks.c @@ -476,6 +476,23 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt, } NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells); +static void check_obsolete_chosen_interrupt_controller(struct check *c, + struct node *dt) +{ + struct node *chosen; + struct property *prop; + + chosen = get_node_by_path(dt, "/chosen"); + if (!chosen) + return; + + prop = get_property(chosen, "interrupt-controller"); + if (prop) + FAIL(c, "/chosen has obsolete \"interrupt-controller\" " + "property"); +} +TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN); + static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &name_is_string, &name_properties, @@ -488,6 +505,7 @@ static struct check *check_table[] = { &addr_size_cells, ®_format, &ranges_format, &avoid_default_addr_size, + &obsolete_chosen_interrupt_controller, }; int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys); @@ -715,27 +733,6 @@ static int check_memory(struct node *root) return ok; } -static int check_chosen(struct node *root) -{ - struct node *chosen; - struct property *prop; - int ok = 1; - - chosen = get_subnode(root, "chosen"); - if (!chosen) - return ok; - - /* give warning for obsolete interrupt-controller property */ - do { - if ((prop = get_property(chosen, "interrupt-controller")) != NULL) { - WARNMSG("%s has obsolete \"%s\" property\n", - chosen->fullpath, "interrupt-controller"); - } - } while (0); - - return ok; -} - int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys) { int ok = 1; @@ -743,7 +740,6 @@ int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys) ok = ok && check_root(dt); ok = ok && check_cpus(dt, outversion, boot_cpuid_phys); ok = ok && check_memory(dt); - ok = ok && check_chosen(dt); if (! ok) return 0; diff --git a/tests/obsolete-chosen-interrupt-controller.dts b/tests/obsolete-chosen-interrupt-controller.dts new file mode 100644 index 0000000..36dd6e8 --- /dev/null +++ b/tests/obsolete-chosen-interrupt-controller.dts @@ -0,0 +1,13 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + PIC: pic@0 { + reg = <0x0 0x10>; + interrupt-controller; + }; + chosen { + interrupt-controller = <&PIC>; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 2ded0e7..83e8d62 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -172,6 +172,7 @@ dtc_tests () { run_test dtc-checkfails.sh reg_format ranges_format -- -I dts -O dtb bad-reg-ranges.dts run_test dtc-checkfails.sh ranges_format -- -I dts -O dtb bad-empty-ranges.dts run_test dtc-checkfails.sh avoid_default_addr_size -- -I dts -O dtb default-addr-size.dts + run_test dtc-checkfails.sh obsolete_chosen_interrupt_controller -- -I dts -O dtb obsolete-chosen-interrupt-controller.dts } while getopts "vt:m" ARG ; do From 3476f9608bd22803c64d5a4ede118784debd0b18 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 7 Dec 2007 14:38:26 +1100 Subject: [PATCH 0182/1198] dtc: Reinstate full old-style reference-to-path for v0 dts files Commit 7c44c2f9cb1cc2df7aacd13decfc4e64b73d1730 broke backwards compatibility more badly than I realised. Contrary to what I thought there are in-kernel, in-use dts files which relied on references-to-path with paths including a comma, which no longer compile after that commit. So, this patch reinstates full support for bare references-to-path in dts-v0 input. This means there will be some rather surprising lexical corner cases when using path-expanded references in v0 files. But, since path-expanded references are new, v0 files shouldn't typically be using them anyway. If the corner cases cause a problem, you can always convert to dts-v1 which handles the lexical issues here more nicely. Signed-off-by: David Gibson --- dtc-lexer.l | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 3c4b798..c811b22 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -27,7 +27,6 @@ PROPNODECHAR [a-zA-Z0-9,._+*#?@-] PATHCHAR ({PROPNODECHAR}|[/]) -LEGACYPATHCHAR [a-zA-Z0-9_@/] LABEL [a-zA-Z_][a-zA-Z0-9_]* %{ @@ -158,7 +157,7 @@ static int dts_version; /* = 0 */ return DT_REF; } -"&/"{LEGACYPATHCHAR}+ { /* old-style path reference */ +"&/"{PATHCHAR}+ { /* old-style path reference */ yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Ref: %s\n", yytext+1); From 0d9d10184b03e352da144fb7e640016bf98fd615 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 7 Dec 2007 15:37:45 +1100 Subject: [PATCH 0183/1198] dtc: Make dtc-checfails.sh script catch deaths-by-signal Since commit 5ba0086bfd0fa6ab25f7ce1870417301a26c104f, the dtc-checkfails.sh script does not check the return code from dtc. That's reasonable, since depending on the checks we're testing, dtc could either complete succesfully or return an error. However, it's never right for dtc to SEGV or otherwise be killed by a signal. So the script should catch that, and fail the testcase if it happens. This patch implements this behaviour. Signed-off-by: David Gibson --- tests/dtc-checkfails.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh index cca4119..16a93e8 100755 --- a/tests/dtc-checkfails.sh +++ b/tests/dtc-checkfails.sh @@ -17,6 +17,10 @@ rm -f $TMPFILE $LOG verbose_run_log "$LOG" "$DTC" -o /dev/null "$@" ret="$?" +if [ "$ret" -gt 127 ]; then + FAIL "dtc killed by signal (ret=$ret)" +fi + for c in $CHECKS; do if ! grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then FAIL "Failed to trigger check \"%c\"" From b7c5eaf3ee93330883ed69c1aae362d039ce5dda Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 7 Dec 2007 18:08:03 +1100 Subject: [PATCH 0184/1198] dtc: Allow gcc format warnings for check_msg() check_msg() takes printf() like arguments, so tell gcc to produce printf() like warnings for it. Signed-off-by: David Gibson --- checks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/checks.c b/checks.c index 6325ee9..2ce961c 100644 --- a/checks.c +++ b/checks.c @@ -87,6 +87,9 @@ struct check { #define BATCH_CHECK(nm, lvl, ...) \ CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__) +#ifdef __GNUC__ +static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); +#endif static inline void check_msg(struct check *c, const char *fmt, ...) { va_list ap; From a68cbc09ffa50fa1d0a3fbea531afefcbd20baae Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 7 Dec 2007 18:08:20 +1100 Subject: [PATCH 0185/1198] dtc: Fix silly typo in dtc-checkfails.sh Too much C coding makes for dumb errors in shell. Signed-off-by: David Gibson --- tests/dtc-checkfails.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh index 16a93e8..23e1ba0 100755 --- a/tests/dtc-checkfails.sh +++ b/tests/dtc-checkfails.sh @@ -23,7 +23,7 @@ fi for c in $CHECKS; do if ! grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then - FAIL "Failed to trigger check \"%c\"" + FAIL "Failed to trigger check \"$c\"" fi done From f819a4e21dddf3a1c43c94a1c68f08c10b81b275 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 17 Dec 2007 14:41:52 +1100 Subject: [PATCH 0186/1198] libfdt: Add more documentation (patch the sixth) This patch adds some more documenting comments to libfdt.h. Specifically this documents all the write-in-place functions. Signed-off-by: David Gibson --- libfdt/libfdt.h | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 6b2fb92..b4bed61 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -655,8 +655,65 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, /* Write-in-place functions */ /**********************************************************************/ +/** + * fdt_setprop_inplace - change a property's value, but not its size + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: pointer to data to replace the property value with + * @len: length of the property value + * + * fdt_setprop_inplace() replaces the value of a given property with + * the data in val, of length len. This function cannot change the + * size of a property, and so will only work if len is equal to the + * current length of the property. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if len is not equal to the property's current length + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len); + +/** + * fdt_setprop_inplace_cell - change the value of a single-cell 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: cell (32-bit integer) value to replace the property with + * + * fdt_setprop_inplace_cell() replaces the value of a given property + * with the 32-bit integer cell value in val, converting val to + * big-endian if necessary. This function cannot change the size of a + * property, and so will only work if the property already exists and + * has length 4. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, const char *name, uint32_t val) { @@ -664,7 +721,54 @@ static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); } +/** + * fdt_nop_property - replace a property with nop tags + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to nop + * @name: name of the property to nop + * + * fdt_nop_property() will replace a given property's representation + * in the blob with FDT_NOP tags, effectively removing it from the + * tree. + * + * This function will alter only the bytes in the blob which contain + * the property, and will not alter or move any other part of the + * tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ int fdt_nop_property(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_nop_node - replace a node (subtree) with nop tags + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to nop + * + * fdt_nop_node() will replace a given node's representation in the + * blob, including all its subnodes, if any, with FDT_NOP tags, + * effectively removing it from the tree. + * + * This function will alter only the bytes in the blob which contain + * the node and its properties and subnodes, and will not alter or + * move any other part of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ int fdt_nop_node(void *fdt, int nodeoffset); /**********************************************************************/ From 30f7fbfbe9f6f9546f641c80a35acb01e45914b3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 17 Dec 2007 14:42:07 +1100 Subject: [PATCH 0187/1198] libfdt: Add more documentation (patch the seventh) This patch adds more documenting comments to libfdt.h. Specifically, these document the read/write functions (not including fdt_open_into() and fdt_pack(), for now). Signed-off-by: David Gibson --- libfdt/libfdt.h | 219 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index b4bed61..ac0f5c3 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -797,23 +797,242 @@ int fdt_finish(void *fdt); int fdt_open_into(const void *fdt, void *buf, int bufsize); int fdt_pack(void *fdt); +/** + * fdt_add_mem_rsv - add one memory reserve map entry + * @fdt: pointer to the device tree blob + * @addres, @size: 64-bit values (native endian) + * + * Adds a reserve map entry to the given blob reserving a region at + * address address of length size. + * + * This function will insert data into the reserve map and will + * therfore change the indexes of some entries in the table. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new reservation entry + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); + +/** + * fdt_del_mem_rsv - remove a memory reserve map entry + * @fdt: pointer to the device tree blob + * @n: entry to remove + * + * fdt_del_mem_rsv() removes the n-th memory reserve map entry from + * the blob. + * + * This function will delete data from the reservation table and will + * therfore change the indexes of some entries in the table. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there + * are less than n+1 reserve map entries) + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ int fdt_del_mem_rsv(void *fdt, int n); +/** + * fdt_setprop - 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 + * @val: pointer to data to set the property value to + * @len: length of the property value + * + * fdt_setprop() sets the value of the named property in the given + * node to the given value and length, creeating 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(void *fdt, int nodeoffset, const char *name, const void *val, int len); + +/** + * 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) + * + * fdt_setprop_cell() sets the value of the named property in the + * given node to the given cell value (converting to big-endian if + * necessary), 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 + */ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, uint32_t val) { val = cpu_to_fdt32(val); return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); } + +/** + * fdt_setprop_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 + * @str: string value for the property + * + * fdt_setprop_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_string(fdt, nodeoffset, name, str) \ fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + +/** + * fdt_delprop - delete a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to nop + * @name: name of the property to nop + * + * fdt_del_property() will delete the given property. + * + * This function will delete data from the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, node does not have the named property + * -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_TRUNCATED, standard meanings + */ 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 + * @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 + * creating subnodes based on a portion of a larger string, such as a + * full path. + */ int fdt_add_subnode_namelen(void *fdt, int parentoffset, const char *name, int namelen); + +/** + * fdt_add_subnode - creates a new node + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * + * fdt_add_subnode() creates a new node as a subnode of the node at + * structure block offset parentoffset, with the given name (which + * should include the unit address, if any). + * + * 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 + * -FDT_ERR_NOTFOUND, if the requested subnode does not exist + * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag + * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of + * the given name + * -FDT_ERR_NOSPACE, if there is insufficient free space in the + * blob to contain the new node + * -FDT_ERR_NOSPACE + * -FDT_ERR_BADLAYOUT + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ int fdt_add_subnode(void *fdt, int parentoffset, const char *name); + +/** + * fdt_del_node - delete a node (subtree) + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to nop + * + * fdt_del_node() will remove the given node, including all its + * subnodes if any, from the blob. + * + * This function will delete data from the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -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_TRUNCATED, standard meanings + */ int fdt_del_node(void *fdt, int nodeoffset); /**********************************************************************/ From d6f9b62fe1263c8266ba899144f29424e1c7a5b0 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 17 Dec 2007 16:39:39 +1100 Subject: [PATCH 0188/1198] dtc: Don't build tests as part of "all" Currently "make all" for dtc will build (but not run) the testcase binaries. This is a problem for cross compiles, because building the tests will attempt to run the dumptrees utility on the host system, which won't work if it's cross-compiled of course. Although it would be possible to separately build host binaries, there's not a lot of value in doing so since we don't have a facility for cross-executing the testsuite anyway. Therefore, remove the tests from the "all" target. It will still, of course, be build as a prerequisite to "make check" which will run the testsuite. Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bcb143f..6e07862 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ else DEPTARGETS = $(filter-out $(NODEPTARGETS),$(MAKECMDGOALS)) endif -all: dtc ftdump libfdt tests +all: dtc ftdump libfdt install: all @$(VECHO) INSTALL From 376ab6f2ed5aac107ef197ff2ec401bf2a8239bd Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 18 Dec 2007 14:54:38 +1100 Subject: [PATCH 0189/1198] dtc: Remove remaining old-style checks The remaining old-style tree checking code: check_root(), check_cpus() and check_memory() really aren't that useful. They mostly check for the presence of particular nodes and properties. That's inherently prone to false-positives, because we could be dealing with an artificial tree (like many of the testcases) or it could be expected that the missing properties are filled in by a bootloader or other agent. If any of these checks really turns out to be useful, we can reimplement them later in a better conceived way on top of the new checking infrastructure. For now, just get rid of them, removing the last vestiges of the old-style checking code (hoorah). Signed-off-by: David Gibson --- checks.c | 215 +------------------------------------------------------ dtc.c | 2 +- dtc.h | 3 +- 3 files changed, 3 insertions(+), 217 deletions(-) diff --git a/checks.c b/checks.c index 2ce961c..8c00c56 100644 --- a/checks.c +++ b/checks.c @@ -511,10 +511,7 @@ static struct check *check_table[] = { &obsolete_chosen_interrupt_controller, }; -int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys); - -void process_checks(int force, struct boot_info *bi, - int checkflag, int outversion, int boot_cpuid_phys) +void process_checks(int force, struct boot_info *bi) { struct node *dt = bi->dt; int i; @@ -537,214 +534,4 @@ void process_checks(int force, struct boot_info *bi, "output forced\n"); } } - - if (checkflag) { - if (error) { - fprintf(stderr, "Warning: Skipping semantic checks due to structural errors\n"); - } else { - if (!check_semantics(bi->dt, outversion, - boot_cpuid_phys)) - fprintf(stderr, "Warning: Input tree has semantic errors\n"); - } - } -} - -/* - * Semantic check functions - */ - -#define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__) -#define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__) - -#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0) - -#define CHECK_HAVE(node, propname) \ - do { \ - if (! (prop = get_property((node), (propname)))) \ - DO_ERR("Missing \"%s\" property in %s\n", (propname), \ - (node)->fullpath); \ - } while (0); - -#define CHECK_HAVE_WARN(node, propname) \ - do { \ - if (! (prop = get_property((node), (propname)))) \ - WARNMSG("%s has no \"%s\" property\n", \ - (node)->fullpath, (propname)); \ - } while (0) - -#define CHECK_HAVE_STRING(node, propname) \ - do { \ - CHECK_HAVE((node), (propname)); \ - if (prop && !data_is_one_string(prop->val)) \ - DO_ERR("\"%s\" property in %s is not a string\n", \ - (propname), (node)->fullpath); \ - } while (0) - -#define CHECK_HAVE_STREQ(node, propname, value) \ - do { \ - CHECK_HAVE_STRING((node), (propname)); \ - if (prop && !streq(prop->val.val, (value))) \ - DO_ERR("%s has wrong %s, %s (should be %s\n", \ - (node)->fullpath, (propname), \ - prop->val.val, (value)); \ - } while (0) - -#define CHECK_HAVE_ONECELL(node, propname) \ - do { \ - CHECK_HAVE((node), (propname)); \ - if (prop && (prop->val.len != sizeof(cell_t))) \ - DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \ - } while (0) - -#define CHECK_HAVE_WARN_ONECELL(node, propname) \ - do { \ - CHECK_HAVE_WARN((node), (propname)); \ - if (prop && (prop->val.len != sizeof(cell_t))) \ - DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \ - } while (0) - -#define CHECK_HAVE_WARN_PHANDLE(xnode, propname, root) \ - do { \ - struct node *ref; \ - CHECK_HAVE_WARN_ONECELL((xnode), (propname)); \ - if (prop) {\ - cell_t phandle = propval_cell(prop); \ - if ((phandle == 0) || (phandle == -1)) { \ - DO_ERR("\"%s\" property in %s contains an invalid phandle %x\n", (propname), (xnode)->fullpath, phandle); \ - } else { \ - ref = get_node_by_phandle((root), propval_cell(prop)); \ - if (! ref) \ - DO_ERR("\"%s\" property in %s refers to non-existant phandle %x\n", (propname), (xnode)->fullpath, propval_cell(prop)); \ - } \ - } \ - } while (0) - -#define CHECK_HAVE_WARN_STRING(node, propname) \ - do { \ - CHECK_HAVE_WARN((node), (propname)); \ - if (prop && !data_is_one_string(prop->val)) \ - DO_ERR("\"%s\" property in %s is not a string\n", \ - (propname), (node)->fullpath); \ - } while (0) - -static int check_root(struct node *root) -{ - struct property *prop; - int ok = 1; - - CHECK_HAVE_STRING(root, "model"); - CHECK_HAVE_WARN(root, "compatible"); - - return ok; -} - -static int check_cpus(struct node *root, int outversion, int boot_cpuid_phys) -{ - struct node *cpus, *cpu; - struct property *prop; - struct node *bootcpu = NULL; - int ok = 1; - - cpus = get_subnode(root, "cpus"); - if (! cpus) { - ERRMSG("Missing /cpus node\n"); - return 0; - } - - if (cpus->addr_cells != 1) - DO_ERR("%s has bad #address-cells value %d (should be 1)\n", - cpus->fullpath, cpus->addr_cells); - if (cpus->size_cells != 0) - DO_ERR("%s has bad #size-cells value %d (should be 0)\n", - cpus->fullpath, cpus->size_cells); - - for_each_child(cpus, cpu) { - CHECK_HAVE_STREQ(cpu, "device_type", "cpu"); - - CHECK_HAVE_ONECELL(cpu, "reg"); - if (prop) { - cell_t unitnum; - char *eptr; - - unitnum = strtol(get_unitname(cpu), &eptr, 16); - if (*eptr) { - WARNMSG("%s has bad format unit name %s (should be CPU number\n", - cpu->fullpath, get_unitname(cpu)); - } else if (unitnum != propval_cell(prop)) { - WARNMSG("%s unit name \"%s\" does not match \"reg\" property <%x>\n", - cpu->fullpath, get_unitname(cpu), - propval_cell(prop)); - } - } - -/* CHECK_HAVE_ONECELL(cpu, "d-cache-line-size"); */ -/* CHECK_HAVE_ONECELL(cpu, "i-cache-line-size"); */ - CHECK_HAVE_ONECELL(cpu, "d-cache-size"); - CHECK_HAVE_ONECELL(cpu, "i-cache-size"); - - CHECK_HAVE_WARN_ONECELL(cpu, "clock-frequency"); - CHECK_HAVE_WARN_ONECELL(cpu, "timebase-frequency"); - - prop = get_property(cpu, "linux,boot-cpu"); - if (prop) { - if (prop->val.len) - WARNMSG("\"linux,boot-cpu\" property in %s is non-empty\n", - cpu->fullpath); - if (bootcpu) - DO_ERR("Multiple boot cpus (%s and %s)\n", - bootcpu->fullpath, cpu->fullpath); - else - bootcpu = cpu; - } - } - - if (outversion < 2) { - if (! bootcpu) - WARNMSG("No cpu has \"linux,boot-cpu\" property\n"); - } else { - if (bootcpu) - WARNMSG("\"linux,boot-cpu\" property is deprecated in blob version 2 or higher\n"); - if (boot_cpuid_phys == 0xfeedbeef) - WARNMSG("physical boot CPU not set. Use -b option to set\n"); - } - - return ok; -} - -static int check_memory(struct node *root) -{ - struct node *mem; - struct property *prop; - int nnodes = 0; - int ok = 1; - - for_each_child(root, mem) { - if (! strneq(mem->name, "memory", mem->basenamelen)) - continue; - - nnodes++; - - CHECK_HAVE_STREQ(mem, "device_type", "memory"); - CHECK_HAVE(mem, "reg"); - } - - if (nnodes == 0) { - ERRMSG("No memory nodes\n"); - return 0; - } - - return ok; -} - -int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys) -{ - int ok = 1; - - ok = ok && check_root(dt); - ok = ok && check_cpus(dt, outversion, boot_cpuid_phys); - ok = ok && check_memory(dt); - if (! ok) - return 0; - - return 1; } diff --git a/dtc.c b/dtc.c index 01131d7..6295b39 100644 --- a/dtc.c +++ b/dtc.c @@ -204,7 +204,7 @@ int main(int argc, char *argv[]) if (! bi || ! bi->dt) die("Couldn't read input tree\n"); - process_checks(force, bi, check, outversion, boot_cpuid_phys); + process_checks(force, bi); if (streq(outname, "-")) { outf = stdout; diff --git a/dtc.h b/dtc.h index 6528177..9b89689 100644 --- a/dtc.h +++ b/dtc.h @@ -240,8 +240,7 @@ struct boot_info *build_boot_info(struct reserve_info *reservelist, /* Checks */ -void process_checks(int force, struct boot_info *bi, - int checkflag, int outversion, int boot_cpuid_phys); +void process_checks(int force, struct boot_info *bi); /* Flattened trees */ From 08c0be206d5d6b035db11048d19be33216332f2b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 19 Dec 2007 11:04:33 +1100 Subject: [PATCH 0190/1198] dtc: Add missing copyright notice for dumptrees.c When I released libfdt, I forgot to add a copyright notice to dumptrees.c (probably because the program is so trivial). Apparently the lack causes trouble for Debian, so this patch adds one. I've gone through the git history and double checked that no-one has touched this file except me (and I barely have myself since its initial commit). Signed-off-by: David Gibson --- tests/dumptrees.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/dumptrees.c b/tests/dumptrees.c index 3db0e2b..ef48c0c 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -1,3 +1,24 @@ +/* + * dumptrees - utility for libfdt testing + * + * (C) Copyright David Gibson , IBM Corporation. 2006. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ #include #include #include From 3e516d961a45a2a410a9dc8f61fbdd62641b5ca0 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 19 Dec 2007 16:07:47 +1100 Subject: [PATCH 0191/1198] dtc: Update TODO files This patch makes a bunch of updates to the TODO files for dtc and libfdt, some of them rather overdue. Signed-off-by: David Gibson --- TODO | 10 ++-------- libfdt/TODO | 4 +--- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/TODO b/TODO index 52d480e..a3e7182 100644 --- a/TODO +++ b/TODO @@ -1,14 +1,8 @@ - Bugfixes: * Proper handling of boot cpu information -- Error handling / reporting - * Better categorization of errors into severity levels - * Don't stop checking for later errors because of earlier ones - whenever possible - Generate mem reserve map * linux,reserve-map property * generating reserve entry for device tree itself * generating reserve entries from tce, rtas etc. properties - - -- Testsuite -- Actually number releases, all that kind of jazz +- Expression support +- Macro system diff --git a/libfdt/TODO b/libfdt/TODO index 794d0a6..288437e 100644 --- a/libfdt/TODO +++ b/libfdt/TODO @@ -1,5 +1,3 @@ -- Find node by linux,phandle property - Tree traversal functions - Graft function -- Merge into dtc -- Make fdt_open_into() re-arrange properly +- Complete libfdt.h documenting comments From 3bb78bfd9758ff726ca80df2cb554a2f2df798a3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 3 Jan 2008 15:48:43 +1100 Subject: [PATCH 0192/1198] dtc: Remove header information dumping Currently, when used in -Idtb mode, dtc will dump information about the input blob's header fields to stderr. This is kind of ugly, and can get in the way of dtc's real output. This patch, therefore, removes this. So that there's still a way of getting this information for debugging purposes, it places something similar to the removed code into ftdump, replacing the couple of header fields it currently prints with a complete header dump. Signed-off-by: David Gibson --- flattree.c | 15 --------------- ftdump.c | 32 ++++++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/flattree.c b/flattree.c index a7cfb84..7b6d7fe 100644 --- a/flattree.c +++ b/flattree.c @@ -898,15 +898,6 @@ struct boot_info *dt_from_blob(FILE *f) off_mem_rsvmap = be32_to_cpu(fdt->off_mem_rsvmap); version = be32_to_cpu(fdt->version); - fprintf(stderr, "\tmagic:\t\t\t0x%x\n", magic); - fprintf(stderr, "\ttotalsize:\t\t%d\n", totalsize); - fprintf(stderr, "\toff_dt_struct:\t\t0x%x\n", off_dt); - fprintf(stderr, "\toff_dt_strings:\t\t0x%x\n", off_str); - fprintf(stderr, "\toff_mem_rsvmap:\t\t0x%x\n", off_mem_rsvmap); - fprintf(stderr, "\tversion:\t\t0x%x\n", version ); - fprintf(stderr, "\tlast_comp_version:\t0x%x\n", - be32_to_cpu(fdt->last_comp_version)); - if (off_mem_rsvmap >= totalsize) die("Mem Reserve structure offset exceeds total size\n"); @@ -916,21 +907,15 @@ struct boot_info *dt_from_blob(FILE *f) if (off_str > totalsize) die("String table offset exceeds total size\n"); - if (version >= 2) - fprintf(stderr, "\tboot_cpuid_phys:\t0x%x\n", - be32_to_cpu(fdt->boot_cpuid_phys)); - size_str = -1; if (version >= 3) { size_str = be32_to_cpu(fdt->size_dt_strings); - fprintf(stderr, "\tsize_dt_strings:\t%d\n", size_str); if (off_str+size_str > totalsize) die("String table extends past total size\n"); } if (version >= 17) { size_dt = be32_to_cpu(fdt->size_dt_struct); - fprintf(stderr, "\tsize_dt_struct:\t\t%d\n", size_dt); if (off_dt+size_dt > totalsize) die("Structure block extends past total size\n"); } diff --git a/ftdump.c b/ftdump.c index 53343d7..0cdae81 100644 --- a/ftdump.c +++ b/ftdump.c @@ -81,11 +81,13 @@ static void print_data(const void *data, int len) static void dump_blob(void *blob) { struct fdt_header *bph = blob; + uint32_t off_mem_rsvmap = be32_to_cpu(bph->off_mem_rsvmap); + uint32_t off_dt = be32_to_cpu(bph->off_dt_struct); + uint32_t off_str = be32_to_cpu(bph->off_dt_strings); struct fdt_reserve_entry *p_rsvmap = - (struct fdt_reserve_entry *)(blob - + be32_to_cpu(bph->off_mem_rsvmap)); - char *p_struct = blob + be32_to_cpu(bph->off_dt_struct); - char *p_strings = blob + be32_to_cpu(bph->off_dt_strings); + (struct fdt_reserve_entry *)(blob + off_mem_rsvmap); + char *p_struct = blob + off_dt; + char *p_strings = blob + off_str; uint32_t version = be32_to_cpu(bph->version); uint32_t totalsize = be32_to_cpu(bph->totalsize); uint32_t tag; @@ -98,8 +100,26 @@ static void dump_blob(void *blob) depth = 0; shift = 4; - printf("// Version 0x%x tree\n", version); - printf("// Totalsize 0x%x(%d)\n", totalsize, totalsize); + printf("// magic:\t\t0x%x\n", be32_to_cpu(bph->magic)); + printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize); + printf("// off_dt_struct:\t0x%x\n", off_dt); + printf("// off_dt_strings:\t0x%x\n", off_str); + printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap); + printf("// version:\t\t%d\n", version); + printf("// last_comp_version:\t%d\n", + be32_to_cpu(bph->last_comp_version)); + if (version >= 2) + printf("// boot_cpuid_phys:\t0x%x\n", + be32_to_cpu(bph->boot_cpuid_phys)); + + if (version >= 3) + printf("// size_dt_strings:\t0x%x\n", + be32_to_cpu(bph->size_dt_strings)); + if (version >= 17) + printf("// size_dt_struct:\t0x%x\n", + be32_to_cpu(bph->size_dt_struct)); + printf("\n"); + for (i = 0; ; i++) { addr = be64_to_cpu(p_rsvmap[i].address); size = be64_to_cpu(p_rsvmap[i].size); From f77fe6a20e75a2289faf86f9b6b529044a07b072 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Thu, 3 Jan 2008 17:43:29 -0600 Subject: [PATCH 0193/1198] Add yyerrorf() for formatted error messages. Signed-off-by: Scott Wood --- dtc-parser.y | 16 +++++++++++++--- srcpos.h | 1 + treesource.c | 1 - 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 002ea7f..ddb7f27 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -307,15 +307,25 @@ label: %% -void yyerror (char const *s) +void yyerrorf(char const *s, ...) { const char *fname = srcpos_filename_for_num(yylloc.filenum); + va_list va; + va_start(va, s); if (strcmp(fname, "-") == 0) fname = "stdin"; - fprintf(stderr, "%s:%d %s\n", - fname, yylloc.first_line, s); + fprintf(stderr, "%s:%d ", fname, yylloc.first_line); + vfprintf(stderr, s, va); + fprintf(stderr, "\n"); + + va_end(va); +} + +void yyerror (char const *s) +{ + yyerrorf("%s", s); } unsigned long long eval_literal(const char *s, int base, int bits) diff --git a/srcpos.h b/srcpos.h index ce7ab5b..e59c788 100644 --- a/srcpos.h +++ b/srcpos.h @@ -63,6 +63,7 @@ typedef struct YYLTYPE { extern void yyerror(char const *); +extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2))); extern int srcpos_filenum; diff --git a/treesource.c b/treesource.c index a6a7767..e7d580f 100644 --- a/treesource.c +++ b/treesource.c @@ -23,7 +23,6 @@ extern FILE *yyin; extern int yyparse(void); -extern void yyerror(char const *); struct boot_info *the_boot_info; From 910efac4b49f43cb1b66eef5aa0bbd020920bf2a Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Thu, 3 Jan 2008 17:43:31 -0600 Subject: [PATCH 0194/1198] Look for include files in the directory of the including file. Looking in the diretory dtc is invoked from is not very useful behavior. As part of the code reorganization to implement this, I removed the uniquifying of name storage -- it seemed a rather dubious optimization given likely usage, and some aspects of it would have been mildly awkward to integrate with the new code. Signed-off-by: Scott Wood --- dtc-lexer.l | 64 ++++++++++++++----------- dtc-parser.y | 2 +- dtc.c | 14 ++++-- srcpos.c | 130 +++++++++++++++++++++++++++------------------------ srcpos.h | 28 +++++++---- 5 files changed, 136 insertions(+), 102 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index c811b22..bfb996e 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -74,7 +74,7 @@ static int dts_version; /* = 0 */ } <*>\"([^\\"]|\\.)*\" { - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("String: %s\n", yytext); yylval.data = data_copy_escape_string(yytext+1, @@ -84,7 +84,7 @@ static int dts_version; /* = 0 */ } <*>"/dts-v1/" { - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("Keyword: /dts-v1/\n"); dts_version = 1; @@ -93,7 +93,7 @@ static int dts_version; /* = 0 */ } <*>"/memreserve/" { - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("Keyword: /memreserve/\n"); BEGIN_DEFAULT(); @@ -101,7 +101,7 @@ static int dts_version; /* = 0 */ } <*>{LABEL}: { - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("Label: %s\n", yytext); yylval.labelref = strdup(yytext); @@ -110,7 +110,7 @@ static int dts_version; /* = 0 */ } [bodh]# { - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; if (*yytext == 'b') yylval.cbase = 2; @@ -125,7 +125,7 @@ static int dts_version; /* = 0 */ } [0-9a-fA-F]+ { - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; yylval.literal = strdup(yytext); DPRINT("Literal: '%s'\n", yylval.literal); @@ -133,7 +133,7 @@ static int dts_version; /* = 0 */ } [0-9]+|0[xX][0-9a-fA-F]+ { - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; yylval.literal = strdup(yytext); DPRINT("Literal: '%s'\n", yylval.literal); @@ -141,7 +141,7 @@ static int dts_version; /* = 0 */ } \&{LABEL} { /* label reference */ - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("Ref: %s\n", yytext+1); yylval.labelref = strdup(yytext+1); @@ -149,7 +149,7 @@ static int dts_version; /* = 0 */ } "&{/"{PATHCHAR}+\} { /* new-style path reference */ - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; yytext[yyleng-1] = '\0'; DPRINT("Ref: %s\n", yytext+2); @@ -158,7 +158,7 @@ static int dts_version; /* = 0 */ } "&/"{PATHCHAR}+ { /* old-style path reference */ - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("Ref: %s\n", yytext+1); yylval.labelref = strdup(yytext+1); @@ -166,7 +166,7 @@ static int dts_version; /* = 0 */ } [0-9a-fA-F]{2} { - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; yylval.byte = strtol(yytext, NULL, 16); DPRINT("Byte: %02x\n", (int)yylval.byte); @@ -174,7 +174,7 @@ static int dts_version; /* = 0 */ } "]" { - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("/BYTESTRING\n"); BEGIN_DEFAULT(); @@ -182,7 +182,7 @@ static int dts_version; /* = 0 */ } {PROPNODECHAR}+ { - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("PropNodeName: %s\n", yytext); yylval.propnodename = strdup(yytext); @@ -190,11 +190,10 @@ static int dts_version; /* = 0 */ return DT_PROPNODENAME; } - <*>[[:space:]]+ /* eat whitespace */ <*>"/*"([^*]|\*+[^*/])*\*+"/" { - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("Comment: %s\n", yytext); /* eat comments */ @@ -203,7 +202,7 @@ static int dts_version; /* = 0 */ <*>"//".*\n /* eat line comments */ <*>. { - yylloc.filenum = srcpos_filenum; + yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("Char: %c (\\x%02x)\n", yytext[0], (unsigned)yytext[0]); @@ -227,8 +226,7 @@ static int dts_version; /* = 0 */ */ struct incl_file { - int filenum; - FILE *file; + struct dtc_file *file; YY_BUFFER_STATE yy_prev_buf; int yy_prev_lineno; struct incl_file *prev; @@ -247,8 +245,9 @@ static int incl_depth = 0; int push_input_file(const char *filename) { - FILE *f; struct incl_file *incl_file; + struct dtc_file *newfile; + struct search_path search, *searchptr = NULL; if (!filename) { yyerror("No include file name given."); @@ -260,7 +259,19 @@ int push_input_file(const char *filename) return 0; } - f = dtc_open_file(filename); + if (srcpos_file) { + search.dir = srcpos_file->dir; + search.next = NULL; + search.prev = NULL; + searchptr = &search; + } + + newfile = dtc_open_file(filename, searchptr); + if (!newfile) { + yyerrorf("Couldn't open \"%s\": %s", + filename, strerror(errno)); + exit(1); + } incl_file = malloc(sizeof(struct incl_file)); if (!incl_file) { @@ -273,8 +284,7 @@ int push_input_file(const char *filename) */ incl_file->yy_prev_buf = YY_CURRENT_BUFFER; incl_file->yy_prev_lineno = yylineno; - incl_file->filenum = srcpos_filenum; - incl_file->file = yyin; + incl_file->file = srcpos_file; incl_file->prev = incl_file_stack; incl_file_stack = incl_file; @@ -282,9 +292,9 @@ int push_input_file(const char *filename) /* * Establish new context. */ - srcpos_filenum = lookup_file_name(filename, 0); + srcpos_file = newfile; yylineno = 1; - yyin = f; + yyin = newfile->file; yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); return 1; @@ -298,7 +308,7 @@ int pop_input_file(void) if (incl_file_stack == 0) return 0; - fclose(yyin); + dtc_close_file(srcpos_file); /* * Pop. @@ -313,8 +323,8 @@ int pop_input_file(void) yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer(incl_file->yy_prev_buf); yylineno = incl_file->yy_prev_lineno; - srcpos_filenum = incl_file->filenum; - yyin = incl_file->file; + srcpos_file = incl_file->file; + yyin = incl_file->file ? incl_file->file->file : NULL; /* * Free old state. diff --git a/dtc-parser.y b/dtc-parser.y index ddb7f27..8ed58e8 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -309,7 +309,7 @@ label: void yyerrorf(char const *s, ...) { - const char *fname = srcpos_filename_for_num(yylloc.filenum); + const char *fname = srcpos_file ? srcpos_file->name : ""; va_list va; va_start(va, s); diff --git a/dtc.c b/dtc.c index 6295b39..fb716f3 100644 --- a/dtc.c +++ b/dtc.c @@ -118,7 +118,7 @@ int main(int argc, char *argv[]) int force = 0, check = 0; const char *arg; int opt; - FILE *inf = NULL; + struct dtc_file *inf = NULL; FILE *outf = NULL; int outversion = DEFAULT_FDT_VERSION; int boot_cpuid_phys = 0xfeedbeef; @@ -192,14 +192,18 @@ int main(int argc, char *argv[]) } else if (streq(inform, "fs")) { bi = dt_from_fs(arg); } else if(streq(inform, "dtb")) { - inf = dtc_open_file(arg); - bi = dt_from_blob(inf); + inf = dtc_open_file(arg, NULL); + if (!inf) + die("Couldn't open \"%s\": %s\n", arg, + strerror(errno)); + + bi = dt_from_blob(inf->file); } else { die("Unknown input format \"%s\"\n", inform); } - if (inf && (inf != stdin)) - fclose(inf); + if (inf && inf->file != stdin) + fclose(inf->file); if (! bi || ! bi->dt) die("Couldn't read input tree\n"); diff --git a/srcpos.c b/srcpos.c index 352b0fe..7340c33 100644 --- a/srcpos.c +++ b/srcpos.c @@ -20,86 +20,94 @@ #include "dtc.h" #include "srcpos.h" - -/* - * Record the complete unique set of opened file names. - * Primarily used to cache source position file names. - */ -#define MAX_N_FILE_NAMES (100) - -const char *file_names[MAX_N_FILE_NAMES]; -static int n_file_names = 0; - /* * Like yylineno, this is the current open file pos. */ -int srcpos_filenum = -1; +struct dtc_file *srcpos_file; - - -FILE *dtc_open_file(const char *fname) +static int dtc_open_one(struct dtc_file *file, + const char *search, + const char *fname) { - FILE *f; + char *fullname; - if (lookup_file_name(fname, 1) < 0) - die("Too many files opened\n"); + if (search) { + fullname = malloc(strlen(search) + strlen(fname) + 2); + if (!fullname) + die("Out of memory\n"); - if (streq(fname, "-")) - f = stdin; - else - f = fopen(fname, "r"); - - if (! f) - die("Couldn't open \"%s\": %s\n", fname, strerror(errno)); - - return f; -} - - - -/* - * Locate and optionally add filename fname in the file_names[] array. - * - * If the filename is currently not in the array and the boolean - * add_it is non-zero, an attempt to add the filename will be made. - * - * Returns; - * Index [0..MAX_N_FILE_NAMES) where the filename is kept - * -1 if the name can not be recorded - */ - -int lookup_file_name(const char *fname, int add_it) -{ - int i; - - for (i = 0; i < n_file_names; i++) { - if (strcmp(file_names[i], fname) == 0) - return i; + strcpy(fullname, search); + strcat(fullname, "/"); + strcat(fullname, fname); + } else { + fullname = strdup(fname); } - if (add_it) { - if (n_file_names < MAX_N_FILE_NAMES) { - file_names[n_file_names] = strdup(fname); - return n_file_names++; - } + file->file = fopen(fullname, "r"); + if (!file->file) { + free(fullname); + return 0; } - return -1; + file->name = fullname; + return 1; } -const char *srcpos_filename_for_num(int filenum) +struct dtc_file *dtc_open_file(const char *fname, + const struct search_path *search) { - if (0 <= filenum && filenum < n_file_names) { - return file_names[filenum]; + static const struct search_path default_search = { NULL, NULL, NULL }; + + struct dtc_file *file; + const char *slash; + + file = malloc(sizeof(struct dtc_file)); + if (!file) + die("Out of memory\n"); + + slash = strrchr(fname, '/'); + if (slash) { + char *dir = malloc(slash - fname + 1); + if (!dir) + die("Out of memory\n"); + + memcpy(dir, fname, slash - fname); + dir[slash - fname] = 0; + file->dir = dir; + } else { + file->dir = NULL; } - return 0; + if (streq(fname, "-")) { + file->name = "stdin"; + file->file = stdin; + return file; + } + + if (!search) + search = &default_search; + + while (search) { + if (dtc_open_one(file, search->dir, fname)) + return file; + + if (errno != ENOENT) + goto out; + + search = search->next; + } + +out: + free(file); + return NULL; } - -const char *srcpos_get_filename(void) +void dtc_close_file(struct dtc_file *file) { - return srcpos_filename_for_num(srcpos_filenum); + if (fclose(file->file)) + die("Error closing \"%s\": %s\n", file->name, strerror(errno)); + + free(file); } diff --git a/srcpos.h b/srcpos.h index e59c788..8108539 100644 --- a/srcpos.h +++ b/srcpos.h @@ -22,13 +22,21 @@ * array of all opened filenames. */ +#include + +struct dtc_file { + const char *dir; + const char *name; + FILE *file; +}; + #if ! defined(YYLTYPE) && ! defined(YYLTYPE_IS_DECLARED) typedef struct YYLTYPE { int first_line; int first_column; int last_line; int last_column; - int filenum; + struct dtc_file *file; } YYLTYPE; #define YYLTYPE_IS_DECLARED 1 @@ -48,7 +56,7 @@ typedef struct YYLTYPE { (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - (Current).filenum = YYRHSLOC (Rhs, N).filenum; \ + (Current).file = YYRHSLOC (Rhs, N).file; \ } \ else \ { \ @@ -56,7 +64,7 @@ typedef struct YYLTYPE { YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ - (Current).filenum = YYRHSLOC (Rhs, 0).filenum; \ + (Current).file = YYRHSLOC (Rhs, 0).file; \ } \ while (YYID (0)) @@ -65,12 +73,16 @@ typedef struct YYLTYPE { extern void yyerror(char const *); extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2))); -extern int srcpos_filenum; +extern struct dtc_file *srcpos_file; extern int push_input_file(const char *filename); extern int pop_input_file(void); -extern FILE *dtc_open_file(const char *fname); -extern int lookup_file_name(const char *fname, int add_it); -extern const char *srcpos_filename_for_num(int filenum); -const char *srcpos_get_filename(void); +struct search_path { + const char *dir; /* NULL for current directory */ + struct search_path *prev, *next; +}; + +extern struct dtc_file *dtc_open_file(const char *fname, + const struct search_path *search); +extern void dtc_close_file(struct dtc_file *file); From ad4f54ae2b67ddcd4d128fd4b5c21c66a640d237 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Thu, 3 Jan 2008 17:43:33 -0600 Subject: [PATCH 0195/1198] Return a non-zero exit code if an error occurs during dts parsing. Previously, only failure to parse caused the reading of the tree to fail; semantic errors that called yyerror() but not YYERROR only emitted a message, without signalling make to stop the build. Signed-off-by: Scott Wood --- dtc-parser.y | 2 ++ dtc.c | 2 +- dtc.h | 1 + livetree.c | 1 + treesource.c | 3 +++ 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/dtc-parser.y b/dtc-parser.y index 8ed58e8..da7f6f5 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -28,6 +28,7 @@ int yylex(void); unsigned long long eval_literal(const char *s, int base, int bits); extern struct boot_info *the_boot_info; +extern int treesource_error; %} @@ -320,6 +321,7 @@ void yyerrorf(char const *s, ...) vfprintf(stderr, s, va); fprintf(stderr, "\n"); + treesource_error = 1; va_end(va); } diff --git a/dtc.c b/dtc.c index fb716f3..c1814c1 100644 --- a/dtc.c +++ b/dtc.c @@ -205,7 +205,7 @@ int main(int argc, char *argv[]) if (inf && inf->file != stdin) fclose(inf->file); - if (! bi || ! bi->dt) + if (! bi || ! bi->dt || bi->error) die("Couldn't read input tree\n"); process_checks(force, bi); diff --git a/dtc.h b/dtc.h index 9b89689..cba9d28 100644 --- a/dtc.h +++ b/dtc.h @@ -233,6 +233,7 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list, struct boot_info { struct reserve_info *reservelist; struct node *dt; /* the device tree */ + int error; }; struct boot_info *build_boot_info(struct reserve_info *reservelist, diff --git a/livetree.c b/livetree.c index 6ba0846..7610e78 100644 --- a/livetree.c +++ b/livetree.c @@ -172,6 +172,7 @@ struct boot_info *build_boot_info(struct reserve_info *reservelist, bi = xmalloc(sizeof(*bi)); bi->reservelist = reservelist; bi->dt = tree; + bi->error = 0; return bi; } diff --git a/treesource.c b/treesource.c index e7d580f..980bda7 100644 --- a/treesource.c +++ b/treesource.c @@ -25,10 +25,12 @@ extern FILE *yyin; extern int yyparse(void); struct boot_info *the_boot_info; +int treesource_error; struct boot_info *dt_from_source(const char *fname) { the_boot_info = NULL; + treesource_error = 0; push_input_file(fname); @@ -37,6 +39,7 @@ struct boot_info *dt_from_source(const char *fname) fill_fullpaths(the_boot_info->dt, ""); + the_boot_info->error = treesource_error; return the_boot_info; } From 7d24bd0a725264495edb679477d14a87145bbbf8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 4 Jan 2008 13:43:24 +1100 Subject: [PATCH 0196/1198] dtc/libfdt: Add README clarifying licensing The fact that the dtc and libfdt are distributed together, but have different licenses, can be a bit confusing. Several people have enquired as to what the deal is with the libfdt licensing, so this patch adds a README clarifying the situation with a rationale. Signed-off-by: David Gibson Signed-off-by: Jon Loeliger --- README.license | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 README.license diff --git a/README.license b/README.license new file mode 100644 index 0000000..d56c88f --- /dev/null +++ b/README.license @@ -0,0 +1,56 @@ +Licensing and contribution policy of dtc and libfdt +=================================================== + +This dtc package contains two pieces of software: dtc itself, and +libfdt which comprises the files in the libfdt/ subdirectory. These +two pieces of software, although closely related, are quite distinct. +dtc does not incoporate or rely on libfdt for its operation, nor vice +versa. It is important that these two pieces of software have +different license conditions. + +As the copyright banners in each source file attest, dtc is licensed +under the GNU GPL. The full text of the GPL can be found in the file +entitled 'GPL' which should be included in this package. dtc code, +therefore, may not be incorporated into works which do not have a GPL +compatible license. + +libfdt, however, is GPL/BSD dual-licensed. That is, it may be used +either under the terms of the GPL, or under the terms of the 2-clause +BSD license (aka the ISC license). The full terms of that license are +given in the copyright banners of each of the libfdt source files. +This is, in practice, equivalent to being BSD licensed, since the +terms of the BSD license are strictly more permissive than the GPL. + +I made the decision to license libfdt in this way because I want to +encourage widespread and correct usage of flattened device trees, +including by proprietary or otherwise GPL-incompatible firmware or +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 +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 +rocket science; so the incentive for such impolite behaviour is small, +and the inconvenience caused therby is not dire. + +Licenses such as the LGPL which would allow code to be used in non-GPL +software, but also require contributions to be returned were +considered. However, libfdt is designed to be used in firmwares and +other environments with unusual technical constraints. It's difficult +to anticipate all possible changes which might be needed to meld +libfdt into such environments and so difficult to suitably word a +license that puts the boundary between what is and isn't permitted in +the intended place. Again, I judged encouraging widespread use of +libfdt by keeping the license terms simple and familiar to be the more +important goal. + +**IMPORTANT** It's intended that all of libfdt as released remain +permissively licensed this way. Therefore only contributions which +are released under these terms can be merged into the libfdt mainline. + + +David Gibson +(principal original author of dtc and libfdt) +2 November 2007 From 5695e99d5f6418f8f5b990bdcb1f153935d0fb06 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Fri, 4 Jan 2008 15:10:45 -0600 Subject: [PATCH 0197/1198] Handle absolute pathnames correctly in dtc_open_file. Also, free file->dir when freeing file. Signed-off-by: Scott Wood --- srcpos.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/srcpos.c b/srcpos.c index 7340c33..7a0c47e 100644 --- a/srcpos.c +++ b/srcpos.c @@ -86,6 +86,16 @@ struct dtc_file *dtc_open_file(const char *fname, return file; } + if (fname[0] == '/') { + file->file = fopen(fname, "r"); + + if (!file->file) + goto out; + + file->name = strdup(fname); + return file; + } + if (!search) search = &default_search; @@ -100,6 +110,7 @@ struct dtc_file *dtc_open_file(const char *fname, } out: + free((void *)file->dir); free(file); return NULL; } @@ -109,5 +120,6 @@ void dtc_close_file(struct dtc_file *file) if (fclose(file->file)) die("Error closing \"%s\": %s\n", file->name, strerror(errno)); + free((void *)file->dir); free(file); } From 3c3ecaacda4f7ef201d02682382a64674661cae3 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Fri, 4 Jan 2008 15:10:47 -0600 Subject: [PATCH 0198/1198] Remove \n from yyerror() call. The \n is provided by yyerror(). Signed-off-by: Scott Wood --- dtc-parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dtc-parser.y b/dtc-parser.y index da7f6f5..bae3c32 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -283,7 +283,7 @@ subnodes: } | subnode propdef { - yyerror("syntax error: properties must precede subnodes\n"); + yyerror("syntax error: properties must precede subnodes"); YYERROR; } ; From 42107f8bba994f718594dd670a937861d40f425d Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 7 Jan 2008 14:27:36 -0600 Subject: [PATCH 0199/1198] Convert malloc() uses to xmalloc(). Signed-off-by: Scott Wood --- dtc-lexer.l | 6 +----- srcpos.c | 12 +++--------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index bfb996e..f2836a8 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -273,11 +273,7 @@ int push_input_file(const char *filename) exit(1); } - incl_file = malloc(sizeof(struct incl_file)); - if (!incl_file) { - yyerror("Can not allocate include file space."); - return 0; - } + incl_file = xmalloc(sizeof(struct incl_file)); /* * Save current context. diff --git a/srcpos.c b/srcpos.c index 7a0c47e..7d0f0a7 100644 --- a/srcpos.c +++ b/srcpos.c @@ -33,9 +33,7 @@ static int dtc_open_one(struct dtc_file *file, char *fullname; if (search) { - fullname = malloc(strlen(search) + strlen(fname) + 2); - if (!fullname) - die("Out of memory\n"); + fullname = xmalloc(strlen(search) + strlen(fname) + 2); strcpy(fullname, search); strcat(fullname, "/"); @@ -63,15 +61,11 @@ struct dtc_file *dtc_open_file(const char *fname, struct dtc_file *file; const char *slash; - file = malloc(sizeof(struct dtc_file)); - if (!file) - die("Out of memory\n"); + file = xmalloc(sizeof(struct dtc_file)); slash = strrchr(fname, '/'); if (slash) { - char *dir = malloc(slash - fname + 1); - if (!dir) - die("Out of memory\n"); + char *dir = xmalloc(slash - fname + 1); memcpy(dir, fname, slash - fname); dir[slash - fname] = 0; From b1a6719aa600e2459ea954c6f92b2090c29c3d90 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 7 Jan 2008 14:27:51 -0600 Subject: [PATCH 0200/1198] Preserve scanner state when /include/ing. This allows /include/s to work when in non-default states, such as PROPNODECHAR. We may want to use state stacks to get rid of BEGIN_DEFAULT() altogether... Signed-off-by: Scott Wood --- dtc-lexer.l | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index f2836a8..920b87f 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -18,7 +18,7 @@ * USA */ -%option noyywrap nounput yylineno +%option noyywrap nounput yylineno stack %x INCLUDE %x BYTESTRING @@ -55,7 +55,7 @@ static int dts_version; /* = 0 */ %} %% -<*>"/include/" BEGIN(INCLUDE); +<*>"/include/" yy_push_state(INCLUDE); \"[^"\n]*\" { yytext[strlen(yytext) - 1] = 0; @@ -63,7 +63,7 @@ static int dts_version; /* = 0 */ /* Some unrecoverable error.*/ exit(1); } - BEGIN_DEFAULT(); + yy_pop_state(); } From 7364cc79b5fa11e416dce01802139bc87d690118 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Thu, 10 Jan 2008 09:09:44 -0600 Subject: [PATCH 0201/1198] Tag Version 1.1.0-rc1 Signed-off-by: Jon Loeliger --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 6e07862..d4705e5 100644 --- a/Makefile +++ b/Makefile @@ -9,9 +9,9 @@ # CONFIG_LOCALVERSION from some future config system. # VERSION = 1 -PATCHLEVEL = 0 +PATCHLEVEL = 1 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION =-rc1 LOCAL_VERSION = CONFIG_LOCALVERSION = From 82b327d38062cdb4e5628856f9b440ad6c96e7f8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 11 Jan 2008 14:55:05 +1100 Subject: [PATCH 0202/1198] libfdt: Add fdt_set_name() function This patch adds an fdt_set_name() function to libfdt, mirroring fdt_get_name(). This is a r/w function which alters the name of a given device tree node. Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 24 ++++++++++++ libfdt/libfdt.h | 26 +++++++++++++ tests/Makefile.tests | 2 +- tests/run_tests.sh | 1 + tests/set_name.c | 91 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 tests/set_name.c diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 6673f8e..a1c70ff 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -252,6 +252,30 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len, return 0; } +int fdt_set_name(void *fdt, int nodeoffset, const char *name) +{ + char *namep; + int oldlen, newlen; + int err; + + if ((err = rw_check_header(fdt))) + return err; + + namep = (char *)fdt_get_name(fdt, nodeoffset, &oldlen); + if (!namep) + return oldlen; + + newlen = strlen(name); + + err = _blob_splice_struct(fdt, namep, ALIGN(oldlen+1, FDT_TAGSIZE), + ALIGN(newlen+1, FDT_TAGSIZE)); + if (err) + return err; + + memcpy(namep, name, newlen+1); + return 0; +} + int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len) { diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index ac0f5c3..d053689 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -845,6 +845,32 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); */ int fdt_del_mem_rsv(void *fdt, int n); +/** + * fdt_set_name - change the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * @name: name to give the node + * + * fdt_set_name() replaces the name (including unit address, if any) + * of the given node with the given string. NOTE: this function can't + * efficiently check if the new name is unique amongst the given + * node's siblings; results are undefined if this function is invoked + * with a name equal to one of the given node's siblings. + * + * 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 name + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_set_name(void *fdt, int nodeoffset, const char *name); + /** * fdt_setprop - create or change a property * @fdt: pointer to the device tree blob diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 8d17b89..0f4d342 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -8,7 +8,7 @@ LIB_TESTS_L = get_mem_rsv \ setprop_inplace nop_property nop_node \ sw_tree1 \ move_and_save mangle-layout \ - open_pack rw_tree1 setprop del_property del_node \ + open_pack rw_tree1 set_name setprop del_property del_node \ string_escapes references path-references \ dtbs_equal_ordered LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 83e8d62..d04bfbe 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -68,6 +68,7 @@ tree1_tests_rw () { TREE=$1 # Read-write tests + run_test set_name $TREE run_test setprop $TREE run_test del_property $TREE run_test del_node $TREE diff --git a/tests/set_name.c b/tests/set_name.c new file mode 100644 index 0000000..49817a9 --- /dev/null +++ b/tests/set_name.c @@ -0,0 +1,91 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_set_name() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void check_set_name(void *fdt, const char *path, const char *newname) +{ + int offset; + const char *getname, *oldname; + int len, err; + + oldname = strrchr(path, '/'); + if (!oldname) + TEST_BUG(); + oldname += 1; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("Couldn't find %s", path); + + getname = fdt_get_name(fdt, offset, &len); + verbose_printf("fdt_get_name(%d) returns \"%s\" (len=%d)\n", + offset, getname, len); + if (!getname) + FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len)); + + if (strcmp(getname, oldname) != 0) + FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"", + path, getname, oldname); + + if (len != strlen(getname)) + FAIL("fdt_get_name(%s) returned length %d instead of %zd", + path, len, strlen(getname)); + + err = fdt_set_name(fdt, offset, newname); + if (err) + FAIL("fdt_set_name(%d, \"%s\"): %s", offset, newname, + fdt_strerror(err)); + + getname = fdt_get_name(fdt, offset, &len); + if (!getname) + FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len)); + + if (strcmp(getname, newname) != 0) + FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"", + path, getname, newname); + + if (len != strlen(getname)) + FAIL("fdt_get_name(%s) returned length %d instead of %zd", + path, len, strlen(getname)); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + fdt = open_blob_rw(fdt); + + 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"); + + PASS(); +} From 0f635df874540ee9ef5bf7137ca2a2d0cc5d807b Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Fri, 11 Jan 2008 13:14:57 -0600 Subject: [PATCH 0203/1198] Remove const from dtc_file::dir. Signed-off-by: Scott Wood --- srcpos.c | 4 ++-- srcpos.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/srcpos.c b/srcpos.c index 7d0f0a7..c8eaa1e 100644 --- a/srcpos.c +++ b/srcpos.c @@ -104,7 +104,7 @@ struct dtc_file *dtc_open_file(const char *fname, } out: - free((void *)file->dir); + free(file->dir); free(file); return NULL; } @@ -114,6 +114,6 @@ void dtc_close_file(struct dtc_file *file) if (fclose(file->file)) die("Error closing \"%s\": %s\n", file->name, strerror(errno)); - free((void *)file->dir); + free(file->dir); free(file); } diff --git a/srcpos.h b/srcpos.h index 8108539..3ed2334 100644 --- a/srcpos.h +++ b/srcpos.h @@ -25,7 +25,7 @@ #include struct dtc_file { - const char *dir; + char *dir; const char *name; FILE *file; }; From 202863e4dd681d17c06a82943f49485bf7860633 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Thu, 24 Jan 2008 10:16:07 -0600 Subject: [PATCH 0204/1198] Tag Version 1.1.0 Signed-off-by: Jon Loeliger --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d4705e5..8a47c34 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ VERSION = 1 PATCHLEVEL = 1 SUBLEVEL = 0 -EXTRAVERSION =-rc1 +EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = From fc9769ac2bae8a32d5d277007d22414c4516b02b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 12 Feb 2008 11:58:31 +1100 Subject: [PATCH 0205/1198] libfdt: Add and use a node iteration helper function. This patch adds an fdt_next_node() function which can be used to iterate through nodes of the tree while keeping track of depth. This function is used to simplify the iteration code in a lot of other functions, and is also exported for use by library users. Signed-off-by: David Gibson --- libfdt/fdt.c | 41 ++++++++ libfdt/fdt_ro.c | 258 ++++++++++++++++-------------------------------- libfdt/libfdt.h | 6 ++ 3 files changed, 131 insertions(+), 174 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 586a361..c61fb53 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -129,6 +129,47 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset) return tag; } +int fdt_next_node(const void *fdt, int offset, int *depth) +{ + int nextoffset = 0; + uint32_t tag; + + if (offset >= 0) { + tag = fdt_next_tag(fdt, offset, &nextoffset); + if (tag != FDT_BEGIN_NODE) + return -FDT_ERR_BADOFFSET; + } + + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_PROP: + case FDT_NOP: + break; + + case FDT_BEGIN_NODE: + if (depth) + (*depth)++; + break; + + case FDT_END_NODE: + if (depth) + (*depth)--; + break; + + case FDT_END: + return -FDT_ERR_NOTFOUND; + + default: + return -FDT_ERR_BADSTRUCTURE; + } + } while (tag != FDT_BEGIN_NODE); + + return offset; +} + const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) { int len = strlen(s) + 1; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 12a37d5..f08941a 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -65,7 +65,7 @@ static int nodename_eq(const void *fdt, int offset, const char *s, int len) { - const char *p = fdt_offset_ptr(fdt, offset, len+1); + const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); if (! p) /* short match */ @@ -104,50 +104,24 @@ int fdt_num_mem_rsv(const void *fdt) return i; } -int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, +int fdt_subnode_offset_namelen(const void *fdt, int offset, const char *name, int namelen) { - int level = 0; - uint32_t tag; - int offset, nextoffset; + int depth; CHECK_HEADER(fdt); - tag = fdt_next_tag(fdt, parentoffset, &nextoffset); - if (tag != FDT_BEGIN_NODE) - return -FDT_ERR_BADOFFSET; + for (depth = 0; + offset >= 0; + offset = fdt_next_node(fdt, offset, &depth)) { + if (depth < 0) + return -FDT_ERR_NOTFOUND; + else if ((depth == 1) + && nodename_eq(fdt, offset, name, namelen)) + return offset; + } - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - - switch (tag) { - case FDT_END: - return -FDT_ERR_TRUNCATED; - - case FDT_BEGIN_NODE: - level++; - if (level != 1) - continue; - if (nodename_eq(fdt, offset+FDT_TAGSIZE, name, namelen)) - /* Found it! */ - return offset; - break; - - case FDT_END_NODE: - level--; - break; - - case FDT_PROP: - case FDT_NOP: - break; - - default: - return -FDT_ERR_BADSTRUCTURE; - } - } while (level >= 0); - - return -FDT_ERR_NOTFOUND; + return offset; /* error */ } int fdt_subnode_offset(const void *fdt, int parentoffset, @@ -307,76 +281,61 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) { - uint32_t tag; - int p = 0, overflow = 0; - int offset, nextoffset, namelen; + int pdepth = 0, p = 0; + int offset, depth, namelen; const char *name; CHECK_HEADER(fdt); - tag = fdt_next_tag(fdt, 0, &nextoffset); - if (tag != FDT_BEGIN_NODE) - return -FDT_ERR_BADSTRUCTURE; - if (buflen < 2) return -FDT_ERR_NOSPACE; - buf[0] = '/'; - p = 1; - while (nextoffset <= nodeoffset) { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - switch (tag) { - case FDT_END: - return -FDT_ERR_BADOFFSET; + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + if (pdepth < depth) + continue; /* overflowed buffer */ - case FDT_BEGIN_NODE: - name = fdt_get_name(fdt, offset, &namelen); - if (!name) - return namelen; - if (overflow || ((p + namelen + 1) > buflen)) { - overflow++; - break; - } + while (pdepth > depth) { + do { + p--; + } while (buf[p-1] != '/'); + pdepth--; + } + + name = fdt_get_name(fdt, offset, &namelen); + if (!name) + return namelen; + if ((p + namelen + 1) <= buflen) { memcpy(buf + p, name, namelen); p += namelen; buf[p++] = '/'; - break; + pdepth++; + } - case FDT_END_NODE: - if (overflow) { - overflow--; - break; - } - do { + if (offset == nodeoffset) { + if (pdepth < (depth + 1)) + return -FDT_ERR_NOSPACE; + + if (p > 1) /* special case so that root path is "/", not "" */ p--; - } while (buf[p-1] != '/'); - break; - - case FDT_PROP: - case FDT_NOP: - break; - - default: - return -FDT_ERR_BADSTRUCTURE; + buf[p] = '\0'; + return p; } } - if (overflow) - return -FDT_ERR_NOSPACE; + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; - if (p > 1) /* special case so that root path is "/", not "" */ - p--; - buf[p] = '\0'; - return p; + return offset; /* error from fdt_next_node() */ } int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int supernodedepth, int *nodedepth) { - int level = -1; - uint32_t tag; - int offset, nextoffset = 0; + int offset, depth; int supernodeoffset = -FDT_ERR_INTERNAL; CHECK_HEADER(fdt); @@ -384,38 +343,29 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, if (supernodedepth < 0) return -FDT_ERR_NOTFOUND; - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - switch (tag) { - case FDT_END: - return -FDT_ERR_BADOFFSET; + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + if (depth == supernodedepth) + supernodeoffset = offset; - case FDT_BEGIN_NODE: - level++; - if (level == supernodedepth) - supernodeoffset = offset; - break; + if (offset == nodeoffset) { + if (nodedepth) + *nodedepth = depth; - case FDT_END_NODE: - level--; - break; - - case FDT_PROP: - case FDT_NOP: - break; - - default: - return -FDT_ERR_BADSTRUCTURE; + if (supernodedepth > depth) + return -FDT_ERR_NOTFOUND; + else + return supernodeoffset; } - } while (offset < nodeoffset); + } - if (nodedepth) - *nodedepth = level; + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; - if (supernodedepth > level) - return -FDT_ERR_NOTFOUND; - return supernodeoffset; + return offset; /* error from fdt_next_node() */ } int fdt_node_depth(const void *fdt, int nodeoffset) @@ -443,51 +393,27 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, const char *propname, const void *propval, int proplen) { - uint32_t tag; - int offset, nextoffset; + int offset; const void *val; int len; CHECK_HEADER(fdt); - if (startoffset >= 0) { - tag = fdt_next_tag(fdt, startoffset, &nextoffset); - if (tag != FDT_BEGIN_NODE) - return -FDT_ERR_BADOFFSET; - } else { - nextoffset = 0; - } - /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_getprop(), then if that didn't * find what we want, we scan over them again making our way * to the next node. Still it's the easiest to implement * approach; performance can come later. */ - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + val = fdt_getprop(fdt, offset, propname, &len); + if (val && (len == proplen) + && (memcmp(val, propval, len) == 0)) + return offset; + } - switch (tag) { - case FDT_BEGIN_NODE: - val = fdt_getprop(fdt, offset, propname, &len); - if (val - && (len == proplen) - && (memcmp(val, propval, len) == 0)) - return offset; - break; - - case FDT_PROP: - case FDT_END: - case FDT_END_NODE: - case FDT_NOP: - break; - - default: - return -FDT_ERR_BADSTRUCTURE; - } - } while (tag != FDT_END); - - return -FDT_ERR_NOTFOUND; + return offset; /* error from fdt_next_node() */ } int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) @@ -553,31 +479,15 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, * that didn't find what we want, we scan over them again * making our way to the next node. Still it's the easiest to * implement approach; performance can come later. */ - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + err = fdt_node_check_compatible(fdt, offset, compatible); + if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) + return err; + else if (err == 0) + return offset; + } - switch (tag) { - case FDT_BEGIN_NODE: - err = fdt_node_check_compatible(fdt, offset, - compatible); - if ((err < 0) - && (err != -FDT_ERR_NOTFOUND)) - return err; - else if (err == 0) - return offset; - break; - - case FDT_PROP: - case FDT_END: - case FDT_END_NODE: - case FDT_NOP: - break; - - default: - return -FDT_ERR_BADSTRUCTURE; - } - } while (tag != FDT_END); - - return -FDT_ERR_NOTFOUND; + return offset; /* error from fdt_next_node() */ } diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index d053689..8645de0 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -130,6 +130,12 @@ 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); +/**********************************************************************/ +/* Traversal functions */ +/**********************************************************************/ + +int fdt_next_node(const void *fdt, int offset, int *depth); + /**********************************************************************/ /* General functions */ /**********************************************************************/ From 089adb9964a222499eb204198b579c231c59c42f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 14 Feb 2008 16:50:34 +1100 Subject: [PATCH 0206/1198] libfdt: Fix NOP handling bug in fdt_add_subnode_namelen() fdt_add_subnode_namelen() has a bug if asked to add a subnode to a node which has NOP tags interspersed with its properties. In this case fdt_add_subnode_namelen() will put the new subnode before the first NOP tag, even if there are properties after it, which will result in an invalid blob. This patch fixes the bug, and adds a testcase for it. Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 2 +- tests/Makefile.tests | 3 +- tests/add_subnode_with_nops.c | 85 +++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 3 ++ 4 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 tests/add_subnode_with_nops.c diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index a1c70ff..ac50195 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -333,7 +333,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, do { offset = nextoffset; tag = fdt_next_tag(fdt, offset, &nextoffset); - } while (tag == FDT_PROP); + } while ((tag == FDT_PROP) || (tag == FDT_NOP)); nh = _fdt_offset_ptr_w(fdt, offset); nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE; diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 0f4d342..15a5ebb 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -10,7 +10,8 @@ LIB_TESTS_L = get_mem_rsv \ move_and_save mangle-layout \ open_pack rw_tree1 set_name setprop del_property del_node \ string_escapes references path-references \ - dtbs_equal_ordered + dtbs_equal_ordered \ + add_subnode_with_nops LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property diff --git a/tests/add_subnode_with_nops.c b/tests/add_subnode_with_nops.c new file mode 100644 index 0000000..4fb8f02 --- /dev/null +++ b/tests/add_subnode_with_nops.c @@ -0,0 +1,85 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_nop_node() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +#define SPACE 65536 + +#define CHECK(code) \ + { \ + err = (code); \ + if (err) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } + +#define OFF_CHECK(off, code) \ + { \ + (off) = (code); \ + if (off < 0) \ + FAIL(#code ": %s", fdt_strerror(off)); \ + } + +int main(int argc, char *argv[]) +{ + void *fdt; + int err; + int offset; + + test_init(argc, argv); + + fdt = xmalloc(SPACE); + + CHECK(fdt_create(fdt, SPACE)); + + CHECK(fdt_finish_reservemap(fdt)); + CHECK(fdt_begin_node(fdt, "")); + CHECK(fdt_property_cell(fdt, "prop1", TEST_VALUE_1)); + CHECK(fdt_property_cell(fdt, "prop2", TEST_VALUE_2)); + CHECK(fdt_end_node(fdt)); + CHECK(fdt_finish(fdt)); + + verbose_printf("Built empty tree, totalsize = %d\n", + fdt_totalsize(fdt)); + + CHECK(fdt_open_into(fdt, fdt, SPACE)); + + check_getprop_cell(fdt, 0, "prop1", TEST_VALUE_1); + check_getprop_cell(fdt, 0, "prop2", TEST_VALUE_2); + + CHECK(fdt_nop_property(fdt, 0, "prop1")); + + check_getprop_cell(fdt, 0, "prop2", TEST_VALUE_2); + + OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode")); + + check_getprop_cell(fdt, 0, "prop2", TEST_VALUE_2); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index d04bfbe..02b1fb0 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -127,6 +127,9 @@ libfdt_tests () { # Tests for behaviour on various sorts of corrupted trees run_test truncated_property + + # Specific bug tests + run_test add_subnode_with_nops } dtc_tests () { From d8b69426662f29f0cdaf67d380a0b366ba420abd Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 15 Feb 2008 15:14:16 +1100 Subject: [PATCH 0207/1198] dtc: Fold comment handling test into testsuite For ages dtc has included a sample dts, comment-test.dts, for checking various lexical corner cases in comment processing. In fact, it predates the automated testsuite, and has never been integrated into it. This patch addresses this oversight, folding the comment handling test in with the rest of the testsuite. Signed-off-by: David Gibson --- tests/comments-cmp.dts | 16 ++++++++++++++++ comment-test.dts => tests/comments.dts | 1 + tests/run_tests.sh | 4 ++++ 3 files changed, 21 insertions(+) create mode 100644 tests/comments-cmp.dts rename comment-test.dts => tests/comments.dts (97%) diff --git a/tests/comments-cmp.dts b/tests/comments-cmp.dts new file mode 100644 index 0000000..4ee9f52 --- /dev/null +++ b/tests/comments-cmp.dts @@ -0,0 +1,16 @@ +/dts-v1/; + +/ { + prop1; + prop2; + prop3; + prop4; + prop5; + prop6; + prop7; + prop8; + prop9; + prop10; + child { + }; +}; diff --git a/comment-test.dts b/tests/comments.dts similarity index 97% rename from comment-test.dts rename to tests/comments.dts index 0174347..0b04b6b 100644 --- a/comment-test.dts +++ b/tests/comments.dts @@ -1,5 +1,6 @@ /* regexps for lexing comments are.. tricky. Check if we've actually * got it right */ +/dts-v1/; / { // line comment diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 02b1fb0..73b9d81 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -154,6 +154,10 @@ dtc_tests () { run_test dtc.sh -I dts -O dtb -o dtc_path-references.test.dtb path-references.dts run_test path-references dtc_path-references.test.dtb + run_test dtc.sh -I dts -O dtb -o dtc_comments.test.dtb comments.dts + run_test dtc.sh -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts + run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb + # Check -Odts mode preserve all dtb information for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb ; do run_test dtc.sh -I dtb -O dts -o odts_$tree.test.dts $tree From a90b5905fede1ebd2d6365103cc1d9b78f76217c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 18 Feb 2008 16:09:25 +1100 Subject: [PATCH 0208/1198] libfdt: More tests of NOP handling behaviour In light of the recently discovered bug with NOP handling, this adds some more testcases for NOP handling. Specifically, it adds a helper program which will add a NOP tag after every existing tag in a dtb, and runs the standard battery of tests over trees mangled in this way. For now, this does not add a NOP at the very beginning of the structure block. This causes problems for libfdt at present, because we assume in many places that the root node's BEGIN_NODE tag is at offset 0. I'm still contemplating what to do about this (with one option being simply to declare such dtbs invalid). Signed-off-by: David Gibson --- tests/Makefile.tests | 2 +- tests/nopulate.c | 107 +++++++++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 7 +++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 tests/nopulate.c diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 15a5ebb..830d0a9 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -7,7 +7,7 @@ LIB_TESTS_L = get_mem_rsv \ notfound \ setprop_inplace nop_property nop_node \ sw_tree1 \ - move_and_save mangle-layout \ + move_and_save mangle-layout nopulate \ open_pack rw_tree1 set_name setprop del_property del_node \ string_escapes references path-references \ dtbs_equal_ordered \ diff --git a/tests/nopulate.c b/tests/nopulate.c new file mode 100644 index 0000000..923ba2d --- /dev/null +++ b/tests/nopulate.c @@ -0,0 +1,107 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase/tool for rearranging blocks of a dtb + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int nopulate_struct(char *buf, const void *fdt) +{ + int offset, nextoffset = 0; + uint32_t tag; + char *p; + + p = buf; + + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + + memcpy(p, fdt + fdt_off_dt_struct(fdt) + offset, + nextoffset - offset); + p += nextoffset - offset; + + *((uint32_t *)p) = cpu_to_fdt32(FDT_NOP); + p += FDT_TAGSIZE; + + } while (tag != FDT_END); + + return p - buf; +} + +int main(int argc, char *argv[]) +{ + void *fdt, *fdt2; + void *buf; + int newsize, struct_start, struct_end_old, struct_end_new, delta; + const char *inname; + char outname[PATH_MAX]; + + test_init(argc, argv); + if (argc != 2) + CONFIG("Usage: %s ", argv[0]); + + inname = argv[1]; + fdt = load_blob(argv[1]); + sprintf(outname, "noppy.%s", inname); + + if (fdt_version(fdt) < 17) + FAIL("Can't deal with version <17"); + + buf = xmalloc(2 * fdt_size_dt_struct(fdt)); + + newsize = nopulate_struct(buf, fdt); + + verbose_printf("Nopulated structure block has new size %d\n", newsize); + + /* Replace old strcutre block with the new */ + + fdt2 = xmalloc(fdt_totalsize(fdt) + newsize); + + struct_start = fdt_off_dt_struct(fdt); + delta = newsize - fdt_size_dt_struct(fdt); + struct_end_old = struct_start + fdt_size_dt_struct(fdt); + struct_end_new = struct_start + newsize; + + memcpy(fdt2, fdt, struct_start); + memcpy(fdt2 + struct_start, buf, newsize); + memcpy(fdt2 + struct_end_new, fdt + struct_end_old, + fdt_totalsize(fdt) - struct_end_old); + + fdt_set_totalsize(fdt2, fdt_totalsize(fdt) + delta); + fdt_set_size_dt_struct(fdt2, newsize); + + if (fdt_off_mem_rsvmap(fdt) > struct_start) + fdt_set_off_mem_rsvmap(fdt2, fdt_off_mem_rsvmap(fdt) + delta); + if (fdt_off_dt_strings(fdt) > struct_start) + fdt_set_off_dt_strings(fdt2, fdt_off_dt_strings(fdt) + delta); + + save_blob(outname, fdt2); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 73b9d81..c1da1fb 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -125,6 +125,13 @@ libfdt_tests () { tree1_tests rw_tree1.test.dtb tree1_tests_rw rw_tree1.test.dtb + for basetree in test_tree1.dtb sw_tree1.test.dtb rw_tree1.test.dtb; do + run_test nopulate $basetree + run_test dtbs_equal_ordered $basetree noppy.$basetree + tree1_tests noppy.$basetree + tree1_tests_rw noppy.$basetree + done + # Tests for behaviour on various sorts of corrupted trees run_test truncated_property From 8a4e75049dd0543aab4f286fafa41f0b404c59b4 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 18 Feb 2008 18:06:31 +1100 Subject: [PATCH 0209/1198] libfdt: Trivial cleanup for CHECK_HEADER) Currently the CHECK_HEADER() macro is defined local to fdt_ro.c. However, there are a handful of functions (fdt_move, rw_check_header, fdt_open_into) from other files which could also use it (currently they open-code something more-or-less identical). Therefore, this patch moves CHECK_HEADER() to libfdt_internal.h and uses it in those places. Signed-off-by: David Gibson --- libfdt/fdt.c | 5 +---- libfdt/fdt_ro.c | 7 ------- libfdt/fdt_rw.c | 8 ++------ libfdt/libfdt_internal.h | 7 +++++++ 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index c61fb53..bd91712 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -184,10 +184,7 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) int fdt_move(const void *fdt, void *buf, int bufsize) { - int err = fdt_check_header(fdt); - - if (err) - return err; + CHECK_HEADER(fdt); if (fdt_totalsize(fdt) > bufsize) return -FDT_ERR_NOSPACE; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index f08941a..15d5f6b 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -55,13 +55,6 @@ #include "libfdt_internal.h" -#define CHECK_HEADER(fdt) \ - { \ - int err; \ - if ((err = fdt_check_header(fdt)) != 0) \ - return err; \ - } - static int nodename_eq(const void *fdt, int offset, const char *s, int len) { diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index ac50195..0df472b 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -69,10 +69,8 @@ static int _blocks_misordered(const void *fdt, static int rw_check_header(void *fdt) { - int err; + CHECK_HEADER(fdt); - if ((err = fdt_check_header(fdt))) - return err; if (fdt_version(fdt) < 17) return -FDT_ERR_BADVERSION; if (_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), @@ -399,9 +397,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) int newsize; void *tmp; - err = fdt_check_header(fdt); - if (err) - return err; + CHECK_HEADER(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 1e60936..52e1b8d 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -58,6 +58,13 @@ #define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) #define streq(p, q) (strcmp((p), (q)) == 0) +#define CHECK_HEADER(fdt) \ + { \ + int err; \ + if ((err = fdt_check_header(fdt)) != 0) \ + return err; \ + } + uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset); const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); int _fdt_node_end_offset(void *fdt, int nodeoffset); From 2512a7eb5c755aeb92222748aa6a441c6840325c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 18 Feb 2008 18:09:04 +1100 Subject: [PATCH 0210/1198] libfdt: Remove no longer used code from fdt_node_offset_by_compatible() Since fdt_node_offset_by_compatible() was converted to the new fdt_next_node() iterator, a chunk of initialization code became redundant, but was not removed by oversight. This patch cleans it up. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 15d5f6b..63fa129 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -453,20 +453,10 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible) { - uint32_t tag; - int offset, nextoffset; - int err; + int offset, err; CHECK_HEADER(fdt); - if (startoffset >= 0) { - tag = fdt_next_tag(fdt, startoffset, &nextoffset); - if (tag != FDT_BEGIN_NODE) - return -FDT_ERR_BADOFFSET; - } else { - nextoffset = 0; - } - /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_node_check_compatible(), then if * that didn't find what we want, we scan over them again From 7c635dcb2f43529bbe7903f5a6ce56984d21b964 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 26 Feb 2008 16:44:29 +1100 Subject: [PATCH 0211/1198] dtc: Fix error reporting in push_input_file() Error reporting in push_input_file() is a mess. One error results in a message and exit(1), others result in a message and return 0 - which is turned into an exit(1) at one callsite. The other callsite doesn't check errors, but probably should. One of the error conditions gives a message, but can only be the result of an internal programming error, not a user error. So. Clean that up by making push_input_file() a void function, using die() to report errors and quit. Signed-off-by: David Gibson --- dtc-lexer.l | 28 ++++++++-------------------- srcpos.h | 2 +- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 920b87f..0cd3f69 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -59,10 +59,7 @@ static int dts_version; /* = 0 */ \"[^"\n]*\" { yytext[strlen(yytext) - 1] = 0; - if (!push_input_file(yytext + 1)) { - /* Some unrecoverable error.*/ - exit(1); - } + push_input_file(yytext + 1); yy_pop_state(); } @@ -243,21 +240,16 @@ struct incl_file *incl_file_stack; static int incl_depth = 0; -int push_input_file(const char *filename) +void push_input_file(const char *filename) { struct incl_file *incl_file; struct dtc_file *newfile; struct search_path search, *searchptr = NULL; - if (!filename) { - yyerror("No include file name given."); - return 0; - } + assert(filename); - if (incl_depth++ >= MAX_INCLUDE_DEPTH) { - yyerror("Includes nested too deeply"); - return 0; - } + if (incl_depth++ >= MAX_INCLUDE_DEPTH) + die("Includes nested too deeply"); if (srcpos_file) { search.dir = srcpos_file->dir; @@ -267,11 +259,9 @@ int push_input_file(const char *filename) } newfile = dtc_open_file(filename, searchptr); - if (!newfile) { - yyerrorf("Couldn't open \"%s\": %s", - filename, strerror(errno)); - exit(1); - } + if (!newfile) + die("Couldn't open \"%s\": %s", filename, strerror(errno)); + incl_file = xmalloc(sizeof(struct incl_file)); @@ -292,8 +282,6 @@ int push_input_file(const char *filename) yylineno = 1; yyin = newfile->file; yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); - - return 1; } diff --git a/srcpos.h b/srcpos.h index 3ed2334..d548c09 100644 --- a/srcpos.h +++ b/srcpos.h @@ -75,7 +75,7 @@ extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2))); extern struct dtc_file *srcpos_file; -extern int push_input_file(const char *filename); +extern void push_input_file(const char *filename); extern int pop_input_file(void); struct search_path { From fa5b520ccb5e8da8d67ebc1926416753684f4e70 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 27 Feb 2008 13:45:13 +1100 Subject: [PATCH 0212/1198] dtc: Implement checks for the format of node and property names This patch adds checks to the checking framework to verify that node and property names contain only legal characters, and in the case of node names there is at most one '@'. At present when coming from dts input, this is mostly already ensured by the grammer, however putting the check later means its easier to generate helpful error messages rather than just "syntax error". For dtb input, these checks replace the older similar check built into flattree.c. Testcases for the checks are also implemented. Signed-off-by: David Gibson --- checks.c | 37 +++++++++++++++++++++++++++++++++++ flattree.c | 28 +++++---------------------- tests/dumptrees.c | 1 + tests/run_tests.sh | 3 +++ tests/testdata.h | 3 +++ tests/trees.S | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 23 deletions(-) diff --git a/checks.c b/checks.c index 8c00c56..d92279e 100644 --- a/checks.c +++ b/checks.c @@ -242,6 +242,42 @@ static void check_duplicate_property_names(struct check *c, struct node *dt, } NODE_CHECK(duplicate_property_names, NULL, ERROR); +#define LOWERCASE "abcdefghijklmnopqrstuvwxyz" +#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define DIGITS "0123456789" +#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-" + +static void check_node_name_chars(struct check *c, struct node *dt, + struct node *node) +{ + int n = strspn(node->name, c->data); + + if (n < strlen(node->name)) + FAIL(c, "Bad character '%c' in node %s", + node->name[n], node->fullpath); +} +NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR); + +static void check_node_name_format(struct check *c, struct node *dt, + struct node *node) +{ + if (strchr(get_unitname(node), '@')) + FAIL(c, "Node %s has multiple '@' characters in name", + node->fullpath); +} +NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars); + +static void check_property_name_chars(struct check *c, struct node *dt, + struct node *node, struct property *prop) +{ + int n = strspn(prop->name, c->data); + + if (n < strlen(prop->name)) + FAIL(c, "Bad character '%c' in property name \"%s\", node %s", + prop->name[n], prop->name, node->fullpath); +} +PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR); + static void check_explicit_phandles(struct check *c, struct node *root, struct node *node) { @@ -498,6 +534,7 @@ TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN); 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, &explicit_phandles, &phandle_references, &path_references, diff --git a/flattree.c b/flattree.c index 7b6d7fe..b6be786 100644 --- a/flattree.c +++ b/flattree.c @@ -729,29 +729,14 @@ static char *nodename_from_path(const char *ppath, const char *cpath) return strdup(lslash+1); } -static const char PROPCHAR[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,._+*#?-"; -static const char UNITCHAR[] = "0123456789abcdef,"; - -static int check_node_name(const char *name) +static int find_basenamelen(const char *name) { - const char *atpos; - int basenamelen; - - atpos = strrchr(name, '@'); + const char *atpos = strchr(name, '@'); if (atpos) - basenamelen = atpos - name; + return atpos - name; else - basenamelen = strlen(name); - - if (strspn(name, PROPCHAR) < basenamelen) - return -1; - - if (atpos - && ((basenamelen + 1 + strspn(atpos+1, UNITCHAR)) < strlen(name))) - return -1; - - return basenamelen; + return strlen(name); } static struct node *unflatten_tree(struct inbuf *dtbuf, @@ -775,10 +760,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, node->fullpath = join_path(parent_path, node->name); } - node->basenamelen = check_node_name(node->name); - if (node->basenamelen < 0) { - fprintf(stderr, "Warning \"%s\" has incorrect format\n", node->name); - } + node->basenamelen = find_basenamelen(node->name); do { struct property *prop; diff --git a/tests/dumptrees.c b/tests/dumptrees.c index ef48c0c..fa1f563 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -37,6 +37,7 @@ struct { } trees[] = { #define TREE(name) { &_##name, #name ".dtb" } TREE(test_tree1), + TREE(bad_node_char), TREE(bad_node_format), TREE(bad_prop_char), }; #define NUM_TREES (sizeof(trees) / sizeof(trees[0])) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c1da1fb..443177f 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -188,6 +188,9 @@ dtc_tests () { run_test dtc-checkfails.sh ranges_format -- -I dts -O dtb bad-empty-ranges.dts run_test dtc-checkfails.sh avoid_default_addr_size -- -I dts -O dtb default-addr-size.dts run_test dtc-checkfails.sh obsolete_chosen_interrupt_controller -- -I dts -O dtb obsolete-chosen-interrupt-controller.dts + run_test dtc-checkfails.sh node_name_chars -- -I dtb -O dtb bad_node_char.dtb + run_test dtc-checkfails.sh node_name_format -- -I dtb -O dtb bad_node_format.dtb + run_test dtc-checkfails.sh prop_name_chars -- -I dtb -O dtb bad_prop_char.dtb } while getopts "vt:m" ARG ; do diff --git a/tests/testdata.h b/tests/testdata.h index 0f7f2fa..9c8b040 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -33,4 +33,7 @@ #ifndef __ASSEMBLY__ extern struct fdt_header _test_tree1; extern struct fdt_header _truncated_property; +extern struct fdt_header _bad_node_char; +extern struct fdt_header _bad_node_format; +extern struct fdt_header _bad_prop_char; #endif /* ! __ASSEMBLY */ diff --git a/tests/trees.S b/tests/trees.S index e3c5d47..cedf5f9 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -136,3 +136,51 @@ truncated_property_strings: truncated_property_strings_end: truncated_property_end: + + + TREE_HDR(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) +bad_node_char_struct_end: + +bad_node_char_strings: +bad_node_char_strings_end: +bad_node_char_end: + + + TREE_HDR(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) +bad_node_format_struct_end: + +bad_node_format_strings: +bad_node_format_strings_end: +bad_node_format_end: + + + TREE_HDR(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) +bad_prop_char_struct_end: + +bad_prop_char_strings: + STRING(bad_prop_char, prop, "prop$erty") +bad_prop_char_strings_end: +bad_prop_char_end: From 2b3a96761afa402ed6df4bab243a54e47ffff935 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 28 Feb 2008 16:42:15 +1100 Subject: [PATCH 0213/1198] dtc: Fix indentation of fixup_phandle_references Somehow the indentation of this function is messed up - 7 spaces instead of 1 tab (probably a bad copy paste from a patch file). This patch fixes it. Signed-off-by: David Gibson --- checks.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/checks.c b/checks.c index d92279e..051368b 100644 --- a/checks.c +++ b/checks.c @@ -337,23 +337,23 @@ NODE_CHECK(name_properties, NULL, ERROR, &name_is_string); static void fixup_phandle_references(struct check *c, struct node *dt, struct node *node, struct property *prop) { - struct marker *m = prop->val.markers; - struct node *refnode; - cell_t phandle; + struct marker *m = prop->val.markers; + struct node *refnode; + cell_t phandle; - for_each_marker_of_type(m, REF_PHANDLE) { - assert(m->offset + sizeof(cell_t) <= prop->val.len); + for_each_marker_of_type(m, REF_PHANDLE) { + assert(m->offset + sizeof(cell_t) <= prop->val.len); - refnode = get_node_by_ref(dt, m->ref); - if (! refnode) { - FAIL(c, "Reference to non-existent node or label \"%s\"\n", - m->ref); - continue; - } + refnode = get_node_by_ref(dt, m->ref); + if (! refnode) { + FAIL(c, "Reference to non-existent node or label \"%s\"\n", + m->ref); + continue; + } - phandle = get_node_phandle(dt, refnode); - *((cell_t *)(prop->val.val + m->offset)) = cpu_to_be32(phandle); - } + phandle = get_node_phandle(dt, refnode); + *((cell_t *)(prop->val.val + m->offset)) = cpu_to_be32(phandle); + } } CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR, &duplicate_node_names, &explicit_phandles); From d028e84140317682140602dcc87dc3aa439e35cb Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 28 Feb 2008 20:53:00 +1100 Subject: [PATCH 0214/1198] dtc: Strip redundant "name" properties If an input device tree has "name" properties which are correct, then they are redundant (because they can be derived from the unit name). Therefore, extend the checking code for correctness of "name" properties to remove them if they are correct. dtc will still insert name properties in the output if that's of a sufficiently old version to require them. Signed-off-by: David Gibson --- checks.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/checks.c b/checks.c index 051368b..34941de 100644 --- a/checks.c +++ b/checks.c @@ -316,9 +316,14 @@ NODE_CHECK(explicit_phandles, NULL, ERROR); static void check_name_properties(struct check *c, struct node *root, struct node *node) { - struct property *prop; + struct property **pp, *prop = NULL; + + for (pp = &node->proplist; *pp; pp = &((*pp)->next)) + if (streq((*pp)->name, "name")) { + prop = *pp; + break; + } - prop = get_property(node, "name"); if (!prop) return; /* No name property, that's fine */ @@ -326,6 +331,12 @@ static void check_name_properties(struct check *c, struct node *root, || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead" " of base node name)", node->fullpath, prop->val.val); + + /* The name property is correct, and therefore redundant. Delete it */ + *pp = prop->next; + free(prop->name); + data_free(prop->val); + free(prop); } CHECK_IS_STRING(name_is_string, "name", ERROR); NODE_CHECK(name_properties, NULL, ERROR, &name_is_string); From a266e5c1e105487795aa2e6fe0b52cfdb8a0a71d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 28 Feb 2008 20:55:37 +1100 Subject: [PATCH 0215/1198] dtc: Test and fix conversion to/from old dtb versions This patch adds testcases which test dtc when used to convert between different dtb versions. These tests uncovered a couple of bugs handling old dtb versions, which are also fixed. Signed-off-by: David Gibson --- flattree.c | 14 ++++++-------- tests/run_tests.sh | 13 +++++++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/flattree.c b/flattree.c index b6be786..6f43a89 100644 --- a/flattree.c +++ b/flattree.c @@ -410,7 +410,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, * the reserve buffer, add the reserve map terminating zeroes, * the device tree itself, and finally the strings. */ - blob = data_append_data(blob, &fdt, sizeof(fdt)); + blob = data_append_data(blob, &fdt, vi->hdr_size); blob = data_append_align(blob, 8); blob = data_merge(blob, reservebuf); blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry)); @@ -809,7 +809,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, struct boot_info *dt_from_blob(FILE *f) { - u32 magic, totalsize, version, size_str, size_dt; + u32 magic, totalsize, version, size_dt; u32 off_dt, off_str, off_mem_rsvmap; int rc; char *blob; @@ -889,11 +889,13 @@ struct boot_info *dt_from_blob(FILE *f) if (off_str > totalsize) die("String table offset exceeds total size\n"); - size_str = -1; if (version >= 3) { - size_str = be32_to_cpu(fdt->size_dt_strings); + u32 size_str = be32_to_cpu(fdt->size_dt_strings); if (off_str+size_str > totalsize) die("String table extends past total size\n"); + inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str); + } else { + inbuf_init(&strbuf, blob + off_str, blob + totalsize); } if (version >= 17) { @@ -911,10 +913,6 @@ struct boot_info *dt_from_blob(FILE *f) inbuf_init(&memresvbuf, blob + off_mem_rsvmap, blob + totalsize); inbuf_init(&dtbuf, blob + off_dt, blob + totalsize); - if (size_str >= 0) - inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str); - else - inbuf_init(&strbuf, blob + off_str, blob + totalsize); reservelist = flat_read_mem_reserve(&memresvbuf); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 443177f..492453d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -172,6 +172,19 @@ dtc_tests () { run_test dtbs_equal_ordered $tree odts_$tree.test.dtb done + # Check version conversions + for tree in test_tree1.dtb ; do + for aver in 1 2 3 16 17; do + atree="ov${aver}_$tree.test.dtb" + run_test dtc.sh -I dtb -O dtb -V$aver -o $atree $tree + for bver in 16 17; do + btree="ov${bver}_$atree" + run_test dtc.sh -I dtb -O dtb -V$bver -o $btree $atree + run_test dtbs_equal_ordered $btree $tree + done + done + done + # Check some checks run_test dtc-checkfails.sh duplicate_node_names -- -I dts -O dtb dup-nodename.dts run_test dtc-checkfails.sh duplicate_property_names -- -I dts -O dtb dup-propname.dts From 5ac97df149a171d63804a889ffcaa85e0feb400b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 28 Feb 2008 20:58:28 +1100 Subject: [PATCH 0216/1198] dtc: Use for_each_marker_of_type in asm_emit_data() For no good reason, asm_emit_data() open-codes the equivalent of the for_each_marker_of_type macro. Use the macro instead. Signed-off-by: David Gibson --- flattree.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/flattree.c b/flattree.c index 6f43a89..41cb740 100644 --- a/flattree.c +++ b/flattree.c @@ -162,14 +162,10 @@ static void asm_emit_data(void *e, struct data d) { FILE *f = e; int off = 0; - struct marker *m; + struct marker *m = d.markers; - m = d.markers; - while (m) { - if (m->type == LABEL) - emit_offset_label(f, m->ref, m->offset); - m = m->next; - } + for_each_marker_of_type(m, LABEL) + emit_offset_label(f, m->ref, m->offset); while ((d.len - off) >= sizeof(u32)) { fprintf(f, "\t.long\t0x%x\n", From b2de518b80eb01b1004e137ff2435b03dc40018d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 29 Feb 2008 16:51:28 +1100 Subject: [PATCH 0217/1198] dtc: Make -I dtb mode use fill_fullpaths() At present -I dts and -I fs modes both use the fill_fullpaths() helper function to fill in the fullpath and basenamelen fields of struct node, which are useful in later parts of the code. -I dtb mode, however, fills these in itself. This patch simplifies flattree.c by making -I dtb mode use fill_fullpaths() like the others. Signed-off-by: David Gibson --- dtc.c | 3 ++- dtc.h | 1 - flattree.c | 55 +++++++++++++++------------------------------------- fstree.c | 2 -- treesource.c | 2 -- 5 files changed, 18 insertions(+), 45 deletions(-) diff --git a/dtc.c b/dtc.c index c1814c1..90e1cce 100644 --- a/dtc.c +++ b/dtc.c @@ -55,7 +55,7 @@ char *join_path(const char *path, const char *name) return str; } -void fill_fullpaths(struct node *tree, const char *prefix) +static void fill_fullpaths(struct node *tree, const char *prefix) { struct node *child; const char *unit; @@ -208,6 +208,7 @@ int main(int argc, char *argv[]) if (! bi || ! bi->dt || bi->error) die("Couldn't read input tree\n"); + fill_fullpaths(bi->dt, ""); process_checks(force, bi); if (streq(outname, "-")) { diff --git a/dtc.h b/dtc.h index cba9d28..dbff5e8 100644 --- a/dtc.h +++ b/dtc.h @@ -264,6 +264,5 @@ struct boot_info *dt_from_fs(const char *dirname); /* misc */ char *join_path(const char *path, const char *name); -void fill_fullpaths(struct node *tree, const char *prefix); #endif /* _DTC_H */ diff --git a/flattree.c b/flattree.c index 41cb740..8675857 100644 --- a/flattree.c +++ b/flattree.c @@ -704,59 +704,37 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) static char *nodename_from_path(const char *ppath, const char *cpath) { - const char *lslash; int plen; - lslash = strrchr(cpath, '/'); - if (! lslash) - return NULL; + plen = strlen(ppath); - plen = lslash - cpath; + if (!strneq(ppath, cpath, plen)) + die("Path \"%s\" is not valid as a child of \"%s\"\n", + cpath, ppath); - if (streq(cpath, "/") && streq(ppath, "")) - return ""; + /* root node is a special case */ + if (!streq(ppath, "/")) + plen++; - if ((plen == 0) && streq(ppath, "/")) - return strdup(lslash+1); - - if (! strneq(ppath, cpath, plen)) - return NULL; - - return strdup(lslash+1); -} - -static int find_basenamelen(const char *name) -{ - const char *atpos = strchr(name, '@'); - - if (atpos) - return atpos - name; - else - return strlen(name); + return strdup(cpath + plen); } static struct node *unflatten_tree(struct inbuf *dtbuf, struct inbuf *strbuf, - const char *parent_path, int flags) + const char *parent_flatname, int flags) { struct node *node; + char *flatname; u32 val; node = build_node(NULL, NULL); - if (flags & FTF_FULLPATH) { - node->fullpath = flat_read_string(dtbuf); - node->name = nodename_from_path(parent_path, node->fullpath); + flatname = flat_read_string(dtbuf); - if (! node->name) - die("Path \"%s\" is not valid as a child of \"%s\"\n", - node->fullpath, parent_path); - } else { - node->name = flat_read_string(dtbuf); - node->fullpath = join_path(parent_path, node->name); - } - - node->basenamelen = find_basenamelen(node->name); + if (flags & FTF_FULLPATH) + node->name = nodename_from_path(parent_flatname, flatname); + else + node->name = flatname; do { struct property *prop; @@ -773,8 +751,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, break; case FDT_BEGIN_NODE: - child = unflatten_tree(dtbuf,strbuf, node->fullpath, - flags); + child = unflatten_tree(dtbuf,strbuf, flatname, flags); add_child(node, child); break; diff --git a/fstree.c b/fstree.c index 2a160a4..2fc5773 100644 --- a/fstree.c +++ b/fstree.c @@ -87,8 +87,6 @@ struct boot_info *dt_from_fs(const char *dirname) tree = read_fstree(dirname); tree = name_node(tree, "", NULL); - fill_fullpaths(tree, ""); - return build_boot_info(NULL, tree); } diff --git a/treesource.c b/treesource.c index 980bda7..9cbf0a9 100644 --- a/treesource.c +++ b/treesource.c @@ -37,8 +37,6 @@ struct boot_info *dt_from_source(const char *fname) if (yyparse() != 0) return NULL; - fill_fullpaths(the_boot_info->dt, ""); - the_boot_info->error = treesource_error; return the_boot_info; } From 6b8e05626a0011fd235dcbd9ccd44fd731a414c0 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 5 Mar 2008 11:47:54 +1100 Subject: [PATCH 0218/1198] dtc: Make eval_literal() static eval_literal() is used only in the parser, so make it a static function. Signed-off-by: David Gibson --- dtc-parser.y | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index bae3c32..4ab1df9 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -24,12 +24,12 @@ #include "dtc.h" #include "srcpos.h" -int yylex(void); -unsigned long long eval_literal(const char *s, int base, int bits); +extern int yylex(void); extern struct boot_info *the_boot_info; extern int treesource_error; +static unsigned long long eval_literal(const char *s, int base, int bits); %} %union { @@ -330,7 +330,7 @@ void yyerror (char const *s) yyerrorf("%s", s); } -unsigned long long eval_literal(const char *s, int base, int bits) +static unsigned long long eval_literal(const char *s, int base, int bits) { unsigned long long val; char *e; From 68fe10ba4efc86c4bd388f5ba68d1b3e2e9e3be2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 5 Mar 2008 16:01:55 +1100 Subject: [PATCH 0219/1198] dtc: Assorted improvements to test harness This patch makes several small improvements to the test harness. * An altered way of invoking shell script testcases from run_tests.sh means scripts no longer need to me marked executable in the repository to work properly. * dtc.sh never did anything that was really dtc specific - with the exception of messages, it would work equally well for any binary that returns 0 in the successful case. Therefore, generalise dtc.sh and fold it into run_tests.sh so we don't need a separate script any more. * Tweak various things so that the valgrind options are properly propagated down to invoke dtc under valgrind when called via wrapper scripts. * Tweak the valgrind suppressions to work properly on a wider range of systems (this was necessary on my machine running Ubuntu Hardy). Signed-off-by: David Gibson --- tests/dtc-checkfails.sh | 5 +- tests/dtc.sh | 10 ---- tests/mangle-layout.supp | 2 +- tests/open_pack.supp | 2 +- tests/run_tests.sh | 110 +++++++++++++++++++++++++-------------- 5 files changed, 77 insertions(+), 52 deletions(-) delete mode 100755 tests/dtc.sh diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh index 23e1ba0..265173c 100755 --- a/tests/dtc-checkfails.sh +++ b/tests/dtc-checkfails.sh @@ -14,11 +14,12 @@ LOG="tmp.log.$$" rm -f $TMPFILE $LOG -verbose_run_log "$LOG" "$DTC" -o /dev/null "$@" +verbose_run_log "$LOG" $VALGRIND "$DTC" -o /dev/null "$@" ret="$?" if [ "$ret" -gt 127 ]; then - FAIL "dtc killed by signal (ret=$ret)" + signame=$(kill -l $[ret - 128]) + FAIL "Killed by SIG$signame" fi for c in $CHECKS; do diff --git a/tests/dtc.sh b/tests/dtc.sh deleted file mode 100755 index c5a7324..0000000 --- a/tests/dtc.sh +++ /dev/null @@ -1,10 +0,0 @@ -#! /bin/sh - -. tests.sh - -if verbose_run "$DTC" "$@"; then - PASS -else - ret="$?" - FAIL "dtc returned error code $ret" -fi diff --git a/tests/mangle-layout.supp b/tests/mangle-layout.supp index 2cc8449..2890420 100644 --- a/tests/mangle-layout.supp +++ b/tests/mangle-layout.supp @@ -2,6 +2,6 @@ uninitialized alignment gaps can be dumped to output Memcheck:Param write(buf) - obj:/lib/ld-2.6.1.so + obj:/lib/ld-*.so fun:main } diff --git a/tests/open_pack.supp b/tests/open_pack.supp index a38abc5..c954fe7 100644 --- a/tests/open_pack.supp +++ b/tests/open_pack.supp @@ -2,6 +2,6 @@ opened blob dumps uninitialized data Memcheck:Param write(buf) - obj:/lib/ld-2.6.1.so + obj:/lib/ld-*.so fun:main } diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 492453d..3d09cfc 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -1,5 +1,7 @@ #! /bin/bash +. tests.sh + export QUIET_TEST=1 export VALGRIND= @@ -12,16 +14,9 @@ tot_config=0 tot_vg=0 tot_strange=0 -run_test () { +base_run_test() { tot_tests=$[tot_tests + 1] - echo -n "$@: " - VGLOCAL="$VALGRIND" - if [ -n "$VALGRIND" ]; then - if [ -f $1.supp ]; then - VGLOCAL="$VGLOCAL --suppressions=$1.supp" - fi - fi - if $VGLOCAL "./$@"; then + if VALGRIND="$VALGRIND" "$@"; then tot_pass=$[tot_pass + 1] else ret="$?" @@ -37,6 +32,45 @@ run_test () { fi } +run_test () { + echo -n "$@: " + if [ -n "$VALGRIND" -a -f $1.supp ]; then + VGSUPP="--suppressions=$1.supp" + fi + base_run_test $VALGRIND $VGSUPP "./$@" +} + +run_sh_test () { + echo -n "$@: " + base_run_test sh "$@" +} + +wrap_test () { + ( + if verbose_run "$@"; then + PASS + else + ret="$?" + if [ "$ret" -gt 127 ]; then + signame=$(kill -l $[ret - 128]) + FAIL "Killed by SIG$signame" + else + FAIL "Returned error code $ret" + fi + fi + ) +} + +run_wrap_test () { + echo -n "$@: " + base_run_test wrap_test "$@" +} + +run_dtc_test () { + echo -n "dtc $@: " + base_run_test wrap_test $VALGRIND $DTC "$@" +} + tree1_tests () { TREE=$1 @@ -140,35 +174,35 @@ libfdt_tests () { } dtc_tests () { - run_test dtc.sh -I dts -O dtb -o dtc_tree1.test.dtb test_tree1.dts + run_dtc_test -I dts -O dtb -o dtc_tree1.test.dtb test_tree1.dts tree1_tests dtc_tree1.test.dtb tree1_tests_rw dtc_tree1.test.dtb run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb - run_test dtc.sh -I dts -O dtb -o dtc_tree1_dts0.test.dtb test_tree1_dts0.dts + run_dtc_test -I dts -O dtb -o dtc_tree1_dts0.test.dtb test_tree1_dts0.dts tree1_tests dtc_tree1_dts0.test.dtb tree1_tests_rw dtc_tree1_dts0.test.dtb - run_test dtc.sh -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts + run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts run_test string_escapes dtc_escapes.test.dtb - run_test dtc.sh -I dts -O dtb -o dtc_references.test.dtb references.dts + run_dtc_test -I dts -O dtb -o dtc_references.test.dtb references.dts run_test references dtc_references.test.dtb - run_test dtc.sh -I dts -O dtb -o dtc_references_dts0.test.dtb references_dts0.dts + run_dtc_test -I dts -O dtb -o dtc_references_dts0.test.dtb references_dts0.dts run_test references dtc_references_dts0.test.dtb - run_test dtc.sh -I dts -O dtb -o dtc_path-references.test.dtb path-references.dts + run_dtc_test -I dts -O dtb -o dtc_path-references.test.dtb path-references.dts run_test path-references dtc_path-references.test.dtb - run_test dtc.sh -I dts -O dtb -o dtc_comments.test.dtb comments.dts - run_test dtc.sh -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts + run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb comments.dts + run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb # Check -Odts mode preserve all dtb information for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb ; do - run_test dtc.sh -I dtb -O dts -o odts_$tree.test.dts $tree - run_test dtc.sh -I dts -O dtb -o odts_$tree.test.dtb odts_$tree.test.dts + run_dtc_test -I dtb -O dts -o odts_$tree.test.dts $tree + run_dtc_test -I dts -O dtb -o odts_$tree.test.dtb odts_$tree.test.dts run_test dtbs_equal_ordered $tree odts_$tree.test.dtb done @@ -176,34 +210,34 @@ dtc_tests () { for tree in test_tree1.dtb ; do for aver in 1 2 3 16 17; do atree="ov${aver}_$tree.test.dtb" - run_test dtc.sh -I dtb -O dtb -V$aver -o $atree $tree + run_dtc_test -I dtb -O dtb -V$aver -o $atree $tree for bver in 16 17; do btree="ov${bver}_$atree" - run_test dtc.sh -I dtb -O dtb -V$bver -o $btree $atree + run_dtc_test -I dtb -O dtb -V$bver -o $btree $atree run_test dtbs_equal_ordered $btree $tree done done done # Check some checks - run_test dtc-checkfails.sh duplicate_node_names -- -I dts -O dtb dup-nodename.dts - run_test dtc-checkfails.sh duplicate_property_names -- -I dts -O dtb dup-propname.dts - run_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb dup-phandle.dts - run_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb zero-phandle.dts - run_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb minusone-phandle.dts - run_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-node-ref.dts - run_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-label-ref.dts - run_test dtc-checkfails.sh name_properties -- -I dts -O dtb bad-name-property.dts + run_sh_test dtc-checkfails.sh duplicate_node_names -- -I dts -O dtb dup-nodename.dts + run_sh_test dtc-checkfails.sh duplicate_property_names -- -I dts -O dtb dup-propname.dts + run_sh_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb dup-phandle.dts + run_sh_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb zero-phandle.dts + run_sh_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb minusone-phandle.dts + run_sh_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-node-ref.dts + run_sh_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-label-ref.dts + run_sh_test dtc-checkfails.sh name_properties -- -I dts -O dtb bad-name-property.dts - run_test dtc-checkfails.sh address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell -- -I dts -O dtb bad-ncells.dts - run_test dtc-checkfails.sh device_type_is_string model_is_string status_is_string -- -I dts -O dtb bad-string-props.dts - run_test dtc-checkfails.sh reg_format ranges_format -- -I dts -O dtb bad-reg-ranges.dts - run_test dtc-checkfails.sh ranges_format -- -I dts -O dtb bad-empty-ranges.dts - run_test dtc-checkfails.sh avoid_default_addr_size -- -I dts -O dtb default-addr-size.dts - run_test dtc-checkfails.sh obsolete_chosen_interrupt_controller -- -I dts -O dtb obsolete-chosen-interrupt-controller.dts - run_test dtc-checkfails.sh node_name_chars -- -I dtb -O dtb bad_node_char.dtb - run_test dtc-checkfails.sh node_name_format -- -I dtb -O dtb bad_node_format.dtb - run_test dtc-checkfails.sh prop_name_chars -- -I dtb -O dtb bad_prop_char.dtb + run_sh_test dtc-checkfails.sh address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell -- -I dts -O dtb bad-ncells.dts + run_sh_test dtc-checkfails.sh device_type_is_string model_is_string status_is_string -- -I dts -O dtb bad-string-props.dts + run_sh_test dtc-checkfails.sh reg_format ranges_format -- -I dts -O dtb bad-reg-ranges.dts + run_sh_test dtc-checkfails.sh ranges_format -- -I dts -O dtb bad-empty-ranges.dts + run_sh_test dtc-checkfails.sh avoid_default_addr_size -- -I dts -O dtb default-addr-size.dts + run_sh_test dtc-checkfails.sh obsolete_chosen_interrupt_controller -- -I dts -O dtb obsolete-chosen-interrupt-controller.dts + run_sh_test dtc-checkfails.sh node_name_chars -- -I dtb -O dtb bad_node_char.dtb + run_sh_test dtc-checkfails.sh node_name_format -- -I dtb -O dtb bad_node_format.dtb + run_sh_test dtc-checkfails.sh prop_name_chars -- -I dtb -O dtb bad_prop_char.dtb } while getopts "vt:m" ARG ; do From 6c2e4d61f83af4233c3270e4f1ec1da01d90466e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 5 Mar 2008 16:22:41 +1100 Subject: [PATCH 0220/1198] dtc: Testcases for input handling This patch adds some testcases checking corner cases of dtc's input file handling. Specifically it checks that dtc works correctly when given input via stdin, and it checks that dtc fails gracefully if given a nonexistent input file (or directory, in the case of -Ifs mode). Signed-off-by: David Gibson --- tests/dtc-fatal.sh | 14 ++++++++++++++ tests/run_tests.sh | 11 +++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/dtc-fatal.sh diff --git a/tests/dtc-fatal.sh b/tests/dtc-fatal.sh new file mode 100644 index 0000000..8eb1b44 --- /dev/null +++ b/tests/dtc-fatal.sh @@ -0,0 +1,14 @@ +#! /bin/sh + +. tests.sh + +verbose_run $VALGRIND "$DTC" -o/dev/null "$@" +ret="$?" + +if [ "$ret" -gt 127 ]; then + FAIL "dtc killed by signal (ret=$ret)" +elif [ "$ret" != "1" ]; then + FAIL "dtc returned incorrect status $ret instead of 1" +fi + +PASS diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 3d09cfc..27dc11a 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -238,6 +238,17 @@ dtc_tests () { run_sh_test dtc-checkfails.sh node_name_chars -- -I dtb -O dtb bad_node_char.dtb run_sh_test dtc-checkfails.sh node_name_format -- -I dtb -O dtb bad_node_format.dtb run_sh_test dtc-checkfails.sh prop_name_chars -- -I dtb -O dtb bad_prop_char.dtb + + # Check for proper behaviour reading from stdin + run_dtc_test -I dts -O dtb -o stdin_dtc_tree1.test.dtb - < test_tree1.dts + run_wrap_test cmp stdin_dtc_tree1.test.dtb dtc_tree1.test.dtb + 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 for graceful failure in some error conditions + run_sh_test dtc-fatal.sh -I dts -O dtb nosuchfile.dts + run_sh_test dtc-fatal.sh -I dtb -O dtb nosuchfile.dtb + run_sh_test dtc-fatal.sh -I fs -O dtb nosuchfile } while getopts "vt:m" ARG ; do From f7ea3708c38bd38851baafa83e98d95602e53cbc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 6 Mar 2008 12:16:55 +1100 Subject: [PATCH 0221/1198] dtc: Make dtc_open_file() die() if unable to open requested file All current callers of dtc_open_file() immediately die() if it returns an error. In a non-interative tool like dtc, it's hard to see what you could sensibly do to recover from a failure to open an input file in any case. Therefore, make dtc_open_file() itself die() if there's an error opening the requested file. This removes the need for error checking at the callsites, and ensures a consistent error message in all cases. While we're at it, change the rror message from fstree.c when we fail to open the input directory to match dtc_open_file()'s error message. Signed-off-by: David Gibson --- dtc-lexer.l | 3 --- dtc.c | 4 ---- fstree.c | 4 ++-- srcpos.c | 11 ++++------- 4 files changed, 6 insertions(+), 16 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 0cd3f69..a643ab3 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -259,9 +259,6 @@ void push_input_file(const char *filename) } newfile = dtc_open_file(filename, searchptr); - if (!newfile) - die("Couldn't open \"%s\": %s", filename, strerror(errno)); - incl_file = xmalloc(sizeof(struct incl_file)); diff --git a/dtc.c b/dtc.c index 90e1cce..75517f9 100644 --- a/dtc.c +++ b/dtc.c @@ -193,10 +193,6 @@ int main(int argc, char *argv[]) bi = dt_from_fs(arg); } else if(streq(inform, "dtb")) { inf = dtc_open_file(arg, NULL); - if (!inf) - die("Couldn't open \"%s\": %s\n", arg, - strerror(errno)); - bi = dt_from_blob(inf->file); } else { die("Unknown input format \"%s\"\n", inform); diff --git a/fstree.c b/fstree.c index 2fc5773..0c0bdf0 100644 --- a/fstree.c +++ b/fstree.c @@ -31,8 +31,8 @@ static struct node *read_fstree(const char *dirname) struct node *tree; d = opendir(dirname); - if (! d) - die("opendir(): %s\n", strerror(errno)); + if (!d) + die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno)); tree = build_node(NULL, NULL); diff --git a/srcpos.c b/srcpos.c index c8eaa1e..9641b76 100644 --- a/srcpos.c +++ b/srcpos.c @@ -82,9 +82,8 @@ struct dtc_file *dtc_open_file(const char *fname, if (fname[0] == '/') { file->file = fopen(fname, "r"); - if (!file->file) - goto out; + goto fail; file->name = strdup(fname); return file; @@ -98,15 +97,13 @@ struct dtc_file *dtc_open_file(const char *fname, return file; if (errno != ENOENT) - goto out; + goto fail; search = search->next; } -out: - free(file->dir); - free(file); - return NULL; +fail: + die("Couldn't open \"%s\": %s\n", fname, strerror(errno)); } void dtc_close_file(struct dtc_file *file) From 8a88ad8badfe54d91b35c5da25889de0db54f43e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 6 Mar 2008 12:45:41 +1100 Subject: [PATCH 0222/1198] dtc: Remove ugly include stack abuse Currently, dt_from_source() uses push_input_file() to set up the initial input file for the lexer. That sounds sensible - put the outermost input file at the bottom of the stack - until you realise that what it *actually* does is pushes the current, uninitialized, lexer input state onto the stack, then sets up the new lexer input. That necessitates an extra check in pop_input_file(), rather than signalling termination in the natural way when the include stack is empty, it has to check when it pops the bogus uninitialized state off the stack. Ick. With that fixed, push_input_file(), pop_input_file() and incl_file_stack itself become local to the lexer, so make them static. Signed-off-by: David Gibson --- dtc-lexer.l | 12 ++++++------ srcpos.h | 3 --- treesource.c | 3 ++- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index a643ab3..04b1753 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -52,6 +52,9 @@ static int dts_version; /* = 0 */ DPRINT("\n"); \ BEGIN(V1); \ } + +static void push_input_file(const char *filename); +static int pop_input_file(void); %} %% @@ -229,7 +232,7 @@ struct incl_file { struct incl_file *prev; }; -struct incl_file *incl_file_stack; +static struct incl_file *incl_file_stack; /* @@ -240,7 +243,7 @@ struct incl_file *incl_file_stack; static int incl_depth = 0; -void push_input_file(const char *filename) +static void push_input_file(const char *filename) { struct incl_file *incl_file; struct dtc_file *newfile; @@ -282,7 +285,7 @@ void push_input_file(const char *filename) } -int pop_input_file(void) +static int pop_input_file(void) { struct incl_file *incl_file; @@ -312,8 +315,5 @@ int pop_input_file(void) */ free(incl_file); - if (YY_CURRENT_BUFFER == 0) - return 0; - return 1; } diff --git a/srcpos.h b/srcpos.h index d548c09..e17c7c0 100644 --- a/srcpos.h +++ b/srcpos.h @@ -75,9 +75,6 @@ extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2))); extern struct dtc_file *srcpos_file; -extern void push_input_file(const char *filename); -extern int pop_input_file(void); - struct search_path { const char *dir; /* NULL for current directory */ struct search_path *prev, *next; diff --git a/treesource.c b/treesource.c index 9cbf0a9..3c24e7f 100644 --- a/treesource.c +++ b/treesource.c @@ -32,7 +32,8 @@ struct boot_info *dt_from_source(const char *fname) the_boot_info = NULL; treesource_error = 0; - push_input_file(fname); + srcpos_file = dtc_open_file(fname, NULL); + yyin = srcpos_file->file; if (yyparse() != 0) return NULL; From 1a9468c9a0c0bd6e3ff1b9bff7547dd7e7aa9bb7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 6 Mar 2008 15:48:04 +1100 Subject: [PATCH 0223/1198] dtc: Abolish asize field of struct data The asize field in struct data is a hangover from the early days when a struct data was sometimes allowed to refer to a static chunk of memory rather than a malloc()ed block. That's long gone, since the lifetime issues were far more trouble than it was worth, so get rid of the asize field. Signed-off-by: David Gibson --- data.c | 8 -------- dtc.h | 1 - 2 files changed, 9 deletions(-) diff --git a/data.c b/data.c index a94718c..0ee1010 100644 --- a/data.c +++ b/data.c @@ -32,8 +32,6 @@ void data_free(struct data d) m = nm; } - assert(!d.val || d.asize); - if (d.val) free(d.val); } @@ -43,9 +41,6 @@ struct data data_grow_for(struct data d, int xlen) struct data nd; int newsize; - /* we must start with an allocated datum */ - assert(!d.val || d.asize); - if (xlen == 0) return d; @@ -56,11 +51,8 @@ struct data data_grow_for(struct data d, int xlen) while ((d.len + xlen) > newsize) newsize *= 2; - nd.asize = newsize; nd.val = xrealloc(d.val, newsize); - assert(nd.asize >= (d.len + xlen)); - return nd; } diff --git a/dtc.h b/dtc.h index dbff5e8..d5be1a5 100644 --- a/dtc.h +++ b/dtc.h @@ -118,7 +118,6 @@ struct marker { struct data { int len; char *val; - int asize; struct marker *markers; }; From 3bdd393965aa1f35c293074e6701b9c550aeae54 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 11 Mar 2008 10:47:14 +1100 Subject: [PATCH 0224/1198] dtc: Add some documentation for the dts formta This patch adds a dts-format.txt in the Documentation directory, with an introduction to the dtc source format. Note that this documentation is also going into the upcoming ePAPR specification. Signed-off-by: David Gibson --- Documentation/dts-format.txt | 110 +++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 Documentation/dts-format.txt diff --git a/Documentation/dts-format.txt b/Documentation/dts-format.txt new file mode 100644 index 0000000..a655b87 --- /dev/null +++ b/Documentation/dts-format.txt @@ -0,0 +1,110 @@ +Device Tree Source Format (version 1) +===================================== + +The Device Tree Source (DTS) format is a textual representation of a +device tree in a form that can be processed by dtc into a binary +device tree in the form expected by the kernel. The description below +is not a formal syntax definition of DTS, but describes the basic +constructs used to represent device trees. + +Node and property definitions +----------------------------- + +Device tree nodes are defined with a node name and unit address with +braces marking the start and end of the node definition. They may be +preceded by a label. + + [label:] node-name[@unit-address] { + [properties definitions] + [child nodes] + } + +Nodes may contain property definitions and/or child node +definitions. If both are present, properties must come before child +nodes. + +Property definitions are name value pairs in the form: + [label:] property-name = value; +except for properties with empty (zero length) value which have the +form: + [label:] property-name; + +Property values may be defined as an array of 32-bit integer cells, as +NUL-terminated strings, as bytestrings or a combination of these. + +* Arrays of cells are represented by angle brackets surrounding a + space separated list of C-style integers + + e.g. interrupts = <17 0xc>; + +* A 64-bit value is represented with two 32-bit cells. + + e.g. clock-frequency = <0x00000001 0x00000000>; + +* A NUL-terminated string value is represented using double quotes + (the property value is considered to include the terminating NUL + character). + + e.g. compatible = "simple-bus"; + +* A bytestring is enclosed in square brackets [] with each byte + represented by two hexadecimal digits. Spaces between each byte are + optional. + + e.g. local-mac-address = [00 00 12 34 56 78]; or equivalently + local-mac-address = [000012345678]; + +* Values may have several comma-separated components, which are + concatenated together. + e.g. compatible = "ns16550", "ns8250"; + example = <0xf00f0000 19>, "a strange property format"; + +* In a cell array a reference to another node will be expanded to that + node's phandle. References may by '&' followed by a node's label: + e.g. interrupt-parent = < &mpic >; + or they may be '&' followed by a node's full path in braces: + e.g. interrupt-parent = < &{/soc/interrupt-controller@40000} >; + +* Outside a cell array, a reference to another node will be expanded + to that node's full path. + e.g. ethernet0 = &EMAC0; + +* Labels may also appear before or after any component of a property + value, or between cells of a cell array, or between bytes of a + bytestring. + e.g. reg = reglabel: <0 sizelabel: 0x1000000>; + e.g. prop = [ab cd ef byte4: 00 ff fe]; + e.g. str = start: "string value" end: ; + + +File layout +----------- + +Version 1 DTS files have the overall layout: + /dts-v1/; + + [memory reservations] + + / { + [property definitions] + [child nodes] + }; + +* The "/dts-v1/;" must be present to identify the file as a version 1 + DTS (dts files without this tag will be treated by dtc as being in + the obsolete "version 0", which uses a different format for integers + amongst other small but incompatible changes). + +* Memory reservations define an entry for the device tree blob's + memory reservation table. They have the form: + e.g. /memreserve/
; + Where
and are 64-bit C-style integers. + +* The / { ... }; section defines the root node of the device tree. + +* C style (/* ... */) and C++ style (// ...) comments are supported. + + + + -- David Gibson + -- Yoder Stuart From 2192d46dfdbb05cea13c853f7579b1386cdc4380 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 17 Mar 2008 17:03:47 +1100 Subject: [PATCH 0225/1198] dtc: Cleanup \nnn and \xNN string escape handling Several small cleanups to the handling of octal and hex string escapes: - Use strncmp() instead dof what were essentially open-coded versions of the same, with short fixed lengths. - The call path to get_oct_char() means an empty escape is not possible. So replace the error message in this case with an assert. - Use die() instead of a non-fatal error message if get_hex_char() is given an empty escape. Change error message to close match gcc's in the same circumstance. Signed-off-by: David Gibson --- data.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/data.c b/data.c index 0ee1010..0a1d81e 100644 --- a/data.c +++ b/data.c @@ -75,16 +75,11 @@ static char get_oct_char(const char *s, int *i) long val; x[3] = '\0'; - x[0] = s[(*i)]; - if (x[0]) { - x[1] = s[(*i)+1]; - if (x[1]) - x[2] = s[(*i)+2]; - } + strncpy(x, s + *i, 3); val = strtol(x, &endx, 8); - if ((endx - x) == 0) - fprintf(stderr, "Empty \\nnn escape\n"); + + assert(endx > x); (*i) += endx - x; return val; @@ -97,13 +92,11 @@ static char get_hex_char(const char *s, int *i) long val; x[2] = '\0'; - x[0] = s[(*i)]; - if (x[0]) - x[1] = s[(*i)+1]; + strncpy(x, s + *i, 2); val = strtol(x, &endx, 16); - if ((endx - x) == 0) - fprintf(stderr, "Empty \\x escape\n"); + if (!(endx > x)) + die("\\x used with no following hex digits\n"); (*i) += endx - x; return val; From 1577696b6d09acafa055957ecc6071b305d6fe9d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 18 Mar 2008 14:04:19 +1100 Subject: [PATCH 0226/1198] dtc: Change exit code for usage message If dtc's command line arguments are invalid, it prints a usage message and returns exit code 2. That's the same exit code as for a failed check, which is potentially confusing if running dtc from an automated harness. Therefore this patch changes the usage exit code to 3. Signed-off-by: David Gibson --- dtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dtc.c b/dtc.c index 75517f9..c641491 100644 --- a/dtc.c +++ b/dtc.c @@ -106,7 +106,7 @@ static void __attribute__ ((noreturn)) usage(void) fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n"); fprintf(stderr, "\t-v\n"); fprintf(stderr, "\t\tPrint DTC version and exit\n"); - exit(2); + exit(3); } int main(int argc, char *argv[]) From 35aa1a273bc407271f8a1e7b91989b9e6787879c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 16 May 2008 13:21:51 +1000 Subject: [PATCH 0227/1198] dtc: Simplify error handling for unparseable input Currently, main() tests if it got a valid input tree from whichever dt_from_*() function it invoked and if not, die()s. For one thing, this test has, for no good reason, three different ways for those functions to communicate a failure to provide input (bi NULL, bi->dt NULL, or bi->error non-zero). For another, in every case save one, if the dt_from_*() functions are unable to provide input they will immediately die() (with a more specific error message) rather than proceeding to the test in main(). Therefore, this patch removes this test, making the one case that could have triggered it (in dt_from_source()) call die() directly instead. With this change, the error field in struct boot_info is now unused, so remove it. Signed-off-by: David Gibson --- dtc.c | 3 --- dtc.h | 1 - livetree.c | 1 - treesource.c | 6 ++++-- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/dtc.c b/dtc.c index c641491..6d67c9a 100644 --- a/dtc.c +++ b/dtc.c @@ -201,9 +201,6 @@ int main(int argc, char *argv[]) if (inf && inf->file != stdin) fclose(inf->file); - if (! bi || ! bi->dt || bi->error) - die("Couldn't read input tree\n"); - fill_fullpaths(bi->dt, ""); process_checks(force, bi); diff --git a/dtc.h b/dtc.h index d5be1a5..d757242 100644 --- a/dtc.h +++ b/dtc.h @@ -232,7 +232,6 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list, struct boot_info { struct reserve_info *reservelist; struct node *dt; /* the device tree */ - int error; }; struct boot_info *build_boot_info(struct reserve_info *reservelist, diff --git a/livetree.c b/livetree.c index 7610e78..6ba0846 100644 --- a/livetree.c +++ b/livetree.c @@ -172,7 +172,6 @@ struct boot_info *build_boot_info(struct reserve_info *reservelist, bi = xmalloc(sizeof(*bi)); bi->reservelist = reservelist; bi->dt = tree; - bi->error = 0; return bi; } diff --git a/treesource.c b/treesource.c index 3c24e7f..468d6b1 100644 --- a/treesource.c +++ b/treesource.c @@ -36,9 +36,11 @@ struct boot_info *dt_from_source(const char *fname) yyin = srcpos_file->file; if (yyparse() != 0) - return NULL; + die("Unable to parse input tree\n"); + + if (treesource_error) + die("Syntax error parsing input tree\n"); - the_boot_info->error = treesource_error; return the_boot_info; } From 6a6c972cdf9e608435777dbdab02197b5c5ca759 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 16 May 2008 13:20:41 +1000 Subject: [PATCH 0228/1198] dtc: Clean up included Makefile fragments Currently the Makefile.dtc and Makefile.libfdt fragments include a number of things that seemed like they might be useful for other projects embedding the pieces, or for a make dist target. Well, we have no make dist target, it's become fairly unclear that these things would actually be useful to embedders (the kernel certainly doesn't use them), and it's a bunch of stuff with no current users. This patch, therefore, removes a bunch of unused definitions from the Makefile fragments. It also removes a dependency declared in Makefile.libfdt (of libfdt.a on the constituent .o files) which was incorrect (wrong path), and if corrected would be redundant with the similar dependency in the top-level makefile. Signed-off-by: David Gibson --- Makefile | 7 ++++--- Makefile.dtc | 18 +----------------- libfdt/Makefile.libfdt | 7 ------- tests/Makefile.tests | 4 ++-- 4 files changed, 7 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index 8a47c34..e75acae 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,7 @@ install: all $(INSTALL) -d $(DESTDIR)$(BINDIR) $(INSTALL) -m 755 dtc $(DESTDIR)$(BINDIR) $(INSTALL) -d $(DESTDIR)$(LIBDIR) - $(INSTALL) -m 644 $(LIBFDT_LIB) $(DESTDIR)$(LIBDIR) + $(INSTALL) -m 644 $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) $(INSTALL) -m 644 $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES)) $(DESTDIR)$(INCLUDEDIR) @@ -135,12 +135,13 @@ endif # LIBFDT_objdir = libfdt LIBFDT_srcdir = libfdt +LIBFDT_lib = $(LIBFDT_objdir)/libfdt.a include $(LIBFDT_srcdir)/Makefile.libfdt .PHONY: libfdt -libfdt: $(LIBFDT_LIB) +libfdt: $(LIBFDT_lib) -$(LIBFDT_LIB): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) +$(LIBFDT_lib): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) libfdt_clean: @$(VECHO) CLEAN "(libfdt)" diff --git a/Makefile.dtc b/Makefile.dtc index d607fdb..6ddf9ec 100644 --- a/Makefile.dtc +++ b/Makefile.dtc @@ -5,21 +5,5 @@ # DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \ checks.c -DTC_EXTRA = dtc.h srcpos.h -DTC_LEXFILES = dtc-lexer.l -DTC_BISONFILES = dtc-parser.y - -DTC_LEX_SRCS = $(DTC_LEXFILES:%.l=%.lex.c) -DTC_BISON_SRCS = $(DTC_BISONFILES:%.y=%.tab.c) -DTC_BISON_INCLUDES = $(DTC_BISONFILES:%.y=%.tab.h) - -DTC_GEN_SRCS = $(DTC_LEX_SRCS) $(DTC_BISON_SRCS) -DTC_GEN_ALL = $(DTC_GEN_SRCS) $(DTC_BISON_INCLUDES) +DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o) - -DTC_CLEANFILES = $(DTC_GEN_ALL) - -# We assume the containing Makefile system can do auto-dependencies for most -# things, but we supply the dependencies on generated header files explicitly - -$(addprefix $(DTC_objdir)/,$(DTC_GEN_SRCS:%.c=%.o)): $(addprefix $(DTC_objdir)/,$(DTC_BISON_INCLUDES)) diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index 82f9c6a..f4f495b 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -4,11 +4,4 @@ # be easily embeddable into other systems of Makefiles. # LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c -LIBFDT_INCLUDES = fdt.h libfdt.h -LIBFDT_EXTRA = libfdt_internal.h -LIBFDT_LIB = libfdt/libfdt.a - LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) - -$(LIBFDT_objdir)/$(LIBFDT_LIB): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) - diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 830d0a9..d7c9ebc 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -35,9 +35,9 @@ BIN += $(TESTS) $(TESTS_PREFIX)dumptrees .PHONY: tests tests: $(TESTS) $(TESTS_TREES) -$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_LIB) +$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_lib) -$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o $(LIBFDT_LIB) +$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o $(LIBFDT_lib) $(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o From c26015443acaefe0780a3209932e5534cd84a330 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 16 May 2008 13:22:35 +1000 Subject: [PATCH 0229/1198] dtc: Trivial formatting fixes This patch fixes some trivial indentation and brace/bracket style problems. --- dtc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dtc.c b/dtc.c index 6d67c9a..9b0164c 100644 --- a/dtc.c +++ b/dtc.c @@ -164,8 +164,8 @@ int main(int argc, char *argv[]) boot_cpuid_phys = strtol(optarg, NULL, 0); break; case 'v': - printf("Version: %s\n", DTC_VERSION); - exit(0); + printf("Version: %s\n", DTC_VERSION); + exit(0); case 'h': default: usage(); @@ -180,9 +180,8 @@ int main(int argc, char *argv[]) arg = argv[optind]; /* minsize and padsize are mutually exclusive */ - if ((minsize) && (padsize)) { + if (minsize && padsize) die("Can't set both -p and -S\n"); - } fprintf(stderr, "DTC: %s->%s on file \"%s\"\n", inform, outform, arg); From a742aade6a28fbebf7a66448b40b983549897253 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 16 May 2008 13:22:09 +1000 Subject: [PATCH 0230/1198] dtc: Make dt_from_blob() open its own input file, like the other input formats Currently, main() has a variable for the input file. It used to be that main() would open the input based on command line arguments before passing it to the dt_from_*() function. However, only dt_from_blob() uses this. dt_from_source() opens its own file, and dt_from_fs() interprets the argument as as a directory and does its own opendir() call. Furthermore, main() opened the file with dtc_open_file() but closed it with a direct call to fclose(). Therefore, to improve the interface consistency between the dt_from_*() functions, make dt_from_blob() open and close its own files like the other dt_from_*() functions. Signed-off-by: David Gibson --- dtc.c | 16 +++++----------- dtc.h | 2 +- flattree.c | 26 ++++++++++++++++---------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/dtc.c b/dtc.c index 9b0164c..267d581 100644 --- a/dtc.c +++ b/dtc.c @@ -118,7 +118,6 @@ int main(int argc, char *argv[]) int force = 0, check = 0; const char *arg; int opt; - struct dtc_file *inf = NULL; FILE *outf = NULL; int outversion = DEFAULT_FDT_VERSION; int boot_cpuid_phys = 0xfeedbeef; @@ -186,19 +185,14 @@ int main(int argc, char *argv[]) fprintf(stderr, "DTC: %s->%s on file \"%s\"\n", inform, outform, arg); - if (streq(inform, "dts")) { + if (streq(inform, "dts")) bi = dt_from_source(arg); - } else if (streq(inform, "fs")) { + else if (streq(inform, "fs")) bi = dt_from_fs(arg); - } else if(streq(inform, "dtb")) { - inf = dtc_open_file(arg, NULL); - bi = dt_from_blob(inf->file); - } else { + else if(streq(inform, "dtb")) + bi = dt_from_blob(arg); + else die("Unknown input format \"%s\"\n", inform); - } - - if (inf && inf->file != stdin) - fclose(inf->file); fill_fullpaths(bi->dt, ""); process_checks(force, bi); diff --git a/dtc.h b/dtc.h index d757242..8935483 100644 --- a/dtc.h +++ b/dtc.h @@ -248,7 +248,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys); -struct boot_info *dt_from_blob(FILE *f); +struct boot_info *dt_from_blob(const char *fname); /* Tree source */ diff --git a/flattree.c b/flattree.c index 8675857..fd69293 100644 --- a/flattree.c +++ b/flattree.c @@ -19,6 +19,7 @@ */ #include "dtc.h" +#include "srcpos.h" #define FTF_FULLPATH 0x1 #define FTF_VARALIGN 0x2 @@ -780,8 +781,9 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, } -struct boot_info *dt_from_blob(FILE *f) +struct boot_info *dt_from_blob(const char *fname) { + struct dtc_file *dtcf; u32 magic, totalsize, version, size_dt; u32 off_dt, off_str, off_mem_rsvmap; int rc; @@ -796,12 +798,14 @@ struct boot_info *dt_from_blob(FILE *f) u32 val; int flags = 0; - rc = fread(&magic, sizeof(magic), 1, f); - if (ferror(f)) + dtcf = dtc_open_file(fname, NULL); + + rc = fread(&magic, sizeof(magic), 1, dtcf->file); + if (ferror(dtcf->file)) die("Error reading DT blob magic number: %s\n", strerror(errno)); if (rc < 1) { - if (feof(f)) + if (feof(dtcf->file)) die("EOF reading DT blob magic number\n"); else die("Mysterious short read reading magic number\n"); @@ -811,11 +815,11 @@ struct boot_info *dt_from_blob(FILE *f) if (magic != FDT_MAGIC) die("Blob has incorrect magic number\n"); - rc = fread(&totalsize, sizeof(totalsize), 1, f); - if (ferror(f)) + rc = fread(&totalsize, sizeof(totalsize), 1, dtcf->file); + if (ferror(dtcf->file)) die("Error reading DT blob size: %s\n", strerror(errno)); if (rc < 1) { - if (feof(f)) + if (feof(dtcf->file)) die("EOF reading DT blob size\n"); else die("Mysterious short read reading blob size\n"); @@ -835,12 +839,12 @@ struct boot_info *dt_from_blob(FILE *f) p = blob + sizeof(magic) + sizeof(totalsize); while (sizeleft) { - if (feof(f)) + if (feof(dtcf->file)) die("EOF before reading %d bytes of DT blob\n", totalsize); - rc = fread(p, 1, sizeleft, f); - if (ferror(f)) + rc = fread(p, 1, sizeleft, dtcf->file); + if (ferror(dtcf->file)) die("Error reading DT blob: %s\n", strerror(errno)); @@ -902,5 +906,7 @@ struct boot_info *dt_from_blob(FILE *f) free(blob); + dtc_close_file(dtcf); + return build_boot_info(reservelist, tree); } From 548767f42eb00a2bac6f2a1361b7fd49f7b76908 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 16 May 2008 13:22:57 +1000 Subject: [PATCH 0231/1198] dtc: Rework handling of boot_cpuid_phys Currently, dtc will put the nonsense value 0xfeedbeef into the boot_cpuid_phys field of an output blob, unless explicitly given another value with the -b command line option. As well as being a totally unuseful default value, this also means that dtc won't properly preserve the boot_cpuid_phys field in -I dtb -O dtb mode. This patch reworks things to improve the boot_cpuid handling. The new semantics are that the output's boot_cpuid_phys value is: the value given on the command line if -b is used otherwise the value from the input, if in -I dtb mode otherwise 0 Implementation-wise we do the following: - boot_cpuid_phys is added to struct boot_info, so that structure now contains all of the blob's semantic information. - dt_to_blob() and dt_to_asm() output the cpuid given in boot_info - dt_from_blob() fills in boot_info based on the input blob - The other dt_from_*() functions just record 0, but we can change this easily if e.g. we invent a way of specifying the boot cpu in the source format. - main() overrides the cpuid in the boot_info between input and output if -b is given We add some testcases to check this new behaviour. Signed-off-by: David Gibson --- dtc-parser.y | 4 ++-- dtc.c | 12 ++++++---- dtc.h | 9 ++++--- flattree.c | 14 +++++------ fstree.c | 2 +- livetree.c | 3 ++- tests/Makefile.tests | 2 +- tests/boot-cpuid.c | 48 ++++++++++++++++++++++++++++++++++++++ tests/dtbs_equal_ordered.c | 7 ++++++ tests/run_tests.sh | 8 +++++++ 10 files changed, 88 insertions(+), 21 deletions(-) create mode 100644 tests/boot-cpuid.c diff --git a/dtc-parser.y b/dtc-parser.y index 4ab1df9..0bf3fcb 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -85,11 +85,11 @@ static unsigned long long eval_literal(const char *s, int base, int bits); sourcefile: DT_V1 ';' memreserves devicetree { - the_boot_info = build_boot_info($3, $4); + the_boot_info = build_boot_info($3, $4, 0); } | v0_memreserves devicetree { - the_boot_info = build_boot_info($1, $2); + the_boot_info = build_boot_info($1, $2, 0); } ; diff --git a/dtc.c b/dtc.c index 267d581..d8fd43b 100644 --- a/dtc.c +++ b/dtc.c @@ -120,7 +120,7 @@ int main(int argc, char *argv[]) int opt; FILE *outf = NULL; int outversion = DEFAULT_FDT_VERSION; - int boot_cpuid_phys = 0xfeedbeef; + long long cmdline_boot_cpuid = -1; quiet = 0; reservenum = 0; @@ -160,7 +160,7 @@ int main(int argc, char *argv[]) quiet++; break; case 'b': - boot_cpuid_phys = strtol(optarg, NULL, 0); + cmdline_boot_cpuid = strtoll(optarg, NULL, 0); break; case 'v': printf("Version: %s\n", DTC_VERSION); @@ -194,9 +194,13 @@ int main(int argc, char *argv[]) else die("Unknown input format \"%s\"\n", inform); + if (cmdline_boot_cpuid != -1) + bi->boot_cpuid_phys = cmdline_boot_cpuid; + fill_fullpaths(bi->dt, ""); process_checks(force, bi); + if (streq(outname, "-")) { outf = stdout; } else { @@ -209,9 +213,9 @@ int main(int argc, char *argv[]) if (streq(outform, "dts")) { dt_to_source(outf, bi); } else if (streq(outform, "dtb")) { - dt_to_blob(outf, bi, outversion, boot_cpuid_phys); + dt_to_blob(outf, bi, outversion); } else if (streq(outform, "asm")) { - dt_to_asm(outf, bi, outversion, boot_cpuid_phys); + dt_to_asm(outf, bi, outversion); } else if (streq(outform, "null")) { /* do nothing */ } else { diff --git a/dtc.h b/dtc.h index 8935483..762706e 100644 --- a/dtc.h +++ b/dtc.h @@ -232,10 +232,11 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list, struct boot_info { struct reserve_info *reservelist; struct node *dt; /* the device tree */ + u32 boot_cpuid_phys; }; struct boot_info *build_boot_info(struct reserve_info *reservelist, - struct node *tree); + struct node *tree, u32 boot_cpuid_phys); /* Checks */ @@ -243,10 +244,8 @@ void process_checks(int force, struct boot_info *bi); /* Flattened trees */ -void dt_to_blob(FILE *f, struct boot_info *bi, int version, - int boot_cpuid_phys); -void dt_to_asm(FILE *f, struct boot_info *bi, int version, - int boot_cpuid_phys); +void dt_to_blob(FILE *f, struct boot_info *bi, int version); +void dt_to_asm(FILE *f, struct boot_info *bi, int version); struct boot_info *dt_from_blob(const char *fname); diff --git a/flattree.c b/flattree.c index fd69293..51f43e7 100644 --- a/flattree.c +++ b/flattree.c @@ -354,8 +354,7 @@ static void make_fdt_header(struct fdt_header *fdt, fdt->size_dt_struct = cpu_to_be32(dtsize); } -void dt_to_blob(FILE *f, struct boot_info *bi, int version, - int boot_cpuid_phys) +void dt_to_blob(FILE *f, struct boot_info *bi, int version) { struct version_info *vi = NULL; int i; @@ -380,7 +379,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version, /* Make header */ make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len, - boot_cpuid_phys); + bi->boot_cpuid_phys); /* * If the user asked for more space than is used, adjust the totalsize. @@ -446,7 +445,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf) } } -void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) +void dt_to_asm(FILE *f, struct boot_info *bi, int version) { struct version_info *vi = NULL; int i; @@ -486,7 +485,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys) if (vi->flags & FTF_BOOTCPUID) fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n", - boot_cpuid_phys); + bi->boot_cpuid_phys); if (vi->flags & FTF_STRTABSIZE) fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n", @@ -784,7 +783,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, struct boot_info *dt_from_blob(const char *fname) { struct dtc_file *dtcf; - u32 magic, totalsize, version, size_dt; + u32 magic, totalsize, version, size_dt, boot_cpuid_phys; u32 off_dt, off_str, off_mem_rsvmap; int rc; char *blob; @@ -856,6 +855,7 @@ struct boot_info *dt_from_blob(const char *fname) off_str = be32_to_cpu(fdt->off_dt_strings); off_mem_rsvmap = be32_to_cpu(fdt->off_mem_rsvmap); version = be32_to_cpu(fdt->version); + boot_cpuid_phys = be32_to_cpu(fdt->boot_cpuid_phys); if (off_mem_rsvmap >= totalsize) die("Mem Reserve structure offset exceeds total size\n"); @@ -908,5 +908,5 @@ struct boot_info *dt_from_blob(const char *fname) dtc_close_file(dtcf); - return build_boot_info(reservelist, tree); + return build_boot_info(reservelist, tree, boot_cpuid_phys); } diff --git a/fstree.c b/fstree.c index 0c0bdf0..766b269 100644 --- a/fstree.c +++ b/fstree.c @@ -87,6 +87,6 @@ struct boot_info *dt_from_fs(const char *dirname) tree = read_fstree(dirname); tree = name_node(tree, "", NULL); - return build_boot_info(NULL, tree); + return build_boot_info(NULL, tree, 0); } diff --git a/livetree.c b/livetree.c index 6ba0846..0b250fb 100644 --- a/livetree.c +++ b/livetree.c @@ -165,13 +165,14 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list, } struct boot_info *build_boot_info(struct reserve_info *reservelist, - struct node *tree) + struct node *tree, u32 boot_cpuid_phys) { struct boot_info *bi; bi = xmalloc(sizeof(*bi)); bi->reservelist = reservelist; bi->dt = tree; + bi->boot_cpuid_phys = boot_cpuid_phys; return bi; } diff --git a/tests/Makefile.tests b/tests/Makefile.tests index d7c9ebc..df331c4 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -9,7 +9,7 @@ LIB_TESTS_L = get_mem_rsv \ sw_tree1 \ move_and_save mangle-layout nopulate \ open_pack rw_tree1 set_name setprop del_property del_node \ - string_escapes references path-references \ + string_escapes references path-references boot-cpuid \ dtbs_equal_ordered \ add_subnode_with_nops LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) diff --git a/tests/boot-cpuid.c b/tests/boot-cpuid.c new file mode 100644 index 0000000..7b5433d --- /dev/null +++ b/tests/boot-cpuid.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + void *fdt; + uint32_t cpuid; + + test_init(argc, argv); + + if (argc != 3) + CONFIG("Usage: %s ", argv[0]); + + fdt = load_blob(argv[1]); + cpuid = strtoul(argv[2], NULL, 0); + + if (fdt_boot_cpuid_phys(fdt) != cpuid) + FAIL("Incorrect boot_cpuid_phys (0x%x instead of 0x%x)", + fdt_boot_cpuid_phys(fdt), cpuid); + + PASS(); +} diff --git a/tests/dtbs_equal_ordered.c b/tests/dtbs_equal_ordered.c index 0c30ad3..2847bbd 100644 --- a/tests/dtbs_equal_ordered.c +++ b/tests/dtbs_equal_ordered.c @@ -125,6 +125,7 @@ void compare_structure(const void *fdt1, const void *fdt2) int main(int argc, char *argv[]) { void *fdt1, *fdt2; + uint32_t cpuid1, cpuid2; test_init(argc, argv); if (argc != 3) @@ -135,5 +136,11 @@ int main(int argc, char *argv[]) compare_mem_rsv(fdt1, fdt2); compare_structure(fdt1, fdt2); + cpuid1 = fdt_boot_cpuid_phys(fdt1); + cpuid2 = fdt_boot_cpuid_phys(fdt2); + if (cpuid1 != cpuid2) + FAIL("boot_cpuid_phys mismatch 0x%x != 0x%x", + cpuid1, cpuid2); + PASS(); } diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 27dc11a..c187ae9 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -199,6 +199,14 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb + # Check boot_cpuid_phys handling + run_dtc_test -I dts -O dtb -b 17 -o boot_cpuid.test.dtb empty.dts + run_test boot-cpuid boot_cpuid.test.dtb 17 + run_dtc_test -I dtb -O dtb -b 17 -o boot_cpuid_test_tree1.test.dtb test_tree1.dtb + run_test boot-cpuid boot_cpuid_test_tree1.test.dtb 17 + run_dtc_test -I dtb -O dtb -o boot_cpuid_preserved_test_tree1.test.dtb boot_cpuid_test_tree1.test.dtb + run_test dtbs_equal_ordered boot_cpuid_preserved_test_tree1.test.dtb boot_cpuid_test_tree1.test.dtb + # Check -Odts mode preserve all dtb information for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb ; do run_dtc_test -I dtb -O dts -o odts_$tree.test.dts $tree From a84c065f44ea0f4dcd75ae4ecb8dd1e25a5f87f7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 15 May 2008 16:39:12 +1000 Subject: [PATCH 0232/1198] dtc: Add program to convert dts files from v0 to v1 This patch adds a new utility program, convert-dtsv0, to the dtc sources. This program will convert dts files from v0 to v1, preserving comments and spacing. It also includes some heuristics to guess an appropriate base to use in the v1 output (so it will use hex for the contents of reg properties and decimal for clock-frequency properties, for example). They're limited and imperfect, but not terrible. The guts of the converter program is a modified version of the lexer from dtc itself. Signed-off-by: David Gibson --- Makefile | 10 +- convert-dtsv0-lexer.l | 260 ++++++++++++++++++++++++++++++++++++++++++ tests/Makefile.tests | 8 +- tests/run_tests.sh | 27 ++++- 4 files changed, 297 insertions(+), 8 deletions(-) create mode 100644 convert-dtsv0-lexer.l diff --git a/Makefile b/Makefile index e75acae..a8f02cb 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ else DEPTARGETS = $(filter-out $(NODEPTARGETS),$(MAKECMDGOALS)) endif -all: dtc ftdump libfdt +all: dtc ftdump convert-dtsv0 libfdt install: all @$(VECHO) INSTALL @@ -121,12 +121,16 @@ ifneq ($(DEPTARGETS),) -include $(DTC_OBJS:%.o=%.d) endif # -# Rules for ftdump +# Rules for ftdump & convert-dtsv0 # -BIN += ftdump +BIN += ftdump convert-dtsv0 ftdump: ftdump.o +convert-dtsv0: convert-dtsv0-lexer.lex.o srcpos.o + @$(VECHO) LD $@ + $(LINK.c) -o $@ $^ + ifneq ($(DEPTARGETS),) -include ftdump.d endif diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l new file mode 100644 index 0000000..d235bd5 --- /dev/null +++ b/convert-dtsv0-lexer.l @@ -0,0 +1,260 @@ +/* + * (C) Copyright David Gibson , IBM Corporation. 2005, 2008. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +%option noyywrap nounput stack + +%x INCLUDE +%x BYTESTRING +%x PROPNODENAME + +PROPNODECHAR [a-zA-Z0-9,._+*#?@-] +PATHCHAR ({PROPNODECHAR}|[/]) +LABEL [a-zA-Z_][a-zA-Z0-9_]* + +%{ +#include +#include +#include +#include "srcpos.h" + +static int v1_tagged; /* = 0 */ +static int cbase = 16; +static int saw_hyphen; /* = 0 */ +static unsigned long long last_val; +static char *last_name; /* = NULL */ + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +static inline void __attribute__((noreturn)) die(char * str, ...) +{ + va_list ap; + + va_start(ap, str); + fprintf(stderr, "FATAL ERROR: "); + vfprintf(stderr, str, ap); + exit(1); +} + +static inline void *xmalloc(size_t len) +{ + void *new = malloc(len); + + if (! new) + die("malloc() failed\n"); + + return new; +} + +const struct { + const char *pattern; + int obase, width; +} guess_table[] = { + { "*-frequency", 10, 0 }, + { "num-*", 10, 0 }, + { "#*-cells", 10, 0 }, + { "*cache-line-size", 10, 0 }, + { "*cache-block-size", 10, 0 }, + { "*cache-size", 10, 0 }, + { "*cache-sets", 10, 0 }, + { "cell-index", 10, 0 }, + { "bank-width", 10, 0 }, + { "*-fifo-size", 10, 0 }, + { "*-frame-size", 10, 0 }, + { "*-channel", 10, 0 }, + { "current-speed", 10, 0 }, + { "phy-map", 16, 8 }, + { "dcr-reg", 16, 3 }, + { "reg", 16, 8 }, + { "ranges", 16, 8}, +}; +%} + +%% +<*>"/include/" { + ECHO; + yy_push_state(INCLUDE); + } + +\"[^"\n]*\" { + ECHO; + yy_pop_state(); + } + + +<*>\"([^\\"]|\\.)*\" ECHO; + +<*>"/dts-v1/" { + die("Input dts file is already version 1\n"); + } + +<*>"/memreserve/" { + if (!v1_tagged) { + fprintf(yyout, "/dts-v1/;\n\n"); + v1_tagged = 1; + } + + ECHO; + BEGIN(INITIAL); + } + +<*>{LABEL}: ECHO; + +[bodh]# { + if (*yytext == 'b') + cbase = 2; + else if (*yytext == 'o') + cbase = 8; + else if (*yytext == 'd') + cbase = 10; + else + cbase = 16; + } + +[0-9a-fA-F]+ { + unsigned long long val; + int obase = 16, width = 0; + int i; + + val = strtoull(yytext, NULL, cbase); + + if (saw_hyphen) + val = val - last_val + 1; + + if (last_name) { + for (i = 0; i < ARRAY_SIZE(guess_table); i++) + if (fnmatch(guess_table[i].pattern, + last_name, 0) == 0) { + obase = guess_table[i].obase; + width = guess_table[i].width; + } + } else { + obase = 16; + width = 16; + } + + if (cbase != 16) + obase = cbase; + + switch (obase) { + case 2: + case 16: + fprintf(yyout, "0x%0*llx", width, val); + break; + case 8: + fprintf(yyout, "0%0*llo", width, val); + break; + case 10: + fprintf(yyout, "%*llu", width, val); + break; + } + + cbase = 16; + last_val = val; + saw_hyphen = 0; + } + +\&{LABEL} ECHO; + +"&{/"{PATHCHAR}+\} ECHO; + +"&/"{PATHCHAR}+ fprintf(yyout, "&{/%s}", yytext + 2); + +[0-9a-fA-F]{2} ECHO; + +"]" { + ECHO; + BEGIN(INITIAL); + } + +{PROPNODECHAR}+ { + ECHO; + last_name = strdup(yytext); + BEGIN(INITIAL); + } + +<*>[[:space:]]+ ECHO; + +<*>"/*"([^*]|\*+[^*/])*\*+"/" ECHO; + +<*>"//".*\n ECHO; + +<*>- { /* Hack to convert old style memreserves */ + saw_hyphen = 1; + fprintf(yyout, " "); + } + +<*>. { + if (!v1_tagged) { + fprintf(yyout, "/dts-v1/;\n\n"); + v1_tagged = 1; + } + + ECHO; + if (yytext[0] == '[') { + BEGIN(BYTESTRING); + } + if ((yytext[0] == '{') + || (yytext[0] == ';')) { + BEGIN(PROPNODENAME); + } + } + +%% +static void usage(void) +{ + fprintf(stderr, "convert-dtsv0 ...\n"); + exit(3); +} + +static void convert_file(const char *fname) +{ + const char suffix[] = "v1"; + int len = strlen(fname); + char *newname; + + newname = xmalloc(len + sizeof(suffix)); + memcpy(newname, fname, len); + memcpy(newname + len, suffix, sizeof(suffix)); + + srcpos_file = dtc_open_file(fname, NULL); + yyin = srcpos_file->file; + + yyout = fopen(newname, "w"); + if (!yyout) + die("Couldn't open output file %s: %s\n", + newname, strerror(errno)); + + while(yylex()) + ; +} + +int main(int argc, char *argv[]) +{ + int i; + + if (argc < 2) + usage(); + + for (i = 1; i < argc; i++) { + fprintf(stderr, "Converting %s from dts v0 to dts v1\n", argv[i]); + convert_file(argv[i]); + } + + exit(0); +} diff --git a/tests/Makefile.tests b/tests/Makefile.tests index df331c4..cb57ac0 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -27,7 +27,7 @@ TESTS_TARGETS = $(TESTS) $(TESTS_TREES) TESTS_DEPFILES = $(TESTS:%=%.d) \ $(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d) -TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts tmp.* +TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts *.dtsv1 tmp.* TESTS_CLEANFILES = $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) BIN += $(TESTS) $(TESTS_PREFIX)dumptrees @@ -50,13 +50,13 @@ tests_clean: rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%) rm -f $(TESTS_CLEANFILES) -check: tests dtc +check: tests dtc convert-dtsv0 cd $(TESTS_PREFIX); ./run_tests.sh -checkm: tests dtc +checkm: tests dtc convert-dtsv0 cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$ -checkv: tests dtc +checkv: tests dtc convert-dtsv0 cd $(TESTS_PREFIX); ./run_tests.sh -v ifneq ($(DEPTARGETS),) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c187ae9..81fdc86 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -71,6 +71,13 @@ run_dtc_test () { base_run_test wrap_test $VALGRIND $DTC "$@" } +CONVERT=../convert-dtsv0 + +run_convert_test () { + echo -n "convert-dtsv0 $@: " + base_run_test wrap_test $VALGRIND $CONVERT "$@" +} + tree1_tests () { TREE=$1 @@ -259,6 +266,21 @@ dtc_tests () { run_sh_test dtc-fatal.sh -I fs -O dtb nosuchfile } +convert_tests () { + V0_DTS="test_tree1_dts0.dts references_dts0.dts empty.dts escapes.dts \ + test01.dts label01.dts" + for dts in $V0_DTS; do + run_dtc_test -I dts -O dtb -o cvtraw_$dts.test.dtb $dts + run_dtc_test -I dts -O dts -o cvtdtc_$dts.test.dts $dts + run_dtc_test -I dts -O dtb -o cvtdtc_$dts.test.dtb cvtdtc_$dts.test.dts + run_convert_test $dts + run_dtc_test -I dts -O dtb -o cvtcvt_$dts.test.dtb ${dts}v1 + + run_wrap_test cmp cvtraw_$dts.test.dtb cvtdtc_$dts.test.dtb + run_wrap_test cmp cvtraw_$dts.test.dtb cvtcvt_$dts.test.dtb + done +} + while getopts "vt:m" ARG ; do case $ARG in "v") @@ -274,7 +296,7 @@ while getopts "vt:m" ARG ; do done if [ -z "$TESTSETS" ]; then - TESTSETS="libfdt dtc" + TESTSETS="libfdt dtc convert" fi # Make sure we don't have stale blobs lying around @@ -288,6 +310,9 @@ for set in $TESTSETS; do "dtc") dtc_tests ;; + "convert") + convert_tests + ;; esac done From e4a64a8cd0205ee61ca164d1628026e5c960fbaa Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 20 May 2008 14:50:50 +1000 Subject: [PATCH 0233/1198] dtc: Remove reference to dead Makefile variables Previous cleanups have removed the LIBFDT_CLEANFILES and DTC_CLEANFILES variables from the Makefiles. However, they're still referenced by the Makefile. This patch gets rid of these last vestiges. Signed-off-by: David Gibson --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a8f02cb..9e0abff 100644 --- a/Makefile +++ b/Makefile @@ -150,7 +150,6 @@ $(LIBFDT_lib): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) libfdt_clean: @$(VECHO) CLEAN "(libfdt)" rm -f $(addprefix $(LIBFDT_objdir)/,$(STD_CLEANFILES)) - rm -f $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_CLEANFILES)) ifneq ($(DEPTARGETS),) -include $(LIBFDT_OBJS:%.o=$(LIBFDT_objdir)/%.d) @@ -170,7 +169,7 @@ STD_CLEANFILES = *~ *.o *.d *.a *.i *.s core a.out vgcore.* \ clean: libfdt_clean tests_clean @$(VECHO) CLEAN - rm -f $(STD_CLEANFILES) $(DTC_CLEANFILES) + rm -f $(STD_CLEANFILES) rm -f $(VERSION_FILE) rm -f $(BIN) From aa1baab3cc184169cfb05dfe289b5179c8333e3c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 20 May 2008 17:19:11 +1000 Subject: [PATCH 0234/1198] libfdt: Several cleanups to parameter checking This patch makes a couple of small cleanups to parameter checking of libfdt functions. - In several functions which take a node offset, we use an idiom involving fdt_next_tag() first to check that we have indeed been given a node offset. This patch adds a helper function _fdt_check_node_offset() to encapsulate this usage of fdt_next_tag(). - In fdt_rw.c in several places we have the expanded version of the RW_CHECK_HEADER() macro for no particular reason. This patch replaces those instances with an invocation of the macro; that's what it's for. - In fdt_sw.c we rename the check_header_sw() function to sw_check_header() to match the analgous function in fdt_rw.c, and we provide an SW_CHECK_HEADER() wrapper macro as RW_CHECK_HEADER() functions in fdt_rw.c Signed-off-by: David Gibson --- libfdt/fdt.c | 17 ++++++++++++----- libfdt/fdt_ro.c | 26 ++++++++------------------ libfdt/fdt_rw.c | 24 ++++++++---------------- libfdt/fdt_sw.c | 31 +++++++++++++++---------------- libfdt/libfdt_internal.h | 1 + 5 files changed, 44 insertions(+), 55 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index bd91712..0d16427 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -129,16 +129,23 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset) return tag; } +int _fdt_check_node_offset(const void *fdt, int offset) +{ + if ((offset < 0) || (offset % FDT_TAGSIZE) + || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) + return -FDT_ERR_BADOFFSET; + + return offset; +} + int fdt_next_node(const void *fdt, int offset, int *depth) { int nextoffset = 0; uint32_t tag; - if (offset >= 0) { - tag = fdt_next_tag(fdt, offset, &nextoffset); - if (tag != FDT_BEGIN_NODE) - return -FDT_ERR_BADOFFSET; - } + if (offset >= 0) + if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0) + return nextoffset; do { offset = nextoffset; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 63fa129..e55872f 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -157,16 +157,12 @@ int fdt_path_offset(const void *fdt, const char *path) const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) { - const struct fdt_node_header *nh; + const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); int err; - if ((err = fdt_check_header(fdt)) != 0) - goto fail; - - err = -FDT_ERR_BADOFFSET; - nh = fdt_offset_ptr(fdt, nodeoffset, sizeof(*nh)); - if (!nh || (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE)) - goto fail; + if (((err = fdt_check_header(fdt)) != 0) + || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) + goto fail; if (len) *len = strlen(nh->name); @@ -189,17 +185,11 @@ const struct fdt_property *fdt_get_property(const void *fdt, int offset, nextoffset; int err; - if ((err = fdt_check_header(fdt)) != 0) - goto fail; - - err = -FDT_ERR_BADOFFSET; - if (nodeoffset % FDT_TAGSIZE) - goto fail; - - tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); - if (tag != FDT_BEGIN_NODE) - goto fail; + if (((err = fdt_check_header(fdt)) != 0) + || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) + goto fail; + nextoffset = err; do { offset = nextoffset; diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 0df472b..ec0738c 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -172,8 +172,7 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) struct fdt_reserve_entry *re; int err; - if ((err = rw_check_header(fdt))) - return err; + RW_CHECK_HEADER(fdt); re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); err = _blob_splice_mem_rsv(fdt, re, 0, 1); @@ -190,8 +189,8 @@ int fdt_del_mem_rsv(void *fdt, int n) struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); int err; - if ((err = rw_check_header(fdt))) - return err; + RW_CHECK_HEADER(fdt); + if (n >= fdt_num_mem_rsv(fdt)) return -FDT_ERR_NOTFOUND; @@ -223,15 +222,13 @@ static int _resize_property(void *fdt, int nodeoffset, const char *name, int len static int _add_property(void *fdt, int nodeoffset, const char *name, int len, struct fdt_property **prop) { - uint32_t tag; int proplen; int nextoffset; int namestroff; int err; - tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); - if (tag != FDT_BEGIN_NODE) - return -FDT_ERR_BADOFFSET; + if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) + return nextoffset; namestroff = _find_add_string(fdt, name); if (namestroff < 0) @@ -256,8 +253,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name) int oldlen, newlen; int err; - if ((err = rw_check_header(fdt))) - return err; + RW_CHECK_HEADER(fdt); namep = (char *)fdt_get_name(fdt, nodeoffset, &oldlen); if (!namep) @@ -280,8 +276,7 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, struct fdt_property *prop; int err; - if ((err = rw_check_header(fdt))) - return err; + RW_CHECK_HEADER(fdt); err = _resize_property(fdt, nodeoffset, name, len, &prop); if (err == -FDT_ERR_NOTFOUND) @@ -452,11 +447,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) int fdt_pack(void *fdt) { int mem_rsv_size; - int err; - err = rw_check_header(fdt); - if (err) - return err; + RW_CHECK_HEADER(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index dda2de3..df09876 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -55,13 +55,21 @@ #include "libfdt_internal.h" -static int check_header_sw(void *fdt) +static int sw_check_header(void *fdt) { if (fdt_magic(fdt) != SW_MAGIC) return -FDT_ERR_BADMAGIC; + /* FIXME: should check more details about the header state */ return 0; } +#define SW_CHECK_HEADER(fdt) \ + { \ + int err; \ + if ((err = sw_check_header(fdt)) != 0) \ + return err; \ + } + static void *grab_space(void *fdt, int len) { int offset = fdt_size_dt_struct(fdt); @@ -102,11 +110,10 @@ int fdt_create(void *buf, int bufsize) int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) { struct fdt_reserve_entry *re; - int err = check_header_sw(fdt); int offset; - if (err) - return err; + SW_CHECK_HEADER(fdt); + if (fdt_size_dt_struct(fdt)) return -FDT_ERR_BADSTATE; @@ -131,11 +138,9 @@ int fdt_finish_reservemap(void *fdt) int fdt_begin_node(void *fdt, const char *name) { struct fdt_node_header *nh; - int err = check_header_sw(fdt); int namelen = strlen(name) + 1; - if (err) - return err; + SW_CHECK_HEADER(fdt); nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE)); if (! nh) @@ -149,10 +154,8 @@ int fdt_begin_node(void *fdt, const char *name) int fdt_end_node(void *fdt) { uint32_t *en; - int err = check_header_sw(fdt); - if (err) - return err; + SW_CHECK_HEADER(fdt); en = grab_space(fdt, FDT_TAGSIZE); if (! en) @@ -188,11 +191,9 @@ static int find_add_string(void *fdt, const char *s) int fdt_property(void *fdt, const char *name, const void *val, int len) { struct fdt_property *prop; - int err = check_header_sw(fdt); int nameoff; - if (err) - return err; + SW_CHECK_HEADER(fdt); nameoff = find_add_string(fdt, name); if (nameoff == 0) @@ -211,15 +212,13 @@ int fdt_property(void *fdt, const char *name, const void *val, int len) int fdt_finish(void *fdt) { - int err = check_header_sw(fdt); char *p = (char *)fdt; uint32_t *end; int oldstroffset, newstroffset; uint32_t tag; int offset, nextoffset; - if (err) - return err; + SW_CHECK_HEADER(fdt); /* Add terminator */ end = grab_space(fdt, sizeof(*end)); diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 52e1b8d..f72e70d 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -66,6 +66,7 @@ } uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset); +int _fdt_check_node_offset(const void *fdt, int offset); const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); int _fdt_node_end_offset(void *fdt, int nodeoffset); From fc6e6f8d916b0d52b59a1c2a66f280e7fb7a80f5 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 29 May 2008 16:16:21 +1000 Subject: [PATCH 0235/1198] dtc: Remove some small bashisms from test scripts Some of the helper scripts used to run testcases contain some constructs that are bashisms. Or at least which don't work on dash, the minimal shell used as /bin/sh on recent Ubuntu systems. This patch removes these constructs so that the testsuite will pass "out of the box" on systems where /bin/sh is dash. Signed-off-by: David Gibson --- tests/dtc-checkfails.sh | 2 +- tests/dtc-fatal.sh | 2 +- tests/tests.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh index 265173c..c58694f 100755 --- a/tests/dtc-checkfails.sh +++ b/tests/dtc-checkfails.sh @@ -1,6 +1,6 @@ #! /bin/sh -. tests.sh +. ./tests.sh for x; do shift diff --git a/tests/dtc-fatal.sh b/tests/dtc-fatal.sh index 8eb1b44..6781ced 100644 --- a/tests/dtc-fatal.sh +++ b/tests/dtc-fatal.sh @@ -1,6 +1,6 @@ #! /bin/sh -. tests.sh +. ./tests.sh verbose_run $VALGRIND "$DTC" -o/dev/null "$@" ret="$?" diff --git a/tests/tests.sh b/tests/tests.sh index 28b3fb1..30ffead 100644 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -23,7 +23,7 @@ verbose_run () { verbose_run_log () { LOG="$1" shift - "$@" &> "$LOG" + "$@" > "$LOG" 2>&1 ret=$? if [ -z "$QUIET_TEST" ]; then cat "$LOG" >&2 From 6aaee513ddcb9f1ee1a0c6294f129546c99d8b5c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 30 May 2008 11:34:18 +1000 Subject: [PATCH 0236/1198] dtc: Fix some printf() format warnings when compiling 64-bit Currently, dtc generates a few gcc build warnings if built for a 64-bit target, due to the altered type of uint64_t and size_t. This patch fixes the warnings (without generating new warnings for 32-bit). Signed-off-by: David Gibson --- tests/dtbs_equal_ordered.c | 5 ++++- tests/references.c | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/dtbs_equal_ordered.c b/tests/dtbs_equal_ordered.c index 2847bbd..a0b42ae 100644 --- a/tests/dtbs_equal_ordered.c +++ b/tests/dtbs_equal_ordered.c @@ -49,7 +49,10 @@ void compare_mem_rsv(const void *fdt1, const void *fdt2) if ((addr1 != addr2) || (size1 != size2)) FAIL("Mismatch in reserve entry %d: " "(0x%llx, 0x%llx) != (0x%llx, 0x%llx)", i, - addr1, size1, addr2, size2); + (unsigned long long)addr1, + (unsigned long long)size1, + (unsigned long long)addr2, + (unsigned long long)size2); } } diff --git a/tests/references.c b/tests/references.c index affc1d7..e98d450 100644 --- a/tests/references.c +++ b/tests/references.c @@ -38,7 +38,7 @@ void check_ref(const void *fdt, int node, uint32_t checkref) if (!p) FAIL("fdt_getprop(%d, \"ref\"): %s", node, fdt_strerror(len)); if (len != sizeof(*p)) - FAIL("'ref' in node at %d has wrong size (%d instead of %d)", + FAIL("'ref' in node at %d has wrong size (%d instead of %zd)", node, len, sizeof(*p)); ref = fdt32_to_cpu(*p); if (ref != checkref) @@ -49,7 +49,7 @@ void check_ref(const void *fdt, int node, uint32_t checkref) if (!p) FAIL("fdt_getprop(%d, \"lref\"): %s", node, fdt_strerror(len)); if (len != sizeof(*p)) - FAIL("'lref' in node at %d has wrong size (%d instead of %d)", + FAIL("'lref' in node at %d has wrong size (%d instead of %zd)", node, len, sizeof(*p)); ref = fdt32_to_cpu(*p); if (ref != checkref) From 050e6f0cff5b93a15fefbc0b554cad9a9ab5ea82 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 30 May 2008 11:36:00 +1000 Subject: [PATCH 0237/1198] dtc: Add a testcase for 'reg' or 'ranges' in / This patch adds an extra testcase to dtc to ensure that the "reg_format" and "ranges_format" checks trigger as they should if a 'reg' or 'ranges' property appears in the root node. Signed-off-by: David Gibson --- tests/reg-ranges-root.dts | 8 ++++++++ tests/run_tests.sh | 1 + 2 files changed, 9 insertions(+) create mode 100644 tests/reg-ranges-root.dts diff --git a/tests/reg-ranges-root.dts b/tests/reg-ranges-root.dts new file mode 100644 index 0000000..9935b41 --- /dev/null +++ b/tests/reg-ranges-root.dts @@ -0,0 +1,8 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + reg = <0x1000 0x10>; + ranges = <0x1000 0x2000 0x1000>; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 81fdc86..72efc08 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -248,6 +248,7 @@ dtc_tests () { run_sh_test dtc-checkfails.sh device_type_is_string model_is_string status_is_string -- -I dts -O dtb bad-string-props.dts run_sh_test dtc-checkfails.sh reg_format ranges_format -- -I dts -O dtb bad-reg-ranges.dts run_sh_test dtc-checkfails.sh ranges_format -- -I dts -O dtb bad-empty-ranges.dts + run_sh_test dtc-checkfails.sh reg_format ranges_format -- -I dts -O dtb reg-ranges-root.dts run_sh_test dtc-checkfails.sh avoid_default_addr_size -- -I dts -O dtb default-addr-size.dts run_sh_test dtc-checkfails.sh obsolete_chosen_interrupt_controller -- -I dts -O dtb obsolete-chosen-interrupt-controller.dts run_sh_test dtc-checkfails.sh node_name_chars -- -I dtb -O dtb bad_node_char.dtb From e37ec7d5889fa04047daaa7a4ff55150ed7954d4 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 11 Jun 2008 11:58:39 +1000 Subject: [PATCH 0238/1198] dtc: Add support for binary includes. On Wed, Jun 04, 2008 at 09:26:23AM -0500, Jon Loeliger wrote: > David Gibson wrote: > >> But as I said that can be dealt with in the future without breaking >> compatibility. Objection withdrawn. >> > > And on that note, I officially implore Scott to > re-submit his binary include patch! Scott's original patch does still have some implementation details I didn't like. So in the interests of saving time, I've addressed some of those, added a testcase, and and now resubmitting my revised version of Scott's patch. dtc: Add support for binary includes. A property's data can be populated with a file's contents as follows: node { prop = /incbin/("path/to/data"); }; A subset of a file can be included by passing start and size parameters. For example, to include bytes 8 through 23: node { prop = /incbin/("path/to/data", 8, 16); }; As with /include/, non-absolute paths are looked for in the directory of the source file that includes them. Implementation revised, and a testcase added by David Gibson Signed-off-by: Scott Wood Signed-off-by: David Gibson Acked-by: Scott Wood --- data.c | 25 ++++++++++++--- dtc-lexer.l | 7 +++++ dtc-parser.y | 31 ++++++++++++++++++ tests/Makefile.tests | 2 +- tests/incbin.bin | 1 + tests/incbin.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ tests/incbin.dts | 6 ++++ tests/run_tests.sh | 4 +++ 8 files changed, 145 insertions(+), 6 deletions(-) create mode 100644 tests/incbin.bin create mode 100644 tests/incbin.c create mode 100644 tests/incbin.dts diff --git a/data.c b/data.c index 0a1d81e..cffa10d 100644 --- a/data.c +++ b/data.c @@ -167,14 +167,29 @@ struct data data_copy_escape_string(const char *s, int len) return d; } -struct data data_copy_file(FILE *f, size_t len) +struct data data_copy_file(FILE *f, size_t maxlen) { - struct data d; + struct data d = empty_data; - d = data_grow_for(empty_data, len); + while (!feof(f) && (d.len < maxlen)) { + size_t chunksize, ret; - d.len = len; - fread(d.val, len, 1, f); + if (maxlen == -1) + chunksize = 4096; + else + chunksize = maxlen - d.len; + + d = data_grow_for(d, chunksize); + ret = fread(d.val + d.len, 1, chunksize, f); + + if (ferror(f)) + die("Error reading file into data: %s", strerror(errno)); + + if (d.len + ret < d.len) + die("Overflow reading file into data\n"); + + d.len += ret; + } return d; } diff --git a/dtc-lexer.l b/dtc-lexer.l index 04b1753..8f15c4d 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -190,6 +190,13 @@ static int pop_input_file(void); return DT_PROPNODENAME; } +"/incbin/" { + yylloc.file = srcpos_file; + yylloc.first_line = yylineno; + DPRINT("Binary Include\n"); + return DT_INCBIN; + } + <*>[[:space:]]+ /* eat whitespace */ <*>"/*"([^*]|\*+[^*/])*\*+"/" { diff --git a/dtc-parser.y b/dtc-parser.y index 0bf3fcb..8d04e49 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -21,6 +21,8 @@ %locations %{ +#include + #include "dtc.h" #include "srcpos.h" @@ -59,6 +61,7 @@ static unsigned long long eval_literal(const char *s, int base, int bits); %token DT_STRING %token DT_LABEL %token DT_REF +%token DT_INCBIN %type propdata %type propdataprefix @@ -197,6 +200,34 @@ propdata: { $$ = data_add_marker($1, REF_PATH, $2); } + | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')' + { + struct search_path path = { srcpos_file->dir, NULL, NULL }; + struct dtc_file *file = dtc_open_file($4.val, &path); + struct data d = empty_data; + + if ($6 != 0) + if (fseek(file->file, $6, SEEK_SET) != 0) + yyerrorf("Couldn't seek to offset %llu in \"%s\": %s", + (unsigned long long)$6, + $4.val, strerror(errno)); + + d = data_copy_file(file->file, $8); + + $$ = data_merge($1, d); + dtc_close_file(file); + } + | propdataprefix DT_INCBIN '(' DT_STRING ')' + { + struct search_path path = { srcpos_file->dir, NULL, NULL }; + struct dtc_file *file = dtc_open_file($4.val, &path); + struct data d = empty_data; + + d = data_copy_file(file->file, -1); + + $$ = data_merge($1, d); + dtc_close_file(file); + } | propdata DT_LABEL { $$ = data_add_marker($1, LABEL, $2); diff --git a/tests/Makefile.tests b/tests/Makefile.tests index cb57ac0..704c95d 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -9,7 +9,7 @@ LIB_TESTS_L = get_mem_rsv \ sw_tree1 \ move_and_save mangle-layout nopulate \ open_pack rw_tree1 set_name setprop del_property del_node \ - string_escapes references path-references boot-cpuid \ + string_escapes references path-references boot-cpuid incbin \ dtbs_equal_ordered \ add_subnode_with_nops LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) diff --git a/tests/incbin.bin b/tests/incbin.bin new file mode 100644 index 0000000..e6e3e48 --- /dev/null +++ b/tests/incbin.bin @@ -0,0 +1 @@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ \ No newline at end of file diff --git a/tests/incbin.c b/tests/incbin.c new file mode 100644 index 0000000..2f8a55a --- /dev/null +++ b/tests/incbin.c @@ -0,0 +1,75 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for string escapes in dtc + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +#define CHUNKSIZE 1024 + +void *load_file(const char *name, int *len) +{ + FILE *f; + void *buf = NULL; + int bufsize = 0, n; + + *len = 0; + + f = fopen(name, "r"); + if (!f) + FAIL("Couldn't open \"%s\": %s", name, strerror(errno)); + + while (!feof(f)) { + if (bufsize < (*len + CHUNKSIZE)) { + buf = xrealloc(buf, *len + CHUNKSIZE); + bufsize = *len + CHUNKSIZE; + } + + n = fread(buf + *len, 1, CHUNKSIZE, f); + if (ferror(f)) + FAIL("Error reading \"%s\": %s", name, strerror(errno)); + *len += n; + } + + return buf; +} + +int main(int argc, char *argv[]) +{ + void *fdt, *incbin; + int len; + + test_init(argc, argv); + + incbin = load_file("incbin.bin", &len); + fdt = load_blob_arg(argc, argv); + + check_getprop(fdt, 0, "incbin", len, incbin); + check_getprop(fdt, 0, "incbin-partial", 17, incbin + 13); + + PASS(); +} diff --git a/tests/incbin.dts b/tests/incbin.dts new file mode 100644 index 0000000..7c30e0e --- /dev/null +++ b/tests/incbin.dts @@ -0,0 +1,6 @@ +/dts-v1/; + +/ { + incbin = /incbin/("incbin.bin"); + incbin-partial = /incbin/("incbin.bin", 13, 17); +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 72efc08..3b78f8d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -206,6 +206,10 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb + # Check /incbin/ directive + run_dtc_test -I dts -O dtb -o incbin.test.dtb incbin.dts + run_test incbin incbin.test.dtb + # Check boot_cpuid_phys handling run_dtc_test -I dts -O dtb -b 17 -o boot_cpuid.test.dtb empty.dts run_test boot-cpuid boot_cpuid.test.dtb 17 From f8bf4bfc8796b46e6086a52f0cd6c1f9ed58645a Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Thu, 19 Jun 2008 11:33:20 -0500 Subject: [PATCH 0239/1198] Tag Version 1.2.0-rc1 Signed-off-by: Jon Loeliger --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 9e0abff..3f4a174 100644 --- a/Makefile +++ b/Makefile @@ -9,9 +9,9 @@ # CONFIG_LOCALVERSION from some future config system. # VERSION = 1 -PATCHLEVEL = 1 +PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION =-rc1 LOCAL_VERSION = CONFIG_LOCALVERSION = From f8e52fe6d87cadbaf0b440073fb9137bef36ee98 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 24 Jun 2008 11:21:44 +1000 Subject: [PATCH 0240/1198] dtc: Testcase for /include/ directive This patch adds a testcase for the /include/ directive. It assembles a sample dts file with many /include/ directives at a variety of different lexical / grammatical contexts. Signed-off-by: David Gibson --- tests/include0.dts | 1 + tests/include1.dts | 23 +++++++++++++++++++++++ tests/include2.dts | 1 + tests/include3.dts | 1 + tests/include4.dts | 1 + tests/include5.dts | 1 + tests/include6.dts | 1 + tests/include7.dts | 9 +++++++++ tests/include8.dts | 1 + tests/run_tests.sh | 4 ++++ 10 files changed, 43 insertions(+) create mode 100644 tests/include0.dts create mode 100644 tests/include1.dts create mode 100644 tests/include2.dts create mode 100644 tests/include3.dts create mode 100644 tests/include4.dts create mode 100644 tests/include5.dts create mode 100644 tests/include6.dts create mode 100644 tests/include7.dts create mode 100644 tests/include8.dts diff --git a/tests/include0.dts b/tests/include0.dts new file mode 100644 index 0000000..355ed6a --- /dev/null +++ b/tests/include0.dts @@ -0,0 +1 @@ +/include/ "include1.dts" diff --git a/tests/include1.dts b/tests/include1.dts new file mode 100644 index 0000000..0c7f42e --- /dev/null +++ b/tests/include1.dts @@ -0,0 +1,23 @@ +/dts-v1/; + +/include/ "include2.dts" +/memreserve/ /include/ "include3.dts"; + +/ { + /include/ "include4.dts" + /include/ "include5.dts" = <0xdeadbeef>; + prop-str = /include/ "include6.dts"; + + /include/ "include7.dts" + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + /include/ "include8.dts" + linux,phandle = <0x2001>; + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; + }; + }; +}; diff --git a/tests/include2.dts b/tests/include2.dts new file mode 100644 index 0000000..7e189dd --- /dev/null +++ b/tests/include2.dts @@ -0,0 +1 @@ +/memreserve/ 0xdeadbeef00000000 0x100000; diff --git a/tests/include3.dts b/tests/include3.dts new file mode 100644 index 0000000..ee9d277 --- /dev/null +++ b/tests/include3.dts @@ -0,0 +1 @@ +123456789 010000 diff --git a/tests/include4.dts b/tests/include4.dts new file mode 100644 index 0000000..b2ddbe5 --- /dev/null +++ b/tests/include4.dts @@ -0,0 +1 @@ + compatible = "test_tree1"; diff --git a/tests/include5.dts b/tests/include5.dts new file mode 100644 index 0000000..9a35dc5 --- /dev/null +++ b/tests/include5.dts @@ -0,0 +1 @@ +prop-int diff --git a/tests/include6.dts b/tests/include6.dts new file mode 100644 index 0000000..cd4bc1a --- /dev/null +++ b/tests/include6.dts @@ -0,0 +1 @@ +"hello world" diff --git a/tests/include7.dts b/tests/include7.dts new file mode 100644 index 0000000..fa726f9 --- /dev/null +++ b/tests/include7.dts @@ -0,0 +1,9 @@ + subnode@1 { + compatible = "subnode1"; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + }; diff --git a/tests/include8.dts b/tests/include8.dts new file mode 100644 index 0000000..ec70064 --- /dev/null +++ b/tests/include8.dts @@ -0,0 +1 @@ +subsubnode@0 { \ No newline at end of file diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 3b78f8d..ed0c450 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -206,6 +206,10 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb + # Check /include/ directive + run_dtc_test -I dts -O dtb -o includes.test.dtb include0.dts + run_test dtbs_equal_ordered includes.test.dtb test_tree1.dtb + # Check /incbin/ directive run_dtc_test -I dts -O dtb -o incbin.test.dtb incbin.dts run_test incbin incbin.test.dtb From 53359016caf6db9ab2347517a323d6ba8eb6671e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 25 Jun 2008 13:53:07 +1000 Subject: [PATCH 0241/1198] dtc: Use stdint.h types throughout dtc Currently, dtc defines Linux-like names for various fixed-size integer types. There's no good reason to do this; even Linux itself doesn't use these names for externally visible things any more. This patch replaces these with the C99 standardized type names from stdint.h. Signed-off-by: David Gibson --- data.c | 4 ++-- dtc-parser.y | 4 ++-- dtc.h | 14 +++++--------- flattree.c | 32 ++++++++++++++++---------------- livetree.c | 5 +++-- 5 files changed, 28 insertions(+), 31 deletions(-) diff --git a/data.c b/data.c index cffa10d..588c87e 100644 --- a/data.c +++ b/data.c @@ -262,9 +262,9 @@ struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) return data_append_data(d, &bere, sizeof(bere)); } -struct data data_append_addr(struct data d, u64 addr) +struct data data_append_addr(struct data d, uint64_t addr) { - u64 beaddr = cpu_to_be64(addr); + uint64_t beaddr = cpu_to_be64(addr); return data_append_data(d, &beaddr, sizeof(beaddr)); } diff --git a/dtc-parser.y b/dtc-parser.y index 8d04e49..b2ab562 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -39,10 +39,10 @@ static unsigned long long eval_literal(const char *s, int base, int bits); char *literal; char *labelref; unsigned int cbase; - u8 byte; + uint8_t byte; struct data data; - u64 addr; + uint64_t addr; cell_t cell; struct property *prop; struct property *proplist; diff --git a/dtc.h b/dtc.h index 762706e..7154bfd 100644 --- a/dtc.h +++ b/dtc.h @@ -75,11 +75,7 @@ static inline void *xrealloc(void *p, size_t len) return new; } -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -typedef u32 cell_t; +typedef uint32_t cell_t; #define cpu_to_be16(x) htons(x) #define be16_to_cpu(x) ntohs(x) @@ -144,7 +140,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m, struct data data_merge(struct data d1, struct data d2); struct data data_append_cell(struct data d, cell_t word); struct data data_append_re(struct data d, const struct fdt_reserve_entry *re); -struct data data_append_addr(struct data d, u64 addr); +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); @@ -222,7 +218,7 @@ struct reserve_info { char *label; }; -struct reserve_info *build_reserve_entry(u64 start, u64 len, char *label); +struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len, char *label); struct reserve_info *chain_reserve_entry(struct reserve_info *first, struct reserve_info *list); struct reserve_info *add_reserve_entry(struct reserve_info *list, @@ -232,11 +228,11 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list, struct boot_info { struct reserve_info *reservelist; struct node *dt; /* the device tree */ - u32 boot_cpuid_phys; + uint32_t boot_cpuid_phys; }; struct boot_info *build_boot_info(struct reserve_info *reservelist, - struct node *tree, u32 boot_cpuid_phys); + struct node *tree, uint32_t boot_cpuid_phys); /* Checks */ diff --git a/flattree.c b/flattree.c index 51f43e7..49514f8 100644 --- a/flattree.c +++ b/flattree.c @@ -168,16 +168,16 @@ static void asm_emit_data(void *e, struct data d) for_each_marker_of_type(m, LABEL) emit_offset_label(f, m->ref, m->offset); - while ((d.len - off) >= sizeof(u32)) { + while ((d.len - off) >= sizeof(uint32_t)) { fprintf(f, "\t.long\t0x%x\n", - be32_to_cpu(*((u32 *)(d.val+off)))); - off += sizeof(u32); + be32_to_cpu(*((uint32_t *)(d.val+off)))); + off += sizeof(uint32_t); } - if ((d.len - off) >= sizeof(u16)) { + if ((d.len - off) >= sizeof(uint16_t)) { fprintf(f, "\t.short\t0x%hx\n", - be16_to_cpu(*((u16 *)(d.val+off)))); - off += sizeof(u16); + be16_to_cpu(*((uint16_t *)(d.val+off)))); + off += sizeof(uint16_t); } if ((d.len - off) >= 1) { @@ -575,9 +575,9 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len) inb->ptr += len; } -static u32 flat_read_word(struct inbuf *inb) +static uint32_t flat_read_word(struct inbuf *inb) { - u32 val; + uint32_t val; assert(((inb->ptr - inb->base) % sizeof(val)) == 0); @@ -611,7 +611,7 @@ static char *flat_read_string(struct inbuf *inb) inb->ptr += len; - flat_realign(inb, sizeof(u32)); + flat_realign(inb, sizeof(uint32_t)); return str; } @@ -628,7 +628,7 @@ static struct data flat_read_data(struct inbuf *inb, int len) flat_read_chunk(inb, d.val, len); - flat_realign(inb, sizeof(u32)); + flat_realign(inb, sizeof(uint32_t)); return d; } @@ -655,7 +655,7 @@ static char *flat_read_stringtable(struct inbuf *inb, int offset) static struct property *flat_read_property(struct inbuf *dtbuf, struct inbuf *strbuf, int flags) { - u32 proplen, stroff; + uint32_t proplen, stroff; char *name; struct data val; @@ -725,7 +725,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, { struct node *node; char *flatname; - u32 val; + uint32_t val; node = build_node(NULL, NULL); @@ -783,8 +783,8 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, struct boot_info *dt_from_blob(const char *fname) { struct dtc_file *dtcf; - u32 magic, totalsize, version, size_dt, boot_cpuid_phys; - u32 off_dt, off_str, off_mem_rsvmap; + uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys; + uint32_t off_dt, off_str, off_mem_rsvmap; int rc; char *blob; struct fdt_header *fdt; @@ -794,7 +794,7 @@ struct boot_info *dt_from_blob(const char *fname) int sizeleft; struct reserve_info *reservelist; struct node *tree; - u32 val; + uint32_t val; int flags = 0; dtcf = dtc_open_file(fname, NULL); @@ -867,7 +867,7 @@ struct boot_info *dt_from_blob(const char *fname) die("String table offset exceeds total size\n"); if (version >= 3) { - u32 size_str = be32_to_cpu(fdt->size_dt_strings); + uint32_t size_str = be32_to_cpu(fdt->size_dt_strings); if (off_str+size_str > totalsize) die("String table extends past total size\n"); inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str); diff --git a/livetree.c b/livetree.c index 0b250fb..51680ae 100644 --- a/livetree.c +++ b/livetree.c @@ -123,7 +123,8 @@ void add_child(struct node *parent, struct node *child) *p = child; } -struct reserve_info *build_reserve_entry(u64 address, u64 size, char *label) +struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size, + char *label) { struct reserve_info *new = xmalloc(sizeof(*new)); @@ -165,7 +166,7 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list, } struct boot_info *build_boot_info(struct reserve_info *reservelist, - struct node *tree, u32 boot_cpuid_phys) + struct node *tree, uint32_t boot_cpuid_phys) { struct boot_info *bi; From c8c374b8565081da08e3d1d73df8ddb0d6a66ae3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 25 Jun 2008 14:27:53 +1000 Subject: [PATCH 0242/1198] dtc: Use the same endian-conversion functions as libfdt Currently both libfdt and dtc define a set of endian conversion macros for accessing the device tree blob which is always big-endian. libfdt uses names like cpu_to_fdt32() and dtc uses names like cpu_to_be32 (as the Linux kernel). This patch switches dtc over to using the libfdt macros (including libfdt_env.h to supply them). This has a couple of small advantages: - Removes some code duplication - Will make conversion a bit easier if we ever need to produce little-endian device tree blobs. - dtc no longer needs to pull in netinet/in.h simply for the ntohs() and ntohl() functions Signed-off-by: David Gibson --- checks.c | 2 +- data.c | 8 +++---- dtc.h | 17 +------------- flattree.c | 66 ++++++++++++++++++++++++---------------------------- livetree.c | 2 +- treesource.c | 2 +- 6 files changed, 38 insertions(+), 59 deletions(-) diff --git a/checks.c b/checks.c index 34941de..0066fb3 100644 --- a/checks.c +++ b/checks.c @@ -363,7 +363,7 @@ static void fixup_phandle_references(struct check *c, struct node *dt, } phandle = get_node_phandle(dt, refnode); - *((cell_t *)(prop->val.val + m->offset)) = cpu_to_be32(phandle); + *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); } } CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR, diff --git a/data.c b/data.c index 588c87e..dd2e3d3 100644 --- a/data.c +++ b/data.c @@ -247,7 +247,7 @@ struct data data_merge(struct data d1, struct data d2) struct data data_append_cell(struct data d, cell_t word) { - cell_t beword = cpu_to_be32(word); + cell_t beword = cpu_to_fdt32(word); return data_append_data(d, &beword, sizeof(beword)); } @@ -256,15 +256,15 @@ struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) { struct fdt_reserve_entry bere; - bere.address = cpu_to_be64(re->address); - bere.size = cpu_to_be64(re->size); + bere.address = cpu_to_fdt64(re->address); + bere.size = cpu_to_fdt64(re->size); return data_append_data(d, &bere, sizeof(bere)); } struct data data_append_addr(struct data d, uint64_t addr) { - uint64_t beaddr = cpu_to_be64(addr); + uint64_t beaddr = cpu_to_fdt64(addr); return data_append_data(d, &beaddr, sizeof(beaddr)); } diff --git a/dtc.h b/dtc.h index 7154bfd..08d54c8 100644 --- a/dtc.h +++ b/dtc.h @@ -30,10 +30,8 @@ #include #include #include -#include -#include -#include +#include #include #define DEFAULT_FDT_VERSION 17 @@ -77,19 +75,6 @@ static inline void *xrealloc(void *p, size_t len) typedef uint32_t cell_t; -#define cpu_to_be16(x) htons(x) -#define be16_to_cpu(x) ntohs(x) - -#define cpu_to_be32(x) htonl(x) -#define be32_to_cpu(x) ntohl(x) - -#if __BYTE_ORDER == __BIG_ENDIAN -#define cpu_to_be64(x) (x) -#define be64_to_cpu(x) (x) -#else -#define cpu_to_be64(x) bswap_64(x) -#define be64_to_cpu(x) bswap_64(x) -#endif #define streq(a, b) (strcmp((a), (b)) == 0) #define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) diff --git a/flattree.c b/flattree.c index 49514f8..76acd28 100644 --- a/flattree.c +++ b/flattree.c @@ -170,17 +170,11 @@ static void asm_emit_data(void *e, struct data d) while ((d.len - off) >= sizeof(uint32_t)) { fprintf(f, "\t.long\t0x%x\n", - be32_to_cpu(*((uint32_t *)(d.val+off)))); + fdt32_to_cpu(*((uint32_t *)(d.val+off)))); off += sizeof(uint32_t); } - if ((d.len - off) >= sizeof(uint16_t)) { - fprintf(f, "\t.short\t0x%hx\n", - be16_to_cpu(*((uint16_t *)(d.val+off)))); - off += sizeof(uint16_t); - } - - if ((d.len - off) >= 1) { + while ((d.len - off) >= 1) { fprintf(f, "\t.byte\t0x%hhx\n", d.val[off]); off += 1; } @@ -333,25 +327,25 @@ static void make_fdt_header(struct fdt_header *fdt, memset(fdt, 0xff, sizeof(*fdt)); - fdt->magic = cpu_to_be32(FDT_MAGIC); - fdt->version = cpu_to_be32(vi->version); - fdt->last_comp_version = cpu_to_be32(vi->last_comp_version); + fdt->magic = cpu_to_fdt32(FDT_MAGIC); + fdt->version = cpu_to_fdt32(vi->version); + fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version); /* Reserve map should be doubleword aligned */ reserve_off = ALIGN(vi->hdr_size, 8); - fdt->off_mem_rsvmap = cpu_to_be32(reserve_off); - fdt->off_dt_struct = cpu_to_be32(reserve_off + reservesize); - fdt->off_dt_strings = cpu_to_be32(reserve_off + reservesize + fdt->off_mem_rsvmap = cpu_to_fdt32(reserve_off); + fdt->off_dt_struct = cpu_to_fdt32(reserve_off + reservesize); + fdt->off_dt_strings = cpu_to_fdt32(reserve_off + reservesize + dtsize); - fdt->totalsize = cpu_to_be32(reserve_off + reservesize + dtsize + strsize); + fdt->totalsize = cpu_to_fdt32(reserve_off + reservesize + dtsize + strsize); if (vi->flags & FTF_BOOTCPUID) - fdt->boot_cpuid_phys = cpu_to_be32(boot_cpuid_phys); + fdt->boot_cpuid_phys = cpu_to_fdt32(boot_cpuid_phys); if (vi->flags & FTF_STRTABSIZE) - fdt->size_dt_strings = cpu_to_be32(strsize); + fdt->size_dt_strings = cpu_to_fdt32(strsize); if (vi->flags & FTF_STRUCTSIZE) - fdt->size_dt_struct = cpu_to_be32(dtsize); + fdt->size_dt_struct = cpu_to_fdt32(dtsize); } void dt_to_blob(FILE *f, struct boot_info *bi, int version) @@ -385,20 +379,20 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version) * If the user asked for more space than is used, adjust the totalsize. */ if (minsize > 0) { - padlen = minsize - be32_to_cpu(fdt.totalsize); + padlen = minsize - fdt32_to_cpu(fdt.totalsize); if ((padlen < 0) && (quiet < 1)) fprintf(stderr, "Warning: blob size %d >= minimum size %d\n", - be32_to_cpu(fdt.totalsize), minsize); + fdt32_to_cpu(fdt.totalsize), minsize); } if (padsize > 0) padlen = padsize; if (padlen > 0) { - int tsize = be32_to_cpu(fdt.totalsize); + int tsize = fdt32_to_cpu(fdt.totalsize); tsize += padlen; - fdt.totalsize = cpu_to_be32(tsize); + fdt.totalsize = cpu_to_fdt32(tsize); } /* @@ -583,7 +577,7 @@ static uint32_t flat_read_word(struct inbuf *inb) flat_read_chunk(inb, &val, sizeof(val)); - return be32_to_cpu(val); + return fdt32_to_cpu(val); } static void flat_realign(struct inbuf *inb, int align) @@ -689,8 +683,8 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) p = inb->ptr; while (1) { flat_read_chunk(inb, &re, sizeof(re)); - re.address = be64_to_cpu(re.address); - re.size = be64_to_cpu(re.size); + re.address = fdt64_to_cpu(re.address); + re.size = fdt64_to_cpu(re.size); if (re.size == 0) break; @@ -810,7 +804,7 @@ struct boot_info *dt_from_blob(const char *fname) die("Mysterious short read reading magic number\n"); } - magic = be32_to_cpu(magic); + magic = fdt32_to_cpu(magic); if (magic != FDT_MAGIC) die("Blob has incorrect magic number\n"); @@ -824,15 +818,15 @@ struct boot_info *dt_from_blob(const char *fname) die("Mysterious short read reading blob size\n"); } - totalsize = be32_to_cpu(totalsize); + totalsize = fdt32_to_cpu(totalsize); if (totalsize < FDT_V1_SIZE) die("DT blob size (%d) is too small\n", totalsize); blob = xmalloc(totalsize); fdt = (struct fdt_header *)blob; - fdt->magic = cpu_to_be32(magic); - fdt->totalsize = cpu_to_be32(totalsize); + fdt->magic = cpu_to_fdt32(magic); + fdt->totalsize = cpu_to_fdt32(totalsize); sizeleft = totalsize - sizeof(magic) - sizeof(totalsize); p = blob + sizeof(magic) + sizeof(totalsize); @@ -851,11 +845,11 @@ struct boot_info *dt_from_blob(const char *fname) p += rc; } - off_dt = be32_to_cpu(fdt->off_dt_struct); - off_str = be32_to_cpu(fdt->off_dt_strings); - off_mem_rsvmap = be32_to_cpu(fdt->off_mem_rsvmap); - version = be32_to_cpu(fdt->version); - boot_cpuid_phys = be32_to_cpu(fdt->boot_cpuid_phys); + off_dt = fdt32_to_cpu(fdt->off_dt_struct); + off_str = fdt32_to_cpu(fdt->off_dt_strings); + off_mem_rsvmap = fdt32_to_cpu(fdt->off_mem_rsvmap); + version = fdt32_to_cpu(fdt->version); + boot_cpuid_phys = fdt32_to_cpu(fdt->boot_cpuid_phys); if (off_mem_rsvmap >= totalsize) die("Mem Reserve structure offset exceeds total size\n"); @@ -867,7 +861,7 @@ struct boot_info *dt_from_blob(const char *fname) die("String table offset exceeds total size\n"); if (version >= 3) { - uint32_t size_str = be32_to_cpu(fdt->size_dt_strings); + uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings); if (off_str+size_str > totalsize) die("String table extends past total size\n"); inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str); @@ -876,7 +870,7 @@ struct boot_info *dt_from_blob(const char *fname) } if (version >= 17) { - size_dt = be32_to_cpu(fdt->size_dt_struct); + size_dt = fdt32_to_cpu(fdt->size_dt_struct); if (off_dt+size_dt > totalsize) die("Structure block extends past total size\n"); } diff --git a/livetree.c b/livetree.c index 51680ae..ba7e263 100644 --- a/livetree.c +++ b/livetree.c @@ -204,7 +204,7 @@ struct property *get_property(struct node *node, const char *propname) cell_t propval_cell(struct property *prop) { assert(prop->val.len == sizeof(cell_t)); - return be32_to_cpu(*((cell_t *)prop->val.val)); + return fdt32_to_cpu(*((cell_t *)prop->val.val)); } struct node *get_subnode(struct node *node, const char *nodename) diff --git a/treesource.c b/treesource.c index 468d6b1..c32e818 100644 --- a/treesource.c +++ b/treesource.c @@ -147,7 +147,7 @@ static void write_propval_cells(FILE *f, struct data val) m = m->next; } - fprintf(f, "0x%x", be32_to_cpu(*cp++)); + fprintf(f, "0x%x", fdt32_to_cpu(*cp++)); if ((void *)cp >= propend) break; fprintf(f, " "); From 11d7100ee5de7d6a6c4a76b735a1e624fbe8466a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 26 Jun 2008 10:43:06 +1000 Subject: [PATCH 0243/1198] dtc: Use libfdt endian conversion functions in libfdt Following on from the last patch, which made dtc use the same endian conversion functions as libfdt, this patch makes ftdump use these functions as well. This brings us down to a single set of endian handling functions in all of dtc and libfdt, so just one place to fix things. Signed-off-by: David Gibson --- ftdump.c | 47 ++++++++++++++++------------------------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/ftdump.c b/ftdump.c index 0cdae81..c8f4092 100644 --- a/ftdump.c +++ b/ftdump.c @@ -6,24 +6,9 @@ #include #include #include -#include -#include #include - -#define cpu_to_be16(x) htons(x) -#define be16_to_cpu(x) ntohs(x) - -#define cpu_to_be32(x) htonl(x) -#define be32_to_cpu(x) ntohl(x) - -#if __BYTE_ORDER == __BIG_ENDIAN -#define cpu_to_be64(x) (x) -#define be64_to_cpu(x) (x) -#else -#define cpu_to_be64(x) bswap_64(x) -#define be64_to_cpu(x) bswap_64(x) -#endif +#include #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) #define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) @@ -81,15 +66,15 @@ static void print_data(const void *data, int len) static void dump_blob(void *blob) { struct fdt_header *bph = blob; - uint32_t off_mem_rsvmap = be32_to_cpu(bph->off_mem_rsvmap); - uint32_t off_dt = be32_to_cpu(bph->off_dt_struct); - uint32_t off_str = be32_to_cpu(bph->off_dt_strings); + uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap); + uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct); + uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings); struct fdt_reserve_entry *p_rsvmap = (struct fdt_reserve_entry *)(blob + off_mem_rsvmap); char *p_struct = blob + off_dt; char *p_strings = blob + off_str; - uint32_t version = be32_to_cpu(bph->version); - uint32_t totalsize = be32_to_cpu(bph->totalsize); + uint32_t version = fdt32_to_cpu(bph->version); + uint32_t totalsize = fdt32_to_cpu(bph->totalsize); uint32_t tag; char *p; char *s, *t; @@ -100,29 +85,29 @@ static void dump_blob(void *blob) depth = 0; shift = 4; - printf("// magic:\t\t0x%x\n", be32_to_cpu(bph->magic)); + printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic)); printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize); printf("// off_dt_struct:\t0x%x\n", off_dt); printf("// off_dt_strings:\t0x%x\n", off_str); printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap); printf("// version:\t\t%d\n", version); printf("// last_comp_version:\t%d\n", - be32_to_cpu(bph->last_comp_version)); + fdt32_to_cpu(bph->last_comp_version)); if (version >= 2) printf("// boot_cpuid_phys:\t0x%x\n", - be32_to_cpu(bph->boot_cpuid_phys)); + fdt32_to_cpu(bph->boot_cpuid_phys)); if (version >= 3) printf("// size_dt_strings:\t0x%x\n", - be32_to_cpu(bph->size_dt_strings)); + fdt32_to_cpu(bph->size_dt_strings)); if (version >= 17) printf("// size_dt_struct:\t0x%x\n", - be32_to_cpu(bph->size_dt_struct)); + fdt32_to_cpu(bph->size_dt_struct)); printf("\n"); for (i = 0; ; i++) { - addr = be64_to_cpu(p_rsvmap[i].address); - size = be64_to_cpu(p_rsvmap[i].size); + addr = fdt64_to_cpu(p_rsvmap[i].address); + size = fdt64_to_cpu(p_rsvmap[i].size); if (addr == 0 && size == 0) break; @@ -131,7 +116,7 @@ static void dump_blob(void *blob) } p = p_struct; - while ((tag = be32_to_cpu(GET_CELL(p))) != FDT_END) { + while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */ @@ -164,8 +149,8 @@ static void dump_blob(void *blob) fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag); break; } - sz = be32_to_cpu(GET_CELL(p)); - s = p_strings + be32_to_cpu(GET_CELL(p)); + sz = fdt32_to_cpu(GET_CELL(p)); + s = p_strings + fdt32_to_cpu(GET_CELL(p)); if (version < 16 && sz >= 8) p = PALIGN(p, 8); t = p; From cdcb415851dc6c3e9550f27139c933fcaeb2d6a7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 26 Jun 2008 11:03:49 +1000 Subject: [PATCH 0244/1198] dtc: Address an assortment of portability problems I've recently worked with a FreeBSD developer, getting dtc and libfdt working on FreeBSD. This showed up a number of portability problems in the dtc package which this patch addresses. Changes are as follows: - the parent_offset and supernode_atdepth_offset testcases used the glibc extension functions strchrnul() and strndupa(). Those are removed, using slightly longer coding with standard C functions instead. - some other testcases had a #define _GNU_SOURCE for no particular reason. This is removed. - run_tests.sh has bash specific constructs removed, and the interpreter changed to /bin/sh. This apparently now runs fine on FreeBSD's /bin/sh, and I've also tested it with both ash and dash. - convert-dtsv0-lexer.l has some extra #includes added. These must have been included indirectly with Linux and glibc, but aren't on FreeBSD. - the endian handling functions in libfdt_env.h, based on endian.h and byteswap.h are replaced with some portable open-coded versions. Unfortunately, these result in fairly crappy code when compiled, but as far as I can determine there doesn't seem to be any POSIX, SUS or de facto standard way of determining endianness at compile time, nor standard names for byteswapping functions. - some more endian handling, from testdata.h using the problematic endian.h is simply removed, since it wasn't actually being used anyway. Signed-off-by: David Gibson --- convert-dtsv0-lexer.l | 5 +++++ libfdt/libfdt_env.h | 27 ++++++++++++++------------- tests/get_path.c | 2 -- tests/parent_offset.c | 9 +++++---- tests/run_tests.sh | 18 +++++++++--------- tests/supernode_atdepth_offset.c | 12 +++++++----- tests/testdata.h | 11 ----------- tests/testutils.c | 2 +- 8 files changed, 41 insertions(+), 45 deletions(-) diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index d235bd5..64e2916 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -28,9 +28,14 @@ PATHCHAR ({PROPNODECHAR}|[/]) LABEL [a-zA-Z_][a-zA-Z0-9_]* %{ +#include +#include #include + +#include #include #include + #include "srcpos.h" static int v1_tagged; /* = 0 */ diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h index 59f2536..449bf60 100644 --- a/libfdt/libfdt_env.h +++ b/libfdt/libfdt_env.h @@ -4,19 +4,20 @@ #include #include #include -#include -#include -#if __BYTE_ORDER == __BIG_ENDIAN -#define fdt32_to_cpu(x) (x) -#define cpu_to_fdt32(x) (x) -#define fdt64_to_cpu(x) (x) -#define cpu_to_fdt64(x) (x) -#else -#define fdt32_to_cpu(x) (bswap_32((x))) -#define cpu_to_fdt32(x) (bswap_32((x))) -#define fdt64_to_cpu(x) (bswap_64((x))) -#define cpu_to_fdt64(x) (bswap_64((x))) -#endif +#define _B(n) ((unsigned long long)((uint8_t *)&x)[n]) +static inline uint32_t fdt32_to_cpu(uint32_t x) +{ + return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3); +} +#define cpu_to_fdt32(x) fdt32_to_cpu(x) + +static inline uint64_t fdt64_to_cpu(uint64_t x) +{ + return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32) + | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7); +} +#define cpu_to_fdt64(x) fdt64_to_cpu(x) +#undef _B #endif /* _LIBFDT_ENV_H */ diff --git a/tests/get_path.c b/tests/get_path.c index eb217bd..0d208bb 100644 --- a/tests/get_path.c +++ b/tests/get_path.c @@ -17,8 +17,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#define _GNU_SOURCE - #include #include #include diff --git a/tests/parent_offset.c b/tests/parent_offset.c index 309ef6c..8336c72 100644 --- a/tests/parent_offset.c +++ b/tests/parent_offset.c @@ -17,8 +17,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#define _GNU_SOURCE - #include #include #include @@ -45,9 +43,12 @@ int path_parent_len(const char *path) void check_path(struct fdt_header *fdt, const char *path) { char *parentpath; - int nodeoffset, parentoffset, parentpathoffset; + int nodeoffset, parentoffset, parentpathoffset, pathparentlen; - parentpath = strndupa(path, path_parent_len(path)); + pathparentlen = path_parent_len(path); + parentpath = alloca(pathparentlen + 1); + strncpy(parentpath, path, pathparentlen); + parentpath[pathparentlen] = '\0'; verbose_printf("Path: \"%s\"\tParent: \"%s\"\n", path, parentpath); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index ed0c450..976176b 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -1,6 +1,6 @@ -#! /bin/bash +#! /bin/sh -. tests.sh +. ./tests.sh export QUIET_TEST=1 @@ -15,19 +15,19 @@ tot_vg=0 tot_strange=0 base_run_test() { - tot_tests=$[tot_tests + 1] + tot_tests=$((tot_tests + 1)) if VALGRIND="$VALGRIND" "$@"; then - tot_pass=$[tot_pass + 1] + tot_pass=$((tot_pass + 1)) else ret="$?" if [ "$ret" == "1" ]; then - tot_config=$[tot_config + 1] + tot_config=$((tot_config + 1)) elif [ "$ret" == "2" ]; then - tot_fail=$[tot_fail + 1] + tot_fail=$((tot_fail + 1)) elif [ "$ret" == "$VGCODE" ]; then - tot_vg=$[tot_vg + 1] + tot_vg=$((tot_vg + 1)) else - tot_strange=$[tot_strange + 1] + tot_strange=$((tot_strange + 1)) fi fi } @@ -52,7 +52,7 @@ wrap_test () { else ret="$?" if [ "$ret" -gt 127 ]; then - signame=$(kill -l $[ret - 128]) + signame=$(kill -l $((ret - 128))) FAIL "Killed by SIG$signame" else FAIL "Returned error code $ret" diff --git a/tests/supernode_atdepth_offset.c b/tests/supernode_atdepth_offset.c index 39cade6..1245813 100644 --- a/tests/supernode_atdepth_offset.c +++ b/tests/supernode_atdepth_offset.c @@ -17,8 +17,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#define _GNU_SOURCE - #include #include #include @@ -64,7 +62,7 @@ int path_prefix(const char *path, int depth) p = path; for (i = 0; i < depth; i++) - p = strchrnul(p+1, '/'); + p = p+1 + strcspn(p+1, "/"); return p - path; } @@ -74,10 +72,14 @@ void check_supernode_atdepth(struct fdt_header *fdt, const char *path, { int pdepth = path_depth(path); char *superpath; - int nodeoffset, supernodeoffset, superpathoffset; + int nodeoffset, supernodeoffset, superpathoffset, pathprefixlen; int nodedepth; - superpath = strndupa(path, path_prefix(path, depth)); + pathprefixlen = path_prefix(path, depth); + superpath = alloca(pathprefixlen + 1); + strncpy(superpath, path, pathprefixlen); + superpath[pathprefixlen] = '\0'; + verbose_printf("Path %s (%d), depth %d, supernode is %s\n", path, pdepth, depth, superpath); diff --git a/tests/testdata.h b/tests/testdata.h index 9c8b040..5b5a9a3 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -1,14 +1,3 @@ -#include - -#if __BYTE_ORDER == __BIG_ENDIAN -#define cell_to_fdt(x) (x) -#else -/* We do this as a big hairy expression instead of using bswap_32() - * because we need it to work in asm as well as C. */ -#define cell_to_fdt(x) ((((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) \ - | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000)) -#endif - #ifdef __ASSEMBLY__ #define ASM_CONST_LL(x) (x) #else diff --git a/tests/testutils.c b/tests/testutils.c index 338e3bd..b4a3d90 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#define _GNU_SOURCE /* for strsignal() */ +#define _GNU_SOURCE /* for strsignal() in glibc. FreeBSD has it either way */ #include #include From 76e0622b687d795bb1379cf183c6ce8613e14658 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 26 Jun 2008 17:08:57 +1000 Subject: [PATCH 0245/1198] dtc: Clean up lexing of include files Currently we scan the /include/ directive as two tokens, the "/include/" keyword itself, then the string giving the file name to include. We use a special scanner state to keep the two linked together, and use the scanner state stack to keep track of the original state while we're parsing the two /include/ tokens. This does mean that we need to enable the 'stack' option in flex, which results in a not-easily-suppressed warning from the flex boilerplate code. This is mildly irritating. However, this two-token scanning of the /include/ directive also has some extremely strange edge cases, because there are a variety of tokens recognized in all scanner states, including INCLUDE. For example the following strange dts file: /include/ /dts-v1/; / { /* ... */ }; Will be processed successfully with the /include/ being effectively ignored: the '/dts-v1/' and ';' are recognized even in INCLUDE state, then the ';' transitions us to PROPNODENAME state, throwing away INCLUDE, and the previous state is never popped off the stack. Or for another example this construct: foo /include/ = "somefile.dts" will be parsed as though it were: foo = /include/ "somefile.dts" Again, the '=' is scanned without leaving INCLUDE state, then the next string triggers the include logic. And finally, we use a different regexp for the string with the included filename than the normal string regexpt, which is also potentially weird. This patch, therefore, cleans up the lexical handling of the /include/ directive. Instead of the INCLUDE state, we instead scan the whole include directive, both keyword and filename as a single token. This does mean a bit more complexity in extracting the filename out of yytext, but I think it's worth it to avoid the strageness described above. It also means it's no longer possible to put a comment between the /include/ and the filename, but I'm really not very worried about breaking files using such a strange construct. --- convert-dtsv0-lexer.l | 24 ++++++++---------------- dtc-lexer.l | 32 +++++++++++++------------------- 2 files changed, 21 insertions(+), 35 deletions(-) diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index 64e2916..12b45ea 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -17,7 +17,7 @@ * USA */ -%option noyywrap nounput stack +%option noyywrap nounput %x INCLUDE %x BYTESTRING @@ -26,6 +26,11 @@ PROPNODECHAR [a-zA-Z0-9,._+*#?@-] PATHCHAR ({PROPNODECHAR}|[/]) LABEL [a-zA-Z_][a-zA-Z0-9_]* +STRING \"([^\\"]|\\.)*\" +WS [[:space:]] +COMMENT "/*"([^*]|\*+[^*/])*\*+"/" +LINECOMMENT "//".*\n +GAP ({WS}|{COMMENT}|{LINECOMMENT})* %{ #include @@ -91,16 +96,7 @@ const struct { %} %% -<*>"/include/" { - ECHO; - yy_push_state(INCLUDE); - } - -\"[^"\n]*\" { - ECHO; - yy_pop_state(); - } - +<*>"/include/"{GAP}{STRING} ECHO; <*>\"([^\\"]|\\.)*\" ECHO; @@ -193,11 +189,7 @@ const struct { BEGIN(INITIAL); } -<*>[[:space:]]+ ECHO; - -<*>"/*"([^*]|\*+[^*/])*\*+"/" ECHO; - -<*>"//".*\n ECHO; +<*>{GAP} ECHO; <*>- { /* Hack to convert old style memreserves */ saw_hyphen = 1; diff --git a/dtc-lexer.l b/dtc-lexer.l index 8f15c4d..44dbfd3 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -18,7 +18,7 @@ * USA */ -%option noyywrap nounput yylineno stack +%option noyywrap nounput yylineno %x INCLUDE %x BYTESTRING @@ -28,6 +28,10 @@ PROPNODECHAR [a-zA-Z0-9,._+*#?@-] PATHCHAR ({PROPNODECHAR}|[/]) LABEL [a-zA-Z_][a-zA-Z0-9_]* +STRING \"([^\\"]|\\.)*\" +WS [[:space:]] +COMMENT "/*"([^*]|\*+[^*/])*\*+"/" +LINECOMMENT "//".*\n %{ #include "dtc.h" @@ -58,22 +62,19 @@ static int pop_input_file(void); %} %% -<*>"/include/" yy_push_state(INCLUDE); - -\"[^"\n]*\" { - yytext[strlen(yytext) - 1] = 0; - push_input_file(yytext + 1); - yy_pop_state(); +<*>"/include/"{WS}*{STRING} { + char *name = strchr(yytext, '\"') + 1; + yytext[yyleng-1] = '\0'; + push_input_file(name); } - <*><> { if (!pop_input_file()) { yyterminate(); } } -<*>\"([^\\"]|\\.)*\" { +<*>{STRING} { yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("String: %s\n", yytext); @@ -197,16 +198,9 @@ static int pop_input_file(void); return DT_INCBIN; } -<*>[[:space:]]+ /* eat whitespace */ - -<*>"/*"([^*]|\*+[^*/])*\*+"/" { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; - DPRINT("Comment: %s\n", yytext); - /* eat comments */ - } - -<*>"//".*\n /* eat line comments */ +<*>{WS}+ /* eat whitespace */ +<*>{COMMENT}+ /* eat C-style comments */ +<*>{LINECOMMENT}+ /* eat C++-style comments */ <*>. { yylloc.file = srcpos_file; From 36786db6154533b67d736b414ef63b4457009326 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 7 Jul 2008 10:10:48 +1000 Subject: [PATCH 0246/1198] dtc: Enable and fix -Wpointer-arith warnings This patch turns on the -Wpointer-arith option in the dtc Makefile, and fixes the resulting warnings due to using (void *) in pointer arithmetic. While convenient, pointer arithmetic on void * is not portable, so it's better that we avoid it, particularly in libfdt. Signed-off-by: David Gibson --- Makefile | 2 +- ftdump.c | 6 ++--- libfdt/fdt.c | 2 +- libfdt/fdt_ro.c | 4 ++-- libfdt/fdt_rw.c | 49 ++++++++++++++++++++++------------------ libfdt/fdt_sw.c | 2 +- libfdt/fdt_wip.c | 2 +- libfdt/libfdt_internal.h | 6 ++--- tests/incbin.c | 7 +++--- tests/mangle-layout.c | 8 +++---- tests/move_and_save.c | 2 +- tests/nopulate.c | 7 +++--- tests/testutils.c | 2 +- 13 files changed, 52 insertions(+), 47 deletions(-) diff --git a/Makefile b/Makefile index 3f4a174..c20fc9e 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ LOCAL_VERSION = CONFIG_LOCALVERSION = CPPFLAGS = -I libfdt -CFLAGS = -Wall -g -Os +CFLAGS = -Wall -g -Os -Wpointer-arith BISON = bison LEX = flex diff --git a/ftdump.c b/ftdump.c index c8f4092..1f94a05 100644 --- a/ftdump.c +++ b/ftdump.c @@ -70,9 +70,9 @@ static void dump_blob(void *blob) uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct); uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings); struct fdt_reserve_entry *p_rsvmap = - (struct fdt_reserve_entry *)(blob + off_mem_rsvmap); - char *p_struct = blob + off_dt; - char *p_strings = blob + off_str; + (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap); + char *p_struct = (char *)blob + off_dt; + char *p_strings = (char *)blob + off_str; uint32_t version = fdt32_to_cpu(bph->version); uint32_t totalsize = fdt32_to_cpu(bph->totalsize); uint32_t tag; diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 0d16427..6b2ca1f 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -76,7 +76,7 @@ int fdt_check_header(const void *fdt) const void *fdt_offset_ptr(const void *fdt, int offset, int len) { - const void *p; + const char *p; if (fdt_version(fdt) >= 0x11) if (((offset + len) < offset) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index e55872f..2a6e905 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -408,10 +408,10 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) &phandle, sizeof(phandle)); } -int _stringlist_contains(const void *strlist, int listlen, const char *str) +int _stringlist_contains(const char *strlist, int listlen, const char *str) { int len = strlen(str); - const void *p; + const char *p; while (listlen >= len) { if (memcmp(str, strlist, len+1) == 0) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index ec0738c..0284a4f 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -94,13 +94,14 @@ static inline int _blob_data_size(void *fdt) return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); } -static int _blob_splice(void *fdt, void *p, int oldlen, int newlen) +static int _blob_splice(void *fdt, void *splicepoint, int oldlen, int newlen) { - void *end = fdt + _blob_data_size(fdt); + char *p = splicepoint; + char *end = (char *)fdt + _blob_data_size(fdt); if (((p + oldlen) < p) || ((p + oldlen) > end)) return -FDT_ERR_BADOFFSET; - if ((end - oldlen + newlen) > (fdt + fdt_totalsize(fdt))) + if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) return -FDT_ERR_NOSPACE; memmove(p + newlen, p + oldlen, end - p - oldlen); return 0; @@ -135,7 +136,8 @@ static int _blob_splice_struct(void *fdt, void *p, static int _blob_splice_string(void *fdt, int newlen) { - void *p = fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); + void *p = (char *)fdt + + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); int err; if ((err = _blob_splice(fdt, p, 0, newlen))) @@ -338,7 +340,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); memset(nh->name, 0, ALIGN(namelen+1, FDT_TAGSIZE)); memcpy(nh->name, name, namelen); - endtag = (uint32_t *)((void *)nh + nodelen - FDT_TAGSIZE); + endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE); *endtag = cpu_to_fdt32(FDT_END_NODE); return offset; @@ -363,7 +365,7 @@ int fdt_del_node(void *fdt, int nodeoffset) endoffset - nodeoffset, 0); } -static void _packblocks(const void *fdt, void *buf, +static void _packblocks(const char *old, char *new, int mem_rsv_size, int struct_size) { int mem_rsv_off, struct_off, strings_off; @@ -372,17 +374,17 @@ static void _packblocks(const void *fdt, void *buf, struct_off = mem_rsv_off + mem_rsv_size; strings_off = struct_off + struct_size; - memmove(buf + mem_rsv_off, fdt + fdt_off_mem_rsvmap(fdt), mem_rsv_size); - fdt_set_off_mem_rsvmap(buf, mem_rsv_off); + memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); + fdt_set_off_mem_rsvmap(new, mem_rsv_off); - memmove(buf + struct_off, fdt + fdt_off_dt_struct(fdt), struct_size); - fdt_set_off_dt_struct(buf, struct_off); - fdt_set_size_dt_struct(buf, struct_size); + memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); + fdt_set_off_dt_struct(new, struct_off); + fdt_set_size_dt_struct(new, struct_size); - memmove(buf + strings_off, fdt + fdt_off_dt_strings(fdt), - fdt_size_dt_strings(fdt)); - fdt_set_off_dt_strings(buf, strings_off); - fdt_set_size_dt_strings(buf, fdt_size_dt_strings(fdt)); + memmove(new + strings_off, old + fdt_off_dt_strings(old), + fdt_size_dt_strings(old)); + fdt_set_off_dt_strings(new, strings_off); + fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); } int fdt_open_into(const void *fdt, void *buf, int bufsize) @@ -390,7 +392,9 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) int err; int mem_rsv_size, struct_size; int newsize; - void *tmp; + const char *fdtstart = fdt; + const char *fdtend = fdtstart + fdt_totalsize(fdt); + char *tmp; CHECK_HEADER(fdt); @@ -423,12 +427,13 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) if (bufsize < newsize) return -FDT_ERR_NOSPACE; - if (((buf + newsize) <= fdt) - || (buf >= (fdt + fdt_totalsize(fdt)))) { - tmp = buf; - } else { - tmp = (void *)fdt + fdt_totalsize(fdt); - if ((tmp + newsize) > (buf + bufsize)) + /* First attempt to build converted tree at beginning of buffer */ + tmp = buf; + /* But if that overlaps with the old tree... */ + if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { + /* Try right after the old tree instead */ + tmp = (char *)fdtend; + if ((tmp + newsize) > ((char *)buf + bufsize)) return -FDT_ERR_NOSPACE; } diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index df09876..92f8f0b 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -121,7 +121,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) return -FDT_ERR_NOSPACE; - re = (struct fdt_reserve_entry *)(fdt + offset); + re = (struct fdt_reserve_entry *)((char *)fdt + offset); re->address = cpu_to_fdt64(addr); re->size = cpu_to_fdt64(size); diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c index 88e24b8..ae6f536 100644 --- a/libfdt/fdt_wip.c +++ b/libfdt/fdt_wip.c @@ -76,7 +76,7 @@ static void nop_region(void *start, int len) { uint32_t *p; - for (p = start; (void *)p < (start + len); p++) + for (p = start; (char *)p < ((char *)start + len); p++) *p = cpu_to_fdt32(FDT_NOP); } diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index f72e70d..2ba30db 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -72,7 +72,7 @@ int _fdt_node_end_offset(void *fdt, int nodeoffset); static inline const void *_fdt_offset_ptr(const void *fdt, int offset) { - return fdt + fdt_off_dt_struct(fdt) + offset; + return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; } static inline void *_fdt_offset_ptr_w(void *fdt, int offset) @@ -82,8 +82,8 @@ static inline void *_fdt_offset_ptr_w(void *fdt, int offset) static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) { - const struct fdt_reserve_entry *rsv_table = - fdt + fdt_off_mem_rsvmap(fdt); + const struct fdt_reserve_entry *rsv_table = (struct fdt_reserve_entry *) + ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); return rsv_table + n; } diff --git a/tests/incbin.c b/tests/incbin.c index 2f8a55a..5ab3508 100644 --- a/tests/incbin.c +++ b/tests/incbin.c @@ -31,10 +31,10 @@ #define CHUNKSIZE 1024 -void *load_file(const char *name, int *len) +char *load_file(const char *name, int *len) { FILE *f; - void *buf = NULL; + char *buf = NULL; int bufsize = 0, n; *len = 0; @@ -60,7 +60,8 @@ void *load_file(const char *name, int *len) int main(int argc, char *argv[]) { - void *fdt, *incbin; + void *fdt; + char *incbin; int len; test_init(argc, argv); diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c index efd6aab..bd6ac40 100644 --- a/tests/mangle-layout.c +++ b/tests/mangle-layout.c @@ -31,7 +31,7 @@ #include "testdata.h" struct bufstate { - void *buf; + char *buf; int size; }; @@ -73,7 +73,7 @@ void add_block(struct bufstate *buf, int version, char block, const void *fdt) case 'm': /* Memory reserve map */ align = 8; - src = fdt + fdt_off_mem_rsvmap(fdt); + src = (const char *)fdt + fdt_off_mem_rsvmap(fdt); size = (fdt_num_mem_rsv(fdt) + 1) * sizeof(struct fdt_reserve_entry); break; @@ -81,14 +81,14 @@ void add_block(struct bufstate *buf, int version, char block, const void *fdt) case 't': /* Structure block */ align = 4; - src = fdt + fdt_off_dt_struct(fdt); + src = (const char *)fdt + fdt_off_dt_struct(fdt); size = fdt_size_dt_struct(fdt); break; case 's': /* Strings block */ align = 1; - src = fdt + fdt_off_dt_strings(fdt); + src = (const char *)fdt + fdt_off_dt_strings(fdt); size = fdt_size_dt_strings(fdt); break; default: diff --git a/tests/move_and_save.c b/tests/move_and_save.c index da73157..410ccb3 100644 --- a/tests/move_and_save.c +++ b/tests/move_and_save.c @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) { void *fdt, *fdt1, *fdt2, *fdt3; - void *buf; + char *buf; int shuntsize; int bufsize; int err; diff --git a/tests/nopulate.c b/tests/nopulate.c index 923ba2d..e56839a 100644 --- a/tests/nopulate.c +++ b/tests/nopulate.c @@ -30,7 +30,7 @@ #include "tests.h" #include "testdata.h" -int nopulate_struct(char *buf, const void *fdt) +int nopulate_struct(char *buf, const char *fdt) { int offset, nextoffset = 0; uint32_t tag; @@ -42,7 +42,7 @@ int nopulate_struct(char *buf, const void *fdt) offset = nextoffset; tag = fdt_next_tag(fdt, offset, &nextoffset); - memcpy(p, fdt + fdt_off_dt_struct(fdt) + offset, + memcpy(p, (const char *)fdt + fdt_off_dt_struct(fdt) + offset, nextoffset - offset); p += nextoffset - offset; @@ -56,8 +56,7 @@ int nopulate_struct(char *buf, const void *fdt) int main(int argc, char *argv[]) { - void *fdt, *fdt2; - void *buf; + char *fdt, *fdt2, *buf; int newsize, struct_start, struct_end_old, struct_end_new, delta; const char *inname; char outname[PATH_MAX]; diff --git a/tests/testutils.c b/tests/testutils.c index b4a3d90..b0a2230 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -200,7 +200,7 @@ void save_blob(const char *filename, void *fdt) int fd; int totalsize; int offset; - void *p; + char *p; int ret; fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); From 1409097db8be6ba662e3808654671554c5803bf0 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 7 Jul 2008 10:14:15 +1000 Subject: [PATCH 0247/1198] dtc: Enable and fix -Wcast-qual warnings Enabling -Wcast-qual warnings in dtc shows up a number of places where we are incorrectly discarding a const qualification. There are also some places where we are intentionally discarding the 'const', and we need an ugly cast through uintptr_t to suppress the warning. However, most of these are pretty well isolated with the *_w() functions. So in the interests of maximum safety with const qualifications, this patch enables the warnings and fixes the existing complaints. Signed-off-by: David Gibson --- Makefile | 2 +- ftdump.c | 4 ++-- libfdt/fdt_ro.c | 2 +- libfdt/fdt_rw.c | 4 ++-- libfdt/libfdt.h | 8 ++++---- libfdt/libfdt_internal.h | 7 ++++--- treesource.c | 2 +- 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index c20fc9e..0fa27b2 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ LOCAL_VERSION = CONFIG_LOCALVERSION = CPPFLAGS = -I libfdt -CFLAGS = -Wall -g -Os -Wpointer-arith +CFLAGS = -Wall -g -Os -Wpointer-arith -Wcast-qual BISON = bison LEX = flex diff --git a/ftdump.c b/ftdump.c index 1f94a05..01e61a4 100644 --- a/ftdump.c +++ b/ftdump.c @@ -48,11 +48,11 @@ static void print_data(const void *data, int len) return; if (is_printable_string(data, len)) { - printf(" = \"%s\"", (char *)data); + printf(" = \"%s\"", (const char *)data); } else if ((len % 4) == 0) { printf(" = <"); for (i = 0; i < len; i += 4) - printf("%08x%s", *((uint32_t *)data + i), + printf("%08x%s", *((const uint32_t *)data + i), i < (len - 4) ? " " : ""); printf(">"); } else { diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 2a6e905..5ce5ccf 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -77,7 +77,7 @@ static int nodename_eq(const void *fdt, int offset, const char *fdt_string(const void *fdt, int stroffset) { - return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset; + return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; } int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 0284a4f..eef32b9 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -257,7 +257,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name) RW_CHECK_HEADER(fdt); - namep = (char *)fdt_get_name(fdt, nodeoffset, &oldlen); + namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); if (!namep) return oldlen; @@ -432,7 +432,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) /* But if that overlaps with the old tree... */ if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { /* Try right after the old tree instead */ - tmp = (char *)fdtend; + tmp = (char *)(uintptr_t)fdtend; if ((tmp + newsize) > ((char *)buf + bufsize)) return -FDT_ERR_NOSPACE; } diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 8645de0..ad58a84 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -125,7 +125,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, int checklen); static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) { - return (void *)fdt_offset_ptr(fdt, offset, checklen); + return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); } uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); @@ -375,8 +375,8 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, const char *name, int *lenp) { - return (struct fdt_property *)fdt_get_property(fdt, nodeoffset, - name, lenp); + return (struct fdt_property *)(uintptr_t) + fdt_get_property(fdt, nodeoffset, name, lenp); } /** @@ -411,7 +411,7 @@ const void *fdt_getprop(const void *fdt, int nodeoffset, static inline void *fdt_getprop_w(void *fdt, int nodeoffset, const char *name, int *lenp) { - return (void *)fdt_getprop(fdt, nodeoffset, name, lenp); + return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); } /** diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 2ba30db..549e345 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -77,19 +77,20 @@ static inline const void *_fdt_offset_ptr(const void *fdt, int offset) static inline void *_fdt_offset_ptr_w(void *fdt, int offset) { - return (void *)_fdt_offset_ptr(fdt, offset); + return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset); } static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) { - const struct fdt_reserve_entry *rsv_table = (struct fdt_reserve_entry *) + const struct fdt_reserve_entry *rsv_table = + (const struct fdt_reserve_entry *) ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); return rsv_table + n; } static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) { - return (void *)_fdt_mem_rsv(fdt, n); + return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n); } #define SW_MAGIC (~FDT_MAGIC) diff --git a/treesource.c b/treesource.c index c32e818..ebeb6eb 100644 --- a/treesource.c +++ b/treesource.c @@ -176,7 +176,7 @@ static void write_propval_bytes(FILE *f, struct data val) } fprintf(f, "%02hhx", *bp++); - if ((void *)bp >= propend) + if ((const void *)bp >= propend) break; fprintf(f, " "); } From 4d7bea7873590ee3a2bfc2905bef3ed8e84a0902 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 7 Jul 2008 11:19:13 +1000 Subject: [PATCH 0248/1198] dtc: Run relevant checks on dtb input as well as dts This patch adjusts the testsuite to run most of the tests for the tree checking code on input in dtb form as well as dts form. Some checks which only make sense for dts input (like reference handling) are excluded, as are those which currently take dtb input because they rely on things which cannot be lexically constructed in a dts file. This shows up two small bugs in dtc, which are also corrected. First, the name_properties test which was is supposed to remove correctly formed 'name' properties (because they can be reconstructed from tne node name) was instead removing 'name' properties even if they weren't correct. Secondly, when using dtb or fs input, the runtime tree in dtc did not have the parent pointer initialized propertly because.built internally. The appropriate initialization is added to the add_child() function. Signed-off-by: David Gibson --- checks.c | 16 +++++++++------- livetree.c | 1 + tests/run_tests.sh | 34 +++++++++++++++++++++------------- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/checks.c b/checks.c index 0066fb3..9548579 100644 --- a/checks.c +++ b/checks.c @@ -328,15 +328,17 @@ static void check_name_properties(struct check *c, struct node *root, return; /* No name property, that's fine */ if ((prop->val.len != node->basenamelen+1) - || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) + || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) { FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead" " of base node name)", node->fullpath, prop->val.val); - - /* The name property is correct, and therefore redundant. Delete it */ - *pp = prop->next; - free(prop->name); - data_free(prop->val); - free(prop); + } else { + /* The name property is correct, and therefore redundant. + * Delete it */ + *pp = prop->next; + free(prop->name); + data_free(prop->val); + free(prop); + } } CHECK_IS_STRING(name_is_string, "name", ERROR); NODE_CHECK(name_properties, NULL, ERROR, &name_is_string); diff --git a/livetree.c b/livetree.c index ba7e263..0ca3de5 100644 --- a/livetree.c +++ b/livetree.c @@ -115,6 +115,7 @@ void add_child(struct node *parent, struct node *child) struct node **p; child->next_sibling = NULL; + child->parent = parent; p = &parent->children; while (*p) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 976176b..7bfc399 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -115,6 +115,14 @@ tree1_tests_rw () { run_test del_node $TREE } +check_tests () { + tree="$1" + shift + run_sh_test dtc-checkfails.sh "$@" -- -I dts -O dtb $tree + run_dtc_test -I dts -O dtb -o $tree.test.dtb -f $tree + run_sh_test dtc-checkfails.sh "$@" -- -I dtb -O dtb $tree.test.dtb +} + ALL_LAYOUTS="mts mst tms tsm smt stm" libfdt_tests () { @@ -243,22 +251,22 @@ dtc_tests () { done # Check some checks - run_sh_test dtc-checkfails.sh duplicate_node_names -- -I dts -O dtb dup-nodename.dts - run_sh_test dtc-checkfails.sh duplicate_property_names -- -I dts -O dtb dup-propname.dts - run_sh_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb dup-phandle.dts - run_sh_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb zero-phandle.dts - run_sh_test dtc-checkfails.sh explicit_phandles -- -I dts -O dtb minusone-phandle.dts + check_tests dup-nodename.dts duplicate_node_names + check_tests dup-propname.dts duplicate_property_names + check_tests dup-phandle.dts explicit_phandles + check_tests zero-phandle.dts explicit_phandles + check_tests minusone-phandle.dts explicit_phandles run_sh_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-node-ref.dts run_sh_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-label-ref.dts - run_sh_test dtc-checkfails.sh name_properties -- -I dts -O dtb bad-name-property.dts + check_tests bad-name-property.dts name_properties - run_sh_test dtc-checkfails.sh address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell -- -I dts -O dtb bad-ncells.dts - run_sh_test dtc-checkfails.sh device_type_is_string model_is_string status_is_string -- -I dts -O dtb bad-string-props.dts - run_sh_test dtc-checkfails.sh reg_format ranges_format -- -I dts -O dtb bad-reg-ranges.dts - run_sh_test dtc-checkfails.sh ranges_format -- -I dts -O dtb bad-empty-ranges.dts - run_sh_test dtc-checkfails.sh reg_format ranges_format -- -I dts -O dtb reg-ranges-root.dts - run_sh_test dtc-checkfails.sh avoid_default_addr_size -- -I dts -O dtb default-addr-size.dts - run_sh_test dtc-checkfails.sh obsolete_chosen_interrupt_controller -- -I dts -O dtb obsolete-chosen-interrupt-controller.dts + check_tests bad-ncells.dts address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell + check_tests bad-string-props.dts device_type_is_string model_is_string status_is_string + check_tests bad-reg-ranges.dts reg_format ranges_format + check_tests bad-empty-ranges.dts ranges_format + check_tests reg-ranges-root.dts reg_format ranges_format + check_tests default-addr-size.dts avoid_default_addr_size + check_tests obsolete-chosen-interrupt-controller.dts obsolete_chosen_interrupt_controller run_sh_test dtc-checkfails.sh node_name_chars -- -I dtb -O dtb bad_node_char.dtb run_sh_test dtc-checkfails.sh node_name_format -- -I dtb -O dtb bad_node_format.dtb run_sh_test dtc-checkfails.sh prop_name_chars -- -I dtb -O dtb bad_prop_char.dtb From b6d80a20fc293f3b995c3ce1a6744a5574192125 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 9 Jul 2008 14:10:24 +1000 Subject: [PATCH 0249/1198] libfdt: Increase namespace-pollution paranoia libfdt is supposed to easy to embed in projects all and sundry. Often, it won't be practical to separate the embedded libfdt's namespace from that of the surrounding project. Which means there can be namespace conflicts between even libfdt's internal/static functions and functions or macros coming from the surrounding project's headers via libfdt_env.h. This patch, therefore, renames a bunch of libfdt internal functions and macros and makes a few other chances to reduce the chances of namespace collisions with embedding projects. Specifically: - Internal functions (even static ones) are now named _fdt_*() - The type and (static) global for the error table in fdt_strerror() gain an fdt_ prefix - The unused macro PALIGN is removed - The memeq and streq macros are removed and open-coded in the users (they were only used once each) - Other macros gain an FDT_ prefix - To save some of the bulk from the previous change, an FDT_TAGALIGN() macro is introduced, where FDT_TAGALIGN(x) == FDT_ALIGN(x, FDT_TAGSIZE) Signed-off-by: David Gibson --- libfdt/fdt.c | 8 +-- libfdt/fdt_ro.c | 22 +++---- libfdt/fdt_rw.c | 121 +++++++++++++++++++-------------------- libfdt/fdt_strerror.c | 34 +++++------ libfdt/fdt_sw.c | 38 ++++++------ libfdt/fdt_wip.c | 7 ++- libfdt/libfdt_internal.h | 11 ++-- 7 files changed, 119 insertions(+), 122 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 6b2ca1f..2acaec5 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -63,7 +63,7 @@ int fdt_check_header(const void *fdt) return -FDT_ERR_BADVERSION; if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) return -FDT_ERR_BADVERSION; - } else if (fdt_magic(fdt) == SW_MAGIC) { + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { /* Unfinished sequential-write blob */ if (fdt_size_dt_struct(fdt) == 0) return -FDT_ERR_BADSTATE; @@ -124,7 +124,7 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset) } if (nextoffset) - *nextoffset = ALIGN(offset, FDT_TAGSIZE); + *nextoffset = FDT_TAGALIGN(offset); return tag; } @@ -184,14 +184,14 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) const char *p; for (p = strtab; p <= last; p++) - if (memeq(p, s, len)) + if (memcmp(p, s, len) == 0) return p; return NULL; } int fdt_move(const void *fdt, void *buf, int bufsize) { - CHECK_HEADER(fdt); + FDT_CHECK_HEADER(fdt); if (fdt_totalsize(fdt) > bufsize) return -FDT_ERR_NOSPACE; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 5ce5ccf..129b532 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -55,8 +55,8 @@ #include "libfdt_internal.h" -static int nodename_eq(const void *fdt, int offset, - const char *s, int len) +static int _fdt_nodename_eq(const void *fdt, int offset, + const char *s, int len) { const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); @@ -82,7 +82,7 @@ const char *fdt_string(const void *fdt, int stroffset) int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) { - CHECK_HEADER(fdt); + FDT_CHECK_HEADER(fdt); *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); return 0; @@ -102,7 +102,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset, { int depth; - CHECK_HEADER(fdt); + FDT_CHECK_HEADER(fdt); for (depth = 0; offset >= 0; @@ -110,7 +110,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset, if (depth < 0) return -FDT_ERR_NOTFOUND; else if ((depth == 1) - && nodename_eq(fdt, offset, name, namelen)) + && _fdt_nodename_eq(fdt, offset, name, namelen)) return offset; } @@ -129,7 +129,7 @@ int fdt_path_offset(const void *fdt, const char *path) const char *p = path; int offset = 0; - CHECK_HEADER(fdt); + FDT_CHECK_HEADER(fdt); if (*path != '/') return -FDT_ERR_BADPATH; @@ -210,7 +210,7 @@ const struct fdt_property *fdt_get_property(const void *fdt, if (! prop) goto fail; namestroff = fdt32_to_cpu(prop->nameoff); - if (streq(fdt_string(fdt, namestroff), name)) { + if (strcmp(fdt_string(fdt, namestroff), name) == 0) { /* Found it! */ int len = fdt32_to_cpu(prop->len); prop = fdt_offset_ptr(fdt, offset, @@ -268,7 +268,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) int offset, depth, namelen; const char *name; - CHECK_HEADER(fdt); + FDT_CHECK_HEADER(fdt); if (buflen < 2) return -FDT_ERR_NOSPACE; @@ -321,7 +321,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int offset, depth; int supernodeoffset = -FDT_ERR_INTERNAL; - CHECK_HEADER(fdt); + FDT_CHECK_HEADER(fdt); if (supernodedepth < 0) return -FDT_ERR_NOTFOUND; @@ -380,7 +380,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, const void *val; int len; - CHECK_HEADER(fdt); + FDT_CHECK_HEADER(fdt); /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_getprop(), then if that didn't @@ -445,7 +445,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, { int offset, err; - CHECK_HEADER(fdt); + FDT_CHECK_HEADER(fdt); /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_node_check_compatible(), then if diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index eef32b9..8e7ec4c 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -55,10 +55,10 @@ #include "libfdt_internal.h" -static int _blocks_misordered(const void *fdt, +static int _fdt_blocks_misordered(const void *fdt, int mem_rsv_size, int struct_size) { - return (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8)) + return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) || (fdt_off_dt_struct(fdt) < (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) || (fdt_off_dt_strings(fdt) < @@ -67,14 +67,14 @@ static int _blocks_misordered(const void *fdt, (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); } -static int rw_check_header(void *fdt) +static int _fdt_rw_check_header(void *fdt) { - CHECK_HEADER(fdt); + FDT_CHECK_HEADER(fdt); if (fdt_version(fdt) < 17) return -FDT_ERR_BADVERSION; - if (_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), - fdt_size_dt_struct(fdt))) + if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), + fdt_size_dt_struct(fdt))) return -FDT_ERR_BADLAYOUT; if (fdt_version(fdt) > 17) fdt_set_version(fdt, 17); @@ -82,22 +82,22 @@ static int rw_check_header(void *fdt) return 0; } -#define RW_CHECK_HEADER(fdt) \ +#define FDT_RW_CHECK_HEADER(fdt) \ { \ int err; \ - if ((err = rw_check_header(fdt)) != 0) \ + if ((err = _fdt_rw_check_header(fdt)) != 0) \ return err; \ } -static inline int _blob_data_size(void *fdt) +static inline int _fdt_data_size(void *fdt) { return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); } -static int _blob_splice(void *fdt, void *splicepoint, int oldlen, int newlen) +static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) { char *p = splicepoint; - char *end = (char *)fdt + _blob_data_size(fdt); + char *end = (char *)fdt + _fdt_data_size(fdt); if (((p + oldlen) < p) || ((p + oldlen) > end)) return -FDT_ERR_BADOFFSET; @@ -107,12 +107,12 @@ static int _blob_splice(void *fdt, void *splicepoint, int oldlen, int newlen) return 0; } -static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, - int oldn, int newn) +static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, + int oldn, int newn) { int delta = (newn - oldn) * sizeof(*p); int err; - err = _blob_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); + err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); if (err) return err; fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); @@ -120,13 +120,13 @@ static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, return 0; } -static int _blob_splice_struct(void *fdt, void *p, - int oldlen, int newlen) +static int _fdt_splice_struct(void *fdt, void *p, + int oldlen, int newlen) { int delta = newlen - oldlen; int err; - if ((err = _blob_splice(fdt, p, oldlen, newlen))) + if ((err = _fdt_splice(fdt, p, oldlen, newlen))) return err; fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); @@ -134,20 +134,20 @@ static int _blob_splice_struct(void *fdt, void *p, return 0; } -static int _blob_splice_string(void *fdt, int newlen) +static int _fdt_splice_string(void *fdt, int newlen) { void *p = (char *)fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); int err; - if ((err = _blob_splice(fdt, p, 0, newlen))) + if ((err = _fdt_splice(fdt, p, 0, newlen))) return err; fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); return 0; } -static int _find_add_string(void *fdt, const char *s) +static int _fdt_find_add_string(void *fdt, const char *s) { char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); const char *p; @@ -161,7 +161,7 @@ static int _find_add_string(void *fdt, const char *s) return (p - strtab); new = strtab + fdt_size_dt_strings(fdt); - err = _blob_splice_string(fdt, len); + err = _fdt_splice_string(fdt, len); if (err) return err; @@ -174,10 +174,10 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) struct fdt_reserve_entry *re; int err; - RW_CHECK_HEADER(fdt); + FDT_RW_CHECK_HEADER(fdt); re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); - err = _blob_splice_mem_rsv(fdt, re, 0, 1); + err = _fdt_splice_mem_rsv(fdt, re, 0, 1); if (err) return err; @@ -191,19 +191,19 @@ int fdt_del_mem_rsv(void *fdt, int n) struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); int err; - RW_CHECK_HEADER(fdt); + FDT_RW_CHECK_HEADER(fdt); if (n >= fdt_num_mem_rsv(fdt)) return -FDT_ERR_NOTFOUND; - err = _blob_splice_mem_rsv(fdt, re, 1, 0); + err = _fdt_splice_mem_rsv(fdt, re, 1, 0); if (err) return err; return 0; } -static int _resize_property(void *fdt, int nodeoffset, const char *name, int len, - struct fdt_property **prop) +static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, + int len, struct fdt_property **prop) { int oldlen; int err; @@ -212,17 +212,16 @@ static int _resize_property(void *fdt, int nodeoffset, const char *name, int len if (! (*prop)) return oldlen; - if ((err = _blob_splice_struct(fdt, (*prop)->data, - ALIGN(oldlen, FDT_TAGSIZE), - ALIGN(len, FDT_TAGSIZE)))) + if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), + FDT_TAGALIGN(len)))) return err; (*prop)->len = cpu_to_fdt32(len); return 0; } -static int _add_property(void *fdt, int nodeoffset, const char *name, int len, - struct fdt_property **prop) +static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, + int len, struct fdt_property **prop) { int proplen; int nextoffset; @@ -232,14 +231,14 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len, if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) return nextoffset; - namestroff = _find_add_string(fdt, name); + namestroff = _fdt_find_add_string(fdt, name); if (namestroff < 0) return namestroff; *prop = _fdt_offset_ptr_w(fdt, nextoffset); - proplen = sizeof(**prop) + ALIGN(len, FDT_TAGSIZE); + proplen = sizeof(**prop) + FDT_TAGALIGN(len); - err = _blob_splice_struct(fdt, *prop, 0, proplen); + err = _fdt_splice_struct(fdt, *prop, 0, proplen); if (err) return err; @@ -255,7 +254,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name) int oldlen, newlen; int err; - RW_CHECK_HEADER(fdt); + FDT_RW_CHECK_HEADER(fdt); namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); if (!namep) @@ -263,8 +262,8 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name) newlen = strlen(name); - err = _blob_splice_struct(fdt, namep, ALIGN(oldlen+1, FDT_TAGSIZE), - ALIGN(newlen+1, FDT_TAGSIZE)); + err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), + FDT_TAGALIGN(newlen+1)); if (err) return err; @@ -278,11 +277,11 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, struct fdt_property *prop; int err; - RW_CHECK_HEADER(fdt); + FDT_RW_CHECK_HEADER(fdt); - err = _resize_property(fdt, nodeoffset, name, len, &prop); + err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); if (err == -FDT_ERR_NOTFOUND) - err = _add_property(fdt, nodeoffset, name, len, &prop); + err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); if (err) return err; @@ -295,14 +294,14 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name) struct fdt_property *prop; int len, proplen; - RW_CHECK_HEADER(fdt); + FDT_RW_CHECK_HEADER(fdt); prop = fdt_get_property_w(fdt, nodeoffset, name, &len); if (! prop) return len; - proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE); - return _blob_splice_struct(fdt, prop, proplen, 0); + proplen = sizeof(*prop) + FDT_TAGALIGN(len); + return _fdt_splice_struct(fdt, prop, proplen, 0); } int fdt_add_subnode_namelen(void *fdt, int parentoffset, @@ -315,7 +314,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, uint32_t tag; uint32_t *endtag; - RW_CHECK_HEADER(fdt); + FDT_RW_CHECK_HEADER(fdt); offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); if (offset >= 0) @@ -331,14 +330,14 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, } while ((tag == FDT_PROP) || (tag == FDT_NOP)); nh = _fdt_offset_ptr_w(fdt, offset); - nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE; + nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; - err = _blob_splice_struct(fdt, nh, 0, nodelen); + err = _fdt_splice_struct(fdt, nh, 0, nodelen); if (err) return err; nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); - memset(nh->name, 0, ALIGN(namelen+1, FDT_TAGSIZE)); + memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); memcpy(nh->name, name, namelen); endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE); *endtag = cpu_to_fdt32(FDT_END_NODE); @@ -355,22 +354,22 @@ int fdt_del_node(void *fdt, int nodeoffset) { int endoffset; - RW_CHECK_HEADER(fdt); + FDT_RW_CHECK_HEADER(fdt); endoffset = _fdt_node_end_offset(fdt, nodeoffset); if (endoffset < 0) return endoffset; - return _blob_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), - endoffset - nodeoffset, 0); + return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), + endoffset - nodeoffset, 0); } -static void _packblocks(const char *old, char *new, - int mem_rsv_size, int struct_size) +static void _fdt_packblocks(const char *old, char *new, + int mem_rsv_size, int struct_size) { int mem_rsv_off, struct_off, strings_off; - mem_rsv_off = ALIGN(sizeof(struct fdt_header), 8); + mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); struct_off = mem_rsv_off + mem_rsv_size; strings_off = struct_off + struct_size; @@ -396,7 +395,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) const char *fdtend = fdtstart + fdt_totalsize(fdt); char *tmp; - CHECK_HEADER(fdt); + FDT_CHECK_HEADER(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); @@ -409,7 +408,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) ; } - if (!_blocks_misordered(fdt, mem_rsv_size, struct_size)) { + if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { /* no further work necessary */ err = fdt_move(fdt, buf, bufsize); if (err) @@ -421,7 +420,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) } /* Need to reorder */ - newsize = ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size + newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size + struct_size + fdt_size_dt_strings(fdt); if (bufsize < newsize) @@ -437,7 +436,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) return -FDT_ERR_NOSPACE; } - _packblocks(fdt, tmp, mem_rsv_size, struct_size); + _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); memmove(buf, tmp, newsize); fdt_set_magic(buf, FDT_MAGIC); @@ -453,12 +452,12 @@ int fdt_pack(void *fdt) { int mem_rsv_size; - RW_CHECK_HEADER(fdt); + FDT_RW_CHECK_HEADER(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); - _packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); - fdt_set_totalsize(fdt, _blob_data_size(fdt)); + _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); + fdt_set_totalsize(fdt, _fdt_data_size(fdt)); return 0; } diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c index f9d32ef..e6c3cee 100644 --- a/libfdt/fdt_strerror.c +++ b/libfdt/fdt_strerror.c @@ -55,29 +55,29 @@ #include "libfdt_internal.h" -struct errtabent { +struct fdt_errtabent { const char *str; }; -#define ERRTABENT(val) \ +#define FDT_ERRTABENT(val) \ [(val)] = { .str = #val, } -static struct errtabent errtable[] = { - ERRTABENT(FDT_ERR_NOTFOUND), - ERRTABENT(FDT_ERR_EXISTS), - ERRTABENT(FDT_ERR_NOSPACE), +static struct fdt_errtabent fdt_errtable[] = { + FDT_ERRTABENT(FDT_ERR_NOTFOUND), + FDT_ERRTABENT(FDT_ERR_EXISTS), + FDT_ERRTABENT(FDT_ERR_NOSPACE), - ERRTABENT(FDT_ERR_BADOFFSET), - ERRTABENT(FDT_ERR_BADPATH), - ERRTABENT(FDT_ERR_BADSTATE), + FDT_ERRTABENT(FDT_ERR_BADOFFSET), + FDT_ERRTABENT(FDT_ERR_BADPATH), + FDT_ERRTABENT(FDT_ERR_BADSTATE), - ERRTABENT(FDT_ERR_TRUNCATED), - ERRTABENT(FDT_ERR_BADMAGIC), - ERRTABENT(FDT_ERR_BADVERSION), - ERRTABENT(FDT_ERR_BADSTRUCTURE), - ERRTABENT(FDT_ERR_BADLAYOUT), + FDT_ERRTABENT(FDT_ERR_TRUNCATED), + FDT_ERRTABENT(FDT_ERR_BADMAGIC), + FDT_ERRTABENT(FDT_ERR_BADVERSION), + FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), + FDT_ERRTABENT(FDT_ERR_BADLAYOUT), }; -#define ERRTABSIZE (sizeof(errtable) / sizeof(errtable[0])) +#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) const char *fdt_strerror(int errval) { @@ -85,8 +85,8 @@ const char *fdt_strerror(int errval) return ""; else if (errval == 0) return ""; - else if (errval > -ERRTABSIZE) { - const char *s = errtable[-errval].str; + else if (errval > -FDT_ERRTABSIZE) { + const char *s = fdt_errtable[-errval].str; if (s) return s; diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 92f8f0b..698329e 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -55,22 +55,22 @@ #include "libfdt_internal.h" -static int sw_check_header(void *fdt) +static int _fdt_sw_check_header(void *fdt) { - if (fdt_magic(fdt) != SW_MAGIC) + if (fdt_magic(fdt) != FDT_SW_MAGIC) return -FDT_ERR_BADMAGIC; /* FIXME: should check more details about the header state */ return 0; } -#define SW_CHECK_HEADER(fdt) \ +#define FDT_SW_CHECK_HEADER(fdt) \ { \ int err; \ - if ((err = sw_check_header(fdt)) != 0) \ + if ((err = _fdt_sw_check_header(fdt)) != 0) \ return err; \ } -static void *grab_space(void *fdt, int len) +static void *_fdt_grab_space(void *fdt, int len) { int offset = fdt_size_dt_struct(fdt); int spaceleft; @@ -94,13 +94,13 @@ int fdt_create(void *buf, int bufsize) memset(buf, 0, bufsize); - fdt_set_magic(fdt, SW_MAGIC); + fdt_set_magic(fdt, FDT_SW_MAGIC); fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); fdt_set_totalsize(fdt, bufsize); - fdt_set_off_mem_rsvmap(fdt, ALIGN(sizeof(struct fdt_header), - sizeof(struct fdt_reserve_entry))); + fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry))); fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); fdt_set_off_dt_strings(fdt, bufsize); @@ -112,7 +112,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) struct fdt_reserve_entry *re; int offset; - SW_CHECK_HEADER(fdt); + FDT_SW_CHECK_HEADER(fdt); if (fdt_size_dt_struct(fdt)) return -FDT_ERR_BADSTATE; @@ -140,9 +140,9 @@ int fdt_begin_node(void *fdt, const char *name) struct fdt_node_header *nh; int namelen = strlen(name) + 1; - SW_CHECK_HEADER(fdt); + FDT_SW_CHECK_HEADER(fdt); - nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE)); + nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); if (! nh) return -FDT_ERR_NOSPACE; @@ -155,9 +155,9 @@ int fdt_end_node(void *fdt) { uint32_t *en; - SW_CHECK_HEADER(fdt); + FDT_SW_CHECK_HEADER(fdt); - en = grab_space(fdt, FDT_TAGSIZE); + en = _fdt_grab_space(fdt, FDT_TAGSIZE); if (! en) return -FDT_ERR_NOSPACE; @@ -165,7 +165,7 @@ int fdt_end_node(void *fdt) return 0; } -static int find_add_string(void *fdt, const char *s) +static int _fdt_find_add_string(void *fdt, const char *s) { char *strtab = (char *)fdt + fdt_totalsize(fdt); const char *p; @@ -193,13 +193,13 @@ int fdt_property(void *fdt, const char *name, const void *val, int len) struct fdt_property *prop; int nameoff; - SW_CHECK_HEADER(fdt); + FDT_SW_CHECK_HEADER(fdt); - nameoff = find_add_string(fdt, name); + nameoff = _fdt_find_add_string(fdt, name); if (nameoff == 0) return -FDT_ERR_NOSPACE; - prop = grab_space(fdt, sizeof(*prop) + ALIGN(len, FDT_TAGSIZE)); + prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); if (! prop) return -FDT_ERR_NOSPACE; @@ -218,10 +218,10 @@ int fdt_finish(void *fdt) uint32_t tag; int offset, nextoffset; - SW_CHECK_HEADER(fdt); + FDT_SW_CHECK_HEADER(fdt); /* Add terminator */ - end = grab_space(fdt, sizeof(*end)); + end = _fdt_grab_space(fdt, sizeof(*end)); if (! end) return -FDT_ERR_NOSPACE; *end = cpu_to_fdt32(FDT_END); diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c index ae6f536..a4652c6 100644 --- a/libfdt/fdt_wip.c +++ b/libfdt/fdt_wip.c @@ -72,7 +72,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, return 0; } -static void nop_region(void *start, int len) +static void _fdt_nop_region(void *start, int len) { uint32_t *p; @@ -89,7 +89,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name) if (! prop) return len; - nop_region(prop, len + sizeof(*prop)); + _fdt_nop_region(prop, len + sizeof(*prop)); return 0; } @@ -139,6 +139,7 @@ int fdt_nop_node(void *fdt, int nodeoffset) if (endoffset < 0) return endoffset; - nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), endoffset - nodeoffset); + _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), + endoffset - nodeoffset); return 0; } diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 549e345..46eb93e 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -52,13 +52,10 @@ */ #include -#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -#define PALIGN(p, a) ((void *)ALIGN((unsigned long)(p), (a))) +#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) -#define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) -#define streq(p, q) (strcmp((p), (q)) == 0) - -#define CHECK_HEADER(fdt) \ +#define FDT_CHECK_HEADER(fdt) \ { \ int err; \ if ((err = fdt_check_header(fdt)) != 0) \ @@ -93,6 +90,6 @@ static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n); } -#define SW_MAGIC (~FDT_MAGIC) +#define FDT_SW_MAGIC (~FDT_MAGIC) #endif /* _LIBFDT_INTERNAL_H */ From 08309aa1a428e35ed66fabfc587dd01a176539c7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 9 Jul 2008 11:22:44 +0200 Subject: [PATCH 0250/1198] libfdt: Improve documentation in libfdt.h Fix a few typos and mistakes. Signed-off-by: Wolfram Sang Acked-by: David Gibson --- libfdt/libfdt.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index ad58a84..ce80e4f 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -213,7 +213,7 @@ int fdt_move(const void *fdt, void *buf, int bufsize); /**********************************************************************/ /** - * fdt_string - retreive a string from the strings block of a device tree + * fdt_string - retrieve a string from the strings block of a device tree * @fdt: pointer to the device tree blob * @stroffset: offset of the string within the strings block (native endian) * @@ -227,7 +227,7 @@ int fdt_move(const void *fdt, void *buf, int bufsize); const char *fdt_string(const void *fdt, int stroffset); /** - * fdt_num_mem_rsv - retreive the number of memory reserve map entries + * fdt_num_mem_rsv - retrieve the number of memory reserve map entries * @fdt: pointer to the device tree blob * * Returns the number of entries in the device tree blob's memory @@ -240,7 +240,7 @@ const char *fdt_string(const void *fdt, int stroffset); int fdt_num_mem_rsv(const void *fdt); /** - * fdt_get_mem_rsv - retreive one memory reserve map entry + * fdt_get_mem_rsv - retrieve one memory reserve map entry * @fdt: pointer to the device tree blob * @address, @size: pointers to 64-bit variables * @@ -320,7 +320,7 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); int fdt_path_offset(const void *fdt, const char *path); /** - * fdt_get_name - retreive the name of a given node + * fdt_get_name - retrieve the name of a given node * @fdt: pointer to the device tree blob * @nodeoffset: structure block offset of the starting node * @lenp: pointer to an integer variable (will be overwritten) or NULL @@ -352,7 +352,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); * fdt_get_property() retrieves a pointer to the fdt_property * structure within the device tree blob corresponding to the property * named 'name' of the node at offset nodeoffset. If lenp is - * non-NULL, the length of the property value also returned, in the + * non-NULL, the length of the property value is also returned, in the * integer pointed to by lenp. * * returns: @@ -389,7 +389,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, * fdt_getprop() retrieves a pointer to the value of the property * 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 also + * If lenp is non-NULL, the length of the property value is also * returned, in the integer pointed to by lenp. * * returns: @@ -415,7 +415,7 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset, } /** - * fdt_get_phandle - retreive the phandle of a given node + * fdt_get_phandle - retrieve the phandle of a given node * @fdt: pointer to the device tree blob * @nodeoffset: structure block offset of the node * @@ -423,7 +423,7 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset, * structure block offset nodeoffset. * * returns: - * the phandle of the node at nodeoffset, on succes (!= 0, != -1) + * the phandle of the node at nodeoffset, on success (!= 0, != -1) * 0, if the node has no phandle, or another error occurs */ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); @@ -522,7 +522,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset); * structure from the start to nodeoffset, *twice*. * * returns: - * stucture block offset of the parent of the node at nodeoffset + * structure block offset of the parent of the node at nodeoffset * (>=0), on success * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, @@ -579,7 +579,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, * @fdt: pointer to the device tree blob * @phandle: phandle value * - * fdt_node_offset_by_prop_value() returns the offset of the node + * fdt_node_offset_by_phandle() returns the offset of the node * which has the given phandle value. If there is more than one node * in the tree with the given phandle (an invalid tree), results are * undefined. @@ -806,13 +806,13 @@ int fdt_pack(void *fdt); /** * fdt_add_mem_rsv - add one memory reserve map entry * @fdt: pointer to the device tree blob - * @addres, @size: 64-bit values (native endian) + * @address, @size: 64-bit values (native endian) * * Adds a reserve map entry to the given blob reserving a region at * address address of length size. * * This function will insert data into the reserve map and will - * therfore change the indexes of some entries in the table. + * therefore change the indexes of some entries in the table. * * returns: * 0, on success @@ -836,7 +836,7 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); * the blob. * * This function will delete data from the reservation table and will - * therfore change the indexes of some entries in the table. + * therefore change the indexes of some entries in the table. * * returns: * 0, on success @@ -886,7 +886,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name); * @len: length of the property value * * fdt_setprop() sets the value of the named property in the given - * node to the given value and length, creeating the property if it + * 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 From 17773b0e5148c5ae281ee21492c871292cb7de20 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Mon, 14 Jul 2008 13:45:08 -0500 Subject: [PATCH 0251/1198] Tag Version 1.2.0-rc2 Signed-off-by: Jon Loeliger --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0fa27b2..e871855 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ VERSION = 1 PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION =-rc1 +EXTRAVERSION =-rc2 LOCAL_VERSION = CONFIG_LOCALVERSION = From a653228522a1af6ca8c43e2a6edb9d0aa77dbd24 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Wed, 23 Jul 2008 10:20:53 -0500 Subject: [PATCH 0252/1198] libfdt: Fix 'make install' target handling of .h files. The definition of LIBFDT_INCLUDES was accidentally dropped. Put it back and add srcdir prefix handling for it. Signed-off-by: Jon Loeliger --- Makefile | 4 +++- libfdt/Makefile.libfdt | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e871855..0222dc0 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,7 @@ install: all $(INSTALL) -d $(DESTDIR)$(LIBDIR) $(INSTALL) -m 644 $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) - $(INSTALL) -m 644 $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES)) $(DESTDIR)$(INCLUDEDIR) + $(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR) # # Rules for versioning @@ -140,6 +140,8 @@ endif LIBFDT_objdir = libfdt LIBFDT_srcdir = libfdt LIBFDT_lib = $(LIBFDT_objdir)/libfdt.a +LIBFDT_include = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES)) + include $(LIBFDT_srcdir)/Makefile.libfdt .PHONY: libfdt diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index f4f495b..6c42acf 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -3,5 +3,6 @@ # This is not a complete Makefile of itself. Instead, it is designed to # be easily embeddable into other systems of Makefiles. # +LIBFDT_INCLUDES = fdt.h libfdt.h LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) From 52c356d81b1b5b5426f53655e782c37793c3637e Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Fri, 25 Jul 2008 16:17:04 -0500 Subject: [PATCH 0253/1198] Tag Version 1.2.0 Signed-off-by: Jon Loeliger --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0222dc0..5ad0189 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ VERSION = 1 PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION =-rc2 +EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = From d5653618d26fb8025dc8ed34a920036b61c48153 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 29 Jul 2008 14:51:22 +1000 Subject: [PATCH 0254/1198] libfdt: Forgot one function when cleaning the namespace In commit b6d80a20fc293f3b995c3ce1a6744a5574192125, we renamed all libfdt functions to be prefixed with fdt_ or _fdt_ to minimise the chance of collisions with things from whatever package libfdt is embedded in, pulled into the libfdt build via that environment's libfdt_env.h. Except... I missed one. This patch applies the same treatment to _stringlist_contains(). While we're at it, also make it static since it's only used in the same file. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 129b532..8f105f2 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -408,7 +408,8 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) &phandle, sizeof(phandle)); } -int _stringlist_contains(const char *strlist, int listlen, const char *str) +static int _fdt_stringlist_contains(const char *strlist, int listlen, + const char *str) { int len = strlen(str); const char *p; @@ -434,7 +435,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); if (!prop) return len; - if (_stringlist_contains(prop, len, compatible)) + if (_fdt_stringlist_contains(prop, len, compatible)) return 0; else return 1; From a1db0749fdb270f57fc3ef8f868700e6b3b5c0dd Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 29 Jul 2008 14:51:36 +1000 Subject: [PATCH 0255/1198] dtc: Remove unused lexer function dtc does not use the input() function in flex. Apparently on some gcc versions the unused function will cause warnings. Therefore, this patch removes the function by using the 'noinput' option to flex. 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 44dbfd3..6f8b7dd 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -18,7 +18,7 @@ * USA */ -%option noyywrap nounput yylineno +%option noyywrap nounput noinput yylineno %x INCLUDE %x BYTESTRING From 315c5d095ebdf29f1912186e76ab9f95e694b18a Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 30 Jul 2008 09:59:16 -0400 Subject: [PATCH 0256/1198] dtc: give advance warning that "-S" is going away. The "-S" option allowed the specification of a minimum size for the blob, however the main reason for caring about the size is so there is enough padding to add a chosen node by u-boot or whoever. In which case, folks don't really care about the absolute size, but rather the size of the padding added for this -- which is what the "-p" option does. Having the "-S" just confuses people. Signed-off-by: Paul Gortmaker --- dtc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dtc.c b/dtc.c index d8fd43b..84bee2d 100644 --- a/dtc.c +++ b/dtc.c @@ -182,6 +182,9 @@ int main(int argc, char *argv[]) if (minsize && padsize) die("Can't set both -p and -S\n"); + if (minsize) + fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n"); + fprintf(stderr, "DTC: %s->%s on file \"%s\"\n", inform, outform, arg); From 01a2d8a3e9f19cb1f5ee923af23682fad783a799 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 4 Aug 2008 15:30:13 +1000 Subject: [PATCH 0257/1198] dtc: Make many functions 'static' This patch marks various functions not shared between c files 'static', as they should be. There are a couple of functions in dtc, and many in the testsuite. This is *almost* enough to enable the -Wmissing-prototypes warning. It's not quite enough, because there's a mess of junk in the flex generated code which triggers that warning which I'm not yet sure how to deal with. Signed-off-by: David Gibson --- data.c | 2 +- tests/dtbs_equal_ordered.c | 4 ++-- tests/get_name.c | 2 +- tests/get_path.c | 4 ++-- tests/get_phandle.c | 2 +- tests/incbin.c | 2 +- tests/mangle-layout.c | 6 +++--- tests/node_check_compatible.c | 3 ++- tests/node_offset_by_compatible.c | 2 +- tests/node_offset_by_phandle.c | 2 +- tests/node_offset_by_prop_value.c | 7 ++++--- tests/nopulate.c | 2 +- tests/notfound.c | 2 +- tests/parent_offset.c | 4 ++-- tests/path-references.c | 2 +- tests/path_offset.c | 2 +- tests/references.c | 2 +- tests/set_name.c | 2 +- tests/subnode_offset.c | 2 +- tests/supernode_atdepth_offset.c | 10 +++++----- treesource.c | 2 +- 21 files changed, 34 insertions(+), 32 deletions(-) diff --git a/data.c b/data.c index dd2e3d3..fe555e8 100644 --- a/data.c +++ b/data.c @@ -217,7 +217,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m, return d; } -struct data data_append_markers(struct data d, struct marker *m) +static struct data data_append_markers(struct data d, struct marker *m) { struct marker **mp = &d.markers; diff --git a/tests/dtbs_equal_ordered.c b/tests/dtbs_equal_ordered.c index a0b42ae..ed9278c 100644 --- a/tests/dtbs_equal_ordered.c +++ b/tests/dtbs_equal_ordered.c @@ -29,7 +29,7 @@ #include "tests.h" #include "testdata.h" -void compare_mem_rsv(const void *fdt1, const void *fdt2) +static void compare_mem_rsv(const void *fdt1, const void *fdt2) { int i; uint64_t addr1, size1, addr2, size2; @@ -56,7 +56,7 @@ void compare_mem_rsv(const void *fdt1, const void *fdt2) } } -void compare_structure(const void *fdt1, const void *fdt2) +static void compare_structure(const void *fdt1, const void *fdt2) { int nextoffset1 = 0, nextoffset2 = 0; int offset1, offset2; diff --git a/tests/get_name.c b/tests/get_name.c index 22003b4..0262a12 100644 --- a/tests/get_name.c +++ b/tests/get_name.c @@ -28,7 +28,7 @@ #include "tests.h" #include "testdata.h" -void check_name(void *fdt, const char *path) +static void check_name(void *fdt, const char *path) { int offset; const char *getname, *getname2, *checkname; diff --git a/tests/get_path.c b/tests/get_path.c index 0d208bb..b9c0f60 100644 --- a/tests/get_path.c +++ b/tests/get_path.c @@ -30,7 +30,7 @@ #define POISON ('\xff') -void check_path_buf(void *fdt, const char *path, int pathlen, int buflen) +static void check_path_buf(void *fdt, const char *path, int pathlen, int buflen) { int offset; char buf[buflen+1]; @@ -63,7 +63,7 @@ void check_path_buf(void *fdt, const char *path, int pathlen, int buflen) FAIL("fdt_get_path([%d bytes]) overran buffer", buflen); } -void check_path(void *fdt, const char *path) +static void check_path(void *fdt, const char *path) { int pathlen = strlen(path); diff --git a/tests/get_phandle.c b/tests/get_phandle.c index f7650b8..5735733 100644 --- a/tests/get_phandle.c +++ b/tests/get_phandle.c @@ -28,7 +28,7 @@ #include "tests.h" #include "testdata.h" -void check_phandle(void *fdt, const char *path, uint32_t checkhandle) +static void check_phandle(void *fdt, const char *path, uint32_t checkhandle) { int offset; uint32_t phandle; diff --git a/tests/incbin.c b/tests/incbin.c index 5ab3508..76d8626 100644 --- a/tests/incbin.c +++ b/tests/incbin.c @@ -31,7 +31,7 @@ #define CHUNKSIZE 1024 -char *load_file(const char *name, int *len) +static char *load_file(const char *name, int *len) { FILE *f; char *buf = NULL; diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c index bd6ac40..5be28b9 100644 --- a/tests/mangle-layout.c +++ b/tests/mangle-layout.c @@ -35,7 +35,7 @@ struct bufstate { int size; }; -void expand_buf(struct bufstate *buf, int newsize) +static void expand_buf(struct bufstate *buf, int newsize) { buf->buf = realloc(buf->buf, newsize); if (!buf->buf) @@ -43,7 +43,7 @@ void expand_buf(struct bufstate *buf, int newsize) buf->size = newsize; } -void new_header(struct bufstate *buf, int version, const void *fdt) +static void new_header(struct bufstate *buf, int version, const void *fdt) { int hdrsize; @@ -63,7 +63,7 @@ void new_header(struct bufstate *buf, int version, const void *fdt) fdt_set_boot_cpuid_phys(buf->buf, fdt_boot_cpuid_phys(fdt)); } -void add_block(struct bufstate *buf, int version, char block, const void *fdt) +static void add_block(struct bufstate *buf, int version, char block, const void *fdt) { int align, size; const void *src; diff --git a/tests/node_check_compatible.c b/tests/node_check_compatible.c index 04b6b40..23abbf5 100644 --- a/tests/node_check_compatible.c +++ b/tests/node_check_compatible.c @@ -29,7 +29,8 @@ #include "tests.h" #include "testdata.h" -void check_compatible(const void *fdt, const char *path, const char *compat) +static void check_compatible(const void *fdt, const char *path, + const char *compat) { int offset, err; diff --git a/tests/node_offset_by_compatible.c b/tests/node_offset_by_compatible.c index 02e9874..2317930 100644 --- a/tests/node_offset_by_compatible.c +++ b/tests/node_offset_by_compatible.c @@ -29,7 +29,7 @@ #include "tests.h" #include "testdata.h" -void check_search(void *fdt, const char *compat, ...) +static void check_search(void *fdt, const char *compat, ...) { va_list ap; int offset = -1, target; diff --git a/tests/node_offset_by_phandle.c b/tests/node_offset_by_phandle.c index e9fd939..a8442f1 100644 --- a/tests/node_offset_by_phandle.c +++ b/tests/node_offset_by_phandle.c @@ -29,7 +29,7 @@ #include "tests.h" #include "testdata.h" -void check_search(void *fdt, uint32_t phandle, int target) +static void check_search(void *fdt, uint32_t phandle, int target) { int offset; diff --git a/tests/node_offset_by_prop_value.c b/tests/node_offset_by_prop_value.c index c55110a..0f2a345 100644 --- a/tests/node_offset_by_prop_value.c +++ b/tests/node_offset_by_prop_value.c @@ -29,7 +29,7 @@ #include "tests.h" #include "testdata.h" -void vcheck_search(void *fdt, const char *propname, const void *propval, +static void vcheck_search(void *fdt, const char *propname, const void *propval, int proplen, va_list ap) { int offset = -1, target; @@ -48,7 +48,7 @@ void vcheck_search(void *fdt, const char *propname, const void *propval, } while (target >= 0); } -void check_search(void *fdt, const char *propname, const void *propval, +static void check_search(void *fdt, const char *propname, const void *propval, int proplen, ...) { va_list ap; @@ -58,7 +58,8 @@ void check_search(void *fdt, const char *propname, const void *propval, va_end(ap); } -void check_search_str(void *fdt, const char *propname, const char *propval, ...) +static void check_search_str(void *fdt, const char *propname, + const char *propval, ...) { va_list ap; diff --git a/tests/nopulate.c b/tests/nopulate.c index e56839a..3cbbe21 100644 --- a/tests/nopulate.c +++ b/tests/nopulate.c @@ -30,7 +30,7 @@ #include "tests.h" #include "testdata.h" -int nopulate_struct(char *buf, const char *fdt) +static int nopulate_struct(char *buf, const char *fdt) { int offset, nextoffset = 0; uint32_t tag; diff --git a/tests/notfound.c b/tests/notfound.c index ae28c44..38918ad 100644 --- a/tests/notfound.c +++ b/tests/notfound.c @@ -28,7 +28,7 @@ #include "tests.h" #include "testdata.h" -void check_error(const char *s, int err) +static void check_error(const char *s, int err) { if (err != -FDT_ERR_NOTFOUND) FAIL("%s return error %s instead of -FDT_ERR_NOTFOUND", s, diff --git a/tests/parent_offset.c b/tests/parent_offset.c index 8336c72..e7affcc 100644 --- a/tests/parent_offset.c +++ b/tests/parent_offset.c @@ -28,7 +28,7 @@ #include "tests.h" #include "testdata.h" -int path_parent_len(const char *path) +static int path_parent_len(const char *path) { const char *p = strrchr(path, '/'); @@ -40,7 +40,7 @@ int path_parent_len(const char *path) return p - path; } -void check_path(struct fdt_header *fdt, const char *path) +static void check_path(struct fdt_header *fdt, const char *path) { char *parentpath; int nodeoffset, parentoffset, parentpathoffset, pathparentlen; diff --git a/tests/path-references.c b/tests/path-references.c index b96c5b2..9f363b3 100644 --- a/tests/path-references.c +++ b/tests/path-references.c @@ -28,7 +28,7 @@ #include "tests.h" #include "testdata.h" -void check_ref(const void *fdt, int node, const char *checkpath) +static void check_ref(const void *fdt, int node, const char *checkpath) { const char *p; int len; diff --git a/tests/path_offset.c b/tests/path_offset.c index 4b014ac..bb092f1 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -28,7 +28,7 @@ #include "tests.h" #include "testdata.h" -int check_subnode(void *fdt, int parent, const char *name) +static int check_subnode(void *fdt, int parent, const char *name) { int offset; const struct fdt_node_header *nh; diff --git a/tests/references.c b/tests/references.c index e98d450..cbc33f8 100644 --- a/tests/references.c +++ b/tests/references.c @@ -28,7 +28,7 @@ #include "tests.h" #include "testdata.h" -void check_ref(const void *fdt, int node, uint32_t checkref) +static void check_ref(const void *fdt, int node, uint32_t checkref) { const uint32_t *p; uint32_t ref; diff --git a/tests/set_name.c b/tests/set_name.c index 49817a9..5d1149e 100644 --- a/tests/set_name.c +++ b/tests/set_name.c @@ -28,7 +28,7 @@ #include "tests.h" #include "testdata.h" -void check_set_name(void *fdt, const char *path, const char *newname) +static void check_set_name(void *fdt, const char *path, const char *newname) { int offset; const char *getname, *oldname; diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c index ac2f32e..17be8d8 100644 --- a/tests/subnode_offset.c +++ b/tests/subnode_offset.c @@ -28,7 +28,7 @@ #include "tests.h" #include "testdata.h" -int check_subnode(struct fdt_header *fdt, int parent, const char *name) +static int check_subnode(struct fdt_header *fdt, int parent, const char *name) { int offset; const struct fdt_node_header *nh; diff --git a/tests/supernode_atdepth_offset.c b/tests/supernode_atdepth_offset.c index 1245813..73f41ae 100644 --- a/tests/supernode_atdepth_offset.c +++ b/tests/supernode_atdepth_offset.c @@ -28,7 +28,7 @@ #include "tests.h" #include "testdata.h" -int path_depth(const char *path) +static int path_depth(const char *path) { const char *p; int depth = 0; @@ -49,7 +49,7 @@ int path_depth(const char *path) return depth; } -int path_prefix(const char *path, int depth) +static int path_prefix(const char *path, int depth) { const char *p; int i; @@ -67,7 +67,7 @@ int path_prefix(const char *path, int depth) return p - path; } -void check_supernode_atdepth(struct fdt_header *fdt, const char *path, +static void check_supernode_atdepth(struct fdt_header *fdt, const char *path, int depth) { int pdepth = path_depth(path); @@ -106,7 +106,7 @@ void check_supernode_atdepth(struct fdt_header *fdt, const char *path, "instead of %d", nodedepth, pdepth); } -void check_supernode_overdepth(struct fdt_header *fdt, const char *path) +static void check_supernode_overdepth(struct fdt_header *fdt, const char *path) { int pdepth = path_depth(path); int nodeoffset, err; @@ -121,7 +121,7 @@ void check_supernode_overdepth(struct fdt_header *fdt, const char *path) "of FDT_ERR_NOTFOUND", path, pdepth+1, err); } -void check_path(struct fdt_header *fdt, const char *path) +static void check_path(struct fdt_header *fdt, const char *path) { int i; diff --git a/treesource.c b/treesource.c index ebeb6eb..1521ff1 100644 --- a/treesource.c +++ b/treesource.c @@ -52,7 +52,7 @@ static void write_prefix(FILE *f, int level) fputc('\t', f); } -int isstring(char c) +static int isstring(char c) { return (isprint(c) || (c == '\0') From cb650ae1430ad0629e5fe88a4c208c8021e19b27 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 6 Aug 2008 14:50:49 +1000 Subject: [PATCH 0258/1198] libfdt: Implement fdt_get_property_namelen() and fdt_getprop_namelen() As well as fdt_subnode_offset(), libfdt includes an fdt_subnode_offset_namelen() function that takes the subnode name to look up not as a NUL-terminated string, but as a string with an explicit length. This can be useful when the caller has the name as part of a longer string, such as a full path. However, we don't have corresponding 'namelen' versions for fdt_get_property() and fdt_getprop(). There are less obvious use cases for these variants on property names, but there are circumstances where they can be useful e.g. looking up property names which need to be parsed from a longer string buffer such as user input or a configuration file, or looking up an alias in a path with IEEE1275 style aliases. So, since it's very easy to implement such variants, this patch does so. The original NUL-terminated variants are, of course, implemented in terms of the namelen versions. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 37 ++++++++++++++++++++++++++++++------- libfdt/libfdt.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 8f105f2..ebd1260 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -80,6 +80,14 @@ const char *fdt_string(const void *fdt, int stroffset) return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; } +static int _fdt_string_eq(const void *fdt, int stroffset, + const char *s, int len) +{ + const char *p = fdt_string(fdt, stroffset); + + return (strlen(p) == len) && (memcmp(p, s, len) == 0); +} + int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) { FDT_CHECK_HEADER(fdt); @@ -175,9 +183,10 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) return NULL; } -const struct fdt_property *fdt_get_property(const void *fdt, - int nodeoffset, - const char *name, int *lenp) +const struct fdt_property *fdt_get_property_namelen(const void *fdt, + int nodeoffset, + const char *name, + int namelen, int *lenp) { uint32_t tag; const struct fdt_property *prop; @@ -210,7 +219,7 @@ const struct fdt_property *fdt_get_property(const void *fdt, if (! prop) goto fail; namestroff = fdt32_to_cpu(prop->nameoff); - if (strcmp(fdt_string(fdt, namestroff), name) == 0) { + if (_fdt_string_eq(fdt, namestroff, name, namelen)) { /* Found it! */ int len = fdt32_to_cpu(prop->len); prop = fdt_offset_ptr(fdt, offset, @@ -238,18 +247,32 @@ const struct fdt_property *fdt_get_property(const void *fdt, return NULL; } -const void *fdt_getprop(const void *fdt, int nodeoffset, - const char *name, int *lenp) +const struct fdt_property *fdt_get_property(const void *fdt, + int nodeoffset, + const char *name, int *lenp) +{ + return fdt_get_property_namelen(fdt, nodeoffset, name, + strlen(name), lenp); +} + +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen, int *lenp) { const struct fdt_property *prop; - prop = fdt_get_property(fdt, nodeoffset, name, lenp); + prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); if (! prop) return NULL; return prop->data; } +const void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp) +{ + return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); +} + uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) { const uint32_t *php; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index ce80e4f..9e4f990 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -342,6 +342,22 @@ int fdt_path_offset(const void *fdt, const char *path); */ const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); +/** + * fdt_get_property_namelen - find a property based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_get_property_namelen(), but only examine the first + * namelen characters of name for matching the property name. + */ +const struct fdt_property *fdt_get_property_namelen(const void *fdt, + int nodeoffset, + const char *name, + int namelen, int *lenp); + /** * fdt_get_property - find a given property in a given node * @fdt: pointer to the device tree blob @@ -379,6 +395,20 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, fdt_get_property(fdt, nodeoffset, name, lenp); } +/** + * fdt_getprop_namelen - get property value based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_getprop(), but only examine the first namelen + * characters of name for matching the property name. + */ +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen, int *lenp); + /** * fdt_getprop - retrieve the value of a given property * @fdt: pointer to the device tree blob From 02cc83540bd7aed689560908da2e4e7f6a39e9b4 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 14 Aug 2008 08:28:19 -0500 Subject: [PATCH 0259/1198] libfdt: Add support for using aliases in fdt_path_offset() If the path doesn't start with '/' check to see if it matches some alias under "/aliases" and substitute the matching alias value in the path and retry the lookup. Signed-off-by: Kumar Gala Acked-by: David Gibson --- libfdt/fdt_ro.c | 21 +++++++++++-- tests/Makefile.tests | 2 +- tests/aliases.dts | 21 +++++++++++++ tests/path_offset_aliases.c | 59 +++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 4 +++ 5 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 tests/aliases.dts create mode 100644 tests/path_offset_aliases.c diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index ebd1260..2f3ff48 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -139,8 +139,25 @@ int fdt_path_offset(const void *fdt, const char *path) FDT_CHECK_HEADER(fdt); - if (*path != '/') - return -FDT_ERR_BADPATH; + /* see if we have an alias */ + if (*path != '/') { + const char *q; + int aliasoffset = fdt_path_offset(fdt, "/aliases"); + + if (aliasoffset < 0) + return -FDT_ERR_BADPATH; + + q = strchr(path, '/'); + if (!q) + q = end; + + p = fdt_getprop_namelen(fdt, aliasoffset, path, q - p, NULL); + if (!p) + return -FDT_ERR_BADPATH; + offset = fdt_path_offset(fdt, p); + + p = q; + } while (*p) { const char *q; diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 704c95d..44021b0 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -11,7 +11,7 @@ LIB_TESTS_L = get_mem_rsv \ open_pack rw_tree1 set_name setprop del_property del_node \ string_escapes references path-references boot-cpuid incbin \ dtbs_equal_ordered \ - add_subnode_with_nops + add_subnode_with_nops path_offset_aliases LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property diff --git a/tests/aliases.dts b/tests/aliases.dts new file mode 100644 index 0000000..39d88ff --- /dev/null +++ b/tests/aliases.dts @@ -0,0 +1,21 @@ +/dts-v1/; + +/ { + aliases { + s1 = &sub1; + ss1 = &subsub1; + sss1 = &subsubsub1; + }; + + sub1: subnode@1 { + compatible = "subnode1"; + + subsub1: subsubnode { + compatible = "subsubnode1", "subsubnode"; + + subsubsub1: subsubsubnode { + compatible = "subsubsubnode1", "subsubsubnode"; + }; + }; + }; +}; diff --git a/tests/path_offset_aliases.c b/tests/path_offset_aliases.c new file mode 100644 index 0000000..191edd2 --- /dev/null +++ b/tests/path_offset_aliases.c @@ -0,0 +1,59 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_path_offset() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2008 Kumar Gala, Freescale Semiconductor, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void check_alias(void *fdt, const char *full_path, const char *alias_path) +{ + int offset, offset_a; + + offset = fdt_path_offset(fdt, full_path); + offset_a = fdt_path_offset(fdt, alias_path); + + if (offset != offset_a) + FAIL("Mismatch between %s path_offset (%d) and %s path_offset alias (%d)", + full_path, offset, alias_path, offset_a); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_alias(fdt, "/subnode@1", "s1"); + check_alias(fdt, "/subnode@1/subsubnode", "ss1"); + check_alias(fdt, "/subnode@1/subsubnode", "s1/subsubnode"); + check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "sss1"); + check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "ss1/subsubsubnode"); + check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "s1/subsubnode/subsubsubnode"); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 7bfc399..eb29462 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -214,6 +214,10 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb + # Check aliases support in fdt_path_offset + run_dtc_test -I dts -O dtb -o aliases.dtb aliases.dts + run_test path_offset_aliases aliases.dtb + # Check /include/ directive run_dtc_test -I dts -O dtb -o includes.test.dtb include0.dts run_test dtbs_equal_ordered includes.test.dtb test_tree1.dtb From 8daae14b742a48078c77fca3ccb24cd376232bc1 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 29 Aug 2008 14:19:13 +1000 Subject: [PATCH 0260/1198] libfdt: Fix bugs in fdt_get_path() The current implementation of fdt_get_path() has a couple of bugs, fixed by this patch. First, contrary to its documentation, on success it returns the length of the node's path, rather than 0. The testcase is correspondingly wrong, and the patch fixes this as well. Second, in some circumstances, it will return -FDT_ERR_BADOFFSET instead of -FDT_ERR_NOSPACE when given insufficient buffer space. Specifically this happens when there is insufficient space even to hold the path's second last component. This behaviour is corrected, and the testcase updated to check it. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 23 +++++++++++------------ tests/get_path.c | 10 +++++++--- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 2f3ff48..1d1e35e 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -316,9 +316,6 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) for (offset = 0, depth = 0; (offset >= 0) && (offset <= nodeoffset); offset = fdt_next_node(fdt, offset, &depth)) { - if (pdepth < depth) - continue; /* overflowed buffer */ - while (pdepth > depth) { do { p--; @@ -326,14 +323,16 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) pdepth--; } - name = fdt_get_name(fdt, offset, &namelen); - if (!name) - return namelen; - if ((p + namelen + 1) <= buflen) { - memcpy(buf + p, name, namelen); - p += namelen; - buf[p++] = '/'; - pdepth++; + if (pdepth >= depth) { + name = fdt_get_name(fdt, offset, &namelen); + if (!name) + return namelen; + if ((p + namelen + 1) <= buflen) { + memcpy(buf + p, name, namelen); + p += namelen; + buf[p++] = '/'; + pdepth++; + } } if (offset == nodeoffset) { @@ -343,7 +342,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) if (p > 1) /* special case so that root path is "/", not "" */ p--; buf[p] = '\0'; - return p; + return 0; } } diff --git a/tests/get_path.c b/tests/get_path.c index b9c0f60..1e05f7c 100644 --- a/tests/get_path.c +++ b/tests/get_path.c @@ -43,6 +43,8 @@ static void check_path_buf(void *fdt, const char *path, int pathlen, int buflen) memset(buf, POISON, sizeof(buf)); /* poison the buffer */ len = fdt_get_path(fdt, offset, buf, buflen); + verbose_printf("get_path() %s -> %d -> %s\n", path, offset, buf); + if (buflen <= pathlen) { if (len != -FDT_ERR_NOSPACE) FAIL("fdt_get_path([%d bytes]) returns %d with " @@ -51,9 +53,9 @@ static void check_path_buf(void *fdt, const char *path, int pathlen, int buflen) if (len < 0) FAIL("fdt_get_path([%d bytes]): %s", buflen, fdt_strerror(len)); - if (len != pathlen) - FAIL("fdt_get_path([%d bytes]) reports length %d " - "instead of %d", buflen, len, pathlen); + if (len != 0) + FAIL("fdt_get_path([%d bytes]) returns %d " + "instead of 0", buflen, len); if (strcmp(buf, path) != 0) FAIL("fdt_get_path([%d bytes]) returns \"%s\" " "instead of \"%s\"", buflen, buf, path); @@ -70,6 +72,8 @@ static void check_path(void *fdt, const char *path) check_path_buf(fdt, path, pathlen, 1024); check_path_buf(fdt, path, pathlen, pathlen+1); check_path_buf(fdt, path, pathlen, pathlen); + check_path_buf(fdt, path, pathlen, 0); + check_path_buf(fdt, path, pathlen, 2); } int main(int argc, char *argv[]) From b236893fc4bc173877adfa4270b14d7d7209fb10 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Thu, 25 Sep 2008 11:02:17 -0500 Subject: [PATCH 0261/1198] Fix an overflow case in fdt_offset_ptr() detected by GCC 4.3. Using Gcc 4.3 detected this problem: ../dtc/libfdt/fdt.c: In function 'fdt_next_tag': ../dtc/libfdt/fdt.c:82: error: assuming signed overflow does not occur when assuming that (X + c) < X is always false To fix the problem, treat the offset as an unsigned int. The problem report and proposed fix were provided by Steve Papacharalambous . Signed-off-by: Jon Loeliger --- libfdt/fdt.c | 2 +- libfdt/libfdt.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 2acaec5..37085c1 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -74,7 +74,7 @@ int fdt_check_header(const void *fdt) return 0; } -const void *fdt_offset_ptr(const void *fdt, int offset, int len) +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { const char *p; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 9e4f990..60dd4a1 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -122,7 +122,7 @@ /* Low-level functions (you probably don't need these) */ /**********************************************************************/ -const void *fdt_offset_ptr(const void *fdt, int offset, int checklen); +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) { return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); From 9c83115351443a132c5c1cbad6cda79d52f63489 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 20 Aug 2008 16:55:14 +1000 Subject: [PATCH 0262/1198] libfdt: Add function to explicitly expand aliases Kumar has already added alias expansion to fdt_path_offset(). However, in some circumstances it may be convenient for the user of libfdt to explicitly get the string expansion of an alias. This patch adds a function to do this, fdt_get_alias(), and uses it to implement fdt_path_offset(). Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 26 ++++++++++++++------ libfdt/libfdt.h | 26 ++++++++++++++++++++ tests/Makefile.tests | 1 + tests/get_alias.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 1 + 5 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 tests/get_alias.c diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 1d1e35e..6365c26 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -141,17 +141,12 @@ int fdt_path_offset(const void *fdt, const char *path) /* see if we have an alias */ if (*path != '/') { - const char *q; - int aliasoffset = fdt_path_offset(fdt, "/aliases"); + const char *q = strchr(path, '/'); - if (aliasoffset < 0) - return -FDT_ERR_BADPATH; - - q = strchr(path, '/'); if (!q) q = end; - p = fdt_getprop_namelen(fdt, aliasoffset, path, q - p, NULL); + p = fdt_get_alias_namelen(fdt, p, q - p); if (!p) return -FDT_ERR_BADPATH; offset = fdt_path_offset(fdt, p); @@ -302,6 +297,23 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) return fdt32_to_cpu(*php); } +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); +} + +const char *fdt_get_alias(const void *fdt, const char *name) +{ + return fdt_get_alias_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 60dd4a1..a11bbf3 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -458,6 +458,32 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset, */ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); +/** + * fdt_get_namelen - get alias based on substring + * @fdt: pointer to the device tree blob + * @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. + */ +const char *fdt_get_alias_namelen(const void *fdt, + const char *name, int namelen); + +/** + * fdt_get_alias - retreive the path referenced by a given alias + * @fdt: pointer to the device tree blob + * @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. + * + * returns: + * a pointer to the expansion of the alias named 'name', of it exists + * NULL, if the given alias or the /aliases node does not exist + */ +const char *fdt_get_alias(const void *fdt, const char *name); + /** * fdt_get_path - determine the full path of a node * @fdt: pointer to the device tree blob diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 44021b0..5fd4d28 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -4,6 +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 \ notfound \ setprop_inplace nop_property nop_node \ sw_tree1 \ diff --git a/tests/get_alias.c b/tests/get_alias.c new file mode 100644 index 0000000..8eeaee4 --- /dev/null +++ b/tests/get_alias.c @@ -0,0 +1,58 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_get_alias() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void check_alias(void *fdt, const char *path, const char *alias) +{ + const char *aliaspath; + + aliaspath = fdt_get_alias(fdt, alias); + + if (path && !aliaspath) + FAIL("fdt_get_alias(%s) failed\n", alias); + + if (strcmp(aliaspath, path) != 0) + FAIL("fdt_get_alias(%s) returned %s instead of %s\n", + alias, aliaspath, path); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_alias(fdt, "/subnode@1", "s1"); + check_alias(fdt, "/subnode@1/subsubnode", "ss1"); + check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "sss1"); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index eb29462..b424664 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -216,6 +216,7 @@ dtc_tests () { # Check aliases support in fdt_path_offset run_dtc_test -I dts -O dtb -o aliases.dtb aliases.dts + run_test get_alias aliases.dtb run_test path_offset_aliases aliases.dtb # Check /include/ directive From 3a90ce6d75ae68c4aadb20fcceeb61a71bc548f3 Mon Sep 17 00:00:00 2001 From: Niklaus Giger Date: Thu, 2 Oct 2008 22:06:35 +0200 Subject: [PATCH 0263/1198] Install & document convert-dtsv0 Signed-off-by: Niklaus Giger Acked-by: David Gibson --- Documentation/manual.txt | 20 ++++++++++++++++++++ Makefile | 1 + 2 files changed, 21 insertions(+) diff --git a/Documentation/manual.txt b/Documentation/manual.txt index b957662..0674384 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -19,6 +19,8 @@ II - The DT block format III - libfdt +IV - Conversion to Version 1 + I - "dtc", the device tree compiler =================================== @@ -613,6 +615,24 @@ strings block. III - libfdt +============ This library should be merged into dtc proper. This library should likely be worked into U-Boot and the kernel. + +IV - Conversion to Version 1 +============================ + +convert-dtsv0 is a small utility program which converts (DTS) +Device Tree Source from the obsolete version 0 to version 1. + +Version 1 DTS files are marked by line "/dts-v1/;" at the top of the file. + +The syntax of the convert-dtsv0 command line is: + +convert-dtsv0 [] + +Each file passed will be converted to the new /dts-v1/ version by creating +a new file with a "v1" appended the filename. + +Comments, empty lines, etc. are preserved. diff --git a/Makefile b/Makefile index 5ad0189..558e10c 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,7 @@ install: all @$(VECHO) INSTALL $(INSTALL) -d $(DESTDIR)$(BINDIR) $(INSTALL) -m 755 dtc $(DESTDIR)$(BINDIR) + $(INSTALL) -m 755 convert-dtsv0 $(DESTDIR)$(BINDIR) $(INSTALL) -d $(DESTDIR)$(LIBDIR) $(INSTALL) -m 644 $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) From e8903fe225f1e3f4a04ea963306c87ca0ac795dc Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Fri, 3 Oct 2008 09:40:39 -0500 Subject: [PATCH 0264/1198] Some Documentation fixes and generalizations. Updated a jdl.com URL reference. Generalized the new section IV to be "Utility Tools" and added a small blurb about ftdump as well. Signed-off-by: Jon Loeliger --- Documentation/manual.txt | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/Documentation/manual.txt b/Documentation/manual.txt index 0674384..f8a8a7b 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -19,7 +19,9 @@ II - The DT block format III - libfdt -IV - Conversion to Version 1 +IV - Utility Tools + 1) convert-dtsv0 -- Conversion to Version 1 + 1) ftdump I - "dtc", the device tree compiler @@ -30,7 +32,7 @@ I - "dtc", the device tree compiler Source code for the Device Tree Compiler can be found at jdl.com. The gitweb interface is: - http://www.jdl.com/git_repos/ + http://git.jdl.com/gitweb/ The repository is here: @@ -39,7 +41,7 @@ The repository is here: Tarballs of the 1.0.0 and latest releases are here: - http://www.jdl.com/software/dtc-1.0.0.tgz + http://www.jdl.com/software/dtc-v1.2.0.tgz http://www.jdl.com/software/dtc-latest.tgz @@ -620,8 +622,11 @@ III - libfdt This library should be merged into dtc proper. This library should likely be worked into U-Boot and the kernel. -IV - Conversion to Version 1 -============================ + +IV - Utility Tools +================== + +1) convert-dtsv0 -- Conversion to Version 1 convert-dtsv0 is a small utility program which converts (DTS) Device Tree Source from the obsolete version 0 to version 1. @@ -630,9 +635,18 @@ Version 1 DTS files are marked by line "/dts-v1/;" at the top of the file. The syntax of the convert-dtsv0 command line is: -convert-dtsv0 [] + convert-dtsv0 [] Each file passed will be converted to the new /dts-v1/ version by creating a new file with a "v1" appended the filename. Comments, empty lines, etc. are preserved. + + +2) ftdump -- Flat Tree dumping utility + +The ftdump program prints a readable version of a flat device tree file. + +The syntax of the ftdump command line is: + + ftdump From 68f98d7b8aa41fab175daf9f1bcb2a5bc22dbc90 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Fri, 3 Oct 2008 10:49:22 -0500 Subject: [PATCH 0265/1198] Rearrange ftdump and convert-dtsv0 into sub-Makefiles. Follows the model of the existing sub-Makefiles for dtc. Adjust $(BIN) definition to represent installable bin programs and use it as the list of installed programs rather than using an enumerated list in the install target. Adjust the tests/Makefile to clean up properly still. Signed-off-by: Jon Loeliger --- Makefile | 70 ++++++++++++++++++++++-------------------- Makefile.convert-dtsv0 | 12 ++++++++ Makefile.ftdump | 12 ++++++++ tests/Makefile.tests | 5 ++- 4 files changed, 63 insertions(+), 36 deletions(-) create mode 100644 Makefile.convert-dtsv0 create mode 100644 Makefile.ftdump diff --git a/Makefile b/Makefile index 558e10c..b3b85a5 100644 --- a/Makefile +++ b/Makefile @@ -46,18 +46,6 @@ else DEPTARGETS = $(filter-out $(NODEPTARGETS),$(MAKECMDGOALS)) endif -all: dtc ftdump convert-dtsv0 libfdt - -install: all - @$(VECHO) INSTALL - $(INSTALL) -d $(DESTDIR)$(BINDIR) - $(INSTALL) -m 755 dtc $(DESTDIR)$(BINDIR) - $(INSTALL) -m 755 convert-dtsv0 $(DESTDIR)$(BINDIR) - $(INSTALL) -d $(DESTDIR)$(LIBDIR) - $(INSTALL) -m 644 $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) - $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) - $(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR) - # # Rules for versioning # @@ -101,40 +89,27 @@ define filechk fi; endef -$(VERSION_FILE): Makefile FORCE - $(call filechk,version) -# -# Rules for dtc proper -# +include Makefile.convert-dtsv0 include Makefile.dtc +include Makefile.ftdump +BIN += convert-dtsv0 BIN += dtc +BIN += ftdump -# This stops make from generating the lex and bison output during -# auto-dependency computation, but throwing them away as an -# intermediate target and building them again "for real" -.SECONDARY: $(DTC_GEN_SRCS) -dtc: $(DTC_OBJS) +all: $(BIN) libfdt + ifneq ($(DEPTARGETS),) -include $(DTC_OBJS:%.o=%.d) +-include $(CONVERT_OBJS:%.o=%.d) +-include $(FTDUMP_OBJS:%.o=%.d) endif -# -# Rules for ftdump & convert-dtsv0 -# -BIN += ftdump convert-dtsv0 -ftdump: ftdump.o -convert-dtsv0: convert-dtsv0-lexer.lex.o srcpos.o - @$(VECHO) LD $@ - $(LINK.c) -o $@ $^ -ifneq ($(DEPTARGETS),) --include ftdump.d -endif # # Rules for libfdt # @@ -158,6 +133,35 @@ ifneq ($(DEPTARGETS),) -include $(LIBFDT_OBJS:%.o=$(LIBFDT_objdir)/%.d) endif +# This stops make from generating the lex and bison output during +# auto-dependency computation, but throwing them away as an +# intermediate target and building them again "for real" +.SECONDARY: $(DTC_GEN_SRCS) $(CONVERT_GEN_SRCS) + + + +install: all + @$(VECHO) INSTALL + $(INSTALL) -d $(DESTDIR)$(BINDIR) + $(INSTALL) -m 755 $(BIN) $(DESTDIR)$(BINDIR) + $(INSTALL) -d $(DESTDIR)$(LIBDIR) + $(INSTALL) -m 644 $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) + $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) + $(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR) + +$(VERSION_FILE): Makefile FORCE + $(call filechk,version) + + +dtc: $(DTC_OBJS) + +convert-dtsv0: $(CONVERT_OBJS) + @$(VECHO) LD $@ + $(LINK.c) -o $@ $^ + +ftdump: $(FTDUMP_OBJS) + + # # Testsuite rules # diff --git a/Makefile.convert-dtsv0 b/Makefile.convert-dtsv0 new file mode 100644 index 0000000..a3f74c9 --- /dev/null +++ b/Makefile.convert-dtsv0 @@ -0,0 +1,12 @@ +# +# This is not a complete Makefile of itself. +# Instead, it is designed to be easily embeddable +# into other systems of Makefiles. +# + +CONVERT_SRCS = \ + srcpos.c + +CONVERT_GEN_SRCS = convert-dtsv0-lexer.lex.c + +CONVERT_OBJS = $(CONVERT_SRCS:%.c=%.o) $(CONVERT_GEN_SRCS:%.c=%.o) diff --git a/Makefile.ftdump b/Makefile.ftdump new file mode 100644 index 0000000..b70905a --- /dev/null +++ b/Makefile.ftdump @@ -0,0 +1,12 @@ +# +# This is not a complete Makefile of itself. +# Instead, it is designed to be easily embeddable +# into other systems of Makefiles. +# + +FTDUMP_SRCS = \ + ftdump.c + +FTDUMP_GEN_SRCS = + +FTDUMP_OBJS = $(FTDUMP_SRCS:%.c=%.o) $(FTDUMP_GEN_SRCS:%.c=%.o) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 5fd4d28..21a311e 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -29,9 +29,8 @@ TESTS_DEPFILES = $(TESTS:%=%.d) \ $(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d) TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts *.dtsv1 tmp.* -TESTS_CLEANFILES = $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) - -BIN += $(TESTS) $(TESTS_PREFIX)dumptrees +TESTS_CLEANFILES_L += dumptrees +TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) .PHONY: tests tests: $(TESTS) $(TESTS_TREES) From 879e4d2590b50d63f82c3c3652bc3c7900591f1c Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Fri, 3 Oct 2008 11:12:33 -0500 Subject: [PATCH 0266/1198] Implement and use an xstrdup() function Many places in dtc use strdup(), but none of them actually check the return value to see if the implied allocation succeeded. This is a potential bug, which we fix in the patch below by replacing strdup() with an xstrdup() which in analogy to xmalloc() will quit with a fatal error if the allocation fails. I felt the introduciton of util.[ch] was a better choice for utility oriented code than directly using srcpos.c for the new string function. This patch is a re-factoring of Dave Gibson's similar patch. Signed-off-by: Jon Loeliger --- Makefile.convert-dtsv0 | 3 ++- Makefile.dtc | 13 +++++++++++-- convert-dtsv0-lexer.l | 3 ++- dtc-lexer.l | 14 +++++++------- dtc.h | 3 +++ flattree.c | 6 +++--- fstree.c | 4 ++-- srcpos.c | 4 ++-- util.c | 30 ++++++++++++++++++++++++++++++ util.h | 20 ++++++++++++++++++++ 10 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 util.c create mode 100644 util.h diff --git a/Makefile.convert-dtsv0 b/Makefile.convert-dtsv0 index a3f74c9..08ea40a 100644 --- a/Makefile.convert-dtsv0 +++ b/Makefile.convert-dtsv0 @@ -5,7 +5,8 @@ # CONVERT_SRCS = \ - srcpos.c + srcpos.c \ + util.c CONVERT_GEN_SRCS = convert-dtsv0-lexer.lex.c diff --git a/Makefile.dtc b/Makefile.dtc index 6ddf9ec..bece49b 100644 --- a/Makefile.dtc +++ b/Makefile.dtc @@ -3,7 +3,16 @@ # This is not a complete Makefile of itself. Instead, it is designed to # be easily embeddable into other systems of Makefiles. # -DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \ - checks.c +DTC_SRCS = \ + checks.c \ + data.c \ + dtc.c \ + flattree.c \ + fstree.c \ + livetree.c \ + srcpos.c \ + treesource.c \ + util.c + DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o) diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index 12b45ea..194f635 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -42,6 +42,7 @@ GAP ({WS}|{COMMENT}|{LINECOMMENT})* #include #include "srcpos.h" +#include "util.h" static int v1_tagged; /* = 0 */ static int cbase = 16; @@ -185,7 +186,7 @@ const struct { {PROPNODECHAR}+ { ECHO; - last_name = strdup(yytext); + last_name = xstrdup(yytext); BEGIN(INITIAL); } diff --git a/dtc-lexer.l b/dtc-lexer.l index 6f8b7dd..35b39ca 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -105,7 +105,7 @@ static int pop_input_file(void); yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("Label: %s\n", yytext); - yylval.labelref = strdup(yytext); + yylval.labelref = xstrdup(yytext); yylval.labelref[yyleng-1] = '\0'; return DT_LABEL; } @@ -128,7 +128,7 @@ static int pop_input_file(void); [0-9a-fA-F]+ { yylloc.file = srcpos_file; yylloc.first_line = yylineno; - yylval.literal = strdup(yytext); + yylval.literal = xstrdup(yytext); DPRINT("Literal: '%s'\n", yylval.literal); return DT_LEGACYLITERAL; } @@ -136,7 +136,7 @@ static int pop_input_file(void); [0-9]+|0[xX][0-9a-fA-F]+ { yylloc.file = srcpos_file; yylloc.first_line = yylineno; - yylval.literal = strdup(yytext); + yylval.literal = xstrdup(yytext); DPRINT("Literal: '%s'\n", yylval.literal); return DT_LITERAL; } @@ -145,7 +145,7 @@ static int pop_input_file(void); yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("Ref: %s\n", yytext+1); - yylval.labelref = strdup(yytext+1); + yylval.labelref = xstrdup(yytext+1); return DT_REF; } @@ -154,7 +154,7 @@ static int pop_input_file(void); yylloc.first_line = yylineno; yytext[yyleng-1] = '\0'; DPRINT("Ref: %s\n", yytext+2); - yylval.labelref = strdup(yytext+2); + yylval.labelref = xstrdup(yytext+2); return DT_REF; } @@ -162,7 +162,7 @@ static int pop_input_file(void); yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("Ref: %s\n", yytext+1); - yylval.labelref = strdup(yytext+1); + yylval.labelref = xstrdup(yytext+1); return DT_REF; } @@ -186,7 +186,7 @@ static int pop_input_file(void); yylloc.file = srcpos_file; yylloc.first_line = yylineno; DPRINT("PropNodeName: %s\n", yytext); - yylval.propnodename = strdup(yytext); + yylval.propnodename = xstrdup(yytext); BEGIN_DEFAULT(); return DT_PROPNODENAME; } diff --git a/dtc.h b/dtc.h index 08d54c8..5ead895 100644 --- a/dtc.h +++ b/dtc.h @@ -34,7 +34,10 @@ #include #include +#include "util.h" + #define DEFAULT_FDT_VERSION 17 + /* * Command line options */ diff --git a/flattree.c b/flattree.c index 76acd28..50190b8 100644 --- a/flattree.c +++ b/flattree.c @@ -601,7 +601,7 @@ static char *flat_read_string(struct inbuf *inb) len++; } while ((*p++) != '\0'); - str = strdup(inb->ptr); + str = xstrdup(inb->ptr); inb->ptr += len; @@ -643,7 +643,7 @@ static char *flat_read_stringtable(struct inbuf *inb, int offset) p++; } - return strdup(inb->base + offset); + return xstrdup(inb->base + offset); } static struct property *flat_read_property(struct inbuf *dtbuf, @@ -710,7 +710,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath) if (!streq(ppath, "/")) plen++; - return strdup(cpath + plen); + return xstrdup(cpath + plen); } static struct node *unflatten_tree(struct inbuf *dtbuf, diff --git a/fstree.c b/fstree.c index 766b269..7aee982 100644 --- a/fstree.c +++ b/fstree.c @@ -58,7 +58,7 @@ static struct node *read_fstree(const char *dirname) "WARNING: Cannot open %s: %s\n", tmpnam, strerror(errno)); } else { - prop = build_property(strdup(de->d_name), + prop = build_property(xstrdup(de->d_name), data_copy_file(pfile, st.st_size), NULL); @@ -69,7 +69,7 @@ static struct node *read_fstree(const char *dirname) struct node *newchild; newchild = read_fstree(tmpnam); - newchild = name_node(newchild, strdup(de->d_name), + newchild = name_node(newchild, xstrdup(de->d_name), NULL); add_child(tree, newchild); } diff --git a/srcpos.c b/srcpos.c index 9641b76..d5a4b2a 100644 --- a/srcpos.c +++ b/srcpos.c @@ -39,7 +39,7 @@ static int dtc_open_one(struct dtc_file *file, strcat(fullname, "/"); strcat(fullname, fname); } else { - fullname = strdup(fname); + fullname = xstrdup(fname); } file->file = fopen(fullname, "r"); @@ -85,7 +85,7 @@ struct dtc_file *dtc_open_file(const char *fname, if (!file->file) goto fail; - file->name = strdup(fname); + file->name = xstrdup(fname); return file; } diff --git a/util.c b/util.c new file mode 100644 index 0000000..33631ce --- /dev/null +++ b/util.c @@ -0,0 +1,30 @@ +/* + * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "dtc.h" + +char *xstrdup(const char *s) +{ + int len = strlen(s) + 1; + char *dup = xmalloc(len); + + memcpy(dup, s, len); + + return dup; +} diff --git a/util.h b/util.h new file mode 100644 index 0000000..1fa78eb --- /dev/null +++ b/util.h @@ -0,0 +1,20 @@ +/* + * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +extern char *xstrdup(const char *s); From 83ac55d9c4669397f3f2454d3c72dd34e5de5490 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Fri, 3 Oct 2008 11:46:43 -0500 Subject: [PATCH 0267/1198] Use flex's YY_USER_ACTION feature to avoid code duplication Current, every lexer rule starts with some boiler plate to update the yylloc value for use by the parser. One of the rules, even mistakenly has a redundant allocation to one of the members. This patch uses the flex YY_USER_ACTION macro hook, which is executed before every rule to avoid this duplication. Signed-off-by: David Gibson --- dtc-lexer.l | 36 +++++------------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 35b39ca..487953c 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -38,6 +38,11 @@ LINECOMMENT "//".*\n #include "srcpos.h" #include "dtc-parser.tab.h" +#define YY_USER_ACTION \ + { \ + yylloc.file = srcpos_file; \ + yylloc.first_line = yylineno; \ + } /*#define LEXDEBUG 1*/ @@ -75,18 +80,13 @@ static int pop_input_file(void); } <*>{STRING} { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; DPRINT("String: %s\n", yytext); yylval.data = data_copy_escape_string(yytext+1, yyleng-2); - yylloc.first_line = yylineno; return DT_STRING; } <*>"/dts-v1/" { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; DPRINT("Keyword: /dts-v1/\n"); dts_version = 1; BEGIN_DEFAULT(); @@ -94,16 +94,12 @@ static int pop_input_file(void); } <*>"/memreserve/" { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; DPRINT("Keyword: /memreserve/\n"); BEGIN_DEFAULT(); return DT_MEMRESERVE; } <*>{LABEL}: { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; DPRINT("Label: %s\n", yytext); yylval.labelref = xstrdup(yytext); yylval.labelref[yyleng-1] = '\0'; @@ -111,8 +107,6 @@ static int pop_input_file(void); } [bodh]# { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; if (*yytext == 'b') yylval.cbase = 2; else if (*yytext == 'o') @@ -126,32 +120,24 @@ static int pop_input_file(void); } [0-9a-fA-F]+ { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; yylval.literal = xstrdup(yytext); DPRINT("Literal: '%s'\n", yylval.literal); return DT_LEGACYLITERAL; } [0-9]+|0[xX][0-9a-fA-F]+ { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; yylval.literal = xstrdup(yytext); DPRINT("Literal: '%s'\n", yylval.literal); return DT_LITERAL; } \&{LABEL} { /* label reference */ - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; DPRINT("Ref: %s\n", yytext+1); yylval.labelref = xstrdup(yytext+1); return DT_REF; } "&{/"{PATHCHAR}+\} { /* new-style path reference */ - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; yytext[yyleng-1] = '\0'; DPRINT("Ref: %s\n", yytext+2); yylval.labelref = xstrdup(yytext+2); @@ -159,32 +145,24 @@ static int pop_input_file(void); } "&/"{PATHCHAR}+ { /* old-style path reference */ - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; DPRINT("Ref: %s\n", yytext+1); yylval.labelref = xstrdup(yytext+1); return DT_REF; } [0-9a-fA-F]{2} { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; yylval.byte = strtol(yytext, NULL, 16); DPRINT("Byte: %02x\n", (int)yylval.byte); return DT_BYTE; } "]" { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; DPRINT("/BYTESTRING\n"); BEGIN_DEFAULT(); return ']'; } {PROPNODECHAR}+ { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; DPRINT("PropNodeName: %s\n", yytext); yylval.propnodename = xstrdup(yytext); BEGIN_DEFAULT(); @@ -192,8 +170,6 @@ static int pop_input_file(void); } "/incbin/" { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; DPRINT("Binary Include\n"); return DT_INCBIN; } @@ -203,8 +179,6 @@ static int pop_input_file(void); <*>{LINECOMMENT}+ /* eat C++-style comments */ <*>. { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; DPRINT("Char: %c (\\x%02x)\n", yytext[0], (unsigned)yytext[0]); if (yytext[0] == '[') { From e5c8e1dcd7f2d3784194498e5ea916e7b48fe33a Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Fri, 12 Sep 2008 13:39:49 -0500 Subject: [PATCH 0268/1198] Enhance source position implementation. Implemented some print and copy routines. Made empty srcpos objects that will be used later. Protected .h file from multiple #include's. Added srcpos_error() and srcpos_warn(). Signed-off-by: Jon Loeliger --- dtc-parser.y | 29 +++-------- srcpos.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++---- srcpos.h | 23 +++++++- 3 files changed, 163 insertions(+), 33 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index b2ab562..ae6f3c4 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -27,6 +27,7 @@ #include "srcpos.h" extern int yylex(void); +extern void yyerror(char const *s); extern struct boot_info *the_boot_info; extern int treesource_error; @@ -208,9 +209,11 @@ propdata: if ($6 != 0) if (fseek(file->file, $6, SEEK_SET) != 0) - yyerrorf("Couldn't seek to offset %llu in \"%s\": %s", - (unsigned long long)$6, - $4.val, strerror(errno)); + srcpos_error(&yyloc, + "Couldn't seek to offset %llu in \"%s\": %s", + (unsigned long long)$6, + $4.val, + strerror(errno)); d = data_copy_file(file->file, $8); @@ -339,26 +342,10 @@ label: %% -void yyerrorf(char const *s, ...) +void yyerror(char const *s) { - const char *fname = srcpos_file ? srcpos_file->name : ""; - va_list va; - va_start(va, s); - - if (strcmp(fname, "-") == 0) - fname = "stdin"; - - fprintf(stderr, "%s:%d ", fname, yylloc.first_line); - vfprintf(stderr, s, va); - fprintf(stderr, "\n"); - + srcpos_error(&yylloc, "%s", s); treesource_error = 1; - va_end(va); -} - -void yyerror (char const *s) -{ - yyerrorf("%s", s); } static unsigned long long eval_literal(const char *s, int base, int bits) diff --git a/srcpos.c b/srcpos.c index d5a4b2a..8bb0c02 100644 --- a/srcpos.c +++ b/srcpos.c @@ -17,18 +17,40 @@ * USA */ +#define _GNU_SOURCE + +#include + #include "dtc.h" #include "srcpos.h" + /* * Like yylineno, this is the current open file pos. */ - struct dtc_file *srcpos_file; -static int dtc_open_one(struct dtc_file *file, - const char *search, - const char *fname) +/* + * The empty source position. + */ + +struct dtc_file dtc_empty_file = { + .dir = NULL, + .name = "", + .file = NULL +}; + +srcpos srcpos_empty = { + .first_line = 0, + .first_column = 0, + .last_line = 0, + .last_column = 0, + .file = &dtc_empty_file +}; + + +static int +dtc_open_one(struct dtc_file *file, const char *search, const char *fname) { char *fullname; @@ -53,8 +75,8 @@ static int dtc_open_one(struct dtc_file *file, } -struct dtc_file *dtc_open_file(const char *fname, - const struct search_path *search) +struct dtc_file * +dtc_open_file(const char *fname, const struct search_path *search) { static const struct search_path default_search = { NULL, NULL, NULL }; @@ -106,11 +128,113 @@ fail: die("Couldn't open \"%s\": %s\n", fname, strerror(errno)); } -void dtc_close_file(struct dtc_file *file) + +void +dtc_close_file(struct dtc_file *file) { if (fclose(file->file)) die("Error closing \"%s\": %s\n", file->name, strerror(errno)); - - free(file->dir); - free(file); +} + + +srcpos * +srcpos_copy(srcpos *pos) +{ + srcpos *pos_new; + + pos_new = xmalloc(sizeof(srcpos)); + memcpy(pos_new, pos, sizeof(srcpos)); + + return pos_new; +} + + + +void +srcpos_dump(srcpos *pos) +{ + printf("file : \"%s\"\n", + pos->file ? (char *) pos->file : ""); + printf("first_line : %d\n", pos->first_line); + printf("first_column: %d\n", pos->first_column); + printf("last_line : %d\n", pos->last_line); + printf("last_column : %d\n", pos->last_column); + printf("file : %s\n", pos->file->name); +} + + +char * +srcpos_string(srcpos *pos) +{ + const char *fname; + char col_buf[100]; + char *pos_str; + + if (!pos) { + fname = ""; + } else if (pos->file->name) { + fname = pos->file->name; + if (strcmp(fname, "-") == 0) + fname = "stdin"; + } else { + fname = ""; + } + + if (pos->first_line == pos->last_line) { + if (pos->first_column == pos->last_column) { + snprintf(col_buf, sizeof(col_buf), + "%d:%d", + pos->first_line, pos->first_column); + } else { + snprintf(col_buf, sizeof(col_buf), + "%d:%d-%d", + pos->first_line, + pos->first_column, pos->last_column); + } + + } else { + snprintf(col_buf, sizeof(col_buf), + "%d:%d - %d:%d", + pos->first_line, pos->first_column, + pos->last_line, pos->last_column); + } + + if (asprintf(&pos_str, "%s %s", fname, col_buf) == -1) + return " Date: Thu, 14 Aug 2008 17:19:37 -0500 Subject: [PATCH 0269/1198] Remove support for the legacy DTS source file format. Now that all in-kernel-tree DTS files are properly /dts-v1/, remove direct support for the older, un-numbered DTS source file format. Convert existing tests to /dts-v1/ and remove support for the conversion tests themselves. For now, though, the conversion tool still exists. Signed-off-by: Jon Loeliger --- dtc-lexer.l | 34 ++--------------------------- dtc-parser.y | 46 --------------------------------------- tests/base01.dts | 24 ++++++++++---------- tests/empty.dts | 2 ++ tests/escapes.dts | 2 ++ tests/label01.dts | 38 +++++++++++++++++--------------- tests/references_dts0.dts | 12 +++++----- tests/run_tests.sh | 27 +---------------------- tests/test01.dts | 38 +++++++++++++++++--------------- tests/test_tree1_dts0.dts | 18 ++++++++------- 10 files changed, 77 insertions(+), 164 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 487953c..d142de5 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -52,15 +52,10 @@ LINECOMMENT "//".*\n #define DPRINT(fmt, ...) do { } while (0) #endif -static int dts_version; /* = 0 */ +static int dts_version = 1; -#define BEGIN_DEFAULT() if (dts_version == 0) { \ - DPRINT("\n"); \ - BEGIN(INITIAL); \ - } else { \ - DPRINT("\n"); \ +#define BEGIN_DEFAULT() DPRINT("\n"); \ BEGIN(V1); \ - } static void push_input_file(const char *filename); static int pop_input_file(void); @@ -106,25 +101,6 @@ static int pop_input_file(void); return DT_LABEL; } -[bodh]# { - if (*yytext == 'b') - yylval.cbase = 2; - else if (*yytext == 'o') - yylval.cbase = 8; - else if (*yytext == 'd') - yylval.cbase = 10; - else - yylval.cbase = 16; - DPRINT("Base: %d\n", yylval.cbase); - return DT_BASE; - } - -[0-9a-fA-F]+ { - yylval.literal = xstrdup(yytext); - DPRINT("Literal: '%s'\n", yylval.literal); - return DT_LEGACYLITERAL; - } - [0-9]+|0[xX][0-9a-fA-F]+ { yylval.literal = xstrdup(yytext); DPRINT("Literal: '%s'\n", yylval.literal); @@ -144,12 +120,6 @@ static int pop_input_file(void); return DT_REF; } -"&/"{PATHCHAR}+ { /* old-style path reference */ - DPRINT("Ref: %s\n", yytext+1); - yylval.labelref = xstrdup(yytext+1); - return DT_REF; - } - [0-9a-fA-F]{2} { yylval.byte = strtol(yytext, NULL, 16); DPRINT("Byte: %02x\n", (int)yylval.byte); diff --git a/dtc-parser.y b/dtc-parser.y index ae6f3c4..4b69c7a 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -56,7 +56,6 @@ static unsigned long long eval_literal(const char *s, int base, int bits); %token DT_MEMRESERVE %token DT_PROPNODENAME %token DT_LITERAL -%token DT_LEGACYLITERAL %token DT_BASE %token DT_BYTE %token DT_STRING @@ -68,11 +67,8 @@ static unsigned long long eval_literal(const char *s, int base, int bits); %type propdataprefix %type memreserve %type memreserves -%type v0_memreserve -%type v0_memreserves %type addr %type celllist -%type cellbase %type cellval %type bytestring %type propdef @@ -91,10 +87,6 @@ sourcefile: { the_boot_info = build_boot_info($3, $4, 0); } - | v0_memreserves devicetree - { - the_boot_info = build_boot_info($1, $2, 0); - } ; memreserves: @@ -115,37 +107,11 @@ memreserve: } ; -v0_memreserves: - /* empty */ - { - $$ = NULL; - } - | v0_memreserve v0_memreserves - { - $$ = chain_reserve_entry($1, $2); - }; - ; - -v0_memreserve: - memreserve - { - $$ = $1; - } - | label DT_MEMRESERVE addr '-' addr ';' - { - $$ = build_reserve_entry($3, $5 - $3 + 1, $1); - } - ; - addr: DT_LITERAL { $$ = eval_literal($1, 0, 64); } - | DT_LEGACYLITERAL - { - $$ = eval_literal($1, 16, 64); - } ; devicetree: @@ -272,23 +238,11 @@ celllist: } ; -cellbase: - /* empty */ - { - $$ = 16; - } - | DT_BASE - ; - cellval: DT_LITERAL { $$ = eval_literal($1, 0, 32); } - | cellbase DT_LEGACYLITERAL - { - $$ = eval_literal($2, $1, 32); - } ; bytestring: diff --git a/tests/base01.dts b/tests/base01.dts index f84bc49..97a5dd5 100644 --- a/tests/base01.dts +++ b/tests/base01.dts @@ -1,3 +1,5 @@ +/dts-v1/; + / { model = "SomeModel"; compatible = "Nothing"; @@ -6,26 +8,26 @@ memory@0 { device_type = "memory"; - reg = <00000000 00000000 00000000 20000000>; + reg = <0x00000000 0x00000000 0x00000000 0x20000000>; }; cpus { #address-cells = <1>; #size-cells = <0>; - d10 = ; // hex: 0xa - d23 = ; // hex: 0x17 - b101 = ; // hex: 0x5 - o17 = ; // hex: 0xf - hd00d = ; // hex: 0xd00d + d10 = < 10>; // hex: 0xa + d23 = < 23>; // hex: 0x17 + b101 = < 0x5>; // hex: 0x5 + o17 = < 017>; // hex: 0xf + hd00d = < 0xd00d>; // hex: 0xd00d // hex: 0x4d2 0x163e 0x2334 0xd80 - stuff = ; + stuff = < 1234 5678 9012 3456>; - bad-d-1 = ; // Hrm. 0 - bad-d-2 = ; - bad-o-1 = ; - bad-o-2 = ; + bad-d-1 = < 0>; // Hrm. 0 + bad-d-2 = < 123456789012345>; + bad-o-1 = < 00>; + bad-o-2 = < 0123456123456>; }; }; diff --git a/tests/empty.dts b/tests/empty.dts index 336d7a2..e160dad 100644 --- a/tests/empty.dts +++ b/tests/empty.dts @@ -1,2 +1,4 @@ +/dts-v1/; + / { }; diff --git a/tests/escapes.dts b/tests/escapes.dts index f1b8dbc..e05ab46 100644 --- a/tests/escapes.dts +++ b/tests/escapes.dts @@ -1,3 +1,5 @@ +/dts-v1/; + / { compatible = "test_string_escapes"; escape-str = "nastystring: \a\b\t\n\v\f\r\\\""; diff --git a/tests/label01.dts b/tests/label01.dts index 372b17a..a895803 100644 --- a/tests/label01.dts +++ b/tests/label01.dts @@ -1,6 +1,8 @@ -/memreserve/ 1000000000000000 0000000002000000; -memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff; -/memreserve/ 0-13; +/dts-v1/; + +/memreserve/ 0x1000000000000000 0x0000000002000000; +memrsv2: /memreserve/ 0x2000000000000000 0x0100000000000000; +/memreserve/ 0x0000000000000000 0x0000000000000014; / { model = "MyBoardName"; @@ -9,28 +11,28 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff; #size-cells = <2>; cpus { - linux,phandle = <1>; + linux,phandle = <0x1>; #address-cells = <1>; #size-cells = <0>; PowerPC,970@0 { name = "PowerPC,970"; device_type = "cpu"; - reg = <0>; - clock-frequency = <5f5e1000>; - timebase-frequency = <1FCA055>; + reg = <0x00000000>; + clock-frequency = <1600000000>; + timebase-frequency = <33333333>; linux,boot-cpu; - i-cache-size = <10000>; - d-cache-size = <8000>; + i-cache-size = <65536>; + d-cache-size = <32768>; }; PowerPC,970@1 { name = "PowerPC,970"; device_type = "cpu"; - reg = <1>; - clock-frequency = <5f5e1000>; - timebase-frequency = <1FCA055>; - i-cache-size = <10000>; - d-cache-size = <8000>; + reg = <0x00000001>; + clock-frequency = <1600000000>; + timebase-frequency = <33333333>; + i-cache-size = <65536>; + d-cache-size = <32768>; }; }; @@ -38,8 +40,8 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff; node: randomnode { prop: string = str: "foo", str_mid: "stuffstuff\t\t\t\n\n\n" str_end: ; blob = [byte: 0a 0b 0c 0d byte_mid: de ea ad be ef byte_end: ]; - ref = < cell: &/memory@0 0 cell_mid: ffffffff cell_end: >; - mixed = "abc", pre: [1234] post: , gap: < aligned: a b c>; + ref = < cell: &{/memory@0} 0x0 cell_mid: 0xffffffff cell_end: >; + mixed = "abc", pre: [1234] post: , gap: < aligned: 0xa 0xb 0xc>; tricky1 = [61 lt1: 62 63 00]; subnode: child { }; @@ -49,12 +51,12 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff; memory@0 { device_type = "memory"; - memreg: reg = <00000000 00000000 00000000 20000000>; + memreg: reg = <0x00000000 0x00000000 0x00000000 0x20000000>; }; chosen { bootargs = "root=/dev/sda2"; - linux,platform = <00000600>; + linux,platform = <0x600>; }; }; diff --git a/tests/references_dts0.dts b/tests/references_dts0.dts index df82c23..36b6f51 100644 --- a/tests/references_dts0.dts +++ b/tests/references_dts0.dts @@ -1,19 +1,21 @@ +/dts-v1/; + / { /* Explicit phandles */ n1: node1 { - linux,phandle = <2000>; - ref = <&/node2>; /* reference precedes target */ + linux,phandle = <0x2000>; + ref = <&{/node2}>; /* reference precedes target */ lref = <&n2>; }; n2: node2 { - linux,phandle = <1>; - ref = <&/node1>; /* reference after target */ + linux,phandle = <0x1>; + ref = <&{/node1}>; /* reference after target */ lref = <&n1>; }; /* Implicit phandles */ n3: node3 { - ref = <&/node4>; + ref = <&{/node4}>; lref = <&n4>; }; n4: node4 { diff --git a/tests/run_tests.sh b/tests/run_tests.sh index b424664..c6ac48e 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -71,13 +71,6 @@ run_dtc_test () { base_run_test wrap_test $VALGRIND $DTC "$@" } -CONVERT=../convert-dtsv0 - -run_convert_test () { - echo -n "convert-dtsv0 $@: " - base_run_test wrap_test $VALGRIND $CONVERT "$@" -} - tree1_tests () { TREE=$1 @@ -288,21 +281,6 @@ dtc_tests () { run_sh_test dtc-fatal.sh -I fs -O dtb nosuchfile } -convert_tests () { - V0_DTS="test_tree1_dts0.dts references_dts0.dts empty.dts escapes.dts \ - test01.dts label01.dts" - for dts in $V0_DTS; do - run_dtc_test -I dts -O dtb -o cvtraw_$dts.test.dtb $dts - run_dtc_test -I dts -O dts -o cvtdtc_$dts.test.dts $dts - run_dtc_test -I dts -O dtb -o cvtdtc_$dts.test.dtb cvtdtc_$dts.test.dts - run_convert_test $dts - run_dtc_test -I dts -O dtb -o cvtcvt_$dts.test.dtb ${dts}v1 - - run_wrap_test cmp cvtraw_$dts.test.dtb cvtdtc_$dts.test.dtb - run_wrap_test cmp cvtraw_$dts.test.dtb cvtcvt_$dts.test.dtb - done -} - while getopts "vt:m" ARG ; do case $ARG in "v") @@ -318,7 +296,7 @@ while getopts "vt:m" ARG ; do done if [ -z "$TESTSETS" ]; then - TESTSETS="libfdt dtc convert" + TESTSETS="libfdt dtc" fi # Make sure we don't have stale blobs lying around @@ -332,9 +310,6 @@ for set in $TESTSETS; do "dtc") dtc_tests ;; - "convert") - convert_tests - ;; esac done diff --git a/tests/test01.dts b/tests/test01.dts index ed2b178..f9fd165 100644 --- a/tests/test01.dts +++ b/tests/test01.dts @@ -1,6 +1,8 @@ -/memreserve/ 1000000000000000 0000000002000000; -/memreserve/ 2000000000000000-20ffffffffffffff; -/memreserve/ 0-13; +/dts-v1/; + +/memreserve/ 0x1000000000000000 0x0000000002000000; +/memreserve/ 0x2000000000000000 0x0100000000000000; +/memreserve/ 0x0000000000000000 0x0000000000000014; / { model = "MyBoardName"; @@ -9,28 +11,28 @@ #size-cells = <2>; cpus { - linux,phandle = <1>; + linux,phandle = <0x1>; #address-cells = <1>; #size-cells = <0>; PowerPC,970@0 { name = "PowerPC,970"; device_type = "cpu"; - reg = <0>; - clock-frequency = <5f5e1000>; - timebase-frequency = <1FCA055>; + reg = <0x00000000>; + clock-frequency = <1600000000>; + timebase-frequency = <33333333>; linux,boot-cpu; - i-cache-size = <10000>; - d-cache-size = <8000>; + i-cache-size = <65536>; + d-cache-size = <32768>; }; PowerPC,970@1 { name = "PowerPC,970"; device_type = "cpu"; - reg = <1>; - clock-frequency = <5f5e1000>; - timebase-frequency = <1FCA055>; - i-cache-size = <10000>; - d-cache-size = <8000>; + reg = <0x00000001>; + clock-frequency = <1600000000>; + timebase-frequency = <33333333>; + i-cache-size = <65536>; + d-cache-size = <32768>; }; }; @@ -38,18 +40,18 @@ randomnode { string = "\xff\0stuffstuff\t\t\t\n\n\n"; blob = [0a 0b 0c 0d de ea ad be ef]; - ref = < &/memory@0 >; - mixed = "abc", [1234], ; + ref = < &{/memory@0} >; + mixed = "abc", [1234], <0xa 0xb 0xc>; }; memory@0 { device_type = "memory"; - memreg: reg = <00000000 00000000 00000000 20000000>; + memreg: reg = <0x00000000 0x00000000 0x00000000 0x20000000>; }; chosen { bootargs = "root=/dev/sda2"; - linux,platform = <00000600>; + linux,platform = <0x600>; }; }; diff --git a/tests/test_tree1_dts0.dts b/tests/test_tree1_dts0.dts index bc65819..6b40cf5 100644 --- a/tests/test_tree1_dts0.dts +++ b/tests/test_tree1_dts0.dts @@ -1,9 +1,11 @@ -/memreserve/ deadbeef00000000-deadbeef000fffff; -/memreserve/ 75bcd15 1000; +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x0000000000100000; +/memreserve/ 0x00000000075bcd15 0x0000000000001000; / { compatible = "test_tree1"; - prop-int = ; + prop-int = <0xdeadbeef>; prop-str = "hello world"; subnode@1 { @@ -12,18 +14,18 @@ subsubnode { compatible = "subsubnode1", "subsubnode"; - prop-int = ; + prop-int = < 0xdeadbeef>; }; }; subnode@2 { - linux,phandle = <2000>; - prop-int = ; + linux,phandle = <0x2000>; + prop-int = < 123456789>; subsubnode@0 { - linux,phandle = <2001>; + linux,phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; - prop-int = ; + prop-int = < 0726746425>; }; }; }; From 2ebe88df6932a3d685e43d921c9beb526129d2be Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Fri, 5 Sep 2008 14:25:44 -0500 Subject: [PATCH 0270/1198] Add conditionalized debug() print macro. Signed-off-by: Jon Loeliger --- dtc.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dtc.h b/dtc.h index 5ead895..5cb9f58 100644 --- a/dtc.h +++ b/dtc.h @@ -36,6 +36,13 @@ #include "util.h" +#ifdef DEBUG +#define debug(fmt,args...) printf(fmt, ##args) +#else +#define debug(fmt,args...) +#endif + + #define DEFAULT_FDT_VERSION 17 /* From f99cd158a9f0b67d3935a08a07dab4f36719fc74 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 30 Oct 2008 13:41:08 +1100 Subject: [PATCH 0271/1198] libfdt: Fix bug in fdt_subnode_offset_namelen() There's currently an off-by-one bug in fdt_subnode_offset_namelen() which causes it to keep searching after it's finished the subnodes of the given parent, and into the subnodes of siblings of the original node which come after it in the tree. This patch fixes the bug. It also extends the subnode_offset testcase (updating all of the 'test_tree1' example trees in the process) to catch it. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 11 +++++++---- tests/include1.dts | 3 +++ tests/include7.dts | 3 +++ tests/rw_tree1.c | 18 +++++++++++------- tests/subnode_offset.c | 11 +++++++++++ tests/sw_tree1.c | 5 +++++ tests/test_tree1.dts | 6 ++++++ tests/test_tree1_dts0.dts | 6 ++++++ tests/trees.S | 8 ++++++++ 9 files changed, 60 insertions(+), 11 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 6365c26..d12c7ee 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -108,12 +108,12 @@ int fdt_num_mem_rsv(const void *fdt) int fdt_subnode_offset_namelen(const void *fdt, int offset, const char *name, int namelen) { - int depth; + int depth = 0; FDT_CHECK_HEADER(fdt); - for (depth = 0; - offset >= 0; + for (depth = 0, offset = fdt_next_node(fdt, offset, &depth); + (offset >= 0) && (depth > 0); offset = fdt_next_node(fdt, offset, &depth)) { if (depth < 0) return -FDT_ERR_NOTFOUND; @@ -122,7 +122,10 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset, return offset; } - return offset; /* error */ + if (offset < 0) + return offset; /* error */ + else + return -FDT_ERR_NOTFOUND; } int fdt_subnode_offset(const void *fdt, int parentoffset, diff --git a/tests/include1.dts b/tests/include1.dts index 0c7f42e..8d7e747 100644 --- a/tests/include1.dts +++ b/tests/include1.dts @@ -19,5 +19,8 @@ compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; }; + + ss2 { + }; }; }; diff --git a/tests/include7.dts b/tests/include7.dts index fa726f9..dba5e47 100644 --- a/tests/include7.dts +++ b/tests/include7.dts @@ -6,4 +6,7 @@ compatible = "subsubnode1", "subsubnode"; prop-int = <0xdeadbeef>; }; + + ss1 { + }; }; diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c index 8f335c9..f0bce88 100644 --- a/tests/rw_tree1.c +++ b/tests/rw_tree1.c @@ -50,7 +50,7 @@ int main(int argc, char *argv[]) { void *fdt; int err; - int offset; + int offset, s1, s2; test_init(argc, argv); @@ -77,21 +77,25 @@ int main(int argc, char *argv[]) CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1)); OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@1")); - CHECK(fdt_setprop_string(fdt, offset, "compatible", "subnode1")); - CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_1)); - OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode")); + s1 = offset; + CHECK(fdt_setprop_string(fdt, s1, "compatible", "subnode1")); + CHECK(fdt_setprop_cell(fdt, s1, "prop-int", TEST_VALUE_1)); + OFF_CHECK(offset, fdt_add_subnode(fdt, s1, "subsubnode")); CHECK(fdt_setprop(fdt, offset, "compatible", "subsubnode1\0subsubnode", 23)); CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_1)); + OFF_CHECK(offset, fdt_add_subnode(fdt, s1, "ss1")); OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@2")); - CHECK(fdt_setprop_cell(fdt, offset, "linux,phandle", PHANDLE_1)); - CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_2)); - OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "subsubnode@0")); + s2 = offset; + CHECK(fdt_setprop_cell(fdt, s2, "linux,phandle", PHANDLE_1)); + CHECK(fdt_setprop_cell(fdt, s2, "prop-int", TEST_VALUE_2)); + OFF_CHECK(offset, fdt_add_subnode(fdt, s2, "subsubnode@0")); CHECK(fdt_setprop_cell(fdt, offset, "linux,phandle", PHANDLE_2)); CHECK(fdt_setprop(fdt, offset, "compatible", "subsubnode2\0subsubnode", 23)); CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_2)); + OFF_CHECK(offset, fdt_add_subnode(fdt, s2, "ss2")); CHECK(fdt_pack(fdt)); diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c index 17be8d8..b961070 100644 --- a/tests/subnode_offset.c +++ b/tests/subnode_offset.c @@ -60,6 +60,7 @@ int main(int argc, char *argv[]) void *fdt; int subnode1_offset, subnode2_offset; int subsubnode1_offset, subsubnode2_offset, subsubnode2_offset2; + int ss11_off, ss12_off, ss21_off, ss22_off; test_init(argc, argv); fdt = load_blob_arg(argc, argv); @@ -84,5 +85,15 @@ int main(int argc, char *argv[]) if (subsubnode2_offset != subsubnode2_offset2) FAIL("Different offsets with and without unit address"); + ss11_off = check_subnode(fdt, subnode1_offset, "ss1"); + ss21_off = fdt_subnode_offset(fdt, subnode2_offset, "ss1"); + if (ss21_off != -FDT_ERR_NOTFOUND) + FAIL("Incorrectly found ss1 in subnode2"); + + ss12_off = fdt_subnode_offset(fdt, subnode1_offset, "ss2"); + if (ss12_off != -FDT_ERR_NOTFOUND) + FAIL("Incorrectly found ss2 in subnode1"); + ss22_off = check_subnode(fdt, subnode2_offset, "ss2"); + PASS(); } diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 2a94b63..687fb82 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -66,6 +66,8 @@ int main(int argc, char *argv[]) 23)); CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_end_node(fdt)); + CHECK(fdt_begin_node(fdt, "ss1")); + CHECK(fdt_end_node(fdt)); CHECK(fdt_end_node(fdt)); CHECK(fdt_begin_node(fdt, "subnode@2")); @@ -77,6 +79,9 @@ int main(int argc, char *argv[]) 23)); CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2)); CHECK(fdt_end_node(fdt)); + CHECK(fdt_begin_node(fdt, "ss2")); + CHECK(fdt_end_node(fdt)); + CHECK(fdt_end_node(fdt)); CHECK(fdt_end_node(fdt)); diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts index 27602af..1593554 100644 --- a/tests/test_tree1.dts +++ b/tests/test_tree1.dts @@ -16,6 +16,9 @@ compatible = "subsubnode1", "subsubnode"; prop-int = <0xdeadbeef>; }; + + ss1 { + }; }; subnode@2 { @@ -27,5 +30,8 @@ compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; }; + + ss2 { + }; }; }; diff --git a/tests/test_tree1_dts0.dts b/tests/test_tree1_dts0.dts index 6b40cf5..032d540 100644 --- a/tests/test_tree1_dts0.dts +++ b/tests/test_tree1_dts0.dts @@ -16,6 +16,9 @@ compatible = "subsubnode1", "subsubnode"; prop-int = < 0xdeadbeef>; }; + + ss1 { + }; }; subnode@2 { @@ -27,5 +30,8 @@ compatible = "subsubnode2", "subsubnode"; prop-int = < 0726746425>; }; + + ss2 { + }; }; }; diff --git a/tests/trees.S b/tests/trees.S index cedf5f9..609cdd6 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -96,6 +96,10 @@ test_tree1_struct: PROP_STR(test_tree1, compatible, "subsubnode1\0subsubnode") PROP_INT(test_tree1, prop_int, TEST_VALUE_1) END_NODE + + BEGIN_NODE("ss1") + END_NODE + END_NODE BEGIN_NODE("subnode@2") @@ -107,6 +111,10 @@ test_tree1_struct: PROP_STR(test_tree1, compatible, "subsubnode2\0subsubnode") PROP_INT(test_tree1, prop_int, TEST_VALUE_2) END_NODE + + BEGIN_NODE("ss2") + END_NODE + END_NODE END_NODE From 0783d7e705f2d73f7148d9f45c600c2587b3c3ce Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 7 Nov 2008 11:41:11 +1100 Subject: [PATCH 0272/1198] dtc: Check return value from fwrite() There's one place in flattree.c where we currently ignore the return value from fwrite(). On some gcc/glibc versions, where fwrite() is declared with attribute warn_unused_result, this causes a warning. This patch fixes the warning, by checking the fwrite() result. Signed-off-by: David Gibson --- flattree.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/flattree.c b/flattree.c index 50190b8..9197511 100644 --- a/flattree.c +++ b/flattree.c @@ -413,10 +413,13 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version) if (padlen > 0) blob = data_append_zeroes(blob, padlen); - fwrite(blob.val, blob.len, 1, f); - - if (ferror(f)) - die("Error writing device tree blob: %s\n", strerror(errno)); + if (fwrite(blob.val, blob.len, 1, f) != 1) { + if (ferror(f)) + die("Error writing device tree blob: %s\n", + strerror(errno)); + else + die("Short write on device tree blob\n"); + } /* * data_merge() frees the right-hand element so only the blob From 2f766233c2189481b4ee36c99410e559f1c9158c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 7 Nov 2008 11:45:48 +1100 Subject: [PATCH 0273/1198] dtc: Use noinput flex option for convert-dtsv0 to remove warning The convert-dtsv0 lexer doesn't use lex's input() macro/function. This can result in "defined but not used" warnings. This patch uses flex's noinput option to prevent this warning (as we already do for dtc-lexer.l). 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 194f635..9e75085 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -17,7 +17,7 @@ * USA */ -%option noyywrap nounput +%option noyywrap nounput noinput %x INCLUDE %x BYTESTRING From 9878f30f311cb56d1ab1914670b38672476916ac Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 7 Nov 2008 12:49:44 +1100 Subject: [PATCH 0274/1198] dtc: Handle linux,phandle properties which self-reference Currently, dtc will generate phandles for nodes which are referenced elsewhere in the tree. phandles can also be explicitly assigned by defining the linux,phandle property. However, there is no way, currently to tell dtc to generate a phandle for a node if it is not referenced elsewhere. This is inconvenient when it's expected that later processing on the flat tree might add nodes which _will_ the node in question. One way one might attempt to do this is with the construct: mynode: mynode { linux,phandle = <&mynode>; /* ... */ }; Though it's a trifle odd, there's really only one sensible meaning which can be assigned to this construct: allocate a unique phandle to "mynode" and put that in its linux,phandle property (as always). Currently, however, dtc will choke on this self-reference. This patch corrects this, making the construct above give the expected results. It also ensures a more meaningful error message is given if you attempt to process the nonsensical construct: mynode: mynode { linux,phandle = <&someothernode>; /* ... */ }; The 'references' testcase is extended to cover this case, as well. Signed-off-by: David Gibson --- checks.c | 18 ++++++++++++++++++ livetree.c | 14 ++++++++------ tests/references.c | 13 +++++++++++-- tests/references.dts | 10 ++++++++++ tests/references_dts0.dts | 3 +++ tests/run_tests.sh | 3 ++- 6 files changed, 52 insertions(+), 9 deletions(-) diff --git a/checks.c b/checks.c index 9548579..35141f9 100644 --- a/checks.c +++ b/checks.c @@ -282,6 +282,7 @@ static void check_explicit_phandles(struct check *c, struct node *root, struct node *node) { struct property *prop; + struct marker *m; struct node *other; cell_t phandle; @@ -295,6 +296,23 @@ static void check_explicit_phandles(struct check *c, struct node *root, return; } + m = prop->val.markers; + for_each_marker_of_type(m, REF_PHANDLE) { + assert(m->offset == 0); + if (node != get_node_by_ref(root, m->ref)) + /* "Set this node's phandle equal to some + * other node's phandle". That's nonsensical + * by construction. */ + FAIL(c, "linux,phandle in %s is a reference to another node", + node->fullpath); + /* But setting this node's phandle equal to its own + * phandle is allowed - that means allocate a unique + * phandle for this node, even if it's not otherwise + * referenced. The value will be filled in later, so + * no further checking for now. */ + return; + } + phandle = propval_cell(prop); if ((phandle == 0) || (phandle == -1)) { FAIL(c, "%s has invalid linux,phandle value 0x%x", diff --git a/livetree.c b/livetree.c index 0ca3de5..2fa1490 100644 --- a/livetree.c +++ b/livetree.c @@ -293,16 +293,18 @@ cell_t get_node_phandle(struct node *root, struct node *node) if ((node->phandle != 0) && (node->phandle != -1)) return node->phandle; - assert(! get_property(node, "linux,phandle")); - while (get_node_by_phandle(root, phandle)) phandle++; node->phandle = phandle; - add_property(node, - build_property("linux,phandle", - data_append_cell(empty_data, phandle), - NULL)); + if (!get_property(node, "linux,phandle")) + add_property(node, + build_property("linux,phandle", + data_append_cell(empty_data, phandle), + NULL)); + /* If the node *does* have a linux,phandle property, we must + * be dealing with a self-referencing phandle, which will be + * fixed up momentarily in the caller */ return node->phandle; } diff --git a/tests/references.c b/tests/references.c index cbc33f8..b20f21f 100644 --- a/tests/references.c +++ b/tests/references.c @@ -60,8 +60,8 @@ static void check_ref(const void *fdt, int node, uint32_t checkref) int main(int argc, char *argv[]) { void *fdt; - int n1, n2, n3, n4; - uint32_t h1, h2, h4; + int n1, n2, n3, n4, n5; + uint32_t h1, h2, h4, h5; test_init(argc, argv); fdt = load_blob_arg(argc, argv); @@ -78,10 +78,14 @@ int main(int argc, char *argv[]) n4 = fdt_path_offset(fdt, "/node4"); if (n4 < 0) FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4)); + n5 = fdt_path_offset(fdt, "/node5"); + if (n5 < 0) + FAIL("fdt_path_offset(/node5): %s", fdt_strerror(n5)); h1 = fdt_get_phandle(fdt, n1); h2 = fdt_get_phandle(fdt, n2); h4 = fdt_get_phandle(fdt, n4); + h5 = fdt_get_phandle(fdt, n5); if (h1 != 0x2000) FAIL("/node1 has wrong phandle, 0x%x instead of 0x%x", @@ -92,6 +96,11 @@ 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)) + FAIL("/node5 has bad phandle, 0x%x", h5); + if ((h5 == h4) || (h5 == h2) || (h5 == h1)) + FAIL("/node5 has duplicate phandle, 0x%x", h5); + check_ref(fdt, n1, h2); check_ref(fdt, n2, h1); check_ref(fdt, n3, h4); diff --git a/tests/references.dts b/tests/references.dts index 36b6f51..19b28ac 100644 --- a/tests/references.dts +++ b/tests/references.dts @@ -20,4 +20,14 @@ }; n4: node4 { }; + + /* Explicit phandle with implicit value */ + /* This self-reference is the standard way to tag a node as requiring + * a phandle (perhaps for reference by nodes that will be dynamically + * added) without explicitly allocating it a phandle. + * The self-reference requires some special internal handling, though + * so check it actually works */ + n5: node5 { + linux,phandle = <&n5>; + }; }; diff --git a/tests/references_dts0.dts b/tests/references_dts0.dts index 36b6f51..d34dbb2 100644 --- a/tests/references_dts0.dts +++ b/tests/references_dts0.dts @@ -20,4 +20,7 @@ }; n4: node4 { }; + n5: node5 { + linux,phandle = <&n5>; + }; }; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c6ac48e..b27e2b5 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -229,7 +229,8 @@ dtc_tests () { run_test dtbs_equal_ordered boot_cpuid_preserved_test_tree1.test.dtb boot_cpuid_test_tree1.test.dtb # Check -Odts mode preserve all dtb information - for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb ; do + for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb \ + dtc_references.test.dtb; do run_dtc_test -I dtb -O dts -o odts_$tree.test.dts $tree run_dtc_test -I dts -O dtb -o odts_$tree.test.dtb odts_$tree.test.dts run_test dtbs_equal_ordered $tree odts_$tree.test.dtb From 787b599c8108f514645d9ee6256ee53dccc9db84 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 2 Jan 2009 08:19:51 -0500 Subject: [PATCH 0275/1198] libfdt: Add version.lds file Add the initial symbol versioning file as groundwork for creating a libfdt shared library Signed-off-by: Josh Boyer --- libfdt/version.lds | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 libfdt/version.lds diff --git a/libfdt/version.lds b/libfdt/version.lds new file mode 100644 index 0000000..3c3994e --- /dev/null +++ b/libfdt/version.lds @@ -0,0 +1,54 @@ +LIBFDT_1.2 { + global: + fdt_next_node; + fdt_check_header; + fdt_move; + fdt_string; + fdt_num_mem_rsv; + fdt_get_mem_rsv; + fdt_subnode_offset_namelen; + fdt_subnode_offset; + fdt_path_offset; + fdt_get_name; + fdt_get_property_namelen; + fdt_get_property; + fdt_getprop_namelen; + fdt_getprop; + fdt_get_phandle; + fdt_get_alias_namelen; + fdt_get_alias; + fdt_get_path; + fdt_supernode_atdepth_offset; + fdt_node_depth; + fdt_parent_offset; + fdt_node_offset_by_prop_value; + fdt_node_offset_by_phandle; + fdt_node_check_compatible; + fdt_node_offset_by_compatible; + fdt_setprop_inplace; + fdt_nop_property; + fdt_nop_node; + fdt_create; + fdt_add_reservemap_entry; + fdt_finish_reservemap; + fdt_begin_node; + fdt_property; + fdt_end_node; + fdt_finish; + fdt_open_into; + fdt_pack; + fdt_add_mem_rsv; + fdt_del_mem_rsv; + fdt_set_name; + fdt_setprop; + fdt_delprop; + fdt_add_subnode_namelen; + fdt_add_subnode; + fdt_del_node; + fdt_strerror; + fdt_offset_ptr; + fdt_next_tag; + + local: + *; +}; From 6272182b417a903a6b5c0d5d6a470957e919d8f4 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 2 Jan 2009 08:20:34 -0500 Subject: [PATCH 0276/1198] libfdt: Introduce libfdt shared library Build a libfdt shared library in addition to the existing .a that is created. Symbol versioning is used from the libfdt/version.lds script. Signed-off-by: Josh Boyer --- Makefile | 15 ++++++++++++--- libfdt/Makefile.libfdt | 1 + tests/Makefile.tests | 4 ++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index b3b85a5..8d5b929 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ LOCAL_VERSION = CONFIG_LOCALVERSION = CPPFLAGS = -I libfdt -CFLAGS = -Wall -g -Os -Wpointer-arith -Wcast-qual +CFLAGS = -Wall -g -Os -fPIC -Wpointer-arith -Wcast-qual BISON = bison LEX = flex @@ -115,19 +115,23 @@ endif # LIBFDT_objdir = libfdt LIBFDT_srcdir = libfdt -LIBFDT_lib = $(LIBFDT_objdir)/libfdt.a +LIBFDT_archive = $(LIBFDT_objdir)/libfdt.a +LIBFDT_lib = $(LIBFDT_objdir)/libfdt.so LIBFDT_include = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES)) +LIBFDT_version = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_VERSION)) include $(LIBFDT_srcdir)/Makefile.libfdt .PHONY: libfdt -libfdt: $(LIBFDT_lib) +libfdt: $(LIBFDT_archive) $(LIBFDT_lib) +$(LIBFDT_archive): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) $(LIBFDT_lib): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) libfdt_clean: @$(VECHO) CLEAN "(libfdt)" rm -f $(addprefix $(LIBFDT_objdir)/,$(STD_CLEANFILES)) + rm -f $(LIBFDT_objdir)/*.so ifneq ($(DEPTARGETS),) -include $(LIBFDT_OBJS:%.o=$(LIBFDT_objdir)/%.d) @@ -215,6 +219,11 @@ clean: libfdt_clean tests_clean @$(VECHO) AR $@ $(AR) $(ARFLAGS) $@ $^ +$(LIBFDT_lib): + @$(VECHO) LD $@ + $(CC) $(LDFLAGS) -fPIC -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,$(notdir $@) -shared -o $(LIBFDT_objdir)/libfdt-$(DTC_VERSION).so $^ + ln -s libfdt-$(DTC_VERSION).so $(LIBFDT_objdir)/libfdt.so + %.lex.c: %.l @$(VECHO) LEX $@ $(LEX) -o$@ $< diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index 6c42acf..341c803 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -4,5 +4,6 @@ # be easily embeddable into other systems of Makefiles. # LIBFDT_INCLUDES = fdt.h libfdt.h +LIBFDT_VERSION = version.lds LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 21a311e..3a041ff 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -35,9 +35,9 @@ TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) .PHONY: tests tests: $(TESTS) $(TESTS_TREES) -$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_lib) +$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_archive) -$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o $(LIBFDT_lib) +$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o $(LIBFDT_archive) $(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o From 75bdd849dc3083038113791c4050746999d60989 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 5 Jan 2009 12:46:00 +1100 Subject: [PATCH 0277/1198] libfdt: Fix error in documentation for fdt_get_alias_namelen() Oops, screwed up the function name in the documenting comment for this function. Trivial correction in this patch. 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 a11bbf3..4a95e11 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -459,7 +459,7 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset, uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); /** - * fdt_get_namelen - get alias based on substring + * fdt_get_alias_namelen - get alias based on substring * @fdt: pointer to the device tree blob * @name: name of the alias th look up * @namelen: number of characters of name to consider From b2b4990bbf03a1b9def187cbc37488eed66a182c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 5 Jan 2009 12:50:23 +1100 Subject: [PATCH 0278/1198] dtc: Move some functions to util.[ch] Now that we have a util.[ch] file shared between dtc and convert-dtsv0, move some functions which are currently duplicated in the two to util files. Specifically we move the die(), xmalloc() and xrealloc() functions. While we're at it, add standard double-include protection to util.h Signed-off-by: David Gibson --- convert-dtsv0-lexer.l | 20 -------------------- dtc.h | 30 ------------------------------ util.h | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 50 deletions(-) diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index 9e75085..59137f1 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -52,26 +52,6 @@ static char *last_name; /* = NULL */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -static inline void __attribute__((noreturn)) die(char * str, ...) -{ - va_list ap; - - va_start(ap, str); - fprintf(stderr, "FATAL ERROR: "); - vfprintf(stderr, str, ap); - exit(1); -} - -static inline void *xmalloc(size_t len) -{ - void *new = malloc(len); - - if (! new) - die("malloc() failed\n"); - - return new; -} - const struct { const char *pattern; int obase, width; diff --git a/dtc.h b/dtc.h index 5cb9f58..45adaed 100644 --- a/dtc.h +++ b/dtc.h @@ -53,36 +53,6 @@ extern int reservenum; /* Number of memory reservation slots */ extern int minsize; /* Minimum blob size */ extern int padsize; /* Additional padding to blob */ -static inline void __attribute__((noreturn)) die(char * str, ...) -{ - va_list ap; - - va_start(ap, str); - fprintf(stderr, "FATAL ERROR: "); - vfprintf(stderr, str, ap); - exit(1); -} - -static inline void *xmalloc(size_t len) -{ - void *new = malloc(len); - - if (! new) - die("malloc() failed\n"); - - return new; -} - -static inline void *xrealloc(void *p, size_t len) -{ - void *new = realloc(p, len); - - if (! new) - die("realloc() failed (len=%d)\n", len); - - return new; -} - typedef uint32_t cell_t; diff --git a/util.h b/util.h index 1fa78eb..0fb60fe 100644 --- a/util.h +++ b/util.h @@ -1,3 +1,6 @@ +#ifndef _UTIL_H +#define _UTIL_H + /* * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. * @@ -17,4 +20,36 @@ * USA */ +static inline void __attribute__((noreturn)) die(char * str, ...) +{ + va_list ap; + + va_start(ap, str); + fprintf(stderr, "FATAL ERROR: "); + vfprintf(stderr, str, ap); + exit(1); +} + +static inline void *xmalloc(size_t len) +{ + void *new = malloc(len); + + if (!new) + die("malloc() failed\n"); + + return new; +} + +static inline void *xrealloc(void *p, size_t len) +{ + void *new = realloc(p, len); + + if (!new) + die("realloc() failed (len=%d)\n", len); + + return new; +} + extern char *xstrdup(const char *s); + +#endif /* _UTIL_H */ From 26d93f6c922c5b199682f9808c933462c1b97855 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 8 Jan 2009 11:47:55 +1100 Subject: [PATCH 0279/1198] dtc: Make asm output more portable and add testcases This patch adds some testcases for dtc's -Oasm mode. Specifically it checks that building the asm will result in the same device tree blob in memory as -Odtb mode would produce, for a variety of trees. This test uncovered two difficulties with our current -Oasm output, both of which are addressed in this patch as well. First, -Oasm output would only be correct if assembled for a big-endian target. Usually that would be the case, when building device trees into a firmware or similar. However this makes life inconvenient for testing on a little-endian target, and one can think up use cases where a program running on a little endian host might want to embed a device tree for a big-endian target. This patch therefore changes -Oasm output to use .byte directives instead of .long throughout in order to generate byte-for-byte identical trees regardless of the endianness of the assembler target. Second, -Oasm output emitted several #define statements which were then used in the innards of the output - i.e. it assumed the output would be processed by cpp before being assembled. That may not be convenient in all build environments, and in any case doesn't work well with the above fix. So, -Oasm output no longer needs to be preprocessed before assembling. Signed-off-by: David Gibson --- Makefile | 2 +- flattree.c | 98 +++++++++++++++++++++++++------------------ tests/Makefile.tests | 7 +++- tests/asm_tree_dump.c | 62 +++++++++++++++++++++++++++ tests/data.S | 3 ++ tests/run_tests.sh | 19 +++++++++ 6 files changed, 149 insertions(+), 42 deletions(-) create mode 100644 tests/asm_tree_dump.c create mode 100644 tests/data.S diff --git a/Makefile b/Makefile index 8d5b929..1cfa28a 100644 --- a/Makefile +++ b/Makefile @@ -175,7 +175,7 @@ include tests/Makefile.tests # # Clean rules # -STD_CLEANFILES = *~ *.o *.d *.a *.i *.s core a.out vgcore.* \ +STD_CLEANFILES = *~ *.o *.so *.d *.a *.i *.s core a.out vgcore.* \ *.tab.[ch] *.lex.c *.output clean: libfdt_clean tests_clean diff --git a/flattree.c b/flattree.c index 9197511..0ff8c45 100644 --- a/flattree.c +++ b/flattree.c @@ -127,11 +127,21 @@ static void emit_offset_label(FILE *f, const char *label, int offset) fprintf(f, "%s\t= . + %d\n", label, offset); } +#define ASM_EMIT_BELONG(f, fmt, ...) \ + { \ + fprintf((f), "\t.byte\t((" fmt ") >> 24) & 0xff\n", __VA_ARGS__); \ + fprintf((f), "\t.byte\t((" fmt ") >> 16) & 0xff\n", __VA_ARGS__); \ + fprintf((f), "\t.byte\t((" fmt ") >> 8) & 0xff\n", __VA_ARGS__); \ + fprintf((f), "\t.byte\t(" fmt ") & 0xff\n", __VA_ARGS__); \ + } + static void asm_emit_cell(void *e, cell_t val) { FILE *f = e; - fprintf(f, "\t.long\t0x%x\n", val); + fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n", + (val >> 24) & 0xff, (val >> 16) & 0xff, + (val >> 8) & 0xff, val & 0xff); } static void asm_emit_string(void *e, char *str, int len) @@ -169,8 +179,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)) { - fprintf(f, "\t.long\t0x%x\n", - fdt32_to_cpu(*((uint32_t *)(d.val+off)))); + asm_emit_cell(e, fdt32_to_cpu(*((uint32_t *)(d.val+off)))); off += sizeof(uint32_t); } @@ -190,14 +199,16 @@ static void asm_emit_beginnode(void *e, const char *label) fprintf(f, "\t.globl\t%s\n", label); fprintf(f, "%s:\n", label); } - fprintf(f, "\t.long\tFDT_BEGIN_NODE\n"); + fprintf(f, "\t/* FDT_BEGIN_NODE */\n"); + asm_emit_cell(e, FDT_BEGIN_NODE); } static void asm_emit_endnode(void *e, const char *label) { FILE *f = e; - fprintf(f, "\t.long\tFDT_END_NODE\n"); + fprintf(f, "\t/* FDT_END_NODE */\n"); + asm_emit_cell(e, FDT_END_NODE); if (label) { fprintf(f, "\t.globl\t%s_end\n", label); fprintf(f, "%s_end:\n", label); @@ -212,7 +223,8 @@ static void asm_emit_property(void *e, const char *label) fprintf(f, "\t.globl\t%s\n", label); fprintf(f, "%s:\n", label); } - fprintf(f, "\t.long\tFDT_PROP\n"); + fprintf(f, "\t/* FDT_PROP */\n"); + asm_emit_cell(e, FDT_PROP); } static struct emitter asm_emitter = { @@ -458,39 +470,44 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version) die("Unknown device tree blob version %d\n", version); fprintf(f, "/* autogenerated by dtc, do not edit */\n\n"); - fprintf(f, "#define FDT_MAGIC 0x%x\n", FDT_MAGIC); - fprintf(f, "#define FDT_BEGIN_NODE 0x%x\n", FDT_BEGIN_NODE); - fprintf(f, "#define FDT_END_NODE 0x%x\n", FDT_END_NODE); - fprintf(f, "#define FDT_PROP 0x%x\n", FDT_PROP); - fprintf(f, "#define FDT_END 0x%x\n", FDT_END); - fprintf(f, "\n"); emit_label(f, symprefix, "blob_start"); emit_label(f, symprefix, "header"); - fprintf(f, "\t.long\tFDT_MAGIC\t\t\t\t/* magic */\n"); - fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start\t/* totalsize */\n", - symprefix, symprefix); - fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start\t/* off_dt_struct */\n", - symprefix, symprefix); - fprintf(f, "\t.long\t_%s_strings_start - _%s_blob_start\t/* off_dt_strings */\n", - symprefix, symprefix); - fprintf(f, "\t.long\t_%s_reserve_map - _%s_blob_start\t/* off_dt_strings */\n", - symprefix, symprefix); - fprintf(f, "\t.long\t%d\t\t\t\t\t/* version */\n", vi->version); - fprintf(f, "\t.long\t%d\t\t\t\t\t/* last_comp_version */\n", - vi->last_comp_version); - - if (vi->flags & FTF_BOOTCPUID) - fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n", - bi->boot_cpuid_phys); - - if (vi->flags & FTF_STRTABSIZE) - fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n", + fprintf(f, "\t/* magic */\n"); + asm_emit_cell(f, FDT_MAGIC); + fprintf(f, "\t/* totalsize */\n"); + ASM_EMIT_BELONG(f, "_%s_blob_abs_end - _%s_blob_start", symprefix, symprefix); + fprintf(f, "\t/* off_dt_struct */\n"); + ASM_EMIT_BELONG(f, "_%s_struct_start - _%s_blob_start", + symprefix, symprefix); + fprintf(f, "\t/* off_dt_strings */\n"); + ASM_EMIT_BELONG(f, "_%s_strings_start - _%s_blob_start", + symprefix, symprefix); + fprintf(f, "\t/* off_mem_rsvmap */\n"); + ASM_EMIT_BELONG(f, "_%s_reserve_map - _%s_blob_start", + symprefix, symprefix); + fprintf(f, "\t/* version */\n"); + asm_emit_cell(f, vi->version); + fprintf(f, "\t/* last_comp_version */\n"); + asm_emit_cell(f, vi->last_comp_version); - if (vi->flags & FTF_STRUCTSIZE) - fprintf(f, "\t.long\t_%s_struct_end - _%s_struct_start\t/* size_dt_struct */\n", + if (vi->flags & FTF_BOOTCPUID) { + fprintf(f, "\t/* boot_cpuid_phys */\n"); + asm_emit_cell(f, bi->boot_cpuid_phys); + } + + if (vi->flags & FTF_STRTABSIZE) { + fprintf(f, "\t/* size_dt_strings */\n"); + ASM_EMIT_BELONG(f, "_%s_strings_end - _%s_strings_start", + symprefix, symprefix); + } + + if (vi->flags & FTF_STRUCTSIZE) { + fprintf(f, "\t/* size_dt_struct */\n"); + ASM_EMIT_BELONG(f, "_%s_struct_end - _%s_struct_start", symprefix, symprefix); + } /* * Reserve map entries. @@ -512,12 +529,11 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version) fprintf(f, "\t.globl\t%s\n", re->label); fprintf(f, "%s:\n", re->label); } - fprintf(f, "\t.long\t0x%08x, 0x%08x\n", - (unsigned int)(re->re.address >> 32), - (unsigned int)(re->re.address & 0xffffffff)); - fprintf(f, "\t.long\t0x%08x, 0x%08x\n", - (unsigned int)(re->re.size >> 32), - (unsigned int)(re->re.size & 0xffffffff)); + ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32)); + ASM_EMIT_BELONG(f, "0x%08x", + (unsigned int)(re->re.address & 0xffffffff)); + ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32)); + ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff)); } for (i = 0; i < reservenum; i++) { fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); @@ -527,7 +543,9 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version) emit_label(f, symprefix, "struct_start"); flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi); - fprintf(f, "\t.long\tFDT_END\n"); + + fprintf(f, "\t/* FDT_END */\n"); + asm_emit_cell(f, FDT_END); emit_label(f, symprefix, "struct_end"); emit_label(f, symprefix, "strings_start"); diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 3a041ff..f09c72a 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -18,7 +18,10 @@ LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%) -TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) +DL_LIB_TESTS_L = asm_tree_dump +DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%) + +TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS) TESTS_TREES_L = test_tree1.dtb TESTS_TREES = $(TESTS_TREES_L:%=$(TESTS_PREFIX)%) @@ -37,6 +40,8 @@ tests: $(TESTS) $(TESTS_TREES) $(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_archive) +$(DL_LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_archive) -ldl + $(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o $(LIBFDT_archive) $(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o diff --git a/tests/asm_tree_dump.c b/tests/asm_tree_dump.c new file mode 100644 index 0000000..5ff5087 --- /dev/null +++ b/tests/asm_tree_dump.c @@ -0,0 +1,62 @@ +/* + * libfdt - Flat Device Tree manipulation + * Tests if an asm tree built into a shared object matches a given dtb + * Copyright (C) 2008 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + void *sohandle; + void *fdt; + int err; + + test_init(argc, argv); + if (argc != 3) + CONFIG("Usage: %s ", argv[0]); + + sohandle = dlopen(argv[1], RTLD_NOW); + if (!sohandle) + FAIL("Couldn't dlopen() %s", argv[1]); + + fdt = dlsym(sohandle, "dt_blob_start"); + if (!fdt) + FAIL("Couldn't locate \"dt_blob_start\" symbol in %s", + argv[1]); + + err = fdt_check_header(fdt); + if (err != 0) + FAIL("%s contains invalid tree: %s", argv[1], + fdt_strerror(err)); + + save_blob(argv[2], fdt); + + PASS(); +} diff --git a/tests/data.S b/tests/data.S new file mode 100644 index 0000000..86ad539 --- /dev/null +++ b/tests/data.S @@ -0,0 +1,3 @@ +/* Used in combination with dtc -Oasm output to embed + * a device tree in the data section of a .o */ + .data diff --git a/tests/run_tests.sh b/tests/run_tests.sh index b27e2b5..040eca9 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -71,6 +71,15 @@ run_dtc_test () { base_run_test wrap_test $VALGRIND $DTC "$@" } +asm_to_so () { + as -o $1.test.o data.S $1.test.s && \ + ld -shared -o $1.test.so $1.test.o +} + +asm_to_so_test () { + run_wrap_test asm_to_so "$@" +} + tree1_tests () { TREE=$1 @@ -228,6 +237,16 @@ dtc_tests () { run_dtc_test -I dtb -O dtb -o boot_cpuid_preserved_test_tree1.test.dtb boot_cpuid_test_tree1.test.dtb run_test dtbs_equal_ordered boot_cpuid_preserved_test_tree1.test.dtb boot_cpuid_test_tree1.test.dtb + # Check -Oasm mode + for tree in test_tree1.dts escapes.dts references.dts path-references.dts \ + comments.dts aliases.dts include0.dts incbin.dts ; do + run_dtc_test -I dts -O asm -o oasm_$tree.test.s $tree + asm_to_so_test oasm_$tree + run_dtc_test -I dts -O dtb -o $tree.test.dtb $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 + done + # Check -Odts mode preserve all dtb information for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb \ dtc_references.test.dtb; do From bae93e8992fef3cfaff681fe85b26fd35e432e31 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 8 Jan 2009 11:48:48 +1100 Subject: [PATCH 0280/1198] dtc: Add testcases for labels within values This patch adds a testcase using asm output mode to check that labels within property values are correctly processed. Signed-off-by: David Gibson --- tests/Makefile.tests | 2 +- tests/run_tests.sh | 5 +- tests/tests.h | 1 + tests/value-labels.c | 128 +++++++++++++++++++++++++++++++++++++++++ tests/value-labels.dts | 8 +++ 5 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 tests/value-labels.c create mode 100644 tests/value-labels.dts diff --git a/tests/Makefile.tests b/tests/Makefile.tests index f09c72a..c5ad834 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -18,7 +18,7 @@ LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%) -DL_LIB_TESTS_L = asm_tree_dump +DL_LIB_TESTS_L = asm_tree_dump value-labels DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%) TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 040eca9..61508a8 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -239,7 +239,8 @@ dtc_tests () { # Check -Oasm mode for tree in test_tree1.dts escapes.dts references.dts path-references.dts \ - comments.dts aliases.dts include0.dts incbin.dts ; do + comments.dts aliases.dts include0.dts incbin.dts \ + value-labels.dts ; do run_dtc_test -I dts -O asm -o oasm_$tree.test.s $tree asm_to_so_test oasm_$tree run_dtc_test -I dts -O dtb -o $tree.test.dtb $tree @@ -247,6 +248,8 @@ dtc_tests () { run_wrap_test cmp oasm_$tree.test.dtb $tree.test.dtb done + run_test value-labels ./oasm_value-labels.dts.test.so + # Check -Odts mode preserve all dtb information for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb \ dtc_references.test.dtb; do diff --git a/tests/tests.h b/tests/tests.h index c273f3c..fcb2b2a 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -34,6 +34,7 @@ void test_init(int argc, char *argv[]); #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define PALIGN(p, a) ((void *)ALIGN((unsigned long)(p), (a))) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define streq(s1, s2) (strcmp((s1),(s2)) == 0) diff --git a/tests/value-labels.c b/tests/value-labels.c new file mode 100644 index 0000000..d11c34e --- /dev/null +++ b/tests/value-labels.c @@ -0,0 +1,128 @@ +/* + * libfdt - Flat Device Tree manipulation + * Test labels within values + * Copyright (C) 2008 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +struct val_label { + const char *labelname; + int propoff; +}; + +struct val_label labels1[] = { + { "start1", 0 }, + { "mid1", 2 }, + { "end1", -1 }, +}; + +struct val_label labels2[] = { + { "start2", 0 }, + { "innerstart2", 0 }, + { "innermid2", 4 }, + { "innerend2", -1 }, + { "end2", -1 }, +}; + +struct val_label labels3[] = { + { "start3", 0 }, + { "innerstart3", 0 }, + { "innermid3", 1 }, + { "innerend3", -1 }, + { "end3", -1 }, +}; + +void check_prop_labels(void *sohandle, void *fdt, const char *name, + const struct val_label* labels, int n) +{ + const struct fdt_property *prop; + const char *p; + int len; + int i; + + prop = fdt_get_property(fdt, 0, name, &len); + if (!prop) + FAIL("Couldn't locate property \"%s\"", name); + + p = dlsym(sohandle, name); + if (!p) + FAIL("Couldn't locate label symbol \"%s\"", name); + + if (p != (const char *)prop) + FAIL("Label \"%s\" does not point to correct property", name); + + for (i = 0; i < n; i++) { + int off = labels[i].propoff; + + if (off == -1) + off = len; + + p = dlsym(sohandle, labels[i].labelname); + if (!p) + FAIL("Couldn't locate label symbol \"%s\"", name); + + if ((p - prop->data) != off) + FAIL("Label \"%s\" points to offset %d instead of %d" + "in property \"%s\"", labels[i].labelname, + p - prop->data, off, name); + } +} + +int main(int argc, char *argv[]) +{ + void *sohandle; + void *fdt; + int err; + + test_init(argc, argv); + if (argc != 2) + CONFIG("Usage: %s ", argv[0]); + + sohandle = dlopen(argv[1], RTLD_NOW); + if (!sohandle) + FAIL("Couldn't dlopen() %s", argv[1]); + + fdt = dlsym(sohandle, "dt_blob_start"); + if (!fdt) + FAIL("Couldn't locate \"dt_blob_start\" symbol in %s", + argv[1]); + + err = fdt_check_header(fdt); + if (err != 0) + FAIL("%s contains invalid tree: %s", argv[1], + fdt_strerror(err)); + + + check_prop_labels(sohandle, fdt, "prop1", labels1, ARRAY_SIZE(labels1)); + check_prop_labels(sohandle, fdt, "prop2", labels2, ARRAY_SIZE(labels2)); + check_prop_labels(sohandle, fdt, "prop3", labels3, ARRAY_SIZE(labels3)); + + PASS(); +} diff --git a/tests/value-labels.dts b/tests/value-labels.dts new file mode 100644 index 0000000..490c609 --- /dev/null +++ b/tests/value-labels.dts @@ -0,0 +1,8 @@ +/dts-v1/; + +/ { + prop1: prop1 = start1: "a", mid1: "b" end1:; + prop2: prop2 = start2: < innerstart2: 0xdeadbeef innermid2: 0xabcd1234 innerend2: > end2:; + prop3: prop3 = start3: [ innerstart3: ab innermid3: cd innerend3: ] end3:; +}; + From ce4d9c0f746b21119bc2b5aa5571bb08799a82bd Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 6 Feb 2009 14:01:56 +1100 Subject: [PATCH 0281/1198] libfdt: Rework fdt_next_node() Currently fdt_next_node() will find the next node in the blob regardless of whether it is above, below or at the same level in the tree as the starting node - the depth parameter is updated to indicate which is the case. When a depth parameter is supplied, this patch makes it instead terminate immediately when it finds the END_NODE tag for a node at depth 0. In this case it returns the offset immediately past the END_NODE tag. This has a couple of advantages. First, this slightly simplifies fdt_subnode_offset(), which no longer needs to explicitly check that fdt_next_node()'s iteration hasn't left the starting node. Second, this allows fdt_next_node() to be used to implement _fdt_node_end_offset() considerably simplifying the latter function. The other users of fdt_next_node() either don't need to iterate out of the starting node, or don't pass a depth parameter at all. Any callers that really need to iterate out of the starting node, but keep tracking depth can do so by biasing the initial depth value. This is a semantic change, but I think it's very unlikely to break any existing library users. Signed-off-by: David Gibson --- libfdt/fdt.c | 4 ++-- libfdt/fdt_ro.c | 20 ++++++++------------ libfdt/fdt_wip.c | 37 +++++-------------------------------- 3 files changed, 15 insertions(+), 46 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 37085c1..2546b5c 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -162,8 +162,8 @@ int fdt_next_node(const void *fdt, int offset, int *depth) break; case FDT_END_NODE: - if (depth) - (*depth)--; + if (depth && ((--(*depth)) < 0)) + return nextoffset; break; case FDT_END: diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index d12c7ee..7a79bb8 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -108,24 +108,20 @@ int fdt_num_mem_rsv(const void *fdt) int fdt_subnode_offset_namelen(const void *fdt, int offset, const char *name, int namelen) { - int depth = 0; + int depth; FDT_CHECK_HEADER(fdt); - for (depth = 0, offset = fdt_next_node(fdt, offset, &depth); - (offset >= 0) && (depth > 0); - offset = fdt_next_node(fdt, offset, &depth)) { - if (depth < 0) - return -FDT_ERR_NOTFOUND; - else if ((depth == 1) - && _fdt_nodename_eq(fdt, offset, name, namelen)) + for (depth = 0; + (offset >= 0) && (depth >= 0); + offset = fdt_next_node(fdt, offset, &depth)) + if ((depth == 1) + && _fdt_nodename_eq(fdt, offset, name, namelen)) return offset; - } - if (offset < 0) - return offset; /* error */ - else + if (depth < 0) return -FDT_ERR_NOTFOUND; + return offset; /* error */ } int fdt_subnode_offset(const void *fdt, int parentoffset, diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c index a4652c6..6025fa1 100644 --- a/libfdt/fdt_wip.c +++ b/libfdt/fdt_wip.c @@ -94,41 +94,14 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name) return 0; } -int _fdt_node_end_offset(void *fdt, int nodeoffset) +int _fdt_node_end_offset(void *fdt, int offset) { - int level = 0; - uint32_t tag; - int offset, nextoffset; + int depth = 0; - tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); - if (tag != FDT_BEGIN_NODE) - return -FDT_ERR_BADOFFSET; - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); + while ((offset >= 0) && (depth >= 0)) + offset = fdt_next_node(fdt, offset, &depth); - switch (tag) { - case FDT_END: - return offset; - - case FDT_BEGIN_NODE: - level++; - break; - - case FDT_END_NODE: - level--; - break; - - case FDT_PROP: - case FDT_NOP: - break; - - default: - return -FDT_ERR_BADSTRUCTURE; - } - } while (level >= 0); - - return nextoffset; + return offset; } int fdt_nop_node(void *fdt, int nodeoffset) From 1a020e403048a56ffacb8c6f71aef0944b901757 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 6 Feb 2009 14:03:24 +1100 Subject: [PATCH 0282/1198] libfdt: Rework/cleanup fdt_next_tag() Currently, callers of fdt_next_tag() must usually follow the call with some sort of call to fdt_offset_ptr() to verify that the blob isn't truncated in the middle of the tag data they're going to process. This is a bit silly, since fdt_next_tag() generally has to call fdt_offset_ptr() on at least some of the data following the tag for its own operation. This patch alters fdt_next_tag() to always use fdt_offset_ptr() to verify the data between its starting offset and the offset it returns in nextoffset. This simplifies fdt_get_property() which no longer has to verify itself that the property data is all present. At the same time, I neaten and clarify the error handling for fdt_next_tag(). Previously, fdt_next_tag() could return -1 instead of a tag value in some circumstances - which almost none of the callers checked for. Also, fdt_next_tag() could return FDT_END either because it encountered an FDT_END tag, or because it reached the end of the structure block - no way was provided to tell between these cases. With this patch, fdt_next_tag() always returns FDT_END with a negative value in nextoffset for an error. This means the several places which loop looking for FDT_END will still work correctly - they only need to check for errors at the end. The errors which fdt_next_tag() can report are: - -FDT_ERR_TRUNCATED if it reached the end of the structure block instead of finding a tag. - -FDT_BADSTRUCTURE if a bad tag was encountered, or if the tag data couldn't be verified with fdt_offset_ptr(). This patch also updates the callers of fdt_next_tag(), where appropriate, to make use of the new error reporting. Finally, the prototype for the long gone _fdt_next_tag() is removed from libfdt_internal.h. Signed-off-by: David Gibson --- libfdt/fdt.c | 46 +++++++++++++++++++++++++--------------- libfdt/fdt_ro.c | 33 ++++++++-------------------- libfdt/fdt_rw.c | 2 ++ libfdt/fdt_sw.c | 9 ++++---- libfdt/libfdt_internal.h | 1 - 5 files changed, 44 insertions(+), 47 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 2546b5c..b1130c2 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -90,42 +90,53 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) return p; } -uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset) +uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) { const uint32_t *tagp, *lenp; uint32_t tag; + int offset = startoffset; const char *p; - if (offset % FDT_TAGSIZE) - return -1; - + *nextoffset = -FDT_ERR_TRUNCATED; tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); - if (! tagp) + if (!tagp) return FDT_END; /* premature end */ tag = fdt32_to_cpu(*tagp); offset += FDT_TAGSIZE; + *nextoffset = -FDT_ERR_BADSTRUCTURE; switch (tag) { case FDT_BEGIN_NODE: /* skip name */ do { p = fdt_offset_ptr(fdt, offset++, 1); } while (p && (*p != '\0')); - if (! p) - return FDT_END; + if (!p) + return FDT_END; /* premature end */ break; + case FDT_PROP: lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); - if (! lenp) - return FDT_END; - /* skip name offset, length and value */ - offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp); + if (!lenp) + return FDT_END; /* premature end */ + /* skip-name offset, length and value */ + offset += sizeof(struct fdt_property) - FDT_TAGSIZE + + fdt32_to_cpu(*lenp); break; + + case FDT_END: + case FDT_END_NODE: + case FDT_NOP: + break; + + default: + return FDT_END; } - if (nextoffset) - *nextoffset = FDT_TAGALIGN(offset); + if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) + return FDT_END; /* premature end */ + *nextoffset = FDT_TAGALIGN(offset); return tag; } @@ -167,10 +178,11 @@ int fdt_next_node(const void *fdt, int offset, int *depth) break; case FDT_END: - return -FDT_ERR_NOTFOUND; - - default: - return -FDT_ERR_BADSTRUCTURE; + if ((nextoffset >= 0) + || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) + return -FDT_ERR_NOTFOUND; + else + return nextoffset; } } while (tag != FDT_BEGIN_NODE); diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 7a79bb8..0446ac0 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -201,7 +201,6 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt, { uint32_t tag; const struct fdt_property *prop; - int namestroff; int offset, nextoffset; int err; @@ -216,38 +215,24 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt, tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_END: - err = -FDT_ERR_TRUNCATED; + if (nextoffset < 0) + err = nextoffset; + else + /* FDT_END tag with unclosed nodes */ + err = -FDT_ERR_BADSTRUCTURE; goto fail; - case FDT_BEGIN_NODE: - case FDT_END_NODE: - case FDT_NOP: - break; - case FDT_PROP: - err = -FDT_ERR_BADSTRUCTURE; - prop = fdt_offset_ptr(fdt, offset, sizeof(*prop)); - if (! prop) - goto fail; - namestroff = fdt32_to_cpu(prop->nameoff); - if (_fdt_string_eq(fdt, namestroff, name, namelen)) { + prop = _fdt_offset_ptr(fdt, offset); + if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), + name, namelen)) { /* Found it! */ - int len = fdt32_to_cpu(prop->len); - prop = fdt_offset_ptr(fdt, offset, - sizeof(*prop)+len); - if (! prop) - goto fail; - if (lenp) - *lenp = len; + *lenp = fdt32_to_cpu(prop->len); return prop; } break; - - default: - err = -FDT_ERR_BADSTRUCTURE; - goto fail; } } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE)); diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 8e7ec4c..994037b 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -406,6 +406,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) struct_size = 0; while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) ; + if (struct_size < 0) + return struct_size; } if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 698329e..2380b27 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, int len) return NULL; fdt_set_size_dt_struct(fdt, offset + len); - return fdt_offset_ptr_w(fdt, offset, len); + return _fdt_offset_ptr_w(fdt, offset); } int fdt_create(void *buf, int bufsize) @@ -237,18 +237,17 @@ int fdt_finish(void *fdt) while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { if (tag == FDT_PROP) { struct fdt_property *prop = - fdt_offset_ptr_w(fdt, offset, sizeof(*prop)); + _fdt_offset_ptr_w(fdt, offset); int nameoff; - if (! prop) - return -FDT_ERR_BADSTRUCTURE; - nameoff = fdt32_to_cpu(prop->nameoff); nameoff += fdt_size_dt_strings(fdt); prop->nameoff = cpu_to_fdt32(nameoff); } offset = nextoffset; } + if (nextoffset < 0) + return nextoffset; /* Finally, adjust the header */ fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 46eb93e..d2dcbd6 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -62,7 +62,6 @@ return err; \ } -uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset); int _fdt_check_node_offset(const void *fdt, int offset); const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); int _fdt_node_end_offset(void *fdt, int nodeoffset); From 925bd8c05472ad4ed45d56293c6aa21b1a39533a Mon Sep 17 00:00:00 2001 From: Emil Medve Date: Tue, 17 Feb 2009 13:43:40 -0600 Subject: [PATCH 0283/1198] Fix libraries (static and dynamic) installation Signed-off-by: Emil Medve --- Makefile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 1cfa28a..be0fc8b 100644 --- a/Makefile +++ b/Makefile @@ -142,14 +142,13 @@ endif # intermediate target and building them again "for real" .SECONDARY: $(DTC_GEN_SRCS) $(CONVERT_GEN_SRCS) - - install: all @$(VECHO) INSTALL $(INSTALL) -d $(DESTDIR)$(BINDIR) - $(INSTALL) -m 755 $(BIN) $(DESTDIR)$(BINDIR) + $(INSTALL) $(BIN) $(DESTDIR)$(BINDIR) $(INSTALL) -d $(DESTDIR)$(LIBDIR) - $(INSTALL) -m 644 $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) + $(INSTALL) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) + $(INSTALL) -m 644 $(LIBFDT_archive) $(DESTDIR)$(LIBDIR) $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) $(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR) From 804fed8dcdb44fe83fcfc2e310c09d45c7602d9d Mon Sep 17 00:00:00 2001 From: Emil Medve Date: Mon, 23 Feb 2009 10:43:36 -0600 Subject: [PATCH 0284/1198] Fix a possible overflow case detected by gcc 4.3.2 .../dtc/libfdt/fdt_sw.c: In function 'fdt_end_node': .../dtc/libfdt/fdt_sw.c:81: error: assuming signed overflow does not occur when assuming that (X + c) < X is always false Signed-off-by: Emil Medve --- 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 2380b27..55ebebf 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -70,7 +70,7 @@ static int _fdt_sw_check_header(void *fdt) return err; \ } -static void *_fdt_grab_space(void *fdt, int len) +static void *_fdt_grab_space(void *fdt, size_t len) { int offset = fdt_size_dt_struct(fdt); int spaceleft; From f281f526d4f039f4c3236176abe6396da4a443fe Mon Sep 17 00:00:00 2001 From: Laurent Gregoire Date: Tue, 3 Mar 2009 14:23:59 +0100 Subject: [PATCH 0285/1198] libfdt: Fix C++ compile-time cast error on gnu 4.2.1 Allow the inclusion of libfdt.h in C++ source. Signed-off-by: Laurent Gregoire Acked-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 4a95e11..18de52b 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -156,7 +156,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth); #define __fdt_set_hdr(name) \ static inline void fdt_set_##name(void *fdt, uint32_t val) \ { \ - struct fdt_header *fdth = fdt; \ + struct fdt_header *fdth = (struct fdt_header*)fdt; \ fdth->name = cpu_to_fdt32(val); \ } __fdt_set_hdr(magic); From 9c1a0df677bf0f4af622a404f6c738ad711326e0 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 26 May 2009 20:07:26 +0200 Subject: [PATCH 0286/1198] add Mac OS X support use dylib shared lib extention allow to specifiy os specific shared lib link option Mac OS use -dynamiclib instead of -shared, -install_name instead of -soname and does not support --version-script add HOSTOS macro to detect the current os you are Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- Makefile | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index be0fc8b..d7549b2 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,17 @@ BINDIR = $(PREFIX)/bin LIBDIR = $(PREFIX)/lib INCLUDEDIR = $(PREFIX)/include +HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ + sed -e 's/\(cygwin\).*/cygwin/') + +ifeq ($(HOSTOS),darwin) +SHAREDLIB_EXT=dylib +SHAREDLIB_LINK_OPTIONS=-dynamiclib -Wl,-install_name -Wl, +else +SHAREDLIB_EXT=so +SHAREDLIB_LINK_OPTIONS=-shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname, +endif + # # Overall rules # @@ -116,7 +127,7 @@ endif LIBFDT_objdir = libfdt LIBFDT_srcdir = libfdt LIBFDT_archive = $(LIBFDT_objdir)/libfdt.a -LIBFDT_lib = $(LIBFDT_objdir)/libfdt.so +LIBFDT_lib = $(LIBFDT_objdir)/libfdt.$(SHAREDLIB_EXT) LIBFDT_include = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES)) LIBFDT_version = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_VERSION)) @@ -220,8 +231,8 @@ clean: libfdt_clean tests_clean $(LIBFDT_lib): @$(VECHO) LD $@ - $(CC) $(LDFLAGS) -fPIC -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,$(notdir $@) -shared -o $(LIBFDT_objdir)/libfdt-$(DTC_VERSION).so $^ - ln -s libfdt-$(DTC_VERSION).so $(LIBFDT_objdir)/libfdt.so + $(CC) $(LDFLAGS) -fPIC $(SHAREDLIB_LINK_OPTIONS)$(notdir $@) -o $(LIBFDT_objdir)/libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) $^ + ln -sf libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) $(LIBFDT_objdir)/libfdt.$(SHAREDLIB_EXT) %.lex.c: %.l @$(VECHO) LEX $@ From c623fe5c21e0358fc38a4e8ddb0d51379f0733e8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 9 Sep 2009 14:38:30 +1000 Subject: [PATCH 0287/1198] Fix bug in -Odts with properties containing multiple terminating nulls When in -Odts mode, dtc will not produce correct output for string-like properties which have more than one \0 character at the end of the property's bytestring. In fact, it generates output which is not syntactically correct. This patch fixes the bug, and adds a testcase for future regressions here. Signed-off-by: David Gibson --- tests/Makefile.tests | 1 + tests/extra-terminating-null.c | 59 ++++++++++++++++++++++++++++++++ tests/extra-terminating-null.dts | 11 ++++++ tests/run_tests.sh | 5 ++- treesource.c | 29 ++++++++-------- 5 files changed, 90 insertions(+), 15 deletions(-) create mode 100644 tests/extra-terminating-null.c create mode 100644 tests/extra-terminating-null.dts diff --git a/tests/Makefile.tests b/tests/Makefile.tests index c5ad834..e35afa6 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -11,6 +11,7 @@ LIB_TESTS_L = get_mem_rsv \ move_and_save mangle-layout nopulate \ open_pack rw_tree1 set_name setprop del_property del_node \ string_escapes references path-references boot-cpuid incbin \ + extra-terminating-null \ dtbs_equal_ordered \ add_subnode_with_nops path_offset_aliases LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) diff --git a/tests/extra-terminating-null.c b/tests/extra-terminating-null.c new file mode 100644 index 0000000..bb71b1a --- /dev/null +++ b/tests/extra-terminating-null.c @@ -0,0 +1,59 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for properties with more than one terminating null + * Copyright (C) 2009 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +void check_extranull(void *fdt, const char *prop, const char *str, int numnulls) +{ + int len = strlen(str); + char checkbuf[len+numnulls]; + + memset(checkbuf, 0, sizeof(checkbuf)); + memcpy(checkbuf, TEST_STRING_1, len); + + check_getprop(fdt, 0, prop, len+numnulls, checkbuf); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + + fdt = load_blob_arg(argc, argv); + + check_extranull(fdt, "extranull0", TEST_STRING_1, 1); + check_extranull(fdt, "extranull1,1", TEST_STRING_1, 2); + check_extranull(fdt, "extranull1,2", TEST_STRING_1, 2); + check_extranull(fdt, "extranull2,1", TEST_STRING_1, 3); + check_extranull(fdt, "extranull2,2", TEST_STRING_1, 3); + check_extranull(fdt, "extranull2,3", TEST_STRING_1, 3); + check_extranull(fdt, "extranull2,4", TEST_STRING_1, 3); + + PASS(); +} diff --git a/tests/extra-terminating-null.dts b/tests/extra-terminating-null.dts new file mode 100644 index 0000000..b6cc19c --- /dev/null +++ b/tests/extra-terminating-null.dts @@ -0,0 +1,11 @@ +/dts-v1/; + +/ { + extranull0 = "hello world"; + extranull1,1 = "hello world\0"; + extranull1,2 = "hello world", ""; + extranull2,1 = "hello world\0\0"; + extranull2,2 = "hello world", "", ""; + extranull2,3 = "hello world\0", ""; + extranull2,4 = "hello world", "\0"; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 61508a8..8e57cf5 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -203,6 +203,9 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts run_test string_escapes dtc_escapes.test.dtb + run_dtc_test -I dts -O dtb -o dtc_extra-terminating-null.test.dtb extra-terminating-null.dts + run_test extra-terminating-null dtc_extra-terminating-null.test.dtb + run_dtc_test -I dts -O dtb -o dtc_references.test.dtb references.dts run_test references dtc_references.test.dtb @@ -252,7 +255,7 @@ dtc_tests () { # Check -Odts mode preserve all dtb information for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb \ - dtc_references.test.dtb; do + dtc_extra-terminating-null.test.dtb dtc_references.test.dtb; do run_dtc_test -I dtb -O dts -o odts_$tree.test.dts $tree run_dtc_test -I dts -O dtb -o odts_$tree.test.dtb odts_$tree.test.dts run_test dtbs_equal_ordered $tree odts_$tree.test.dtb diff --git a/treesource.c b/treesource.c index 1521ff1..cc1751d 100644 --- a/treesource.c +++ b/treesource.c @@ -63,26 +63,20 @@ static void write_propval_string(FILE *f, struct data val) { const char *str = val.val; int i; - int newchunk = 1; struct marker *m = val.markers; assert(str[val.len-1] == '\0'); + while (m && (m->offset == 0)) { + if (m->type == LABEL) + fprintf(f, "%s: ", m->ref); + m = m->next; + } + fprintf(f, "\""); + for (i = 0; i < (val.len-1); i++) { char c = str[i]; - if (newchunk) { - while (m && (m->offset <= i)) { - if (m->type == LABEL) { - assert(m->offset == i); - fprintf(f, "%s: ", m->ref); - } - m = m->next; - } - fprintf(f, "\""); - newchunk = 0; - } - switch (c) { case '\a': fprintf(f, "\\a"); @@ -113,7 +107,14 @@ static void write_propval_string(FILE *f, struct data val) break; case '\0': fprintf(f, "\", "); - newchunk = 1; + while (m && (m->offset < i)) { + if (m->type == LABEL) { + assert(m->offset == (i+1)); + fprintf(f, "%s: ", m->ref); + } + m = m->next; + } + fprintf(f, "\""); break; default: if (isprint(c)) From 350c9cce9e559a5609f31fd7229dffbd69d85ff2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 12 Nov 2009 11:14:04 +1100 Subject: [PATCH 0288/1198] Use yylloc instead of yyloc yylloc is the correct way to get token positioning information. yyloc is a bison internal variable that only works by accident. Signed-off-by: David Gibson --- dtc-parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dtc-parser.y b/dtc-parser.y index 4b69c7a..31c14d7 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -175,7 +175,7 @@ propdata: if ($6 != 0) if (fseek(file->file, $6, SEEK_SET) != 0) - srcpos_error(&yyloc, + srcpos_error(&yylloc, "Couldn't seek to offset %llu in \"%s\": %s", (unsigned long long)$6, $4.val, From f2f6d0f2f02b4713e9d0cdc840e211535689a2e6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 12 Nov 2009 11:56:34 +1100 Subject: [PATCH 0289/1198] Don't use echo -e in run_tests.sh In one section, the run_tests script attempts to use the -e (interpret escapes) option to echo. This option is not portable - for example the echo built into dash, now the default /bin/sh on several distributions does not support it and will just echo "-e" literally. Since we don't actually use any of the escapes that -e enables, this patch simply removes it. Signed-off-by: David Gibson --- tests/run_tests.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 8e57cf5..db413a1 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -339,14 +339,14 @@ for set in $TESTSETS; do esac done -echo -e "********** TEST SUMMARY" -echo -e "* Total testcases: $tot_tests" -echo -e "* PASS: $tot_pass" -echo -e "* FAIL: $tot_fail" -echo -e "* Bad configuration: $tot_config" +echo "********** TEST SUMMARY" +echo "* Total testcases: $tot_tests" +echo "* PASS: $tot_pass" +echo "* FAIL: $tot_fail" +echo "* Bad configuration: $tot_config" if [ -n "$VALGRIND" ]; then - echo -e "* valgrind errors: $tot_vg" + echo "* valgrind errors: $tot_vg" fi -echo -e "* Strange test result: $tot_strange" -echo -e "**********" +echo "* Strange test result: $tot_strange" +echo "**********" From b31b271f91b867343fe21a20da4d24b03c1ef421 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 12 Nov 2009 13:30:02 +1100 Subject: [PATCH 0290/1198] Fix dtc bugs for 64-bit compile I've just tested building dtc as an x86_64 binary on a 32-bit i386 host by using: make CC="gcc -m64" This patch fixes a handful of minor bugs thus discovered: * There is a printf() type mismatch on 64-bit in value-labels.c * For the tests which use libdl, we were using the GNU make feature where it will find libdl.so given a dependency in the form '-ldl'. But this built-in make logic doesn't know we're compiling 64-bit so finds the 32-bit version of the library. We avoid using this and instead explicitly pass -ldl to CC, which being the 64-bit version does know where to look. * To process dtc's asm output into .so files, run_tests.sh was directly invoking the (default instance of) the assembler and linker. Instead invoke these via the CC driver, and allow that to be overriden from the make environment. * The x86_64 assembler doesn't 0 fill with the .balign directive (presumably it is NOP filling). That doesn't produce strictly incorrect trees, but it is confusing and confounds are testcases which do byte-by-byte comparison of the trees produced by asm output with direct dtb output (which does 0 pad where necessary, of course). This patch uses the optional second argument to .balign to force gas to zero-fill instead. Signed-off-by: David Gibson --- flattree.c | 2 +- tests/Makefile.tests | 4 +++- tests/run_tests.sh | 7 +++++-- tests/value-labels.c | 4 ++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/flattree.c b/flattree.c index 0ff8c45..3eb0201 100644 --- a/flattree.c +++ b/flattree.c @@ -166,7 +166,7 @@ static void asm_emit_align(void *e, int a) { FILE *f = e; - fprintf(f, "\t.balign\t%d\n", a); + fprintf(f, "\t.balign\t%d, 0\n", a); } static void asm_emit_data(void *e, struct data d) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index e35afa6..2696581 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -41,7 +41,9 @@ tests: $(TESTS) $(TESTS_TREES) $(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_archive) -$(DL_LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_archive) -ldl +$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o $(LIBFDT_archive) + @$(VECHO) LD [libdl] $@ + $(LINK.c) -o $@ $^ -ldl $(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o $(LIBFDT_archive) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index db413a1..5d901c2 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -2,6 +2,10 @@ . ./tests.sh +if [ -z "$CC" ]; then + CC=gcc +fi + export QUIET_TEST=1 export VALGRIND= @@ -72,8 +76,7 @@ run_dtc_test () { } asm_to_so () { - as -o $1.test.o data.S $1.test.s && \ - ld -shared -o $1.test.so $1.test.o + $CC -shared -o $1.test.so data.S $1.test.s } asm_to_so_test () { diff --git a/tests/value-labels.c b/tests/value-labels.c index d11c34e..c5aea8f 100644 --- a/tests/value-labels.c +++ b/tests/value-labels.c @@ -89,9 +89,9 @@ void check_prop_labels(void *sohandle, void *fdt, const char *name, FAIL("Couldn't locate label symbol \"%s\"", name); if ((p - prop->data) != off) - FAIL("Label \"%s\" points to offset %d instead of %d" + FAIL("Label \"%s\" points to offset %ld instead of %d" "in property \"%s\"", labels[i].labelname, - p - prop->data, off, name); + (long)(p - prop->data), off, name); } } From 0ef21055ee414697aac7226c171d921214ef3981 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 17 Nov 2009 17:00:53 +1100 Subject: [PATCH 0291/1198] Assorted cleanups and extensions for ftdump This patch makes a number of minor changes to the ftdump debugging tool. * There was an endian bug in one place, which this fixes. * We now use const qualifiers in a number of places where we can * ftdump can now be instructed to read from stdin by giving "-" as the filename. * The buffer into which the blob is read is increased from 16k to 64k, and is now dynamically allocated. * ftdump now emits source in dts-v1 format Since ftdump is little used these days, these fixes are arguably of little use. On the other hand, I already did the work of making the changes some time back, so I guess we might as well fold these small fixes and improvements in. Signed-off-by: David Gibson --- ftdump.c | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/ftdump.c b/ftdump.c index 01e61a4..bce6535 100644 --- a/ftdump.c +++ b/ftdump.c @@ -4,15 +4,18 @@ #include #include +#include #include #include #include #include +#define FTDUMP_BUF_SIZE 65536 + #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) #define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) -#define GET_CELL(p) (p += 4, *((uint32_t *)(p-4))) +#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) static int is_printable_string(const void *data, int len) { @@ -38,10 +41,10 @@ static int is_printable_string(const void *data, int len) return 1; } -static void print_data(const void *data, int len) +static void print_data(const char *data, int len) { int i; - const uint8_t *s; + const char *p = data; /* no data, don't print */ if (len == 0) @@ -52,13 +55,13 @@ static void print_data(const void *data, int len) } else if ((len % 4) == 0) { printf(" = <"); for (i = 0; i < len; i += 4) - printf("%08x%s", *((const uint32_t *)data + i), + printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)), i < (len - 4) ? " " : ""); printf(">"); } else { printf(" = ["); - for (i = 0, s = data; i < len; i++) - printf("%02x%s", s[i], i < len - 1 ? " " : ""); + for (i = 0; i < len; i++) + printf("%02x%s", *p++, i < len - 1 ? " " : ""); printf("]"); } } @@ -71,13 +74,12 @@ static void dump_blob(void *blob) uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings); struct fdt_reserve_entry *p_rsvmap = (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap); - char *p_struct = (char *)blob + off_dt; - char *p_strings = (char *)blob + off_str; + const char *p_struct = (const char *)blob + off_dt; + const char *p_strings = (const char *)blob + off_str; uint32_t version = fdt32_to_cpu(bph->version); uint32_t totalsize = fdt32_to_cpu(bph->totalsize); uint32_t tag; - char *p; - char *s, *t; + const char *p, *s, *t; int depth, sz, shift; int i; uint64_t addr, size; @@ -85,6 +87,7 @@ static void dump_blob(void *blob) depth = 0; shift = 4; + printf("/dts-v1/;\n"); printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic)); printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize); printf("// off_dt_struct:\t0x%x\n", off_dt); @@ -167,7 +170,7 @@ static void dump_blob(void *blob) int main(int argc, char *argv[]) { FILE *fp; - char buf[16384]; /* 16k max */ + char *buf; int size; if (argc < 2) { @@ -175,15 +178,25 @@ int main(int argc, char *argv[]) return 5; } - fp = fopen(argv[1], "rb"); - if (fp == NULL) { - fprintf(stderr, "unable to open %s\n", argv[1]); + if (strcmp(argv[1], "-") == 0) { + fp = stdin; + } else { + fp = fopen(argv[1], "rb"); + if (fp == NULL) { + fprintf(stderr, "unable to open %s\n", argv[1]); + return 10; + } + } + + buf = malloc(FTDUMP_BUF_SIZE); + if (!buf) { + fprintf(stderr, "Couldn't allocate %d byte buffer\n", FTDUMP_BUF_SIZE); return 10; } - size = fread(buf, 1, sizeof(buf), fp); - if (size == sizeof(buf)) { /* too large */ - fprintf(stderr, "file too large\n"); + size = fread(buf, 1, FTDUMP_BUF_SIZE, fp); + if (size == FTDUMP_BUF_SIZE) { + fprintf(stderr, "file too large (maximum is %d bytes)\n", FTDUMP_BUF_SIZE); return 10; } From d75b33af676d0beac8398651a7f09037555a550b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 26 Nov 2009 15:37:13 +1100 Subject: [PATCH 0292/1198] Support ePAPR compliant phandle properties Currently, the Linux kernel, libfdt and dtc, when using flattened device trees encode a node's phandle into a property named "linux,phandle". The ePAPR specification, however - aiming as it is to not be a Linux specific spec - requires that phandles be encoded in a property named simply "phandle". This patch adds support for this newer approach to dtc and libfdt. Specifically: - fdt_get_phandle() will now return the correct phandle if it is supplied in either of these properties - fdt_node_offset_by_phandle() will correctly find a node with the given phandle encoded in either property. - By default, when auto-generating phandles, dtc will encode it into both properties for maximum compatibility. A new -H option allows either only old-style or only new-style properties to be generated. - If phandle properties are explicitly supplied in the dts file, dtc will not auto-generate ones in the alternate format. - If both properties are supplied, dtc will check that they have the same value. - Some existing testcases are updated to use a mix of old and new-style phandles, partially testing the changes. - A new phandle_format test further tests the libfdt support, and the -H option. Signed-off-by: David Gibson --- checks.c | 34 ++++++++++-------- dtc.c | 20 ++++++++++- dtc.h | 5 +++ libfdt/fdt_ro.c | 33 ++++++++++++++---- livetree.c | 14 ++++++-- tests/Makefile.tests | 3 +- tests/include1.dts | 2 +- tests/phandle_format.c | 78 ++++++++++++++++++++++++++++++++++++++++++ tests/references.dts | 3 +- tests/run_tests.sh | 6 ++++ tests/sw_tree1.c | 2 +- tests/test_tree1.dts | 2 +- tests/trees.S | 5 +-- 13 files changed, 177 insertions(+), 30 deletions(-) create mode 100644 tests/phandle_format.c diff --git a/checks.c b/checks.c index 35141f9..031cc59 100644 --- a/checks.c +++ b/checks.c @@ -279,20 +279,19 @@ static void check_property_name_chars(struct check *c, struct node *dt, PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR); static void check_explicit_phandles(struct check *c, struct node *root, - struct node *node) + struct node *node, struct property *prop) { - struct property *prop; struct marker *m; struct node *other; cell_t phandle; - prop = get_property(node, "linux,phandle"); - if (! prop) - return; /* No phandle, that's fine */ + if (!streq(prop->name, "phandle") + && !streq(prop->name, "linux,phandle")) + return; if (prop->val.len != sizeof(cell_t)) { - FAIL(c, "%s has bad length (%d) linux,phandle property", - node->fullpath, prop->val.len); + FAIL(c, "%s has bad length (%d) %s property", + node->fullpath, prop->val.len, prop->name); return; } @@ -302,9 +301,11 @@ static void check_explicit_phandles(struct check *c, struct node *root, if (node != get_node_by_ref(root, m->ref)) /* "Set this node's phandle equal to some * other node's phandle". That's nonsensical - * by construction. */ - FAIL(c, "linux,phandle in %s is a reference to another node", - node->fullpath); + * by construction. */ { + FAIL(c, "%s in %s is a reference to another node", + prop->name, node->fullpath); + return; + } /* But setting this node's phandle equal to its own * phandle is allowed - that means allocate a unique * phandle for this node, even if it's not otherwise @@ -314,14 +315,19 @@ static void check_explicit_phandles(struct check *c, struct node *root, } phandle = propval_cell(prop); + if ((phandle == 0) || (phandle == -1)) { - FAIL(c, "%s has invalid linux,phandle value 0x%x", - node->fullpath, phandle); + FAIL(c, "%s has bad value (0x%x) in %s property", + node->fullpath, phandle, prop->name); return; } + if (node->phandle && (node->phandle != phandle)) + FAIL(c, "%s has %s property which replaces existing phandle information", + node->fullpath, prop->name); + other = get_node_by_phandle(root, phandle); - if (other) { + if (other && (other != node)) { FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)", node->fullpath, phandle, other->fullpath); return; @@ -329,7 +335,7 @@ static void check_explicit_phandles(struct check *c, struct node *root, node->phandle = phandle; } -NODE_CHECK(explicit_phandles, NULL, ERROR); +PROP_CHECK(explicit_phandles, NULL, ERROR); static void check_name_properties(struct check *c, struct node *root, struct node *node) diff --git a/dtc.c b/dtc.c index 84bee2d..800664c 100644 --- a/dtc.c +++ b/dtc.c @@ -30,6 +30,7 @@ int quiet; /* Level of quietness */ int reservenum; /* Number of memory reservation slots */ int minsize; /* Minimum blob size */ int padsize; /* Additional padding to blob */ +int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */ char *join_path(const char *path, const char *name) { @@ -106,6 +107,11 @@ static void __attribute__ ((noreturn)) usage(void) fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n"); fprintf(stderr, "\t-v\n"); fprintf(stderr, "\t\tPrint DTC version and exit\n"); + fprintf(stderr, "\t-H \n"); + fprintf(stderr, "\t\tphandle formats are:\n"); + fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n"); + fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n"); + fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n"); exit(3); } @@ -127,7 +133,7 @@ int main(int argc, char *argv[]) minsize = 0; padsize = 0; - while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:v")) != EOF) { + while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:vH:")) != EOF) { switch (opt) { case 'I': inform = optarg; @@ -165,6 +171,18 @@ int main(int argc, char *argv[]) case 'v': printf("Version: %s\n", DTC_VERSION); exit(0); + case 'H': + if (streq(optarg, "legacy")) + phandle_format = PHANDLE_LEGACY; + else if (streq(optarg, "epapr")) + phandle_format = PHANDLE_EPAPR; + else if (streq(optarg, "both")) + phandle_format = PHANDLE_BOTH; + else + die("Invalid argument \"%s\" to -H option\n", + optarg); + break; + case 'h': default: usage(); diff --git a/dtc.h b/dtc.h index 45adaed..0d7f0ed 100644 --- a/dtc.h +++ b/dtc.h @@ -52,6 +52,11 @@ extern int quiet; /* Level of quietness */ extern int reservenum; /* Number of memory reservation slots */ extern int minsize; /* Minimum blob size */ extern int padsize; /* Additional padding to blob */ +extern int phandle_format; /* Use linux,phandle or phandle properties */ + +#define PHANDLE_LEGACY 0x1 +#define PHANDLE_EPAPR 0x2 +#define PHANDLE_BOTH 0x3 typedef uint32_t cell_t; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 0446ac0..951cc74 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -274,9 +274,14 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) const uint32_t *php; int len; - php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); - if (!php || (len != sizeof(*php))) - return 0; + /* FIXME: This is a bit sub-optimal, since we potentially scan + * over all the properties twice. */ + php = fdt_getprop(fdt, nodeoffset, "phandle", &len); + if (!php || (len != sizeof(*php))) { + php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); + if (!php || (len != sizeof(*php))) + return 0; + } return fdt32_to_cpu(*php); } @@ -436,11 +441,27 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) { + int offset; + if ((phandle == 0) || (phandle == -1)) return -FDT_ERR_BADPHANDLE; - phandle = cpu_to_fdt32(phandle); - return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle", - &phandle, sizeof(phandle)); + + FDT_CHECK_HEADER(fdt); + + /* FIXME: The algorithm here is pretty horrible: we + * potentially scan each property of a node in + * fdt_get_phandle(), then if that didn't find what + * we want, we scan over them again making our way to the next + * node. Still it's the easiest to implement approach; + * performance can come later. */ + for (offset = fdt_next_node(fdt, -1, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + if (fdt_get_phandle(fdt, offset) == phandle) + return offset; + } + + return offset; /* error from fdt_next_node() */ } static int _fdt_stringlist_contains(const char *strlist, int listlen, diff --git a/livetree.c b/livetree.c index 2fa1490..9a482a8 100644 --- a/livetree.c +++ b/livetree.c @@ -297,12 +297,22 @@ cell_t get_node_phandle(struct node *root, struct node *node) phandle++; node->phandle = phandle; - if (!get_property(node, "linux,phandle")) + + if (!get_property(node, "linux,phandle") + && (phandle_format & PHANDLE_LEGACY)) add_property(node, build_property("linux,phandle", data_append_cell(empty_data, phandle), NULL)); - /* If the node *does* have a linux,phandle property, we must + + if (!get_property(node, "phandle") + && (phandle_format & PHANDLE_EPAPR)) + add_property(node, + build_property("phandle", + data_append_cell(empty_data, phandle), + NULL)); + + /* If the node *does* have a phandle property, we must * be dealing with a self-referencing phandle, which will be * fixed up momentarily in the caller */ diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 2696581..ac21ade 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -10,7 +10,8 @@ LIB_TESTS_L = get_mem_rsv \ sw_tree1 \ move_and_save mangle-layout nopulate \ open_pack rw_tree1 set_name setprop del_property del_node \ - string_escapes references path-references boot-cpuid incbin \ + string_escapes references path-references phandle_format \ + boot-cpuid incbin \ extra-terminating-null \ dtbs_equal_ordered \ add_subnode_with_nops path_offset_aliases diff --git a/tests/include1.dts b/tests/include1.dts index 8d7e747..5d59d83 100644 --- a/tests/include1.dts +++ b/tests/include1.dts @@ -15,7 +15,7 @@ prop-int = <123456789>; /include/ "include8.dts" - linux,phandle = <0x2001>; + phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; }; diff --git a/tests/phandle_format.c b/tests/phandle_format.c new file mode 100644 index 0000000..7e4d816 --- /dev/null +++ b/tests/phandle_format.c @@ -0,0 +1,78 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for phandle format options + * Copyright (C) 2009 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +#define PHANDLE_LEGACY 0x1 +#define PHANDLE_EPAPR 0x2 +#define PHANDLE_BOTH 0x3 + +int main(int argc, char *argv[]) +{ + void *fdt; + int phandle_format; + int n4; + uint32_t h4; + + if (argc != 3) + CONFIG("Usage: %s \n", argv[0]); + + test_init(argc, argv); + fdt = load_blob(argv[1]); + + if (streq(argv[2], "legacy")) + phandle_format = PHANDLE_LEGACY; + else if (streq(argv[2], "epapr")) + phandle_format = PHANDLE_EPAPR; + else if (streq(argv[2], "both")) + phandle_format = PHANDLE_BOTH; + else + CONFIG("Usage: %s \n", argv[0]); + + n4 = fdt_path_offset(fdt, "/node4"); + if (n4 < 0) + FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4)); + + h4 = fdt_get_phandle(fdt, n4); + if ((h4 == 0) || (h4 == -1)) + FAIL("/node4 has bad phandle 0x%x\n", h4); + + if (phandle_format & PHANDLE_LEGACY) + check_getprop_cell(fdt, n4, "linux,phandle", h4); + else + if (fdt_getprop(fdt, n4, "linux,phandle", NULL)) + FAIL("linux,phandle property present in non-legacy mode"); + + if (phandle_format & PHANDLE_EPAPR) + check_getprop_cell(fdt, n4, "phandle", h4); + else + if (fdt_getprop(fdt, n4, "phandle", NULL)) + FAIL("phandle property present in legacy-only mode"); + + PASS(); +} diff --git a/tests/references.dts b/tests/references.dts index 19b28ac..640c931 100644 --- a/tests/references.dts +++ b/tests/references.dts @@ -8,7 +8,7 @@ lref = <&n2>; }; n2: node2 { - linux,phandle = <0x1>; + phandle = <0x1>; ref = <&{/node1}>; /* reference after target */ lref = <&n1>; }; @@ -29,5 +29,6 @@ * so check it actually works */ n5: node5 { linux,phandle = <&n5>; + phandle = <&n5>; }; }; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 5d901c2..c532030 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -218,6 +218,12 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_path-references.test.dtb path-references.dts run_test path-references dtc_path-references.test.dtb + run_test phandle_format dtc_references.test.dtb both + for f in legacy epapr both; do + run_dtc_test -I dts -O dtb -H $f -o dtc_references.test.$f.dtb references.dts + run_test phandle_format dtc_references.test.$f.dtb $f + done + run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb comments.dts run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 687fb82..f2c430a 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -74,7 +74,7 @@ int main(int argc, char *argv[]) CHECK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_1)); CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2)); CHECK(fdt_begin_node(fdt, "subsubnode@0")); - CHECK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_2)); + CHECK(fdt_property_cell(fdt, "phandle", PHANDLE_2)); CHECK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode", 23)); CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2)); diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts index 1593554..218c382 100644 --- a/tests/test_tree1.dts +++ b/tests/test_tree1.dts @@ -26,7 +26,7 @@ prop-int = <123456789>; subsubnode@0 { - linux,phandle = <0x2001>; + phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; }; diff --git a/tests/trees.S b/tests/trees.S index 609cdd6..66adf3f 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -103,7 +103,7 @@ test_tree1_struct: END_NODE BEGIN_NODE("subnode@2") - PROP_INT(test_tree1, phandle, PHANDLE_1) + PROP_INT(test_tree1, linux_phandle, PHANDLE_1) PROP_INT(test_tree1, prop_int, TEST_VALUE_2) BEGIN_NODE("subsubnode@0") @@ -125,7 +125,8 @@ test_tree1_strings: STRING(test_tree1, compatible, "compatible") STRING(test_tree1, prop_int, "prop-int") STRING(test_tree1, prop_str, "prop-str") - STRING(test_tree1, phandle, "linux,phandle") + STRING(test_tree1, linux_phandle, "linux,phandle") + STRING(test_tree1, phandle, "phandle") test_tree1_strings_end: test_tree1_end: From d68cb36b0bebc7711ada9b750f3c19398c44efb7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 Dec 2009 14:24:42 +1100 Subject: [PATCH 0293/1198] dtc: Simpler interface to source file management This patch cleans up our handling of input files, particularly dts source files, but also (to an extent) other input files such as those used by /incbin/ and those used in -I dtb and -I fs modes. We eliminate the current clunky mechanism which combines search paths (which we don't actually use at present) with the open relative to current source file behaviour, which we do. Instead there's a single srcfile_relative_open() entry point for callers which opens a new input file relative to the current source file (which the srcpos code tracks internally). It doesn't currently do search paths, but we can add that later without messing with the callers, by drawing the search path from a global (which makes sense anyway, rather than shuffling it around the rest of the processing code). That suffices for non-dts input files. For the actual dts files, srcfile_push() and srcfile_pop() wrappers open the file while also keeping track of it as the current source file for future opens. Signed-off-by: David Gibson --- convert-dtsv0-lexer.l | 6 +- dtc-lexer.l | 91 +++------------------ dtc-parser.y | 18 ++-- dtc.c | 24 ------ dtc.h | 4 - flattree.c | 24 +++--- srcpos.c | 185 +++++++++++++++++++----------------------- srcpos.h | 27 +++--- treesource.c | 4 +- util.c | 24 ++++++ util.h | 1 + 11 files changed, 158 insertions(+), 250 deletions(-) diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index 59137f1..edb9110 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -210,8 +210,10 @@ static void convert_file(const char *fname) memcpy(newname, fname, len); memcpy(newname + len, suffix, sizeof(suffix)); - srcpos_file = dtc_open_file(fname, NULL); - yyin = srcpos_file->file; + yyin = fopen(fname, "r"); + if (!yyin) + die("Couldn't open input file %s: %s\n", + fname, strerror(errno)); yyout = fopen(newname, "w"); if (!yyout) diff --git a/dtc-lexer.l b/dtc-lexer.l index d142de5..12467c0 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -40,7 +40,7 @@ LINECOMMENT "//".*\n #define YY_USER_ACTION \ { \ - yylloc.file = srcpos_file; \ + yylloc.file = current_srcfile; \ yylloc.first_line = yylineno; \ } @@ -165,100 +165,29 @@ static int pop_input_file(void); %% - -/* - * Stack of nested include file contexts. - */ - -struct incl_file { - struct dtc_file *file; - YY_BUFFER_STATE yy_prev_buf; - int yy_prev_lineno; - struct incl_file *prev; -}; - -static struct incl_file *incl_file_stack; - - -/* - * Detect infinite include recursion. - */ -#define MAX_INCLUDE_DEPTH (100) - -static int incl_depth = 0; - - static void push_input_file(const char *filename) { - struct incl_file *incl_file; - struct dtc_file *newfile; - struct search_path search, *searchptr = NULL; - assert(filename); - if (incl_depth++ >= MAX_INCLUDE_DEPTH) - die("Includes nested too deeply"); + current_srcfile->lineno = yylineno; - if (srcpos_file) { - search.dir = srcpos_file->dir; - search.next = NULL; - search.prev = NULL; - searchptr = &search; - } + srcfile_push(filename); - newfile = dtc_open_file(filename, searchptr); - - incl_file = xmalloc(sizeof(struct incl_file)); - - /* - * Save current context. - */ - incl_file->yy_prev_buf = YY_CURRENT_BUFFER; - incl_file->yy_prev_lineno = yylineno; - incl_file->file = srcpos_file; - incl_file->prev = incl_file_stack; - - incl_file_stack = incl_file; - - /* - * Establish new context. - */ - srcpos_file = newfile; + yyin = current_srcfile->f; yylineno = 1; - yyin = newfile->file; - yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + + yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE)); } static int pop_input_file(void) { - struct incl_file *incl_file; - - if (incl_file_stack == 0) + if (srcfile_pop() == 0) return 0; - dtc_close_file(srcpos_file); - - /* - * Pop. - */ - --incl_depth; - incl_file = incl_file_stack; - incl_file_stack = incl_file->prev; - - /* - * Recover old context. - */ - yy_delete_buffer(YY_CURRENT_BUFFER); - yy_switch_to_buffer(incl_file->yy_prev_buf); - yylineno = incl_file->yy_prev_lineno; - srcpos_file = incl_file->file; - yyin = incl_file->file ? incl_file->file->file : NULL; - - /* - * Free old state. - */ - free(incl_file); + yypop_buffer_state(); + yylineno = current_srcfile->lineno; + yyin = current_srcfile->f; return 1; } diff --git a/dtc-parser.y b/dtc-parser.y index 31c14d7..b7c7dbd 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -169,33 +169,31 @@ propdata: } | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')' { - struct search_path path = { srcpos_file->dir, NULL, NULL }; - struct dtc_file *file = dtc_open_file($4.val, &path); - struct data d = empty_data; + FILE *f = srcfile_relative_open($4.val, NULL); + struct data d; if ($6 != 0) - if (fseek(file->file, $6, SEEK_SET) != 0) + if (fseek(f, $6, SEEK_SET) != 0) srcpos_error(&yylloc, "Couldn't seek to offset %llu in \"%s\": %s", (unsigned long long)$6, $4.val, strerror(errno)); - d = data_copy_file(file->file, $8); + d = data_copy_file(f, $8); $$ = data_merge($1, d); - dtc_close_file(file); + fclose(f); } | propdataprefix DT_INCBIN '(' DT_STRING ')' { - struct search_path path = { srcpos_file->dir, NULL, NULL }; - struct dtc_file *file = dtc_open_file($4.val, &path); + FILE *f = srcfile_relative_open($4.val, NULL); struct data d = empty_data; - d = data_copy_file(file->file, -1); + d = data_copy_file(f, -1); $$ = data_merge($1, d); - dtc_close_file(file); + fclose(f); } | propdata DT_LABEL { diff --git a/dtc.c b/dtc.c index 800664c..8b31d20 100644 --- a/dtc.c +++ b/dtc.c @@ -32,30 +32,6 @@ int minsize; /* Minimum blob size */ int padsize; /* Additional padding to blob */ int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */ -char *join_path(const char *path, const char *name) -{ - int lenp = strlen(path); - int lenn = strlen(name); - int len; - int needslash = 1; - char *str; - - len = lenp + lenn + 2; - if ((lenp > 0) && (path[lenp-1] == '/')) { - needslash = 0; - len--; - } - - str = xmalloc(len); - memcpy(str, path, lenp); - if (needslash) { - str[lenp] = '/'; - lenp++; - } - memcpy(str+lenp, name, lenn+1); - return str; -} - static void fill_fullpaths(struct node *tree, const char *prefix) { struct node *child; diff --git a/dtc.h b/dtc.h index 0d7f0ed..a85e5b7 100644 --- a/dtc.h +++ b/dtc.h @@ -224,8 +224,4 @@ struct boot_info *dt_from_source(const char *f); struct boot_info *dt_from_fs(const char *dirname); -/* misc */ - -char *join_path(const char *path, const char *name); - #endif /* _DTC_H */ diff --git a/flattree.c b/flattree.c index 3eb0201..8637407 100644 --- a/flattree.c +++ b/flattree.c @@ -797,7 +797,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, struct boot_info *dt_from_blob(const char *fname) { - struct dtc_file *dtcf; + FILE *f; uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys; uint32_t off_dt, off_str, off_mem_rsvmap; int rc; @@ -812,14 +812,14 @@ struct boot_info *dt_from_blob(const char *fname) uint32_t val; int flags = 0; - dtcf = dtc_open_file(fname, NULL); + f = srcfile_relative_open(fname, NULL); - rc = fread(&magic, sizeof(magic), 1, dtcf->file); - if (ferror(dtcf->file)) + rc = fread(&magic, sizeof(magic), 1, f); + if (ferror(f)) die("Error reading DT blob magic number: %s\n", strerror(errno)); if (rc < 1) { - if (feof(dtcf->file)) + if (feof(f)) die("EOF reading DT blob magic number\n"); else die("Mysterious short read reading magic number\n"); @@ -829,11 +829,11 @@ struct boot_info *dt_from_blob(const char *fname) if (magic != FDT_MAGIC) die("Blob has incorrect magic number\n"); - rc = fread(&totalsize, sizeof(totalsize), 1, dtcf->file); - if (ferror(dtcf->file)) + rc = fread(&totalsize, sizeof(totalsize), 1, f); + if (ferror(f)) die("Error reading DT blob size: %s\n", strerror(errno)); if (rc < 1) { - if (feof(dtcf->file)) + if (feof(f)) die("EOF reading DT blob size\n"); else die("Mysterious short read reading blob size\n"); @@ -853,12 +853,12 @@ struct boot_info *dt_from_blob(const char *fname) p = blob + sizeof(magic) + sizeof(totalsize); while (sizeleft) { - if (feof(dtcf->file)) + if (feof(f)) die("EOF before reading %d bytes of DT blob\n", totalsize); - rc = fread(p, 1, sizeleft, dtcf->file); - if (ferror(dtcf->file)) + rc = fread(p, 1, sizeleft, f); + if (ferror(f)) die("Error reading DT blob: %s\n", strerror(errno)); @@ -921,7 +921,7 @@ struct boot_info *dt_from_blob(const char *fname) free(blob); - dtc_close_file(dtcf); + fclose(f); return build_boot_info(reservelist, tree, boot_cpuid_phys); } diff --git a/srcpos.c b/srcpos.c index 8bb0c02..f08c1c3 100644 --- a/srcpos.c +++ b/srcpos.c @@ -25,118 +25,103 @@ #include "srcpos.h" -/* - * Like yylineno, this is the current open file pos. - */ -struct dtc_file *srcpos_file; +static char *dirname(const char *path) +{ + const char *slash = strrchr(path, '/'); + + if (slash) { + int len = slash - path; + char *dir = xmalloc(len + 1); + + memcpy(dir, path, len); + dir[len] = '\0'; + return dir; + } + return NULL; +} + +struct srcfile_state *current_srcfile; /* = NULL */ + +/* Detect infinite include recursion. */ +#define MAX_SRCFILE_DEPTH (100) +static int srcfile_depth; /* = 0 */ + +FILE *srcfile_relative_open(const char *fname, char **fullnamep) +{ + FILE *f; + char *fullname; + + if (streq(fname, "-")) { + f = stdin; + fullname = xstrdup(""); + } else { + if (!current_srcfile || !current_srcfile->dir + || (fname[0] == '/')) + fullname = xstrdup(fname); + else + fullname = join_path(current_srcfile->dir, fname); + + f = fopen(fullname, "r"); + if (!f) + die("Couldn't open \"%s\": %s\n", fname, + strerror(errno)); + } + + if (fullnamep) + *fullnamep = fullname; + else + free(fullname); + + return f; +} + +void srcfile_push(const char *fname) +{ + struct srcfile_state *srcfile; + + if (srcfile_depth++ >= MAX_SRCFILE_DEPTH) + die("Includes nested too deeply"); + + srcfile = xmalloc(sizeof(*srcfile)); + + srcfile->f = srcfile_relative_open(fname, &srcfile->name); + srcfile->dir = dirname(srcfile->name); + srcfile->prev = current_srcfile; + current_srcfile = srcfile; +} + +int srcfile_pop(void) +{ + struct srcfile_state *srcfile = current_srcfile; + + assert(srcfile); + + current_srcfile = srcfile->prev; + + if (fclose(srcfile->f)) + die("Error closing \"%s\": %s\n", srcfile->name, strerror(errno)); + + /* FIXME: We allow the srcfile_state structure to leak, + * because it could still be referenced from a location + * variable being carried through the parser somewhere. To + * fix this we could either allocate all the files from a + * table, or use a pool allocator. */ + + return current_srcfile ? 1 : 0; +} /* * The empty source position. */ -struct dtc_file dtc_empty_file = { - .dir = NULL, - .name = "", - .file = NULL -}; - srcpos srcpos_empty = { .first_line = 0, .first_column = 0, .last_line = 0, .last_column = 0, - .file = &dtc_empty_file + .file = NULL, }; - -static int -dtc_open_one(struct dtc_file *file, const char *search, const char *fname) -{ - char *fullname; - - if (search) { - fullname = xmalloc(strlen(search) + strlen(fname) + 2); - - strcpy(fullname, search); - strcat(fullname, "/"); - strcat(fullname, fname); - } else { - fullname = xstrdup(fname); - } - - file->file = fopen(fullname, "r"); - if (!file->file) { - free(fullname); - return 0; - } - - file->name = fullname; - return 1; -} - - -struct dtc_file * -dtc_open_file(const char *fname, const struct search_path *search) -{ - static const struct search_path default_search = { NULL, NULL, NULL }; - - struct dtc_file *file; - const char *slash; - - file = xmalloc(sizeof(struct dtc_file)); - - slash = strrchr(fname, '/'); - if (slash) { - char *dir = xmalloc(slash - fname + 1); - - memcpy(dir, fname, slash - fname); - dir[slash - fname] = 0; - file->dir = dir; - } else { - file->dir = NULL; - } - - if (streq(fname, "-")) { - file->name = "stdin"; - file->file = stdin; - return file; - } - - if (fname[0] == '/') { - file->file = fopen(fname, "r"); - if (!file->file) - goto fail; - - file->name = xstrdup(fname); - return file; - } - - if (!search) - search = &default_search; - - while (search) { - if (dtc_open_one(file, search->dir, fname)) - return file; - - if (errno != ENOENT) - goto fail; - - search = search->next; - } - -fail: - die("Couldn't open \"%s\": %s\n", fname, strerror(errno)); -} - - -void -dtc_close_file(struct dtc_file *file) -{ - if (fclose(file->file)) - die("Error closing \"%s\": %s\n", file->name, strerror(errno)); -} - - srcpos * srcpos_copy(srcpos *pos) { diff --git a/srcpos.h b/srcpos.h index a6d0077..38cc988 100644 --- a/srcpos.h +++ b/srcpos.h @@ -27,19 +27,27 @@ #include -struct dtc_file { +struct srcfile_state { + FILE *f; + char *name; char *dir; - const char *name; - FILE *file; + int lineno; + struct srcfile_state *prev; }; +extern struct srcfile_state *current_srcfile; /* = NULL */ + +FILE *srcfile_relative_open(const char *fname, char **fullnamep); +void srcfile_push(const char *fname); +int srcfile_pop(void); + #if ! defined(YYLTYPE) && ! defined(YYLTYPE_IS_DECLARED) typedef struct YYLTYPE { int first_line; int first_column; int last_line; int last_column; - struct dtc_file *file; + struct srcfile_state *file; } YYLTYPE; #define YYLTYPE_IS_DECLARED 1 @@ -81,17 +89,6 @@ typedef YYLTYPE srcpos; */ extern srcpos srcpos_empty; -extern struct dtc_file *srcpos_file; - -struct search_path { - const char *dir; /* NULL for current directory */ - struct search_path *prev, *next; -}; - -extern struct dtc_file *dtc_open_file(const char *fname, - const struct search_path *search); -extern void dtc_close_file(struct dtc_file *file); - extern srcpos *srcpos_copy(srcpos *pos); extern char *srcpos_string(srcpos *pos); extern void srcpos_dump(srcpos *pos); diff --git a/treesource.c b/treesource.c index cc1751d..331c22c 100644 --- a/treesource.c +++ b/treesource.c @@ -32,8 +32,8 @@ struct boot_info *dt_from_source(const char *fname) the_boot_info = NULL; treesource_error = 0; - srcpos_file = dtc_open_file(fname, NULL); - yyin = srcpos_file->file; + srcfile_push(fname); + yyin = current_srcfile->f; if (yyparse() != 0) die("Unable to parse input tree\n"); diff --git a/util.c b/util.c index 33631ce..c1d3ca4 100644 --- a/util.c +++ b/util.c @@ -28,3 +28,27 @@ char *xstrdup(const char *s) return dup; } + +char *join_path(const char *path, const char *name) +{ + int lenp = strlen(path); + int lenn = strlen(name); + int len; + int needslash = 1; + char *str; + + len = lenp + lenn + 2; + if ((lenp > 0) && (path[lenp-1] == '/')) { + needslash = 0; + len--; + } + + str = xmalloc(len); + memcpy(str, path, lenp); + if (needslash) { + str[lenp] = '/'; + lenp++; + } + memcpy(str+lenp, name, lenn+1); + return str; +} diff --git a/util.h b/util.h index 0fb60fe..9cead84 100644 --- a/util.h +++ b/util.h @@ -51,5 +51,6 @@ static inline void *xrealloc(void *p, size_t len) } extern char *xstrdup(const char *s); +extern char *join_path(const char *path, const char *name); #endif /* _UTIL_H */ From 728c5e87c655c17c2fbc1d5386b12ff328e0fc76 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 Dec 2009 14:24:42 +1100 Subject: [PATCH 0294/1198] dtc: Cleanup line number tracking, add column number tracking Our YYLTYPE current carries around first and last line and first and last column information. However, of these, on the first line information is actually filled in properly. Furthermore, filling in the line number information from yylineno is kind of clunky: we have to copy its value to the srcfile stack and back to handle include file positioning correctly. This patch cleans this up. We turn off flex's yylineno option and instead track the line and column number ourselves from YY_USER_ACTION. The line and column number are stored directly inside the srcfile_state structure, so it's automatically a per-file quantity. We now also fill in all the yylloc from YY_USER_ACTION. Signed-off-by: David Gibson --- dtc-lexer.l | 11 ++++------- srcpos.c | 33 ++++++++++++++++++++++++++++++++- srcpos.h | 3 ++- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 12467c0..9021231 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -18,7 +18,7 @@ * USA */ -%option noyywrap nounput noinput yylineno +%option noyywrap nounput noinput %x INCLUDE %x BYTESTRING @@ -38,10 +38,11 @@ LINECOMMENT "//".*\n #include "srcpos.h" #include "dtc-parser.tab.h" + +/* CAUTION: this will stop working if we ever use yyless() or yyunput() */ #define YY_USER_ACTION \ { \ - yylloc.file = current_srcfile; \ - yylloc.first_line = yylineno; \ + srcpos_update(&yylloc, yytext, yyleng); \ } /*#define LEXDEBUG 1*/ @@ -169,12 +170,9 @@ static void push_input_file(const char *filename) { assert(filename); - current_srcfile->lineno = yylineno; - srcfile_push(filename); yyin = current_srcfile->f; - yylineno = 1; yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE)); } @@ -186,7 +184,6 @@ static int pop_input_file(void) return 0; yypop_buffer_state(); - yylineno = current_srcfile->lineno; yyin = current_srcfile->f; return 1; diff --git a/srcpos.c b/srcpos.c index f08c1c3..ca322bb 100644 --- a/srcpos.c +++ b/srcpos.c @@ -87,6 +87,10 @@ void srcfile_push(const char *fname) srcfile->f = srcfile_relative_open(fname, &srcfile->name); srcfile->dir = dirname(srcfile->name); srcfile->prev = current_srcfile; + + srcfile->lineno = 1; + srcfile->colno = 1; + current_srcfile = srcfile; } @@ -99,7 +103,8 @@ int srcfile_pop(void) current_srcfile = srcfile->prev; if (fclose(srcfile->f)) - die("Error closing \"%s\": %s\n", srcfile->name, strerror(errno)); + die("Error closing \"%s\": %s\n", srcfile->name, + strerror(errno)); /* FIXME: We allow the srcfile_state structure to leak, * because it could still be referenced from a location @@ -122,6 +127,32 @@ srcpos srcpos_empty = { .file = NULL, }; +#define TAB_SIZE 8 + +void srcpos_update(srcpos *pos, const char *text, int len) +{ + int i; + + pos->file = current_srcfile; + + pos->first_line = current_srcfile->lineno; + pos->first_column = current_srcfile->colno; + + for (i = 0; i < len; i++) + if (text[i] == '\n') { + current_srcfile->lineno++; + current_srcfile->colno = 1; + } else if (text[i] == '\t') { + current_srcfile->colno = + ALIGN(current_srcfile->colno, TAB_SIZE); + } else { + current_srcfile->colno++; + } + + pos->last_line = current_srcfile->lineno; + pos->last_column = current_srcfile->colno; +} + srcpos * srcpos_copy(srcpos *pos) { diff --git a/srcpos.h b/srcpos.h index 38cc988..eb60244 100644 --- a/srcpos.h +++ b/srcpos.h @@ -31,7 +31,7 @@ struct srcfile_state { FILE *f; char *name; char *dir; - int lineno; + int lineno, colno; struct srcfile_state *prev; }; @@ -89,6 +89,7 @@ typedef YYLTYPE srcpos; */ extern srcpos srcpos_empty; +extern void srcpos_update(srcpos *pos, const char *text, int len); extern srcpos *srcpos_copy(srcpos *pos); extern char *srcpos_string(srcpos *pos); extern void srcpos_dump(srcpos *pos); From e1fee329e2a74141fc6872a5c4307d078c4ba553 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 Dec 2009 14:24:42 +1100 Subject: [PATCH 0295/1198] dtc: Cleanup srcpos_string() There are several small problems with the current srcpos_string(). - The code unnecessarily uses a temp buffer and two rounds of *printf(); a single asprintf() will suffice. - With previous changes, pos->file->name can never be NULL, and the name field for a srcfile bound to stdin is already set to something sensible. - On allocation failure in asprintf() it returns a bogus result, instead of causing a fatal error like every other failed allocation. - The format for representing file/line/column is gratuitously different from the file/line format we used to use, and the format used by gcc and bison. This patch addresses all of these. There remains the problem that asprintf() is not portable, but that can wait until another patch. Signed-off-by: David Gibson --- srcpos.c | 45 ++++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/srcpos.c b/srcpos.c index ca322bb..59ecbce 100644 --- a/srcpos.c +++ b/srcpos.c @@ -182,41 +182,28 @@ srcpos_dump(srcpos *pos) char * srcpos_string(srcpos *pos) { - const char *fname; - char col_buf[100]; + const char *fname = ""; char *pos_str; + int rc; - if (!pos) { - fname = ""; - } else if (pos->file->name) { + if (pos) fname = pos->file->name; - if (strcmp(fname, "-") == 0) - fname = "stdin"; - } else { - fname = ""; - } - if (pos->first_line == pos->last_line) { - if (pos->first_column == pos->last_column) { - snprintf(col_buf, sizeof(col_buf), - "%d:%d", - pos->first_line, pos->first_column); - } else { - snprintf(col_buf, sizeof(col_buf), - "%d:%d-%d", - pos->first_line, - pos->first_column, pos->last_column); - } - } else { - snprintf(col_buf, sizeof(col_buf), - "%d:%d - %d:%d", - pos->first_line, pos->first_column, - pos->last_line, pos->last_column); - } + if (pos->first_line != pos->last_line) + rc = asprintf(&pos_str, "%s:%d.%d-%d.%d", fname, + pos->first_line, pos->first_column, + pos->last_line, pos->last_column); + else if (pos->first_column != pos->last_column) + rc = asprintf(&pos_str, "%s:%d.%d-%d", fname, + pos->first_line, pos->first_column, + pos->last_column); + else + rc = asprintf(&pos_str, "%s:%d.%d", fname, + pos->first_line, pos->first_column); - if (asprintf(&pos_str, "%s %s", fname, col_buf) == -1) - return " Date: Tue, 8 Dec 2009 14:24:42 +1100 Subject: [PATCH 0296/1198] dtc: Cleanup YYLTYPE and YYLLOC_DEFAULT declarations This patch makes some small cleanups to the declaration of YYLTYPE, YYLLOC_DEFAULT and related things. - We used to use undocumented magic #defines for bison, YYLTYPE_IS_DECLARED and YYLTYPE_IS_TRIVIAL. This may not be portable across bison versions. Instead define YYLTYPE as a macro in terms of struct srcpos, as the info pages suggest. - Our kernel-derived coding style discourages typedefed structures. So use 'struct srcpos' instead of 'srcpos' throughout'. - Indent the YYLLOC_DEFAULT macro according to our coding style (it was in GNU indent style, since it was taken from the example in the bison info). Signed-off-by: David Gibson --- srcpos.c | 22 +++++++++--------- srcpos.h | 70 +++++++++++++++++++++----------------------------------- 2 files changed, 37 insertions(+), 55 deletions(-) diff --git a/srcpos.c b/srcpos.c index 59ecbce..87d7f17 100644 --- a/srcpos.c +++ b/srcpos.c @@ -119,7 +119,7 @@ int srcfile_pop(void) * The empty source position. */ -srcpos srcpos_empty = { +struct srcpos srcpos_empty = { .first_line = 0, .first_column = 0, .last_line = 0, @@ -129,7 +129,7 @@ srcpos srcpos_empty = { #define TAB_SIZE 8 -void srcpos_update(srcpos *pos, const char *text, int len) +void srcpos_update(struct srcpos *pos, const char *text, int len) { int i; @@ -153,13 +153,13 @@ void srcpos_update(srcpos *pos, const char *text, int len) pos->last_column = current_srcfile->colno; } -srcpos * -srcpos_copy(srcpos *pos) +struct srcpos * +srcpos_copy(struct srcpos *pos) { - srcpos *pos_new; + struct srcpos *pos_new; - pos_new = xmalloc(sizeof(srcpos)); - memcpy(pos_new, pos, sizeof(srcpos)); + pos_new = xmalloc(sizeof(struct srcpos)); + memcpy(pos_new, pos, sizeof(struct srcpos)); return pos_new; } @@ -167,7 +167,7 @@ srcpos_copy(srcpos *pos) void -srcpos_dump(srcpos *pos) +srcpos_dump(struct srcpos *pos) { printf("file : \"%s\"\n", pos->file ? (char *) pos->file : ""); @@ -180,7 +180,7 @@ srcpos_dump(srcpos *pos) char * -srcpos_string(srcpos *pos) +srcpos_string(struct srcpos *pos) { const char *fname = ""; char *pos_str; @@ -210,7 +210,7 @@ srcpos_string(srcpos *pos) void -srcpos_error(srcpos *pos, char const *fmt, ...) +srcpos_error(struct srcpos *pos, char const *fmt, ...) { const char *srcstr; va_list va; @@ -227,7 +227,7 @@ srcpos_error(srcpos *pos, char const *fmt, ...) void -srcpos_warn(srcpos *pos, char const *fmt, ...) +srcpos_warn(struct srcpos *pos, char const *fmt, ...) { const char *srcstr; va_list va; diff --git a/srcpos.h b/srcpos.h index eb60244..985f847 100644 --- a/srcpos.h +++ b/srcpos.h @@ -20,11 +20,6 @@ #ifndef _SRCPOS_H_ #define _SRCPOS_H_ -/* - * Augment the standard YYLTYPE with a filenum index into an - * array of all opened filenames. - */ - #include struct srcfile_state { @@ -41,62 +36,49 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep); void srcfile_push(const char *fname); int srcfile_pop(void); -#if ! defined(YYLTYPE) && ! defined(YYLTYPE_IS_DECLARED) -typedef struct YYLTYPE { +struct srcpos { int first_line; int first_column; int last_line; int last_column; struct srcfile_state *file; -} YYLTYPE; +}; -#define YYLTYPE_IS_DECLARED 1 -#define YYLTYPE_IS_TRIVIAL 1 -#endif +#define YYLTYPE struct srcpos -/* Cater to old parser templates. */ -#ifndef YYID -#define YYID(n) (n) -#endif +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do { \ + if (N) { \ + (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + (Current).file = YYRHSLOC(Rhs, N).file; \ + } else { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC(Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC(Rhs, 0).last_column; \ + (Current).file = YYRHSLOC (Rhs, 0).file; \ + } \ + } while (0) -#define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - (Current).file = YYRHSLOC (Rhs, N).file; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - (Current).file = YYRHSLOC (Rhs, 0).file; \ - } \ - while (YYID (0)) - - -typedef YYLTYPE srcpos; /* * Fictional source position used for IR nodes that are * created without otherwise knowing a true source position. * For example,constant definitions from the command line. */ -extern srcpos srcpos_empty; +extern struct srcpos srcpos_empty; -extern void srcpos_update(srcpos *pos, const char *text, int len); -extern srcpos *srcpos_copy(srcpos *pos); -extern char *srcpos_string(srcpos *pos); -extern void srcpos_dump(srcpos *pos); +extern void srcpos_update(struct srcpos *pos, const char *text, int len); +extern struct srcpos *srcpos_copy(struct srcpos *pos); +extern char *srcpos_string(struct srcpos *pos); +extern void srcpos_dump(struct srcpos *pos); -extern void srcpos_error(srcpos *pos, char const *, ...) +extern void srcpos_error(struct srcpos *pos, char const *, ...) __attribute__((format(printf, 2, 3))); -extern void srcpos_warn(srcpos *pos, char const *, ...) +extern void srcpos_warn(struct srcpos *pos, char const *, ...) __attribute__((format(printf, 2, 3))); #endif /* _SRCPOS_H_ */ From 5c8d2e2b57f50ff9a3d66e31032693e4273af85c Mon Sep 17 00:00:00 2001 From: Lukasz Wojcik Date: Fri, 29 Jan 2010 17:31:51 +0100 Subject: [PATCH 0297/1198] Modification of lexer and parser, improving dtc portability. This mod allows successful build of dtc using both bison/flex and yacc/lex. Signed-off-by: Lukasz Wojcik Acked-by: David Gibson --- dtc-lexer.l | 1 + dtc-parser.y | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 9021231..3c3434c 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -38,6 +38,7 @@ LINECOMMENT "//".*\n #include "srcpos.h" #include "dtc-parser.tab.h" +YYLTYPE yylloc; /* CAUTION: this will stop working if we ever use yyless() or yyunput() */ #define YY_USER_ACTION \ diff --git a/dtc-parser.y b/dtc-parser.y index b7c7dbd..a2c0925 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -18,14 +18,14 @@ * USA */ -%locations - %{ #include #include "dtc.h" #include "srcpos.h" +YYLTYPE yylloc; + extern int yylex(void); extern void yyerror(char const *s); From 15ad6d862ec7f66dc00783798705a8db1c5d9aca Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 19 Feb 2010 15:50:50 +1100 Subject: [PATCH 0298/1198] dtc: Automatically pick a sensible boot_cpuid_phys Currently, when in -Idts -Odtb or -Ifs -Odtb modes, dtc always defaults to using 0 as the value for the boot_cpuid_phys header field. That's correct quite often, but there are some systems where there is no CPU with hardware ID of 0, or where we don't want to use the CPU with hardware ID 0 at all (e.g. for AMP-style partitioning). The only way to override this default currently, is with the -b command line option. This patch improves dtc to instead base the default boot_cpuid_phys value on the reg property of the first listed subnode of /cpus. This means that dtc will get boot_cpuid_phys correct by default in a greater proportion of cases (since the boot cpu is usually listed first, and this way at least the boot_cpuid_phys default will match some existing cpu node). If the node doesn't exist or has an invalid 'reg' property (missing or not 4 bytes in length), then boot_cpuid_phys is set to 0. Signed-off-by: David Gibson --- dtc-parser.y | 3 ++- dtc.h | 2 ++ fstree.c | 2 +- livetree.c | 23 +++++++++++++++++++++++ tests/boot-cpuid.dts | 16 ++++++++++++++++ tests/run_tests.sh | 26 ++++++++++++++++++++------ 6 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 tests/boot-cpuid.dts diff --git a/dtc-parser.y b/dtc-parser.y index a2c0925..bd9e097 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -85,7 +85,8 @@ static unsigned long long eval_literal(const char *s, int base, int bits); sourcefile: DT_V1 ';' memreserves devicetree { - the_boot_info = build_boot_info($3, $4, 0); + the_boot_info = build_boot_info($3, $4, + guess_boot_cpuid($4)); } ; diff --git a/dtc.h b/dtc.h index a85e5b7..13136e4 100644 --- a/dtc.h +++ b/dtc.h @@ -178,6 +178,8 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle); struct node *get_node_by_ref(struct node *tree, const char *ref); cell_t get_node_phandle(struct node *root, struct node *node); +uint32_t guess_boot_cpuid(struct node *tree); + /* Boot info (tree plus memreserve information */ struct reserve_info { diff --git a/fstree.c b/fstree.c index 7aee982..d43343a 100644 --- a/fstree.c +++ b/fstree.c @@ -87,6 +87,6 @@ struct boot_info *dt_from_fs(const char *dirname) tree = read_fstree(dirname); tree = name_node(tree, "", NULL); - return build_boot_info(NULL, tree, 0); + return build_boot_info(NULL, tree, guess_boot_cpuid(tree)); } diff --git a/livetree.c b/livetree.c index 9a482a8..0230949 100644 --- a/livetree.c +++ b/livetree.c @@ -318,3 +318,26 @@ cell_t get_node_phandle(struct node *root, struct node *node) return node->phandle; } + +uint32_t guess_boot_cpuid(struct node *tree) +{ + struct node *cpus, *bootcpu; + struct property *reg; + + cpus = get_node_by_path(tree, "/cpus"); + if (!cpus) + return 0; + + + bootcpu = cpus->children; + if (!bootcpu) + return 0; + + reg = get_property(bootcpu, "reg"); + if (!reg || (reg->val.len != sizeof(uint32_t))) + return 0; + + /* FIXME: Sanity check node? */ + + return propval_cell(reg); +} diff --git a/tests/boot-cpuid.dts b/tests/boot-cpuid.dts new file mode 100644 index 0000000..7021a24 --- /dev/null +++ b/tests/boot-cpuid.dts @@ -0,0 +1,16 @@ +/dts-v1/; + +/ { + cpus { + cpu@10 { + device_type = "cpu"; + compatible = "fake-cpu"; + reg = <0x10>; + }; + cpu@11 { + device_type = "cpu"; + compatible = "fake-cpu"; + reg = <0x11>; + }; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c532030..ca46051 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -242,12 +242,26 @@ dtc_tests () { run_test incbin incbin.test.dtb # Check boot_cpuid_phys handling - run_dtc_test -I dts -O dtb -b 17 -o boot_cpuid.test.dtb empty.dts - run_test boot-cpuid boot_cpuid.test.dtb 17 - run_dtc_test -I dtb -O dtb -b 17 -o boot_cpuid_test_tree1.test.dtb test_tree1.dtb - run_test boot-cpuid boot_cpuid_test_tree1.test.dtb 17 - run_dtc_test -I dtb -O dtb -o boot_cpuid_preserved_test_tree1.test.dtb boot_cpuid_test_tree1.test.dtb - run_test dtbs_equal_ordered boot_cpuid_preserved_test_tree1.test.dtb boot_cpuid_test_tree1.test.dtb + run_dtc_test -I dts -O dtb -o boot_cpuid.test.dtb boot-cpuid.dts + run_test boot-cpuid boot_cpuid.test.dtb 16 + + run_dtc_test -I dts -O dtb -b 17 -o boot_cpuid_17.test.dtb boot-cpuid.dts + run_test boot-cpuid boot_cpuid_17.test.dtb 17 + + run_dtc_test -I dtb -O dtb -o preserve_boot_cpuid.test.dtb boot_cpuid.test.dtb + run_test boot-cpuid preserve_boot_cpuid.test.dtb 16 + run_test dtbs_equal_ordered preserve_boot_cpuid.test.dtb boot_cpuid.test.dtb + + run_dtc_test -I dtb -O dtb -o preserve_boot_cpuid_17.test.dtb boot_cpuid_17.test.dtb + run_test boot-cpuid preserve_boot_cpuid_17.test.dtb 17 + run_test dtbs_equal_ordered preserve_boot_cpuid_17.test.dtb boot_cpuid_17.test.dtb + + run_dtc_test -I dtb -O dtb -b17 -o override17_boot_cpuid.test.dtb boot_cpuid.test.dtb + run_test boot-cpuid override17_boot_cpuid.test.dtb 17 + + run_dtc_test -I dtb -O dtb -b0 -o override0_boot_cpuid_17.test.dtb boot_cpuid_17.test.dtb + run_test boot-cpuid override0_boot_cpuid_17.test.dtb 0 + # Check -Oasm mode for tree in test_tree1.dts escapes.dts references.dts path-references.dts \ From 329055dbbc3c09e21386ceae788256991f4c8aec Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 23 Feb 2010 19:56:41 +1100 Subject: [PATCH 0299/1198] Disallow re-use of the same label within a dts file Currently, nothing will stop you from re-using the same label string multiple times in a dts, e.g.: / { samelabel: prop1 = "foo"; samelabel: prop2 = "bar"; }; or / { samelabel: prop1 = "foo"; samelabel: subnode { }; }; When using node references by label, this could lead to confusing results (with no warning), and in -Oasm mode will result in output which the assembler will complain about (since it too will have duplicate labels). This patch, therefore, adds code to checks.c to give errors if you attempt to re-use the same label. It treats all labels (node, property, and value) as residing in the same namespace, since the assembler will treat them so for -Oasm mode. Testcases for the new code are also added. Signed-off-by: David Gibson --- checks.c | 56 ++++++++++++++++++++++++++++++++++++++++++ dtc.h | 4 +++ livetree.c | 51 ++++++++++++++++++++++++++++++++++++++ tests/reuse-label.dts | 15 +++++++++++ tests/reuse-label1.dts | 10 ++++++++ tests/reuse-label2.dts | 6 +++++ tests/reuse-label3.dts | 9 +++++++ tests/reuse-label4.dts | 5 ++++ tests/reuse-label5.dts | 6 +++++ tests/reuse-label6.dts | 6 +++++ tests/run_tests.sh | 7 ++++++ 11 files changed, 175 insertions(+) create mode 100644 tests/reuse-label.dts create mode 100644 tests/reuse-label1.dts create mode 100644 tests/reuse-label2.dts create mode 100644 tests/reuse-label3.dts create mode 100644 tests/reuse-label4.dts create mode 100644 tests/reuse-label5.dts create mode 100644 tests/reuse-label6.dts diff --git a/checks.c b/checks.c index 031cc59..1f35cb9 100644 --- a/checks.c +++ b/checks.c @@ -278,6 +278,59 @@ static void check_property_name_chars(struct check *c, struct node *dt, } PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR); +#define DESCLABEL_FMT "%s%s%s%s%s" +#define DESCLABEL_ARGS(node,prop,mark) \ + ((mark) ? "value of " : ""), \ + ((prop) ? "'" : ""), \ + ((prop) ? (prop)->name : ""), \ + ((prop) ? "' in " : ""), (node)->fullpath + +static void check_duplicate_label(struct check *c, struct node *dt, + const char *label, struct node *node, + struct property *prop, struct marker *mark) +{ + struct node *othernode = NULL; + struct property *otherprop = NULL; + struct marker *othermark = NULL; + + othernode = get_node_by_label(dt, label); + + if (!othernode) + otherprop = get_property_by_label(dt, label, &othernode); + if (!othernode) + othermark = get_marker_label(dt, label, &othernode, + &otherprop); + + if (!othernode) + return; + + if ((othernode != node) || (otherprop != prop) || (othermark != mark)) + FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT + " and " DESCLABEL_FMT, + label, DESCLABEL_ARGS(node, prop, mark), + DESCLABEL_ARGS(othernode, otherprop, othermark)); +} + +static void check_duplicate_label_node(struct check *c, struct node *dt, + struct node *node) +{ + if (node->label) + check_duplicate_label(c, dt, node->label, node, NULL, NULL); +} +static void check_duplicate_label_prop(struct check *c, struct node *dt, + struct node *node, struct property *prop) +{ + struct marker *m = prop->val.markers; + + if (prop->label) + check_duplicate_label(c, dt, prop->label, node, prop, NULL); + + for_each_marker_of_type(m, LABEL) + check_duplicate_label(c, dt, m->ref, node, prop, m); +} +CHECK(duplicate_label, NULL, check_duplicate_label_node, + check_duplicate_label_prop, NULL, ERROR); + static void check_explicit_phandles(struct check *c, struct node *root, struct node *node, struct property *prop) { @@ -573,6 +626,9 @@ 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, + + &duplicate_label, + &explicit_phandles, &phandle_references, &path_references, diff --git a/dtc.h b/dtc.h index 13136e4..5367198 100644 --- a/dtc.h +++ b/dtc.h @@ -171,6 +171,10 @@ void add_child(struct node *parent, struct node *child); const char *get_unitname(struct node *node); struct property *get_property(struct node *node, const char *propname); cell_t propval_cell(struct property *prop); +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, + struct node **node, struct property **prop); struct node *get_subnode(struct node *node, const char *nodename); struct node *get_node_by_path(struct node *tree, const char *path); struct node *get_node_by_label(struct node *tree, const char *label); diff --git a/livetree.c b/livetree.c index 0230949..aa0edf1 100644 --- a/livetree.c +++ b/livetree.c @@ -208,6 +208,57 @@ cell_t propval_cell(struct property *prop) return fdt32_to_cpu(*((cell_t *)prop->val.val)); } +struct property *get_property_by_label(struct node *tree, const char *label, + struct node **node) +{ + struct property *prop; + struct node *c; + + *node = tree; + + for_each_property(tree, prop) { + if (prop->label && streq(prop->label, label)) + return prop; + } + + for_each_child(tree, c) { + prop = get_property_by_label(c, label, node); + if (prop) + return prop; + } + + *node = NULL; + return NULL; +} + +struct marker *get_marker_label(struct node *tree, const char *label, + struct node **node, struct property **prop) +{ + struct marker *m; + struct property *p; + struct node *c; + + *node = tree; + + for_each_property(tree, p) { + *prop = p; + m = p->val.markers; + for_each_marker_of_type(m, LABEL) + if (streq(m->ref, label)) + return m; + } + + for_each_child(tree, c) { + m = get_marker_label(c, label, node, prop); + if (m) + return m; + } + + *prop = NULL; + *node = NULL; + return NULL; +} + struct node *get_subnode(struct node *node, const char *nodename) { struct node *child; diff --git a/tests/reuse-label.dts b/tests/reuse-label.dts new file mode 100644 index 0000000..98b5ca9 --- /dev/null +++ b/tests/reuse-label.dts @@ -0,0 +1,15 @@ +/dts-v1/; + +/ { + label: property1 = "foo"; + label: property2 = "bar"; + + test1 = &label; + + label: node1 { + prop = "foo"; + }; + label: node2 { + prop = "bar"; + }; +}; diff --git a/tests/reuse-label1.dts b/tests/reuse-label1.dts new file mode 100644 index 0000000..f229569 --- /dev/null +++ b/tests/reuse-label1.dts @@ -0,0 +1,10 @@ +/dts-v1/; + +/ { + label: node1 { + prop = "foo"; + }; + label: node2 { + prop = "bar"; + }; +}; diff --git a/tests/reuse-label2.dts b/tests/reuse-label2.dts new file mode 100644 index 0000000..01ea6b2 --- /dev/null +++ b/tests/reuse-label2.dts @@ -0,0 +1,6 @@ +/dts-v1/; + +/ { + label: property1 = "foo"; + label: property2 = "bar"; +}; diff --git a/tests/reuse-label3.dts b/tests/reuse-label3.dts new file mode 100644 index 0000000..fa3d2c7 --- /dev/null +++ b/tests/reuse-label3.dts @@ -0,0 +1,9 @@ +/dts-v1/; + +/ { + label: property = "foo"; + + label: node { + property = "foo"; + }; +}; diff --git a/tests/reuse-label4.dts b/tests/reuse-label4.dts new file mode 100644 index 0000000..6805de3 --- /dev/null +++ b/tests/reuse-label4.dts @@ -0,0 +1,5 @@ +/dts-v1/; + +/ { + property = label: "foo" label:; +}; diff --git a/tests/reuse-label5.dts b/tests/reuse-label5.dts new file mode 100644 index 0000000..b7238e6 --- /dev/null +++ b/tests/reuse-label5.dts @@ -0,0 +1,6 @@ +/dts-v1/; + +/ { + prop1 = label: "foo"; + prop2 = "bar" label:; +}; diff --git a/tests/reuse-label6.dts b/tests/reuse-label6.dts new file mode 100644 index 0000000..f5d507c --- /dev/null +++ b/tests/reuse-label6.dts @@ -0,0 +1,6 @@ +/dts-v1/; + +/ { + label: prop1 = "foo"; + prop2 = "bar" label:; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index ca46051..eb46819 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -318,6 +318,13 @@ dtc_tests () { run_sh_test dtc-checkfails.sh node_name_format -- -I dtb -O dtb bad_node_format.dtb run_sh_test dtc-checkfails.sh prop_name_chars -- -I dtb -O dtb bad_prop_char.dtb + run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label1.dts + run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label2.dts + run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label3.dts + run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label4.dts + run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label5.dts + run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label6.dts + # Check for proper behaviour reading from stdin run_dtc_test -I dts -O dtb -o stdin_dtc_tree1.test.dtb - < test_tree1.dts run_wrap_test cmp stdin_dtc_tree1.test.dtb dtc_tree1.test.dtb From 49c2da308534a4bffb67d53b5a7f8e5f05c305b9 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 24 Feb 2010 01:23:37 +1100 Subject: [PATCH 0300/1198] Remove obsolete references_dts0 test The only purpose of the dtc_references_dts0 testcase was to check handling of references in the old dts v0 syntax. Since we no longer support the old syntax, and the references_dts0.dts has been converted to the new format, it's entirely redundant. This patch removes it. Signed-off-by: David Gibson --- tests/references_dts0.dts | 26 -------------------------- tests/run_tests.sh | 3 --- 2 files changed, 29 deletions(-) delete mode 100644 tests/references_dts0.dts diff --git a/tests/references_dts0.dts b/tests/references_dts0.dts deleted file mode 100644 index d34dbb2..0000000 --- a/tests/references_dts0.dts +++ /dev/null @@ -1,26 +0,0 @@ -/dts-v1/; - -/ { - /* Explicit phandles */ - n1: node1 { - linux,phandle = <0x2000>; - ref = <&{/node2}>; /* reference precedes target */ - lref = <&n2>; - }; - n2: node2 { - linux,phandle = <0x1>; - ref = <&{/node1}>; /* reference after target */ - lref = <&n1>; - }; - - /* Implicit phandles */ - n3: node3 { - ref = <&{/node4}>; - lref = <&n4>; - }; - n4: node4 { - }; - n5: node5 { - linux,phandle = <&n5>; - }; -}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index eb46819..a7c58b3 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -212,9 +212,6 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_references.test.dtb references.dts run_test references dtc_references.test.dtb - run_dtc_test -I dts -O dtb -o dtc_references_dts0.test.dtb references_dts0.dts - run_test references dtc_references_dts0.test.dtb - run_dtc_test -I dts -O dtb -o dtc_path-references.test.dtb path-references.dts run_test path-references dtc_path-references.test.dtb From 05898c67c15d73fe50bd87fc939bd9ee6a4275ce Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 24 Feb 2010 18:22:17 +1100 Subject: [PATCH 0301/1198] dtc: Allow multiple labels on nodes and properties At present, both the grammar and our internal data structures mean that there can be only one label on a node or property. This is a fairly arbitrary constraint, given that any number of value labels can appear at the same point, and that in C you can have any number of labels on the same statement. This is pretty much a non-issue now, but it may become important with some of the extensions that Grant and I have in mind. It's not that hard to change, so this patch does so, allowing an arbitrary number of labels on any given node or property. As usual a testcase is added too. Signed-off-by: David Gibson Acked-by: Grant Likely --- checks.c | 11 +++++---- dtc-parser.y | 43 +++++++++++++++++---------------- dtc.h | 22 ++++++++++++----- flattree.c | 57 ++++++++++++++++++++++++-------------------- fstree.c | 8 +++---- livetree.c | 49 ++++++++++++++++++++----------------- tests/multilabel.dts | 38 +++++++++++++++++++++++++++++ tests/run_tests.sh | 3 +++ treesource.c | 15 +++++++----- 9 files changed, 157 insertions(+), 89 deletions(-) create mode 100644 tests/multilabel.dts diff --git a/checks.c b/checks.c index 1f35cb9..a662a00 100644 --- a/checks.c +++ b/checks.c @@ -314,16 +314,19 @@ static void check_duplicate_label(struct check *c, struct node *dt, static void check_duplicate_label_node(struct check *c, struct node *dt, struct node *node) { - if (node->label) - check_duplicate_label(c, dt, node->label, node, NULL, NULL); + struct label *l; + + for_each_label(node->labels, l) + check_duplicate_label(c, dt, l->label, node, NULL, NULL); } static void check_duplicate_label_prop(struct check *c, struct node *dt, struct node *node, struct property *prop) { struct marker *m = prop->val.markers; + struct label *l; - if (prop->label) - check_duplicate_label(c, dt, prop->label, node, prop, NULL); + for_each_label(prop->labels, l) + check_duplicate_label(c, dt, l->label, node, prop, NULL); for_each_marker_of_type(m, LABEL) check_duplicate_label(c, dt, m->ref, node, prop, m); diff --git a/dtc-parser.y b/dtc-parser.y index bd9e097..8fa1e4f 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -78,7 +78,6 @@ static unsigned long long eval_literal(const char *s, int base, int bits); %type nodedef %type subnode %type subnodes -%type label %% @@ -102,9 +101,14 @@ memreserves: ; memreserve: - label DT_MEMRESERVE addr addr ';' + DT_MEMRESERVE addr addr ';' { - $$ = build_reserve_entry($3, $4, $1); + $$ = build_reserve_entry($2, $3); + } + | DT_LABEL memreserve + { + add_label(&$2->labels, $1); + $$ = $2; } ; @@ -118,7 +122,7 @@ addr: devicetree: '/' nodedef { - $$ = name_node($2, "", NULL); + $$ = name_node($2, ""); } ; @@ -141,13 +145,18 @@ proplist: ; propdef: - label DT_PROPNODENAME '=' propdata ';' + DT_PROPNODENAME '=' propdata ';' { - $$ = build_property($2, $4, $1); + $$ = build_property($1, $3); } - | label DT_PROPNODENAME ';' + | DT_PROPNODENAME ';' { - $$ = build_property($2, empty_data, $1); + $$ = build_property($1, empty_data); + } + | DT_LABEL propdef + { + add_label(&$2->labels, $1); + $$ = $2; } ; @@ -264,7 +273,7 @@ subnodes: { $$ = NULL; } - | subnode subnodes + | subnode subnodes { $$ = chain_node($1, $2); } @@ -276,20 +285,14 @@ subnodes: ; subnode: - label DT_PROPNODENAME nodedef + DT_PROPNODENAME nodedef { - $$ = name_node($3, $2, $1); + $$ = name_node($2, $1); } - ; - -label: - /* empty */ + | DT_LABEL subnode { - $$ = NULL; - } - | DT_LABEL - { - $$ = $1; + add_label(&$2->labels, $1); + $$ = $2; } ; diff --git a/dtc.h b/dtc.h index 5367198..6d61b6d 100644 --- a/dtc.h +++ b/dtc.h @@ -125,13 +125,18 @@ int data_is_one_string(struct data d); #define MAX_NODENAME_LEN 31 /* Live trees */ +struct label { + char *label; + struct label *next; +}; + struct property { char *name; struct data val; struct property *next; - char *label; + struct label *labels; }; struct node { @@ -148,21 +153,26 @@ struct node { cell_t phandle; int addr_cells, size_cells; - char *label; + struct label *labels; }; +#define for_each_label(l0, l) \ + for ((l) = (l0); (l); (l) = (l)->next) + #define for_each_property(n, p) \ for ((p) = (n)->proplist; (p); (p) = (p)->next) #define for_each_child(n, c) \ for ((c) = (n)->children; (c); (c) = (c)->next_sibling) -struct property *build_property(char *name, struct data val, char *label); +void add_label(struct label **labels, char *label); + +struct property *build_property(char *name, struct data val); struct property *chain_property(struct property *first, struct property *list); struct property *reverse_properties(struct property *first); struct node *build_node(struct property *proplist, struct node *children); -struct node *name_node(struct node *node, char *name, char *label); +struct node *name_node(struct node *node, char *name); struct node *chain_node(struct node *first, struct node *list); void add_property(struct node *node, struct property *prop); @@ -191,10 +201,10 @@ struct reserve_info { struct reserve_info *next; - char *label; + struct label *labels; }; -struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len, char *label); +struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len); struct reserve_info *chain_reserve_entry(struct reserve_info *first, struct reserve_info *list); struct reserve_info *add_reserve_entry(struct reserve_info *list, diff --git a/flattree.c b/flattree.c index 8637407..ead0332 100644 --- a/flattree.c +++ b/flattree.c @@ -52,9 +52,9 @@ struct emitter { void (*string)(void *, char *, int); void (*align)(void *, int); void (*data)(void *, struct data); - void (*beginnode)(void *, const char *); - void (*endnode)(void *, const char *); - void (*property)(void *, const char *); + void (*beginnode)(void *, struct label *labels); + void (*endnode)(void *, struct label *labels); + void (*property)(void *, struct label *labels); }; static void bin_emit_cell(void *e, cell_t val) @@ -89,17 +89,17 @@ static void bin_emit_data(void *e, struct data d) *dtbuf = data_append_data(*dtbuf, d.val, d.len); } -static void bin_emit_beginnode(void *e, const char *label) +static void bin_emit_beginnode(void *e, struct label *labels) { bin_emit_cell(e, FDT_BEGIN_NODE); } -static void bin_emit_endnode(void *e, const char *label) +static void bin_emit_endnode(void *e, struct label *labels) { bin_emit_cell(e, FDT_END_NODE); } -static void bin_emit_property(void *e, const char *label) +static void bin_emit_property(void *e, struct label *labels) { bin_emit_cell(e, FDT_PROP); } @@ -191,37 +191,40 @@ static void asm_emit_data(void *e, struct data d) assert(off == d.len); } -static void asm_emit_beginnode(void *e, const char *label) +static void asm_emit_beginnode(void *e, struct label *labels) { FILE *f = e; + struct label *l; - if (label) { - fprintf(f, "\t.globl\t%s\n", label); - fprintf(f, "%s:\n", label); + for_each_label(labels, l) { + fprintf(f, "\t.globl\t%s\n", l->label); + fprintf(f, "%s:\n", l->label); } fprintf(f, "\t/* FDT_BEGIN_NODE */\n"); asm_emit_cell(e, FDT_BEGIN_NODE); } -static void asm_emit_endnode(void *e, const char *label) +static void asm_emit_endnode(void *e, struct label *labels) { FILE *f = e; + struct label *l; fprintf(f, "\t/* FDT_END_NODE */\n"); asm_emit_cell(e, FDT_END_NODE); - if (label) { - fprintf(f, "\t.globl\t%s_end\n", label); - fprintf(f, "%s_end:\n", label); + for_each_label(labels, l) { + fprintf(f, "\t.globl\t%s_end\n", l->label); + fprintf(f, "%s_end:\n", l->label); } } -static void asm_emit_property(void *e, const char *label) +static void asm_emit_property(void *e, struct label *labels) { FILE *f = e; + struct label *l; - if (label) { - fprintf(f, "\t.globl\t%s\n", label); - fprintf(f, "%s:\n", label); + for_each_label(labels, l) { + fprintf(f, "\t.globl\t%s\n", l->label); + fprintf(f, "%s:\n", l->label); } fprintf(f, "\t/* FDT_PROP */\n"); asm_emit_cell(e, FDT_PROP); @@ -260,7 +263,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit, struct node *child; int seen_name_prop = 0; - emit->beginnode(etarget, tree->label); + emit->beginnode(etarget, tree->labels); if (vi->flags & FTF_FULLPATH) emit->string(etarget, tree->fullpath, 0); @@ -277,7 +280,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit, nameoff = stringtable_insert(strbuf, prop->name); - emit->property(etarget, prop->label); + emit->property(etarget, prop->labels); emit->cell(etarget, prop->val.len); emit->cell(etarget, nameoff); @@ -304,7 +307,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit, flatten_tree(child, emit, etarget, strbuf, vi); } - emit->endnode(etarget, tree->label); + emit->endnode(etarget, tree->labels); } static struct data flatten_reserve_list(struct reserve_info *reservelist, @@ -525,9 +528,11 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version) * as it appears .quad isn't available in some assemblers. */ for (re = bi->reservelist; re; re = re->next) { - if (re->label) { - fprintf(f, "\t.globl\t%s\n", re->label); - fprintf(f, "%s:\n", re->label); + struct label *l; + + for_each_label(re->labels, l) { + fprintf(f, "\t.globl\t%s\n", l->label); + fprintf(f, "%s:\n", l->label); } ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32)); ASM_EMIT_BELONG(f, "0x%08x", @@ -684,7 +689,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf, val = flat_read_data(dtbuf, proplen); - return build_property(name, val, NULL); + return build_property(name, val); } @@ -709,7 +714,7 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) if (re.size == 0) break; - new = build_reserve_entry(re.address, re.size, NULL); + new = build_reserve_entry(re.address, re.size); reservelist = add_reserve_entry(reservelist, new); } diff --git a/fstree.c b/fstree.c index d43343a..ba0da9d 100644 --- a/fstree.c +++ b/fstree.c @@ -60,8 +60,7 @@ static struct node *read_fstree(const char *dirname) } else { prop = build_property(xstrdup(de->d_name), data_copy_file(pfile, - st.st_size), - NULL); + st.st_size)); add_property(tree, prop); fclose(pfile); } @@ -69,8 +68,7 @@ static struct node *read_fstree(const char *dirname) struct node *newchild; newchild = read_fstree(tmpnam); - newchild = name_node(newchild, xstrdup(de->d_name), - NULL); + newchild = name_node(newchild, xstrdup(de->d_name)); add_child(tree, newchild); } @@ -85,7 +83,7 @@ struct boot_info *dt_from_fs(const char *dirname) struct node *tree; tree = read_fstree(dirname); - tree = name_node(tree, "", NULL); + tree = name_node(tree, ""); return build_boot_info(NULL, tree, guess_boot_cpuid(tree)); } diff --git a/livetree.c b/livetree.c index aa0edf1..f612b72 100644 --- a/livetree.c +++ b/livetree.c @@ -24,17 +24,24 @@ * Tree building functions */ -struct property *build_property(char *name, struct data val, char *label) +void add_label(struct label **labels, char *label) +{ + struct label *new = xmalloc(sizeof(*new)); + + new->label = label; + new->next = *labels; + *labels = new; +} + +struct property *build_property(char *name, struct data val) { struct property *new = xmalloc(sizeof(*new)); + memset(new, 0, sizeof(*new)); + new->name = name; new->val = val; - new->next = NULL; - - new->label = label; - return new; } @@ -78,14 +85,12 @@ struct node *build_node(struct property *proplist, struct node *children) return new; } -struct node *name_node(struct node *node, char *name, char * label) +struct node *name_node(struct node *node, char *name) { assert(node->name == NULL); node->name = name; - node->label = label; - return node; } @@ -124,18 +129,15 @@ void add_child(struct node *parent, struct node *child) *p = child; } -struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size, - char *label) +struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) { struct reserve_info *new = xmalloc(sizeof(*new)); + memset(new, 0, sizeof(*new)); + new->re.address = address; new->re.size = size; - new->next = NULL; - - new->label = label; - return new; } @@ -217,8 +219,11 @@ struct property *get_property_by_label(struct node *tree, const char *label, *node = tree; for_each_property(tree, prop) { - if (prop->label && streq(prop->label, label)) - return prop; + struct label *l; + + for_each_label(prop->labels, l) + if (streq(l->label, label)) + return prop; } for_each_child(tree, c) { @@ -296,11 +301,13 @@ struct node *get_node_by_path(struct node *tree, const char *path) struct node *get_node_by_label(struct node *tree, const char *label) { struct node *child, *node; + struct label *l; assert(label && (strlen(label) > 0)); - if (tree->label && streq(tree->label, label)) - return tree; + for_each_label(tree->labels, l) + if (streq(l->label, label)) + return tree; for_each_child(tree, child) { node = get_node_by_label(child, label); @@ -353,15 +360,13 @@ cell_t get_node_phandle(struct node *root, struct node *node) && (phandle_format & PHANDLE_LEGACY)) add_property(node, build_property("linux,phandle", - data_append_cell(empty_data, phandle), - NULL)); + data_append_cell(empty_data, phandle))); if (!get_property(node, "phandle") && (phandle_format & PHANDLE_EPAPR)) add_property(node, build_property("phandle", - data_append_cell(empty_data, phandle), - NULL)); + data_append_cell(empty_data, phandle))); /* If the node *does* have a phandle property, we must * be dealing with a self-referencing phandle, which will be diff --git a/tests/multilabel.dts b/tests/multilabel.dts new file mode 100644 index 0000000..87c175c --- /dev/null +++ b/tests/multilabel.dts @@ -0,0 +1,38 @@ +/dts-v1/; + +m1: mq: /memreserve/ 0 0x1000; + +/ { + p1: px: prop = "foo"; + + /* Explicit phandles */ + n1: nx: node1 { + linux,phandle = <0x2000>; + ref = <&{/node2}>; /* reference precedes target */ + lref = <&ny>; + }; + ny: n2: node2 { + phandle = <0x1>; + ref = <&{/node1}>; /* reference after target */ + lref = <&nx>; + }; + + /* Implicit phandles */ + n3: node3 { + ref = <&{/node4}>; + lref = <&n4>; + }; + n4: node4 { + }; + + /* Explicit phandle with implicit value */ + /* This self-reference is the standard way to tag a node as requiring + * a phandle (perhaps for reference by nodes that will be dynamically + * added) without explicitly allocating it a phandle. + * The self-reference requires some special internal handling, though + * so check it actually works */ + n5: nz: node5 { + linux,phandle = <&n5>; + phandle = <&nz>; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index a7c58b3..08535ad 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -221,6 +221,9 @@ dtc_tests () { run_test phandle_format dtc_references.test.$f.dtb $f done + run_dtc_test -I dts -O dtb -o multilabel.test.dtb multilabel.dts + run_test references multilabel.test.dtb + run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb comments.dts run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb diff --git a/treesource.c b/treesource.c index 331c22c..c09aafa 100644 --- a/treesource.c +++ b/treesource.c @@ -235,10 +235,11 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) { struct property *prop; struct node *child; + struct label *l; write_prefix(f, level); - if (tree->label) - fprintf(f, "%s: ", tree->label); + for_each_label(tree->labels, l) + fprintf(f, "%s: ", l->label); if (tree->name && (*tree->name)) fprintf(f, "%s {\n", tree->name); else @@ -246,8 +247,8 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) for_each_property(tree, prop) { write_prefix(f, level+1); - if (prop->label) - fprintf(f, "%s: ", prop->label); + for_each_label(prop->labels, l) + fprintf(f, "%s: ", l->label); fprintf(f, "%s", prop->name); write_propval(f, prop); } @@ -267,8 +268,10 @@ void dt_to_source(FILE *f, struct boot_info *bi) fprintf(f, "/dts-v1/;\n\n"); for (re = bi->reservelist; re; re = re->next) { - if (re->label) - fprintf(f, "%s: ", re->label); + struct label *l; + + for_each_label(re->labels, l) + fprintf(f, "%s: ", l->label); fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", (unsigned long long)re->re.address, (unsigned long long)re->re.size); From 716418849a0ed4cc7689d4b82a73597a8726de92 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 24 Feb 2010 22:29:19 +1100 Subject: [PATCH 0302/1198] dtc: Audit and fix valgrind errors The somewhat embarrasing bug in the first version of my previous patch would have been detected by valgrind. Thus reminded, I've run the testsuite under valgrind and fixed any errors I found. This turned out to be just some uninitialized buffers in test programs. The fragments of uninitialized data aren't particularly important, but we might as well squash the valgrind warnings, so that future valgrind errors will stand out. Signed-off-by: David Gibson --- tests/mangle-layout.c | 7 ++++--- tests/open_pack.c | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c index 5be28b9..3b19788 100644 --- a/tests/mangle-layout.c +++ b/tests/mangle-layout.c @@ -65,7 +65,7 @@ static void new_header(struct bufstate *buf, int version, const void *fdt) static void add_block(struct bufstate *buf, int version, char block, const void *fdt) { - int align, size; + int align, size, oldsize; const void *src; int offset; @@ -95,9 +95,10 @@ static void add_block(struct bufstate *buf, int version, char block, const void CONFIG("Bad block '%c'", block); } - offset = ALIGN(buf->size, align); - + oldsize = buf->size; + offset = ALIGN(oldsize, align); expand_buf(buf, offset+size); + memset(buf->buf + oldsize, 0, offset - oldsize); memcpy(buf->buf + offset, src, size); diff --git a/tests/open_pack.c b/tests/open_pack.c index d614024..0a5a3fc 100644 --- a/tests/open_pack.c +++ b/tests/open_pack.c @@ -48,6 +48,8 @@ int main(int argc, char *argv[]) bufsize = oldsize * 2; buf = xmalloc(bufsize); + /* don't leak uninitialized memory into our output */ + memset(buf, 0, bufsize); fdt1 = buf; err = fdt_open_into(fdt, fdt1, bufsize); From 83da1b2a4ee272ac97647a82fc652d9b4b1505ee Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 25 Feb 2010 09:58:29 -0700 Subject: [PATCH 0303/1198] Allow device tree to be modified by additonal device tree sections This patch allows the following construct: / { property-a = "old"; property-b = "does not change"; }; / { property-a = "changed"; property-c = "new"; node-a { }; }; Where the later device tree overrides the properties found in the earlier tree. This is useful for laying down a template device tree in an include file and modifying it for a specific board without having to clone the entire tree. Signed-off-by: Grant Likely --- dtc-parser.y | 14 ++++++- dtc.h | 1 + livetree.c | 75 +++++++++++++++++++++++++++++++++++++- tests/multilabel.dts | 12 ++++-- tests/multilabel_merge.dts | 66 +++++++++++++++++++++++++++++++++ tests/run_tests.sh | 7 ++++ tests/test_tree1_merge.dts | 45 +++++++++++++++++++++++ 7 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 tests/multilabel_merge.dts create mode 100644 tests/test_tree1_merge.dts diff --git a/dtc-parser.y b/dtc-parser.y index 8fa1e4f..dea19c1 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -75,6 +75,7 @@ static unsigned long long eval_literal(const char *s, int base, int bits); %type proplist %type devicetree +%type devicetrees %type nodedef %type subnode %type subnodes @@ -82,7 +83,7 @@ static unsigned long long eval_literal(const char *s, int base, int bits); %% sourcefile: - DT_V1 ';' memreserves devicetree + DT_V1 ';' memreserves devicetrees { the_boot_info = build_boot_info($3, $4, guess_boot_cpuid($4)); @@ -119,6 +120,17 @@ addr: } ; +devicetrees: + devicetree + { + $$ = $1; + } + | devicetrees devicetree + { + $$ = merge_nodes($1, $2); + } + ; + devicetree: '/' nodedef { diff --git a/dtc.h b/dtc.h index 6d61b6d..b36ac5d 100644 --- a/dtc.h +++ b/dtc.h @@ -174,6 +174,7 @@ struct property *reverse_properties(struct property *first); struct node *build_node(struct property *proplist, struct node *children); struct node *name_node(struct node *node, char *name); struct node *chain_node(struct node *first, struct node *list); +struct node *merge_nodes(struct node *old_node, struct node *new_node); void add_property(struct node *node, struct property *prop); void add_child(struct node *parent, struct node *child); diff --git a/livetree.c b/livetree.c index f612b72..13c5f10 100644 --- a/livetree.c +++ b/livetree.c @@ -26,8 +26,14 @@ void add_label(struct label **labels, char *label) { - struct label *new = xmalloc(sizeof(*new)); + struct label *new; + /* Make sure the label isn't already there */ + for_each_label(*labels, new) + if (streq(new->label, label)) + return; + + new = xmalloc(sizeof(*new)); new->label = label; new->next = *labels; *labels = new; @@ -94,6 +100,73 @@ struct node *name_node(struct node *node, char *name) return node; } +struct node *merge_nodes(struct node *old_node, struct node *new_node) +{ + struct property *new_prop, *old_prop; + struct node *new_child, *old_child; + struct label *l; + + /* Add new node labels to old node */ + for_each_label(new_node->labels, l) + add_label(&old_node->labels, l->label); + + /* Move properties from the new node to the old node. If there + * is a collision, replace the old value with the new */ + while (new_node->proplist) { + /* Pop the property off the list */ + new_prop = new_node->proplist; + new_node->proplist = new_prop->next; + new_prop->next = NULL; + + /* Look for a collision, set new value if there is */ + for_each_property(old_node, old_prop) { + if (streq(old_prop->name, new_prop->name)) { + /* Add new labels to old property */ + for_each_label(new_prop->labels, l) + add_label(&old_prop->labels, l->label); + + old_prop->val = new_prop->val; + free(new_prop); + new_prop = NULL; + break; + } + } + + /* if no collision occurred, add property to the old node. */ + if (new_prop) + add_property(old_node, new_prop); + } + + /* Move the override child nodes into the primary node. If + * there is a collision, then merge the nodes. */ + while (new_node->children) { + /* Pop the child node off the list */ + new_child = new_node->children; + new_node->children = new_child->next_sibling; + new_child->parent = NULL; + new_child->next_sibling = NULL; + + /* Search for a collision. Merge if there is */ + for_each_child(old_node, old_child) { + if (streq(old_child->name, new_child->name)) { + merge_nodes(old_child, new_child); + new_child = NULL; + break; + } + } + + /* if no collision occured, add child to the old node. */ + if (new_child) + add_child(old_node, new_child); + } + + /* The new node contents are now merged into the old node. Free + * the new node. */ + free(new_node); + + return old_node; +} + struct node *chain_node(struct node *first, struct node *list) { assert(first->next_sibling == NULL); diff --git a/tests/multilabel.dts b/tests/multilabel.dts index 87c175c..31116ce 100644 --- a/tests/multilabel.dts +++ b/tests/multilabel.dts @@ -3,26 +3,27 @@ m1: mq: /memreserve/ 0 0x1000; / { - p1: px: prop = "foo"; + p0: pw: prop = "foo"; /* Explicit phandles */ n1: nx: node1 { linux,phandle = <0x2000>; ref = <&{/node2}>; /* reference precedes target */ - lref = <&ny>; + p1: px: lref = <&ny>; }; ny: n2: node2 { - phandle = <0x1>; + p2: py: phandle = <0x1>; ref = <&{/node1}>; /* reference after target */ lref = <&nx>; }; /* Implicit phandles */ n3: node3 { - ref = <&{/node4}>; + p3: ref = <&{/node4}>; lref = <&n4>; }; n4: node4 { + p4: prop; }; /* Explicit phandle with implicit value */ @@ -34,5 +35,8 @@ m1: mq: /memreserve/ 0 0x1000; n5: nz: node5 { linux,phandle = <&n5>; phandle = <&nz>; + n1 = &n1; + n2 = &n2; + n3 = &n3; }; }; diff --git a/tests/multilabel_merge.dts b/tests/multilabel_merge.dts new file mode 100644 index 0000000..1632300 --- /dev/null +++ b/tests/multilabel_merge.dts @@ -0,0 +1,66 @@ +/dts-v1/; + +m1: mq: /memreserve/ 0 0x1000; + +/ { + p0: pw: prop = "foo"; + + /* Explicit phandles */ + n1: node1 { + linux,phandle = <0x2000>; + ref = <&{/node2}>; /* reference precedes target */ + p1: lref; + }; + node2 { + phandle = <0x1>; + ref = <&{/node1}>; /* reference after target */ + lref = <&nx>; + }; + + /* Implicit phandles */ + n3: node3 { + p3: ref = <&{/node4}>; + lref = <&n4>; + }; + n4: node4 { + p4: prop = "foo"; + }; + + /* Explicit phandle with implicit value */ + /* This self-reference is the standard way to tag a node as requiring + * a phandle (perhaps for reference by nodes that will be dynamically + * added) without explicitly allocating it a phandle. + * The self-reference requires some special internal handling, though + * so check it actually works */ + n5: nz: node5 { + linux,phandle = <&n5>; + phandle = <&nz>; + n1 = &n1; + n2 = &n2; + n3 = &n3; + }; +}; + +/ { + /* Append labels (also changes property content) */ + nx: node1 { + px: lref = <&ny>; + }; + + /* Add multiple labels */ + ny: n2: node2 { + /* Add a label to a property */ + p2: py: phandle = <0x1>; + }; + + /* Reassigning the same label should be a no-op */ + n3: node3 { + p3: ref = <&{/node4}>; + }; + + /* Redefining a node/property should not remove labels */ + node4 { + prop; + }; + +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 08535ad..43b9d44 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -297,6 +297,13 @@ dtc_tests () { done done + # Check merge/overlay functionality + run_dtc_test -I dts -O dtb -o dtc_tree1_merge.test.dtb test_tree1_merge.dts + tree1_tests dtc_tree1_merge.test.dtb test_tree1.dtb + run_dtc_test -I dts -O dtb -o multilabel_merge.test.dtb multilabel_merge.dts + run_test references multilabel.test.dtb + run_test dtbs_equal_ordered multilabel.test.dtb multilabel_merge.test.dtb + # Check some checks check_tests dup-nodename.dts duplicate_node_names check_tests dup-propname.dts duplicate_property_names diff --git a/tests/test_tree1_merge.dts b/tests/test_tree1_merge.dts new file mode 100644 index 0000000..f580da8 --- /dev/null +++ b/tests/test_tree1_merge.dts @@ -0,0 +1,45 @@ +/dts-v1/; +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; + +/ { + compatible = "test_tree1"; + prop-int = "wrong!"; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + ss2 { + }; + }; +}; + +/ { + prop-int = <0xdeadbeef>; + subnode@1 { + prop-int = [deadbeef]; + }; + subnode@2 { + subsubnode@0 { + phandle = <0x2001>; + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; + }; + }; +}; + + From 9dfb495f80a8d4b63ad281001625ad2a5bb20472 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 24 Feb 2010 12:06:23 -0700 Subject: [PATCH 0304/1198] Update .gitignore files Filter out all the generated bits from git revision control Signed-off-by: Grant Likely --- .gitignore | 7 +++++-- tests/.gitignore | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 tests/.gitignore diff --git a/.gitignore b/.gitignore index 92f9a34..ae7a46a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,8 @@ *~ *.tab.[ch] lex.yy.c -dtc -ftdump +*.lex.c +/dtc +/ftdump +/convert-dtsv0 +/version_gen.h diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..c4e1205 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,47 @@ +*.dtb +*.dtb.test.dts +*.dts.test.s +/add_subnode_with_nops +/asm_tree_dump +/boot-cpuid +/del_node +/del_property +/dtbs_equal_ordered +/dumptrees +/extra-terminating-null +/find_property +/get_alias +/get_mem_rsv +/get_name +/get_path +/get_phandle +/getprop +/incbin +/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 +/parent_offset +/path-references +/path_offset +/path_offset_aliases +/phandle_format +/references +/root_node +/rw_tree1 +/set_name +/setprop +/setprop_inplace +/string_escapes +/subnode_offset +/supernode_atdepth_offset +/sw_tree1 +/truncated_property +/value-labels From 8765874963852b2733777e69686251205238ad3d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 3 Mar 2010 16:38:01 +1100 Subject: [PATCH 0305/1198] dtc: Correct headers in util.c Since util.c is used in programs other than full dtc, it shouldn't include the full dtc.h, just util.h which has prototypes directly relevant to it. This patch makes the change, and also adds includes of the necessary system headers which were previously included indirectly by dtc.h. Signed-off-by: David Gibson --- util.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/util.c b/util.c index c1d3ca4..d7ac27d 100644 --- a/util.c +++ b/util.c @@ -17,7 +17,12 @@ * USA */ -#include "dtc.h" +#include +#include +#include +#include + +#include "util.h" char *xstrdup(const char *s) { From 74f6a51b1f71ffc7d9557e063630469a93eeddec Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 9 Mar 2010 10:49:33 +1100 Subject: [PATCH 0306/1198] dtc: Enable more warnings This patch turns on a bunch of extra gcc warnings, most of which are probably a good idea. Of the new warnings -Wnested-externs and -Wstrict-prototypes need no code changes, we're already warning-clean. The remaining one, -Wmissing-prototypes requires trivial changes in some of the tests (making functions local). This patch also rearranges the warnings flags into a separate make variable for convenience, and turns on -Werror, to really encourage people to keep the code warning-clean. Signed-off-by: David Gibson --- Makefile | 4 +++- tests/extra-terminating-null.c | 2 +- tests/get_alias.c | 2 +- tests/path_offset_aliases.c | 2 +- tests/value-labels.c | 4 ++-- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index d7549b2..b49aebb 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,9 @@ LOCAL_VERSION = CONFIG_LOCALVERSION = CPPFLAGS = -I libfdt -CFLAGS = -Wall -g -Os -fPIC -Wpointer-arith -Wcast-qual +WARNINGS = -Werror -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \ + -Wstrict-prototypes -Wmissing-prototypes +CFLAGS = -g -Os -fPIC -Werror $(WARNINGS) BISON = bison LEX = flex diff --git a/tests/extra-terminating-null.c b/tests/extra-terminating-null.c index bb71b1a..8a2043f 100644 --- a/tests/extra-terminating-null.c +++ b/tests/extra-terminating-null.c @@ -28,7 +28,7 @@ #include "tests.h" #include "testdata.h" -void check_extranull(void *fdt, const char *prop, const char *str, int numnulls) +static void check_extranull(void *fdt, const char *prop, const char *str, int numnulls) { int len = strlen(str); char checkbuf[len+numnulls]; diff --git a/tests/get_alias.c b/tests/get_alias.c index 8eeaee4..1e0faf4 100644 --- a/tests/get_alias.c +++ b/tests/get_alias.c @@ -29,7 +29,7 @@ #include "tests.h" #include "testdata.h" -void check_alias(void *fdt, const char *path, const char *alias) +static void check_alias(void *fdt, const char *path, const char *alias) { const char *aliaspath; diff --git a/tests/path_offset_aliases.c b/tests/path_offset_aliases.c index 191edd2..3682da4 100644 --- a/tests/path_offset_aliases.c +++ b/tests/path_offset_aliases.c @@ -29,7 +29,7 @@ #include "tests.h" #include "testdata.h" -void check_alias(void *fdt, const char *full_path, const char *alias_path) +static void check_alias(void *fdt, const char *full_path, const char *alias_path) { int offset, offset_a; diff --git a/tests/value-labels.c b/tests/value-labels.c index c5aea8f..abe2721 100644 --- a/tests/value-labels.c +++ b/tests/value-labels.c @@ -59,8 +59,8 @@ struct val_label labels3[] = { { "end3", -1 }, }; -void check_prop_labels(void *sohandle, void *fdt, const char *name, - const struct val_label* labels, int n) +static void check_prop_labels(void *sohandle, void *fdt, const char *name, + const struct val_label* labels, int n) { const struct fdt_property *prop; const char *p; From 73dca9ae0b9abe6924ba640164ecce9f8df69c5a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 9 Mar 2010 17:39:14 +1100 Subject: [PATCH 0307/1198] libfdt: Implement property iteration functions For ages, we've been talking about adding functions to libfdt to allow iteration through properties. So, finally, here are some. I got bogged down on this for a long time because I didn't want to expose offsets directly to properties to the callers. But without that, attempting to make reasonable iteration functions just became horrible. So eventually, I settled on an interface which does now expose property offsets. fdt_first_property_offset() and fdt_next_property_offset() are used to step through the offsets of the properties starting from a particularly node offset. The details of the property at each offset can then be retrieved with either fdt_get_property_by_offset() or fdt_getprop_by_offset() which have interfaces similar to fdt_get_property() and fdt_getprop() respectively. No explicit testcases are included, but we do use the new functions to reimplement the existing fdt_get_property() function. Signed-off-by: David Gibson --- libfdt/fdt.c | 9 +++ libfdt/fdt_ro.c | 125 +++++++++++++++++++++++++++------------ libfdt/libfdt.h | 103 ++++++++++++++++++++++++++++++++ libfdt/libfdt_internal.h | 1 + 4 files changed, 201 insertions(+), 37 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index b1130c2..e56833a 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -149,6 +149,15 @@ int _fdt_check_node_offset(const void *fdt, int offset) return 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)) + return -FDT_ERR_BADOFFSET; + + return offset; +} + int fdt_next_node(const void *fdt, int offset, int *depth) { int nextoffset = 0; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 951cc74..02b6d68 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -105,6 +105,30 @@ int fdt_num_mem_rsv(const void *fdt) return i; } +static int _nextprop(const void *fdt, int offset) +{ + uint32_t tag; + int nextoffset; + + do { + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_END: + if (nextoffset >= 0) + return -FDT_ERR_BADSTRUCTURE; + else + return nextoffset; + + case FDT_PROP: + return offset; + } + offset = nextoffset; + } while (tag == FDT_NOP); + + return -FDT_ERR_NOTFOUND; +} + int fdt_subnode_offset_namelen(const void *fdt, int offset, const char *name, int namelen) { @@ -194,52 +218,66 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) return NULL; } +int fdt_first_property_offset(const void *fdt, int nodeoffset) +{ + int offset; + + if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) + return offset; + + return _nextprop(fdt, offset); +} + +int fdt_next_property_offset(const void *fdt, int offset) +{ + if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) + return offset; + + return _nextprop(fdt, offset); +} + +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, + int offset, + int *lenp) +{ + int err; + const struct fdt_property *prop; + + if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { + if (lenp) + *lenp = err; + return NULL; + } + + prop = _fdt_offset_ptr(fdt, offset); + + if (lenp) + *lenp = fdt32_to_cpu(prop->len); + + return prop; +} + const struct fdt_property *fdt_get_property_namelen(const void *fdt, - int nodeoffset, + int offset, const char *name, int namelen, int *lenp) { - uint32_t tag; - const struct fdt_property *prop; - int offset, nextoffset; - int err; + for (offset = fdt_first_property_offset(fdt, offset); + (offset >= 0); + (offset = fdt_next_property_offset(fdt, offset))) { + const struct fdt_property *prop; - if (((err = fdt_check_header(fdt)) != 0) - || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) - goto fail; - - nextoffset = err; - do { - offset = nextoffset; - - tag = fdt_next_tag(fdt, offset, &nextoffset); - switch (tag) { - case FDT_END: - if (nextoffset < 0) - err = nextoffset; - else - /* FDT_END tag with unclosed nodes */ - err = -FDT_ERR_BADSTRUCTURE; - goto fail; - - case FDT_PROP: - prop = _fdt_offset_ptr(fdt, offset); - if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), - name, namelen)) { - /* Found it! */ - if (lenp) - *lenp = fdt32_to_cpu(prop->len); - - return prop; - } + if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { + offset = -FDT_ERR_INTERNAL; break; } - } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE)); + if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), + name, namelen)) + return prop; + } - err = -FDT_ERR_NOTFOUND; - fail: if (lenp) - *lenp = err; + *lenp = offset; return NULL; } @@ -263,6 +301,19 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, return prop->data; } +const void *fdt_getprop_by_offset(const void *fdt, int offset, + const char **namep, int *lenp) +{ + const struct fdt_property *prop; + + prop = fdt_get_property_by_offset(fdt, offset, lenp); + if (!prop) + return NULL; + if (namep) + *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); + return prop->data; +} + const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp) { diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 18de52b..55f3eb3 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -342,6 +342,75 @@ int fdt_path_offset(const void *fdt, const char *path); */ const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); +/** + * fdt_first_property_offset - find the offset of a node's first property + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * + * fdt_first_property_offset() finds the first property of the node at + * the given structure block offset. + * + * returns: + * 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_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_first_property_offset(const void *fdt, int nodeoffset); + +/** + * fdt_next_property_offset - step through a node's properties + * @fdt: pointer to the device tree blob + * @offset: structure block offset of a property + * + * fdt_next_property_offset() finds the property immediately after the + * one at the given structure block offset. This will be a property + * of the same node as the given property. + * + * returns: + * 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_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_next_property_offset(const void *fdt, int offset); + +/** + * fdt_get_property_by_offset - retrieve the property at a given offset + * @fdt: pointer to the device tree blob + * @offset: offset of the property to retrieve + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_property_by_offset() retrieves a pointer to the + * fdt_property structure within the device tree blob at the given + * offset. 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 structure representing the property + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, + int offset, + int *lenp); + /** * fdt_get_property_namelen - find a property based on substring * @fdt: pointer to the device tree blob @@ -395,6 +464,40 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, fdt_get_property(fdt, nodeoffset, name, lenp); } +/** + * fdt_getprop_by_offset - retrieve the value of a property at a given offset + * @fdt: pointer to the device tree blob + * @ffset: offset of the property to read + * @namep: pointer to a string variable (will be overwritten) or NULL + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_getprop_by_offset() retrieves a pointer to the value of the + * property at structure block offset 'offset' (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 namep is non-NULL, + * the property's namne 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). + * + * returns: + * 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 + * name. + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const void *fdt_getprop_by_offset(const void *fdt, int offset, + const char **namep, int *lenp); + /** * fdt_getprop_namelen - get property value based on substring * @fdt: pointer to the device tree blob diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index d2dcbd6..381133b 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -63,6 +63,7 @@ } 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); int _fdt_node_end_offset(void *fdt, int nodeoffset); From 341df2bdc3f9664587a57f947249c3208da77c9b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 30 Apr 2010 15:27:32 +1000 Subject: [PATCH 0308/1198] dtc: Add -Wredundant-decls (resend) We are almost clean already with the -Wredundant-decls warning. The only exception is a declaration for isatty() inside the flex-generated code. This can be removed by using flex's "never-interactive" option, which we probably should be using anyway, since we never parse interactively in the sense that this option implies. Signed-off-by: David Gibson --- Makefile | 2 +- convert-dtsv0-lexer.l | 2 +- dtc-lexer.l | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index b49aebb..af467ef 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ CONFIG_LOCALVERSION = CPPFLAGS = -I libfdt WARNINGS = -Werror -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \ - -Wstrict-prototypes -Wmissing-prototypes + -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls CFLAGS = -g -Os -fPIC -Werror $(WARNINGS) BISON = bison diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index edb9110..89d540a 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -17,7 +17,7 @@ * USA */ -%option noyywrap nounput noinput +%option noyywrap nounput noinput never-interactive %x INCLUDE %x BYTESTRING diff --git a/dtc-lexer.l b/dtc-lexer.l index 3c3434c..f8953f4 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -18,7 +18,7 @@ * USA */ -%option noyywrap nounput noinput +%option noyywrap nounput noinput never-interactive %x INCLUDE %x BYTESTRING From e3b32b75b54834bc4d55db22636b6504eabb788e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 30 Apr 2010 15:30:00 +1000 Subject: [PATCH 0309/1198] dtc: Extend and better test dtbs_equal utility programs (resend) The dtbs_equal_ordered test program is used to implement a number of testcases. However, the test program itself has never been particularly well tested. In addition there are testcases coming in future for which it would be useful to have a corresponding "dtbs_equal_unordered" which checks for equality of device trees, not considering the internal ordering of elements. Finally, for some tests we may want it would be useful to check trees for equality with the PASS case being when they are *not* equal. This patch addresses all of the above. A dtbs_equal_unordered is added, and both it and the existing dtbs_equal_ordered program now take a -n option to make the PASS case be where the trees are not equal. A number of example trees with slight modifications from test_tree1 are used to verify that both these programs correctly identify when the tree is altered, and a dtb_reverse program is used to verify that the unordered version does not depend on internal ordering. These new testcases for the equality testing programs are split out into a new test group in run_tests.sh. dtbs_equal_unordered uses the new property iteration functions, and so this also acts as further testing for those functions. dtbs_equal_unordered will be useful for further testing the recently added tree-merging code and its upcoming extensions. Signed-off-by: David Gibson --- tests/Makefile.tests | 1 + tests/dtb_reverse.c | 164 +++++++++++++++++++++++++ tests/dtbs_equal_ordered.c | 87 +++++++++----- tests/dtbs_equal_unordered.c | 224 +++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 37 +++++- tests/test_tree1_wrong1.dts | 36 ++++++ tests/test_tree1_wrong2.dts | 36 ++++++ tests/test_tree1_wrong3.dts | 36 ++++++ tests/test_tree1_wrong4.dts | 34 ++++++ tests/test_tree1_wrong5.dts | 37 ++++++ tests/test_tree1_wrong6.dts | 38 ++++++ tests/test_tree1_wrong7.dts | 39 ++++++ tests/test_tree1_wrong8.dts | 37 ++++++ tests/test_tree1_wrong9.dts | 38 ++++++ 14 files changed, 812 insertions(+), 32 deletions(-) create mode 100644 tests/dtb_reverse.c create mode 100644 tests/dtbs_equal_unordered.c create mode 100644 tests/test_tree1_wrong1.dts create mode 100644 tests/test_tree1_wrong2.dts create mode 100644 tests/test_tree1_wrong3.dts create mode 100644 tests/test_tree1_wrong4.dts create mode 100644 tests/test_tree1_wrong5.dts create mode 100644 tests/test_tree1_wrong6.dts create mode 100644 tests/test_tree1_wrong7.dts create mode 100644 tests/test_tree1_wrong8.dts create mode 100644 tests/test_tree1_wrong9.dts diff --git a/tests/Makefile.tests b/tests/Makefile.tests index ac21ade..c564e72 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -14,6 +14,7 @@ LIB_TESTS_L = get_mem_rsv \ boot-cpuid incbin \ extra-terminating-null \ dtbs_equal_ordered \ + dtb_reverse dtbs_equal_unordered \ add_subnode_with_nops path_offset_aliases LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) diff --git a/tests/dtb_reverse.c b/tests/dtb_reverse.c new file mode 100644 index 0000000..25e1eef --- /dev/null +++ b/tests/dtb_reverse.c @@ -0,0 +1,164 @@ +/* + * libfdt - Flat Device Tree manipulation + * Tests if two given dtbs are structurally equal (including order) + * Copyright (C) 2010 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +#define CHECK(code) \ + { \ + err = (code); \ + if (err) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } + +static void reverse_reservemap(void *in, void *out, int n) +{ + int err; + uint64_t addr, size; + + verbose_printf("reverse_reservemap(): %d/%d\n", + n, fdt_num_mem_rsv(in)); + + if (n < (fdt_num_mem_rsv(in)-1)) + reverse_reservemap(in, out, n+1); + + CHECK(fdt_get_mem_rsv(in, n, &addr, &size)); + CHECK(fdt_add_reservemap_entry(out, addr, size)); + verbose_printf("Added entry 0x%llx 0x%llx\n", + (unsigned long long)addr, (unsigned long long)size); +} + +static void reverse_properties(void *in, void *out, int offset) +{ + int err; + int len; + const char *name; + const void *data; + + data = fdt_getprop_by_offset(in, offset, &name, &len); + if (!data) + FAIL("fdt_getprop_by_offset(): %s\n", fdt_strerror(len)); + + verbose_printf("reverse_properties(): offset=%d name=%s\n", + offset, name); + + offset = fdt_next_property_offset(in, offset); + if (offset >= 0) + reverse_properties(in, out, offset); + else if (offset != -FDT_ERR_NOTFOUND) + FAIL("fdt_next_property_offset(): %s\n", fdt_strerror(offset)); + + CHECK(fdt_property(out, name, data, len)); + verbose_printf(" -> output property %s\n", name); +} + +static void reverse_node(void *in, void *out, int nodeoffset); + +static void reverse_children(void *in, void *out, int offset) +{ + int err; + int nextoffset = offset; + int depth = 1; + + do { + char path[PATH_MAX]; + + CHECK(fdt_get_path(in, nextoffset, path, sizeof(path))); + verbose_printf("reverse_children() offset=%d nextoffset=%d [%s]" + " depth=%d\n", offset, nextoffset, path, depth); + + nextoffset = fdt_next_node(in, nextoffset, &depth); + } while ((depth >= 0) && (depth != 1)); + + if (depth == 1) + reverse_children(in, out, nextoffset); + + reverse_node(in, out, offset); +} + +static void reverse_node(void *in, void *out, int nodeoffset) +{ + const char *name = fdt_get_name(in, nodeoffset, NULL); + char path[PATH_MAX]; + int err; + int offset; + int depth = 0; + + CHECK(fdt_get_path(in, nodeoffset, path, sizeof(path))); + verbose_printf("reverse_node(): nodeoffset=%d [%s]\n", + nodeoffset, path); + + CHECK(fdt_begin_node(out, name)); + + offset = fdt_first_property_offset(in, nodeoffset); + if (offset >= 0) + reverse_properties(in, out, offset); + else if (offset != -FDT_ERR_NOTFOUND) + FAIL("fdt_first_property(): %s\n", fdt_strerror(offset)); + + offset = fdt_next_node(in, nodeoffset, &depth); + + if (depth == 1) + reverse_children(in, out, offset); + + CHECK(fdt_end_node(out)); +} + +int main(int argc, char *argv[]) +{ + void *in, *out; + char outname[PATH_MAX]; + int bufsize; + int err; + + test_init(argc, argv); + if (argc != 2) + CONFIG("Usage: %s ", argv[0]); + + in = load_blob(argv[1]); + sprintf(outname, "%s.reversed.test.dtb", argv[1]); + + bufsize = fdt_totalsize(in); + out = xmalloc(bufsize); + + CHECK(fdt_create(out, bufsize)); + + fdt_set_boot_cpuid_phys(out, fdt_boot_cpuid_phys(in)); + + reverse_reservemap(in, out, 0); + CHECK(fdt_finish_reservemap(out)); + + reverse_node(in, out, 0); + + CHECK(fdt_finish(out)); + + save_blob(outname, out); + + PASS(); +} diff --git a/tests/dtbs_equal_ordered.c b/tests/dtbs_equal_ordered.c index ed9278c..1db25f4 100644 --- a/tests/dtbs_equal_ordered.c +++ b/tests/dtbs_equal_ordered.c @@ -29,6 +29,31 @@ #include "tests.h" #include "testdata.h" +int notequal; /* = 0 */ + +#define MISMATCH(fmt, ...) \ + do { \ + if (notequal) \ + PASS(); \ + else \ + FAIL(fmt, ##__VA_ARGS__); \ + } while (0) + +#define MATCH() \ + do { \ + if (!notequal) \ + PASS(); \ + else \ + FAIL("Trees match which shouldn't"); \ + } while (0) + +#define CHECK(code) \ + { \ + err = (code); \ + if (err) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } + static void compare_mem_rsv(const void *fdt1, const void *fdt2) { int i; @@ -36,23 +61,18 @@ static void compare_mem_rsv(const void *fdt1, const void *fdt2) int err; if (fdt_num_mem_rsv(fdt1) != fdt_num_mem_rsv(fdt2)) - FAIL("Trees have different number of reserve entries"); + MISMATCH("Trees have different number of reserve entries"); for (i = 0; i < fdt_num_mem_rsv(fdt1); i++) { - err = fdt_get_mem_rsv(fdt1, i, &addr1, &size1); - if (err) - FAIL("fdt_get_mem_rsv(fdt1, %d, ...): %s", i, - fdt_strerror(err)); - err = fdt_get_mem_rsv(fdt2, i, &addr2, &size2); - if (err) - FAIL("fdt_get_mem_rsv(fdt2, %d, ...): %s", i, - fdt_strerror(err)); + CHECK(fdt_get_mem_rsv(fdt1, i, &addr1, &size1)); + CHECK(fdt_get_mem_rsv(fdt2, i, &addr2, &size2)); + if ((addr1 != addr2) || (size1 != size2)) - FAIL("Mismatch in reserve entry %d: " - "(0x%llx, 0x%llx) != (0x%llx, 0x%llx)", i, - (unsigned long long)addr1, - (unsigned long long)size1, - (unsigned long long)addr2, - (unsigned long long)size2); + MISMATCH("Mismatch in reserve entry %d: " + "(0x%llx, 0x%llx) != (0x%llx, 0x%llx)", i, + (unsigned long long)addr1, + (unsigned long long)size1, + (unsigned long long)addr2, + (unsigned long long)size2); } } @@ -77,7 +97,7 @@ static void compare_structure(const void *fdt1, const void *fdt2) } while (tag2 == FDT_NOP); if (tag1 != tag2) - FAIL("Tag mismatch (%d != %d) at (%d, %d)", + MISMATCH("Tag mismatch (%d != %d) at (%d, %d)", tag1, tag2, offset1, offset2); switch (tag1) { @@ -90,9 +110,10 @@ static void compare_structure(const void *fdt1, const void *fdt2) if (!name2) FAIL("fdt_get_name(fdt2, %d, ..): %s", offset2, fdt_strerror(err)); + if (!streq(name1, name2)) - FAIL("Name mismatch (\"%s\" != \"%s\") at (%d, %d)", - name1, name2, offset1, offset2); + MISMATCH("Name mismatch (\"%s\" != \"%s\") at (%d, %d)", + name1, name2, offset1, offset2); break; case FDT_PROP: @@ -106,17 +127,17 @@ static void compare_structure(const void *fdt1, const void *fdt2) name1 = fdt_string(fdt1, fdt32_to_cpu(prop1->nameoff)); name2 = fdt_string(fdt2, fdt32_to_cpu(prop2->nameoff)); if (!streq(name1, name2)) - FAIL("Property name mismatch \"%s\" != \"%s\" " - "at (%d, %d)", name1, name2, offset1, offset2); + MISMATCH("Property name mismatch \"%s\" != \"%s\" " + "at (%d, %d)", name1, name2, offset1, offset2); len1 = fdt32_to_cpu(prop1->len); len2 = fdt32_to_cpu(prop2->len); if (len1 != len2) - FAIL("Property length mismatch %u != %u " - "at (%d, %d)", len1, len2, offset1, offset2); + MISMATCH("Property length mismatch %u != %u " + "at (%d, %d)", len1, len2, offset1, offset2); if (memcmp(prop1->data, prop2->data, len1) != 0) - FAIL("Property value mismatch at (%d, %d)", - offset1, offset2); + MISMATCH("Property value mismatch at (%d, %d)", + offset1, offset2); break; case FDT_END: @@ -131,10 +152,14 @@ int main(int argc, char *argv[]) uint32_t cpuid1, cpuid2; test_init(argc, argv); - if (argc != 3) - CONFIG("Usage: %s ", argv[0]); - fdt1 = load_blob(argv[1]); - fdt2 = load_blob(argv[2]); + if ((argc != 3) + && ((argc != 4) || !streq(argv[1], "-n"))) + CONFIG("Usage: %s [-n] ", argv[0]); + if (argc == 4) + notequal = 1; + + fdt1 = load_blob(argv[argc-2]); + fdt2 = load_blob(argv[argc-1]); compare_mem_rsv(fdt1, fdt2); compare_structure(fdt1, fdt2); @@ -142,8 +167,8 @@ int main(int argc, char *argv[]) cpuid1 = fdt_boot_cpuid_phys(fdt1); cpuid2 = fdt_boot_cpuid_phys(fdt2); if (cpuid1 != cpuid2) - FAIL("boot_cpuid_phys mismatch 0x%x != 0x%x", - cpuid1, cpuid2); + MISMATCH("boot_cpuid_phys mismatch 0x%x != 0x%x", + cpuid1, cpuid2); - PASS(); + MATCH(); } diff --git a/tests/dtbs_equal_unordered.c b/tests/dtbs_equal_unordered.c new file mode 100644 index 0000000..df53318 --- /dev/null +++ b/tests/dtbs_equal_unordered.c @@ -0,0 +1,224 @@ +/* + * libfdt - Flat Device Tree manipulation + * Tests if two given dtbs are structurally equal (including order) + * Copyright (C) 2007 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int notequal; /* = 0 */ + +#define MISMATCH(fmt, ...) \ + do { \ + if (notequal) \ + PASS(); \ + else \ + FAIL(fmt, ##__VA_ARGS__); \ + } while (0) + +#define MATCH() \ + do { \ + if (!notequal) \ + PASS(); \ + else \ + FAIL("Trees match which shouldn't"); \ + } while (0) + +#define CHECK(code) \ + { \ + err = (code); \ + if (err) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } + +static int mem_rsv_cmp(const void *p1, const void *p2) +{ + const struct fdt_reserve_entry *re1 = p1; + const struct fdt_reserve_entry *re2 = p2; + + if (re1->address < re2->address) + return -1; + else if (re1->address > re2->address) + return 1; + + if (re1->size < re2->size) + return -1; + else if (re1->size > re2->size) + return 1; + + return 0; +} + +static void compare_mem_rsv(void *fdt1, void *fdt2) +{ + int i; + uint64_t addr1, size1, addr2, size2; + int err; + + if (fdt_num_mem_rsv(fdt1) != fdt_num_mem_rsv(fdt2)) + MISMATCH("Trees have different number of reserve entries"); + + qsort((char *)fdt1 + fdt_off_mem_rsvmap(fdt1), fdt_num_mem_rsv(fdt1), + sizeof(struct fdt_reserve_entry), mem_rsv_cmp); + qsort((char *)fdt2 + fdt_off_mem_rsvmap(fdt2), fdt_num_mem_rsv(fdt2), + sizeof(struct fdt_reserve_entry), mem_rsv_cmp); + + for (i = 0; i < fdt_num_mem_rsv(fdt1); i++) { + CHECK(fdt_get_mem_rsv(fdt1, i, &addr1, &size1)); + CHECK(fdt_get_mem_rsv(fdt2, i, &addr2, &size2)); + + if ((addr1 != addr2) || (size1 != size2)) + MISMATCH("Mismatch in reserve entry %d: " + "(0x%llx, 0x%llx) != (0x%llx, 0x%llx)", i, + (unsigned long long)addr1, + (unsigned long long)size1, + (unsigned long long)addr2, + (unsigned long long)size2); + } +} + +static void compare_properties(const void *fdt1, int offset1, + const void *fdt2, int offset2) +{ + int offset = offset1; + + /* Check the properties */ + for (offset = fdt_first_property_offset(fdt1, offset1); + offset >= 0; + offset = fdt_next_property_offset(fdt1, offset)) { + const char *name; + int len1, len2; + const void *data1, *data2; + int i; + + data1 = fdt_getprop_by_offset(fdt1, offset, &name, &len1); + if (!data1) + FAIL("fdt_getprop_by_offset(): %s\n", + fdt_strerror(len1)); + + verbose_printf("Property '%s'\n", name); + + data2 = fdt_getprop(fdt2, offset2, name, &len2); + if (!data2) { + if (len2 == -FDT_ERR_NOTFOUND) + MISMATCH("Property '%s' missing\n", name); + else + FAIL("fdt_get_property(): %s\n", + fdt_strerror(len2)); + } + + verbose_printf("len1=%d data1=", len1); + for (i = 0; i < len1; i++) + verbose_printf(" %02x", ((const char *)data1)[i]); + verbose_printf("\nlen2=%d data2=", len2); + for (i = 0; i < len1; i++) + verbose_printf(" %02x", ((const char *)data2)[i]); + verbose_printf("\n"); + + if (len1 != len2) + MISMATCH("Property '%s' mismatched length %d vs. %d\n", + name, len1, len2); + else if (memcmp(data1, data2, len1) != 0) + MISMATCH("Property '%s' mismatched value\n", name); + } +} + +static void compare_node(const void *fdt1, int offset1, + const void *fdt2, int offset2); + +static void compare_subnodes(const void *fdt1, int offset1, + const void *fdt2, int offset2, + int recurse) +{ + int coffset1, coffset2, depth; + + for (depth = 0, coffset1 = offset1; + (coffset1 >= 0) && (depth >= 0); + coffset1 = fdt_next_node(fdt1, coffset1, &depth)) + if (depth == 1) { + const char *name = fdt_get_name(fdt1, coffset1, NULL); + + verbose_printf("Subnode %s\n", name); + coffset2 = fdt_subnode_offset(fdt2, offset2, name); + if (coffset2 == -FDT_ERR_NOTFOUND) + MISMATCH("Subnode %s missing\n", name); + else if (coffset2 < 0) + FAIL("fdt_subnode_offset(): %s\n", + fdt_strerror(coffset2)); + + if (recurse) + compare_node(fdt1, coffset1, fdt2, coffset2); + } +} + +static void compare_node(const void *fdt1, int offset1, + const void *fdt2, int offset2) +{ + int err; + char path1[PATH_MAX], path2[PATH_MAX]; + + CHECK(fdt_get_path(fdt1, offset1, path1, sizeof(path1))); + CHECK(fdt_get_path(fdt2, offset2, path2, sizeof(path2))); + + if (!streq(path1, path2)) + TEST_BUG("Path mismatch %s vs. %s\n", path1, path2); + + verbose_printf("Checking %s\n", path1); + + compare_properties(fdt1, offset1, fdt2, offset2); + compare_properties(fdt2, offset2, fdt1, offset1); + + compare_subnodes(fdt1, offset1, fdt2, offset2, 1); + compare_subnodes(fdt2, offset2, fdt1, offset1, 0); +} + +int main(int argc, char *argv[]) +{ + void *fdt1, *fdt2; + uint32_t cpuid1, cpuid2; + + test_init(argc, argv); + if ((argc != 3) + && ((argc != 4) || !streq(argv[1], "-n"))) + CONFIG("Usage: %s [-n] ", argv[0]); + if (argc == 4) + notequal = 1; + + fdt1 = load_blob(argv[argc-2]); + fdt2 = load_blob(argv[argc-1]); + + compare_mem_rsv(fdt1, fdt2); + compare_node(fdt1, 0, fdt2, 0); + + cpuid1 = fdt_boot_cpuid_phys(fdt1); + cpuid2 = fdt_boot_cpuid_phys(fdt2); + if (cpuid1 != cpuid2) + MISMATCH("boot_cpuid_phys mismatch 0x%x != 0x%x", + cpuid1, cpuid2); + + MATCH(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 43b9d44..4cec62c 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -344,6 +344,38 @@ dtc_tests () { run_sh_test dtc-fatal.sh -I fs -O dtb nosuchfile } +cmp_tests () { + basetree="$1" + shift + wrongtrees="$@" + + run_test dtb_reverse $basetree + + # First dtbs_equal_ordered + run_test dtbs_equal_ordered $basetree $basetree + run_test dtbs_equal_ordered -n $basetree $basetree.reversed.test.dtb + for tree in $wrongtrees; do + run_test dtbs_equal_ordered -n $basetree $tree + done + + # now unordered + run_test dtbs_equal_unordered $basetree $basetree + run_test dtbs_equal_unordered $basetree $basetree.reversed.test.dtb + run_test dtbs_equal_unordered $basetree.reversed.test.dtb $basetree + for tree in $wrongtrees; do + run_test dtbs_equal_unordered -n $basetree $tree + done +} + +dtbs_equal_tests () { + WRONG_TREE1="" + for x in 1 2 3 4 5 6 7 8 9; do + run_dtc_test -I dts -O dtb -o test_tree1_wrong$x.test.dtb test_tree1_wrong$x.dts + WRONG_TREE1="$WRONG_TREE1 test_tree1_wrong$x.test.dtb" + done + cmp_tests test_tree1.dtb $WRONG_TREE1 +} + while getopts "vt:m" ARG ; do case $ARG in "v") @@ -359,7 +391,7 @@ while getopts "vt:m" ARG ; do done if [ -z "$TESTSETS" ]; then - TESTSETS="libfdt dtc" + TESTSETS="libfdt dtc dtbs_equal" fi # Make sure we don't have stale blobs lying around @@ -373,6 +405,9 @@ for set in $TESTSETS; do "dtc") dtc_tests ;; + "dtbs_equal") + dtbs_equal_tests + ;; esac done diff --git a/tests/test_tree1_wrong1.dts b/tests/test_tree1_wrong1.dts new file mode 100644 index 0000000..d71820a --- /dev/null +++ b/tests/test_tree1_wrong1.dts @@ -0,0 +1,36 @@ +/dts-v1/; + +/memreserve/ 123456789 010000; + +/ { + compatible = "test_tree1"; + prop-int = <0xdeadbeef>; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + subsubnode@0 { + phandle = <0x2001>; + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; + }; + + ss2 { + }; + }; +}; diff --git a/tests/test_tree1_wrong2.dts b/tests/test_tree1_wrong2.dts new file mode 100644 index 0000000..ac27023 --- /dev/null +++ b/tests/test_tree1_wrong2.dts @@ -0,0 +1,36 @@ +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; + +/ { + compatible = "test_tree1"; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + subsubnode@0 { + phandle = <0x2001>; + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; + }; + + ss2 { + }; + }; +}; diff --git a/tests/test_tree1_wrong3.dts b/tests/test_tree1_wrong3.dts new file mode 100644 index 0000000..80be2fa --- /dev/null +++ b/tests/test_tree1_wrong3.dts @@ -0,0 +1,36 @@ +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; + +/ { + compatible = "test_tree1"; + prop-int = <0xdeadbeef>; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + subsubnode@0 { + phandle = <0x2001>; + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; + }; + + ss2 { + }; + }; +}; diff --git a/tests/test_tree1_wrong4.dts b/tests/test_tree1_wrong4.dts new file mode 100644 index 0000000..09bb13b --- /dev/null +++ b/tests/test_tree1_wrong4.dts @@ -0,0 +1,34 @@ +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; + +/ { + compatible = "test_tree1"; + prop-int = <0xdeadbeef>; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + subsubnode@0 { + phandle = <0x2001>; + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; + }; + }; +}; diff --git a/tests/test_tree1_wrong5.dts b/tests/test_tree1_wrong5.dts new file mode 100644 index 0000000..ef4c4f7 --- /dev/null +++ b/tests/test_tree1_wrong5.dts @@ -0,0 +1,37 @@ +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; + +/ { + compatible = "test_tree1"; + prop-int = <0xdeadbefe>; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + subsubnode@0 { + phandle = <0x2001>; + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; + }; + + ss2 { + }; + }; +}; diff --git a/tests/test_tree1_wrong6.dts b/tests/test_tree1_wrong6.dts new file mode 100644 index 0000000..98d6eda --- /dev/null +++ b/tests/test_tree1_wrong6.dts @@ -0,0 +1,38 @@ +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; + +/ { + compatible = "test_tree1"; + prop-int = <0xdeadbeef>; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + extra-prop; + }; + }; + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + subsubnode@0 { + phandle = <0x2001>; + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; + }; + + ss2 { + }; + }; +}; diff --git a/tests/test_tree1_wrong7.dts b/tests/test_tree1_wrong7.dts new file mode 100644 index 0000000..f57ace0 --- /dev/null +++ b/tests/test_tree1_wrong7.dts @@ -0,0 +1,39 @@ +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; + +/ { + compatible = "test_tree1"; + prop-int = <0xdeadbeef>; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + subsubnode@0 { + phandle = <0x2001>; + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; + }; + + ss2 { + extranode { + }; + }; + }; +}; diff --git a/tests/test_tree1_wrong8.dts b/tests/test_tree1_wrong8.dts new file mode 100644 index 0000000..811ce6c --- /dev/null +++ b/tests/test_tree1_wrong8.dts @@ -0,0 +1,37 @@ +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010001; + +/ { + compatible = "test_tree1"; + prop-int = <0xdeadbeef>; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + subsubnode@0 { + phandle = <0x2001>; + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; + }; + + ss2 { + }; + }; +}; diff --git a/tests/test_tree1_wrong9.dts b/tests/test_tree1_wrong9.dts new file mode 100644 index 0000000..6ff6fab --- /dev/null +++ b/tests/test_tree1_wrong9.dts @@ -0,0 +1,38 @@ +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; +/memreserve/ 0 1; + +/ { + compatible = "test_tree1"; + prop-int = <0xdeadbeef>; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + subsubnode@0 { + phandle = <0x2001>; + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; + }; + + ss2 { + }; + }; +}; From 0e89e8c5a02eab5655f21e732c8f2ff145712ba8 Mon Sep 17 00:00:00 2001 From: Martin Ettl Date: Wed, 14 Jul 2010 16:10:56 +1000 Subject: [PATCH 0310/1198] Fix a filehandle leak During a check of the current git head of the linux kernel with the static code analysis tool cppcheck (http://sourceforge.net/apps/mediawiki/cppcheck/index.php?title=Main_Page) the tool discovered a resource leak in linux-2.6/scripts/dtc/fstree.c. Please refer the attached patch, that fixes the issue. Fixes https://bugzilla.kernel.org/show_bug.cgi?id=15363 Signed-off-by: Martin Ettl Signed-off-by: Michal Marek Signed-off-by: David Gibson --- fstree.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fstree.c b/fstree.c index ba0da9d..f377453 100644 --- a/fstree.c +++ b/fstree.c @@ -75,6 +75,7 @@ static struct node *read_fstree(const char *dirname) free(tmpnam); } + closedir(d); return tree; } From 390635762d97502bda9c295fcb61b45d04d3d8d2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 30 Aug 2010 12:53:03 +1000 Subject: [PATCH 0311/1198] Remove another bashism from run_tests.sh Current we check for various error codes with [ $x == "NN" ]. However '==' is not actually a correct operator for the [ (test) command. It should be either '=' for string comparison or '-eq' for integer comparison. It appears that the bash builtin version of test implements '==' though, so we were getting away with it, as long as /bin/sh was bash - or the testsuite generated no errors. This patch fixes the usage of test so that it should work on non-bash shells. Signed-off-by: David Gibson --- tests/run_tests.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 4cec62c..c2c39b6 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -24,11 +24,11 @@ base_run_test() { tot_pass=$((tot_pass + 1)) else ret="$?" - if [ "$ret" == "1" ]; then + if [ "$ret" -eq 1 ]; then tot_config=$((tot_config + 1)) - elif [ "$ret" == "2" ]; then + elif [ "$ret" -eq 2 ]; then tot_fail=$((tot_fail + 1)) - elif [ "$ret" == "$VGCODE" ]; then + elif [ "$ret" -eq $VGCODE ]; then tot_vg=$((tot_vg + 1)) else tot_strange=$((tot_strange + 1)) From 8773e12fa9f5109172a779aa2a83b4464e5273cc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 20 Sep 2010 16:33:34 -0600 Subject: [PATCH 0312/1198] Add merging of labelled subnodes. This patch allows the following syntax: / { child { label: subchild { }; }; }; &label { prop = "value"; }; which will result in the following tree: / { child { label: subchild { prop = "value"; }; }; }; Signed-off-by: David Gibson Signed-off-by: Grant Likely --- dtc-lexer.l | 2 +- dtc-parser.y | 30 ++++++++++++--------- tests/nonexist-node-ref2.dts | 10 +++++++ tests/run_tests.sh | 3 +++ tests/test_tree1.dts | 2 +- tests/test_tree1_merge.dts | 4 +-- tests/test_tree1_merge_labelled.dts | 41 +++++++++++++++++++++++++++++ 7 files changed, 74 insertions(+), 18 deletions(-) create mode 100644 tests/nonexist-node-ref2.dts create mode 100644 tests/test_tree1_merge_labelled.dts diff --git a/dtc-lexer.l b/dtc-lexer.l index f8953f4..081e13a 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -109,7 +109,7 @@ static int pop_input_file(void); return DT_LITERAL; } -\&{LABEL} { /* label reference */ +<*>\&{LABEL} { /* label reference */ DPRINT("Ref: %s\n", yytext+1); yylval.labelref = xstrdup(yytext+1); return DT_REF; diff --git a/dtc-parser.y b/dtc-parser.y index dea19c1..0aaf8e8 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -75,7 +75,6 @@ static unsigned long long eval_literal(const char *s, int base, int bits); %type proplist %type devicetree -%type devicetrees %type nodedef %type subnode %type subnodes @@ -83,7 +82,7 @@ static unsigned long long eval_literal(const char *s, int base, int bits); %% sourcefile: - DT_V1 ';' memreserves devicetrees + DT_V1 ';' memreserves devicetree { the_boot_info = build_boot_info($3, $4, guess_boot_cpuid($4)); @@ -120,22 +119,27 @@ addr: } ; -devicetrees: - devicetree - { - $$ = $1; - } - | devicetrees devicetree - { - $$ = merge_nodes($1, $2); - } - ; - devicetree: '/' nodedef { $$ = name_node($2, ""); } + | devicetree '/' nodedef + { + $$ = merge_nodes($1, $3); + } + | devicetree DT_REF nodedef + { + struct node *target; + + target = get_node_by_label($1, $2); + if (target) + merge_nodes(target, $3); + else + yyerror("label does not exist in " + " node redefinition"); + $$ = $1; + } ; nodedef: diff --git a/tests/nonexist-node-ref2.dts b/tests/nonexist-node-ref2.dts new file mode 100644 index 0000000..44b4ebe --- /dev/null +++ b/tests/nonexist-node-ref2.dts @@ -0,0 +1,10 @@ +/dts-v1/; + +/ { + label: node { + }; +}; + +/* Try to redefine a node using a non-existent label */ +&nosuchnode { +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c2c39b6..77ce80d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -300,6 +300,8 @@ dtc_tests () { # Check merge/overlay functionality run_dtc_test -I dts -O dtb -o dtc_tree1_merge.test.dtb test_tree1_merge.dts tree1_tests dtc_tree1_merge.test.dtb test_tree1.dtb + run_dtc_test -I dts -O dtb -o dtc_tree1_merge_labelled.test.dtb test_tree1_merge_labelled.dts + tree1_tests dtc_tree1_merge_labelled.test.dtb test_tree1.dtb run_dtc_test -I dts -O dtb -o multilabel_merge.test.dtb multilabel_merge.dts run_test references multilabel.test.dtb run_test dtbs_equal_ordered multilabel.test.dtb multilabel_merge.test.dtb @@ -312,6 +314,7 @@ dtc_tests () { check_tests minusone-phandle.dts explicit_phandles run_sh_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-node-ref.dts run_sh_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-label-ref.dts + run_sh_test dtc-fatal.sh -I dts -O dtb nonexist-node-ref2.dts check_tests bad-name-property.dts name_properties check_tests bad-ncells.dts address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts index 218c382..4f0ce45 100644 --- a/tests/test_tree1.dts +++ b/tests/test_tree1.dts @@ -25,7 +25,7 @@ linux,phandle = <0x2000>; prop-int = <123456789>; - subsubnode@0 { + ssn0: subsubnode@0 { phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; diff --git a/tests/test_tree1_merge.dts b/tests/test_tree1_merge.dts index f580da8..fc191fd 100644 --- a/tests/test_tree1_merge.dts +++ b/tests/test_tree1_merge.dts @@ -34,12 +34,10 @@ prop-int = [deadbeef]; }; subnode@2 { - subsubnode@0 { + ssn0: subsubnode@0 { phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; }; }; }; - - diff --git a/tests/test_tree1_merge_labelled.dts b/tests/test_tree1_merge_labelled.dts new file mode 100644 index 0000000..46a6840 --- /dev/null +++ b/tests/test_tree1_merge_labelled.dts @@ -0,0 +1,41 @@ +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; + +/ { + compatible = "test_tree1"; + prop-int = <0xdeadbeef>; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + ssn0: subsubnode@0 { + phandle = <0x2001>; + prop-int = <0xbad>; + }; + + ss2 { + }; + }; +}; + +&ssn0 { + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; +}; From c0fa2e6d4e59e62f2e9f23db1a2d94532fa4ae98 Mon Sep 17 00:00:00 2001 From: John Bonesio Date: Wed, 20 Oct 2010 14:44:58 -0700 Subject: [PATCH 0313/1198] Create new and use new print_error that uses printf style formatting. yyerror is meant to be called by the parser internal code, and it's interface is limited. Instead create and call a new error message routine that allows formatted strings to be used. yyerror uses the new routine so error formatting remains consistent. Signed-of-by: John Bonesio Acked-by: David Gibson Signed-off-by: Grant Likely --- dtc-parser.y | 28 ++++++++++++++++++---------- srcpos.c | 21 +++++++++++++-------- srcpos.h | 2 ++ 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 0aaf8e8..b58ba8e 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -27,6 +27,7 @@ YYLTYPE yylloc; extern int yylex(void); +extern void print_error(char const *fmt, ...); extern void yyerror(char const *s); extern struct boot_info *the_boot_info; @@ -136,8 +137,7 @@ devicetree: if (target) merge_nodes(target, $3); else - yyerror("label does not exist in " - " node redefinition"); + print_error("label, '%s' not found", $2); $$ = $1; } ; @@ -200,8 +200,7 @@ propdata: if ($6 != 0) if (fseek(f, $6, SEEK_SET) != 0) - srcpos_error(&yylloc, - "Couldn't seek to offset %llu in \"%s\": %s", + print_error("Couldn't seek to offset %llu in \"%s\": %s", (unsigned long long)$6, $4.val, strerror(errno)); @@ -295,7 +294,7 @@ subnodes: } | subnode propdef { - yyerror("syntax error: properties must precede subnodes"); + print_error("syntax error: properties must precede subnodes"); YYERROR; } ; @@ -314,12 +313,21 @@ subnode: %% -void yyerror(char const *s) +void print_error(char const *fmt, ...) { - srcpos_error(&yylloc, "%s", s); + va_list va; + + va_start(va, fmt); + srcpos_verror(&yylloc, fmt, va); + va_end(va); + treesource_error = 1; } +void yyerror(char const *s) { + print_error("%s", s); +} + static unsigned long long eval_literal(const char *s, int base, int bits) { unsigned long long val; @@ -328,11 +336,11 @@ static unsigned long long eval_literal(const char *s, int base, int bits) errno = 0; val = strtoull(s, &e, base); if (*e) - yyerror("bad characters in literal"); + print_error("bad characters in literal"); else if ((errno == ERANGE) || ((bits < 64) && (val >= (1ULL << bits)))) - yyerror("literal out of range"); + print_error("literal out of range"); else if (errno != 0) - yyerror("bad literal"); + print_error("bad literal"); return val; } diff --git a/srcpos.c b/srcpos.c index 87d7f17..2dbc874 100644 --- a/srcpos.c +++ b/srcpos.c @@ -208,20 +208,25 @@ srcpos_string(struct srcpos *pos) return pos_str; } +void +srcpos_verror(struct srcpos *pos, char const *fmt, va_list va) +{ + const char *srcstr; + + srcstr = srcpos_string(pos); + + fprintf(stdout, "Error: %s ", srcstr); + vfprintf(stdout, fmt, va); + fprintf(stdout, "\n"); +} void srcpos_error(struct srcpos *pos, char const *fmt, ...) { - const char *srcstr; va_list va; + va_start(va, fmt); - - srcstr = srcpos_string(pos); - - fprintf(stderr, "Error: %s ", srcstr); - vfprintf(stderr, fmt, va); - fprintf(stderr, "\n"); - + srcpos_verror(pos, fmt, va); va_end(va); } diff --git a/srcpos.h b/srcpos.h index 985f847..bd7966e 100644 --- a/srcpos.h +++ b/srcpos.h @@ -76,6 +76,8 @@ extern struct srcpos *srcpos_copy(struct srcpos *pos); extern char *srcpos_string(struct srcpos *pos); extern void srcpos_dump(struct srcpos *pos); +extern void srcpos_verror(struct srcpos *pos, char const *, va_list va) + __attribute__((format(printf, 2, 0))); extern void srcpos_error(struct srcpos *pos, char const *, ...) __attribute__((format(printf, 2, 3))); extern void srcpos_warn(struct srcpos *pos, char const *, ...) From 73ae43ea44a40c2ac00dd94523f270177a1e72e9 Mon Sep 17 00:00:00 2001 From: John Bonesio Date: Tue, 2 Nov 2010 15:55:04 -0700 Subject: [PATCH 0314/1198] Allow nodes to be referenced by path at the top level. When nodes are modified by merging device trees, nodes to be updated/merged can be specified by a label. Specifying nodes by full path (instead of label) doesn't quite work. This patch fixes that. Signed-off-by: John Bonesio Acked-by: David Gibson --- dtc-lexer.l | 2 +- dtc-parser.y | 5 ++-- tests/run_tests.sh | 2 ++ tests/test_tree1_merge_path.dts | 41 +++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 tests/test_tree1_merge_path.dts diff --git a/dtc-lexer.l b/dtc-lexer.l index 081e13a..e866ea5 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -115,7 +115,7 @@ static int pop_input_file(void); return DT_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 b58ba8e..5e84a67 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -131,13 +131,12 @@ devicetree: } | devicetree DT_REF nodedef { - struct node *target; + struct node *target = get_node_by_ref($1, $2); - target = get_node_by_label($1, $2); if (target) merge_nodes(target, $3); else - print_error("label, '%s' not found", $2); + print_error("label or path, '%s', not found", $2); $$ = $1; } ; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 77ce80d..a887254 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -305,6 +305,8 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o multilabel_merge.test.dtb multilabel_merge.dts run_test references multilabel.test.dtb run_test dtbs_equal_ordered multilabel.test.dtb multilabel_merge.test.dtb + run_dtc_test -I dts -O dtb -o dtc_tree1_merge_path.test.dtb test_tree1_merge_path.dts + tree1_tests dtc_tree1_merge_path.test.dtb test_tree1.dtb # Check some checks check_tests dup-nodename.dts duplicate_node_names diff --git a/tests/test_tree1_merge_path.dts b/tests/test_tree1_merge_path.dts new file mode 100644 index 0000000..d68713b --- /dev/null +++ b/tests/test_tree1_merge_path.dts @@ -0,0 +1,41 @@ +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; + +/ { + compatible = "test_tree1"; + prop-int = <0xdeadbeef>; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + ssn0: subsubnode@0 { + phandle = <0x2001>; + prop-int = <0xbad>; + }; + + ss2 { + }; + }; +}; + +&{/subnode@2/subsubnode@0} { + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; +}; From 37c0b6a0916c31a5eae0a9ddfcc5d0b8fb4569c6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 10 Nov 2010 09:51:09 +1100 Subject: [PATCH 0315/1198] dtc: Add code to make diffing trees easier This patch adds a "dtdiff" script to do a useful form diff of two device trees. This automatically converts the tree to dts form (if it's not already) and uses a new "-s" option in dtc to "sort" the tree. That is, it sorts the reserve entries, it sorts the properties within each node by name, and it sorts nodes by name within their parent. This gives a pretty sensible diff between the trees, which will ignore semantically null internal rearrangements (directly diffing the dts files can give a lot of noise due to the order changes). Signed-off-by: David Gibson --- Makefile | 5 +- dtc.c | 12 +++- dtc.h | 1 + dtdiff | 38 +++++++++++++ livetree.c | 137 +++++++++++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 7 +++ 6 files changed, 196 insertions(+), 4 deletions(-) create mode 100644 dtdiff diff --git a/Makefile b/Makefile index af467ef..a07648c 100644 --- a/Makefile +++ b/Makefile @@ -111,6 +111,7 @@ BIN += convert-dtsv0 BIN += dtc BIN += ftdump +SCRIPTS = dtdiff all: $(BIN) libfdt @@ -155,10 +156,10 @@ endif # intermediate target and building them again "for real" .SECONDARY: $(DTC_GEN_SRCS) $(CONVERT_GEN_SRCS) -install: all +install: all $(SCRIPTS) @$(VECHO) INSTALL $(INSTALL) -d $(DESTDIR)$(BINDIR) - $(INSTALL) $(BIN) $(DESTDIR)$(BINDIR) + $(INSTALL) $(BIN) $(SCRIPTS) $(DESTDIR)$(BINDIR) $(INSTALL) -d $(DESTDIR)$(LIBDIR) $(INSTALL) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) $(INSTALL) -m 644 $(LIBFDT_archive) $(DESTDIR)$(LIBDIR) diff --git a/dtc.c b/dtc.c index 8b31d20..cbc0193 100644 --- a/dtc.c +++ b/dtc.c @@ -81,6 +81,8 @@ static void __attribute__ ((noreturn)) usage(void) fprintf(stderr, "\t\tSet the physical boot cpu\n"); fprintf(stderr, "\t-f\n"); fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n"); + fprintf(stderr, "\t-s\n"); + fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n"); fprintf(stderr, "\t-v\n"); fprintf(stderr, "\t\tPrint DTC version and exit\n"); fprintf(stderr, "\t-H \n"); @@ -97,7 +99,7 @@ int main(int argc, char *argv[]) const char *inform = "dts"; const char *outform = "dts"; const char *outname = "-"; - int force = 0, check = 0; + int force = 0, check = 0, sort = 0; const char *arg; int opt; FILE *outf = NULL; @@ -109,7 +111,7 @@ int main(int argc, char *argv[]) minsize = 0; padsize = 0; - while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:vH:")) != EOF) { + while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:vH:s")) != EOF) { switch (opt) { case 'I': inform = optarg; @@ -159,6 +161,10 @@ int main(int argc, char *argv[]) optarg); break; + case 's': + sort = 1; + break; + case 'h': default: usage(); @@ -197,6 +203,8 @@ int main(int argc, char *argv[]) fill_fullpaths(bi->dt, ""); process_checks(force, bi); + if (sort) + sort_tree(bi); if (streq(outname, "-")) { outf = stdout; diff --git a/dtc.h b/dtc.h index b36ac5d..f37c97e 100644 --- a/dtc.h +++ b/dtc.h @@ -220,6 +220,7 @@ struct boot_info { struct boot_info *build_boot_info(struct reserve_info *reservelist, struct node *tree, uint32_t boot_cpuid_phys); +void sort_tree(struct boot_info *bi); /* Checks */ diff --git a/dtdiff b/dtdiff new file mode 100644 index 0000000..5fa772b --- /dev/null +++ b/dtdiff @@ -0,0 +1,38 @@ +#! /bin/bash + +# This script uses the bash <(...) extension. +# If you want to change this to work with a generic /bin/sh, make sure +# you fix that. + + +DTC=dtc + +source_and_sort () { + DT="$1" + if [ -d "$DT" ]; then + IFORMAT=fs + elif [ -f "$DT" ]; then + case "$DT" in + *.dts) + IFORMAT=dts + ;; + *.dtb) + IFORMAT=dtb + ;; + esac + fi + + if [ -z "$IFORMAT" ]; then + echo "Unrecognized format for $DT" >&2 + exit 2 + fi + + $DTC -I $IFORMAT -O dts -qq -f -s -o - "$DT" +} + +if [ $# != 2 ]; then + echo "Usage: dtdiff " >&2 + exit 1 +fi + +diff -u <(source_and_sort "$1") <(source_and_sort "$2") diff --git a/livetree.c b/livetree.c index 13c5f10..c9209d5 100644 --- a/livetree.c +++ b/livetree.c @@ -470,3 +470,140 @@ uint32_t guess_boot_cpuid(struct node *tree) return propval_cell(reg); } + +static int cmp_reserve_info(const void *ax, const void *bx) +{ + const struct reserve_info *a, *b; + + a = *((const struct reserve_info * const *)ax); + b = *((const struct reserve_info * const *)bx); + + if (a->re.address < b->re.address) + return -1; + else if (a->re.address > b->re.address) + return 1; + else if (a->re.size < b->re.size) + return -1; + else if (a->re.size > b->re.size) + return 1; + else + return 0; +} + +static void sort_reserve_entries(struct boot_info *bi) +{ + struct reserve_info *ri, **tbl; + int n = 0, i = 0; + + for (ri = bi->reservelist; + ri; + ri = ri->next) + n++; + + if (n == 0) + return; + + tbl = xmalloc(n * sizeof(*tbl)); + + for (ri = bi->reservelist; + ri; + ri = ri->next) + tbl[i++] = ri; + + qsort(tbl, n, sizeof(*tbl), cmp_reserve_info); + + bi->reservelist = tbl[0]; + for (i = 0; i < (n-1); i++) + tbl[i]->next = tbl[i+1]; + tbl[n-1]->next = NULL; + + free(tbl); +} + +static int cmp_prop(const void *ax, const void *bx) +{ + const struct property *a, *b; + + a = *((const struct property * const *)ax); + b = *((const struct property * const *)bx); + + return strcmp(a->name, b->name); +} + +static void sort_properties(struct node *node) +{ + int n = 0, i = 0; + struct property *prop, **tbl; + + for_each_property(node, prop) + n++; + + if (n == 0) + return; + + tbl = xmalloc(n * sizeof(*tbl)); + + for_each_property(node, prop) + tbl[i++] = prop; + + qsort(tbl, n, sizeof(*tbl), cmp_prop); + + node->proplist = tbl[0]; + for (i = 0; i < (n-1); i++) + tbl[i]->next = tbl[i+1]; + tbl[n-1]->next = NULL; + + free(tbl); +} + +static int cmp_subnode(const void *ax, const void *bx) +{ + const struct node *a, *b; + + a = *((const struct node * const *)ax); + b = *((const struct node * const *)bx); + + return strcmp(a->name, b->name); +} + +static void sort_subnodes(struct node *node) +{ + int n = 0, i = 0; + struct node *subnode, **tbl; + + for_each_child(node, subnode) + n++; + + if (n == 0) + return; + + tbl = xmalloc(n * sizeof(*tbl)); + + for_each_child(node, subnode) + tbl[i++] = subnode; + + qsort(tbl, n, sizeof(*tbl), cmp_subnode); + + node->children = tbl[0]; + for (i = 0; i < (n-1); i++) + tbl[i]->next_sibling = tbl[i+1]; + tbl[n-1]->next_sibling = NULL; + + free(tbl); +} + +static void sort_node(struct node *node) +{ + struct node *c; + + sort_properties(node); + sort_subnodes(node); + for_each_child(node, c) + sort_node(c); +} + +void sort_tree(struct boot_info *bi) +{ + sort_reserve_entries(bi); + sort_node(bi->dt); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index a887254..72dda32 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -370,6 +370,13 @@ cmp_tests () { for tree in $wrongtrees; do run_test dtbs_equal_unordered -n $basetree $tree done + + # now dtc --sort + run_dtc_test -I dtb -O dtb -s -o $basetree.sorted.test.dtb $basetree + run_test dtbs_equal_unordered $basetree $basetree.sorted.test.dtb + run_dtc_test -I dtb -O dtb -s -o $basetree.reversed.sorted.test.dtb $basetree.reversed.test.dtb + run_test dtbs_equal_unordered $basetree.reversed.test.dtb $basetree.reversed.sorted.test.dtb + run_test dtbs_equal_ordered $basetree.sorted.test.dtb $basetree.reversed.sorted.test.dtb } dtbs_equal_tests () { From 99c1db78dcbe31cb92d6d3af3a162ce6b014f6f0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 26 Apr 2011 20:45:27 +1000 Subject: [PATCH 0316/1198] libfdt: include version number in soname The libfdt shared library is only installed by its unversioned name. Including it properly in a distribution requires installation of both the versioned name (used in the binary-only package) and the unversioned name (used in the development package). The latter is just a symbolic link, so you need to change the soname in turn to include the version. While at it, use Makefile variables to shorten some lines and avoid cut-and-paste typos; and clean up remnants of when shared libraries were not supported on Darwin. Signed-off-by: Paolo Bonzini Signed-off-by: David Gibson --- Makefile | 9 +++++---- libfdt/Makefile.libfdt | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index a07648c..22f79a0 100644 --- a/Makefile +++ b/Makefile @@ -130,7 +130,7 @@ endif LIBFDT_objdir = libfdt LIBFDT_srcdir = libfdt LIBFDT_archive = $(LIBFDT_objdir)/libfdt.a -LIBFDT_lib = $(LIBFDT_objdir)/libfdt.$(SHAREDLIB_EXT) +LIBFDT_lib = $(LIBFDT_objdir)/libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) LIBFDT_include = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES)) LIBFDT_version = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_VERSION)) @@ -162,6 +162,8 @@ install: all $(SCRIPTS) $(INSTALL) $(BIN) $(SCRIPTS) $(DESTDIR)$(BINDIR) $(INSTALL) -d $(DESTDIR)$(LIBDIR) $(INSTALL) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) + ln -sf $(notdir $(LIBFDT_lib)) $(DESTDIR)$(LIBDIR)/$(LIBFDT_soname) + ln -sf $(LIBFDT_soname) $(DESTDIR)$(LIBDIR)/libfdt.$(SHAREDLIB_EXT) $(INSTALL) -m 644 $(LIBFDT_archive) $(DESTDIR)$(LIBDIR) $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) $(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR) @@ -188,7 +190,7 @@ include tests/Makefile.tests # # Clean rules # -STD_CLEANFILES = *~ *.o *.so *.d *.a *.i *.s core a.out vgcore.* \ +STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* \ *.tab.[ch] *.lex.c *.output clean: libfdt_clean tests_clean @@ -234,8 +236,7 @@ clean: libfdt_clean tests_clean $(LIBFDT_lib): @$(VECHO) LD $@ - $(CC) $(LDFLAGS) -fPIC $(SHAREDLIB_LINK_OPTIONS)$(notdir $@) -o $(LIBFDT_objdir)/libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) $^ - ln -sf libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) $(LIBFDT_objdir)/libfdt.$(SHAREDLIB_EXT) + $(CC) $(LDFLAGS) -fPIC $(SHAREDLIB_LINK_OPTIONS)$(LIBFDT_soname) -o $(LIBFDT_lib) $^ %.lex.c: %.l @$(VECHO) LEX $@ diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index 341c803..d55a6f8 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -3,6 +3,7 @@ # This is not a complete Makefile of itself. Instead, it is designed to # be easily embeddable into other systems of Makefiles. # +LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 LIBFDT_INCLUDES = fdt.h libfdt.h LIBFDT_VERSION = version.lds LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c From bc895d6d09695d05ceb8b52486ffe861d6cfbdde Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sun, 8 May 2011 14:45:39 -0500 Subject: [PATCH 0317/1198] Tag Version 1.3.0 Signed-off-by: Jon Loeliger --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 22f79a0..2172d9a 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ # CONFIG_LOCALVERSION from some future config system. # VERSION = 1 -PATCHLEVEL = 2 +PATCHLEVEL = 3 SUBLEVEL = 0 EXTRAVERSION = LOCAL_VERSION = From 0a5aca98ba104ec4101322ccaf36da45064ad3ce Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 28 Jun 2011 08:47:09 -0400 Subject: [PATCH 0318/1198] dtc: Remove unused check variable Commit 376ab6f2 removed the old style check functionality from DTC, however the check option and variable were not removed. This leads to build failures when -Werror=unused-but-set-variable is specified: dtc.c: In function 'main': dtc.c:102:17: error: variable 'check' set but not used [-Werror=unused-but-set-variable] cc1: all warnings being treated as errors make: *** [dtc.o] Error 1 make: *** Waiting for unfinished jobs.... Remove the check variable. Signed-off-by: Josh Boyer Acked-by: David Gibson --- dtc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/dtc.c b/dtc.c index cbc0193..15d2fc2 100644 --- a/dtc.c +++ b/dtc.c @@ -99,7 +99,7 @@ int main(int argc, char *argv[]) const char *inform = "dts"; const char *outform = "dts"; const char *outname = "-"; - int force = 0, check = 0, sort = 0; + int force = 0, sort = 0; const char *arg; int opt; FILE *outf = NULL; @@ -111,7 +111,7 @@ int main(int argc, char *argv[]) minsize = 0; padsize = 0; - while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:vH:s")) != EOF) { + while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fqb:vH:s")) != EOF) { switch (opt) { case 'I': inform = optarg; @@ -137,9 +137,6 @@ int main(int argc, char *argv[]) case 'f': force = 1; break; - case 'c': - check = 1; - break; case 'q': quiet++; break; From d5b3165023b1cc3914e9943b91964ec9ad4be8b2 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 28 Jun 2011 09:47:11 -0400 Subject: [PATCH 0319/1198] dtc: Remove unused variable in flat_read_mem_reserve The *p variable is declared and used to save inb->ptr, however p is later never used. This has been the case since commit 6c0f3676 and can lead to build failures with -Werror=unused-but-set-variable: flattree.c: In function 'flat_read_mem_reserve': flattree.c:700:14: error: variable 'p' set but not used [-Werror=unused-but-set-variable] cc1: all warnings being treated as errors make: *** [flattree.o] Error 1 Remove the variable. Signed-off-by: Josh Boyer Acked-by: David Gibson --- flattree.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/flattree.c b/flattree.c index ead0332..28d0b23 100644 --- a/flattree.c +++ b/flattree.c @@ -697,7 +697,6 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) { struct reserve_info *reservelist = NULL; struct reserve_info *new; - const char *p; struct fdt_reserve_entry re; /* @@ -706,7 +705,6 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) * * First pass, count entries. */ - p = inb->ptr; while (1) { flat_read_chunk(inb, &re, sizeof(re)); re.address = fdt64_to_cpu(re.address); From 492f9d5de7db74aeb3a905246c4efd7cb29227a8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 5 Jul 2011 12:02:49 -0700 Subject: [PATCH 0320/1198] Split out is_printable_string() into util.c This useful function is split out so it will be available to programs other than ftdump. Signed-off-by: Simon Glass Acked-by: David Gibson --- Makefile.ftdump | 3 ++- ftdump.c | 28 +++------------------------- util.c | 28 ++++++++++++++++++++++++++++ util.h | 11 +++++++++++ 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/Makefile.ftdump b/Makefile.ftdump index b70905a..2744a18 100644 --- a/Makefile.ftdump +++ b/Makefile.ftdump @@ -5,7 +5,8 @@ # FTDUMP_SRCS = \ - ftdump.c + ftdump.c \ + util.c FTDUMP_GEN_SRCS = diff --git a/ftdump.c b/ftdump.c index bce6535..db932e3 100644 --- a/ftdump.c +++ b/ftdump.c @@ -11,36 +11,14 @@ #include #include +#include "util.h" + #define FTDUMP_BUF_SIZE 65536 #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) #define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) #define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) -static int is_printable_string(const void *data, int len) -{ - const char *s = data; - const char *ss; - - /* zero length is not */ - if (len == 0) - return 0; - - /* must terminate with zero */ - if (s[len - 1] != '\0') - return 0; - - ss = s; - while (*s && isprint(*s)) - s++; - - /* not zero, or not done yet */ - if (*s != '\0' || (s + 1 - ss) < len) - return 0; - - return 1; -} - static void print_data(const char *data, int len) { int i; @@ -50,7 +28,7 @@ static void print_data(const char *data, int len) if (len == 0) return; - if (is_printable_string(data, len)) { + if (util_is_printable_string(data, len)) { printf(" = \"%s\"", (const char *)data); } else if ((len % 4) == 0) { printf(" = <"); diff --git a/util.c b/util.c index d7ac27d..994436f 100644 --- a/util.c +++ b/util.c @@ -1,6 +1,9 @@ /* * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. * + * util_is_printable_string contributed by + * Pantelis Antoniou + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the @@ -17,6 +20,7 @@ * USA */ +#include #include #include #include @@ -57,3 +61,27 @@ char *join_path(const char *path, const char *name) memcpy(str+lenp, name, lenn+1); return str; } + +int util_is_printable_string(const void *data, int len) +{ + const char *s = data; + const char *ss; + + /* zero length is not */ + if (len == 0) + return 0; + + /* must terminate with zero */ + if (s[len - 1] != '\0') + return 0; + + ss = s; + while (*s && isprint(*s)) + s++; + + /* not zero, or not done yet */ + if (*s != '\0' || (s + 1 - ss) < len) + return 0; + + return 1; +} diff --git a/util.h b/util.h index 9cead84..cc68933 100644 --- a/util.h +++ b/util.h @@ -1,6 +1,8 @@ #ifndef _UTIL_H #define _UTIL_H +#include + /* * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. * @@ -53,4 +55,13 @@ static inline void *xrealloc(void *p, size_t len) extern char *xstrdup(const char *s); extern char *join_path(const char *path, const char *name); +/** + * Check a string of a given length to see if it is all printable and + * has a valid terminator. + * + * @param data The string to check + * @param len The string length including terminator + * @return 1 if a valid printable string, 0 if not */ +int util_is_printable_string(const void *data, int len); + #endif /* _UTIL_H */ From ed8fee1a649b5430afc9b551e3bb6746ebe32449 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 5 Jul 2011 12:02:52 -0700 Subject: [PATCH 0321/1198] Add missing tests to .gitignore Signed-off-by: Simon Glass Acked-by: David Gibson --- tests/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/.gitignore b/tests/.gitignore index c4e1205..f4e58b2 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -45,3 +45,5 @@ /sw_tree1 /truncated_property /value-labels +/dtb_reverse +/dtbs_equal_unordered From b43335a23854b2620140eda6cca2ffae59e8de23 Mon Sep 17 00:00:00 2001 From: Anton Staaf Date: Fri, 9 Sep 2011 12:16:29 -0700 Subject: [PATCH 0322/1198] dtc: Refactor character literal parsing code Move the parsing of hex, octal and escaped characters from data.c to util.c where it can be used for character literal parsing within strings as well as for stand alone C style character literals. Signed-off-by: Anton Staaf Acked-by: David Gibson --- data.c | 83 ++---------------------------------------------- util.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util.h | 8 +++++ 3 files changed, 110 insertions(+), 80 deletions(-) diff --git a/data.c b/data.c index fe555e8..b5f3066 100644 --- a/data.c +++ b/data.c @@ -68,40 +68,6 @@ struct data data_copy_mem(const char *mem, int len) return d; } -static char get_oct_char(const char *s, int *i) -{ - char x[4]; - char *endx; - long val; - - x[3] = '\0'; - strncpy(x, s + *i, 3); - - val = strtol(x, &endx, 8); - - assert(endx > x); - - (*i) += endx - x; - return val; -} - -static char get_hex_char(const char *s, int *i) -{ - char x[3]; - char *endx; - long val; - - x[2] = '\0'; - strncpy(x, s + *i, 2); - - val = strtol(x, &endx, 16); - if (!(endx > x)) - die("\\x used with no following hex digits\n"); - - (*i) += endx - x; - return val; -} - struct data data_copy_escape_string(const char *s, int len) { int i = 0; @@ -114,53 +80,10 @@ struct data data_copy_escape_string(const char *s, int len) while (i < len) { char c = s[i++]; - if (c != '\\') { - q[d.len++] = c; - continue; - } + if (c == '\\') + c = get_escape_char(s, &i); - c = s[i++]; - assert(c); - switch (c) { - case 'a': - q[d.len++] = '\a'; - break; - case 'b': - q[d.len++] = '\b'; - break; - case 't': - q[d.len++] = '\t'; - break; - case 'n': - q[d.len++] = '\n'; - break; - case 'v': - q[d.len++] = '\v'; - break; - case 'f': - q[d.len++] = '\f'; - break; - case 'r': - q[d.len++] = '\r'; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - i--; /* need to re-read the first digit as - * part of the octal value */ - q[d.len++] = get_oct_char(s, &i); - break; - case 'x': - q[d.len++] = get_hex_char(s, &i); - break; - default: - q[d.len++] = c; - } + q[d.len++] = c; } q[d.len++] = '\0'; diff --git a/util.c b/util.c index 994436f..6d07292 100644 --- a/util.c +++ b/util.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "util.h" @@ -85,3 +86,101 @@ int util_is_printable_string(const void *data, int len) return 1; } + +/* + * Parse a octal encoded character starting at index i in string s. The + * resulting character will be returned and the index i will be updated to + * point at the character directly after the end of the encoding, this may be + * the '\0' terminator of the string. + */ +static char get_oct_char(const char *s, int *i) +{ + char x[4]; + char *endx; + long val; + + x[3] = '\0'; + strncpy(x, s + *i, 3); + + val = strtol(x, &endx, 8); + + assert(endx > x); + + (*i) += endx - x; + return val; +} + +/* + * Parse a hexadecimal encoded character starting at index i in string s. The + * resulting character will be returned and the index i will be updated to + * point at the character directly after the end of the encoding, this may be + * the '\0' terminator of the string. + */ +static char get_hex_char(const char *s, int *i) +{ + char x[3]; + char *endx; + long val; + + x[2] = '\0'; + strncpy(x, s + *i, 2); + + val = strtol(x, &endx, 16); + if (!(endx > x)) + die("\\x used with no following hex digits\n"); + + (*i) += endx - x; + return val; +} + +char get_escape_char(const char *s, int *i) +{ + char c = s[*i]; + int j = *i + 1; + char val; + + assert(c); + switch (c) { + case 'a': + val = '\a'; + break; + case 'b': + val = '\b'; + break; + case 't': + val = '\t'; + break; + case 'n': + val = '\n'; + break; + case 'v': + val = '\v'; + break; + case 'f': + val = '\f'; + break; + case 'r': + val = '\r'; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + j--; /* need to re-read the first digit as + * part of the octal value */ + val = get_oct_char(s, &j); + break; + case 'x': + val = get_hex_char(s, &j); + break; + default: + val = c; + } + + (*i) = j; + return val; +} diff --git a/util.h b/util.h index cc68933..f251480 100644 --- a/util.h +++ b/util.h @@ -64,4 +64,12 @@ extern char *join_path(const char *path, const char *name); * @return 1 if a valid printable string, 0 if not */ int util_is_printable_string(const void *data, int len); +/* + * Parse an escaped character starting at index i in string s. The resulting + * character will be returned and the index i will be updated to point at the + * character directly after the end of the encoding, this may be the '\0' + * terminator of the string. + */ +char get_escape_char(const char *s, int *i); + #endif /* _UTIL_H */ From 83df28bd39979b32a75656cac291c36dbd4e5497 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 12 Sep 2011 11:18:43 +1000 Subject: [PATCH 0323/1198] dtc: Remove gcc 4.6 "set but not used" warnings A number of the dtc testcases trigger the new "variable set but not used" warning from gcc 4.6. That is they have variables which are assigned, but then never read after that point. In a couple of cases this is just because the variables aren't needed, so this patch removes them. In subnode_offset.c, it's because one pair of variables we clearly intended to test we don't actually test. This patch also adds this missing check. This patch makes the testsuite compile clean with gcc 4.6. Signed-off-by: David Gibson --- tests/notfound.c | 8 +++----- tests/path_offset.c | 4 ++++ tests/subnode_offset.c | 6 +++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/notfound.c b/tests/notfound.c index 38918ad..4d55b88 100644 --- a/tests/notfound.c +++ b/tests/notfound.c @@ -37,27 +37,25 @@ static void check_error(const char *s, int err) int main(int argc, char *argv[]) { - const struct fdt_property *prop; void *fdt; int offset; int subnode1_offset; - const void *val; int lenerr; test_init(argc, argv); fdt = load_blob_arg(argc, argv); - prop = fdt_get_property(fdt, 0, "nonexistant-property", &lenerr); + fdt_get_property(fdt, 0, "nonexistant-property", &lenerr); check_error("fdt_get_property(\"nonexistant-property\")", lenerr); - val = fdt_getprop(fdt, 0, "nonexistant-property", &lenerr); + fdt_getprop(fdt, 0, "nonexistant-property", &lenerr); check_error("fdt_getprop(\"nonexistant-property\"", lenerr); subnode1_offset = fdt_subnode_offset(fdt, 0, "subnode@1"); if (subnode1_offset < 0) FAIL("Couldn't find subnode1: %s", fdt_strerror(subnode1_offset)); - val = fdt_getprop(fdt, subnode1_offset, "prop-str", &lenerr); + fdt_getprop(fdt, subnode1_offset, "prop-str", &lenerr); check_error("fdt_getprop(\"prop-str\")", lenerr); offset = fdt_subnode_offset(fdt, 0, "nonexistant-subnode"); diff --git a/tests/path_offset.c b/tests/path_offset.c index bb092f1..d3e1f8e 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -104,5 +104,9 @@ int main(int argc, char *argv[]) FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)", subsubnode2_offset, subsubnode2_offset_p); + if (subsubnode2_offset2 != subsubnode2_offset2_p) + FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)", + subsubnode2_offset2, subsubnode2_offset2_p); + PASS(); } diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c index b961070..e58c192 100644 --- a/tests/subnode_offset.c +++ b/tests/subnode_offset.c @@ -60,7 +60,7 @@ int main(int argc, char *argv[]) void *fdt; int subnode1_offset, subnode2_offset; int subsubnode1_offset, subsubnode2_offset, subsubnode2_offset2; - int ss11_off, ss12_off, ss21_off, ss22_off; + int ss12_off, ss21_off; test_init(argc, argv); fdt = load_blob_arg(argc, argv); @@ -85,7 +85,7 @@ int main(int argc, char *argv[]) if (subsubnode2_offset != subsubnode2_offset2) FAIL("Different offsets with and without unit address"); - ss11_off = check_subnode(fdt, subnode1_offset, "ss1"); + check_subnode(fdt, subnode1_offset, "ss1"); ss21_off = fdt_subnode_offset(fdt, subnode2_offset, "ss1"); if (ss21_off != -FDT_ERR_NOTFOUND) FAIL("Incorrectly found ss1 in subnode2"); @@ -93,7 +93,7 @@ int main(int argc, char *argv[]) ss12_off = fdt_subnode_offset(fdt, subnode1_offset, "ss2"); if (ss12_off != -FDT_ERR_NOTFOUND) FAIL("Incorrectly found ss2 in subnode1"); - ss22_off = check_subnode(fdt, subnode2_offset, "ss2"); + check_subnode(fdt, subnode2_offset, "ss2"); PASS(); } From a4ea2fa9518ff0f4d7f4a08647599a727faac2e0 Mon Sep 17 00:00:00 2001 From: Anton Staaf Date: Fri, 9 Sep 2011 12:16:30 -0700 Subject: [PATCH 0324/1198] dtc: Support character literals in cell lists With this patch the following property assignment: property = <0x12345678 'a' '\r' 100>; is equivalent to: property = <0x12345678 0x00000061 0x0000000D 0x00000064> Signed-off-by: Anton Staaf Acked-by: David Gibson --- Documentation/dts-format.txt | 2 +- dtc-lexer.l | 8 ++++++ dtc-parser.y | 32 +++++++++++++++++++++++ tests/.gitignore | 1 + tests/Makefile.tests | 1 + tests/char_literal.c | 50 ++++++++++++++++++++++++++++++++++++ tests/char_literal.dts | 5 ++++ tests/run_tests.sh | 3 +++ tests/testdata.h | 6 +++++ 9 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 tests/char_literal.c create mode 100644 tests/char_literal.dts diff --git a/Documentation/dts-format.txt b/Documentation/dts-format.txt index a655b87..eae8b76 100644 --- a/Documentation/dts-format.txt +++ b/Documentation/dts-format.txt @@ -33,7 +33,7 @@ Property values may be defined as an array of 32-bit integer cells, as NUL-terminated strings, as bytestrings or a combination of these. * Arrays of cells are represented by angle brackets surrounding a - space separated list of C-style integers + space separated list of C-style integers or character literals. e.g. interrupts = <17 0xc>; diff --git a/dtc-lexer.l b/dtc-lexer.l index e866ea5..494e342 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -29,6 +29,7 @@ PROPNODECHAR [a-zA-Z0-9,._+*#?@-] PATHCHAR ({PROPNODECHAR}|[/]) LABEL [a-zA-Z_][a-zA-Z0-9_]* STRING \"([^\\"]|\\.)*\" +CHAR_LITERAL '([^']|\\')*' WS [[:space:]] COMMENT "/*"([^*]|\*+[^*/])*\*+"/" LINECOMMENT "//".*\n @@ -109,6 +110,13 @@ static int pop_input_file(void); return DT_LITERAL; } +<*>{CHAR_LITERAL} { + yytext[yyleng-1] = '\0'; + yylval.literal = xstrdup(yytext+1); + DPRINT("Character literal: %s\n", yylval.literal); + return DT_CHAR_LITERAL; + } + <*>\&{LABEL} { /* label reference */ DPRINT("Ref: %s\n", yytext+1); yylval.labelref = xstrdup(yytext+1); diff --git a/dtc-parser.y b/dtc-parser.y index 5e84a67..554f11a 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -34,6 +34,7 @@ extern struct boot_info *the_boot_info; extern int treesource_error; static unsigned long long eval_literal(const char *s, int base, int bits); +static unsigned char eval_char_literal(const char *s); %} %union { @@ -57,6 +58,7 @@ static unsigned long long eval_literal(const char *s, int base, int bits); %token DT_MEMRESERVE %token DT_PROPNODENAME %token DT_LITERAL +%token DT_CHAR_LITERAL %token DT_BASE %token DT_BYTE %token DT_STRING @@ -265,6 +267,10 @@ cellval: { $$ = eval_literal($1, 0, 32); } + | DT_CHAR_LITERAL + { + $$ = eval_char_literal($1); + } ; bytestring: @@ -343,3 +349,29 @@ static unsigned long long eval_literal(const char *s, int base, int bits) print_error("bad literal"); return val; } + +static unsigned char eval_char_literal(const char *s) +{ + int i = 1; + char c = s[0]; + + if (c == '\0') + { + print_error("empty character literal"); + return 0; + } + + /* + * If the first character in the character literal is a \ then process + * the remaining characters as an escape encoding. If the first + * character is neither an escape or a terminator it should be the only + * character in the literal and will be returned. + */ + if (c == '\\') + c = get_escape_char(s, &i); + + if (s[i] != '\0') + print_error("malformed character literal"); + + return c; +} diff --git a/tests/.gitignore b/tests/.gitignore index f4e58b2..a3e9bd1 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -4,6 +4,7 @@ /add_subnode_with_nops /asm_tree_dump /boot-cpuid +/char_literal /del_node /del_property /dtbs_equal_ordered diff --git a/tests/Makefile.tests b/tests/Makefile.tests index c564e72..e718b63 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -5,6 +5,7 @@ LIB_TESTS_L = get_mem_rsv \ node_offset_by_prop_value node_offset_by_phandle \ node_check_compatible node_offset_by_compatible \ get_alias \ + char_literal \ notfound \ setprop_inplace nop_property nop_node \ sw_tree1 \ diff --git a/tests/char_literal.c b/tests/char_literal.c new file mode 100644 index 0000000..150f2a0 --- /dev/null +++ b/tests/char_literal.c @@ -0,0 +1,50 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for character literals in dtc + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright (C) 2011 The Chromium Authors. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + void *fdt; + uint32_t expected_cells[5]; + + expected_cells[0] = cpu_to_fdt32((unsigned char)TEST_CHAR1); + expected_cells[1] = cpu_to_fdt32((unsigned char)TEST_CHAR2); + expected_cells[2] = cpu_to_fdt32((unsigned char)TEST_CHAR3); + expected_cells[3] = cpu_to_fdt32((unsigned char)TEST_CHAR4); + expected_cells[4] = cpu_to_fdt32((unsigned char)TEST_CHAR5); + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_getprop(fdt, 0, "char-literal-cells", + sizeof(expected_cells), expected_cells); + + PASS(); +} diff --git a/tests/char_literal.dts b/tests/char_literal.dts new file mode 100644 index 0000000..22e17ed --- /dev/null +++ b/tests/char_literal.dts @@ -0,0 +1,5 @@ +/dts-v1/; + +/ { + char-literal-cells = <'\r' 'b' '\0' '\'' '\xff'>; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 72dda32..1246df1 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -206,6 +206,9 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts run_test string_escapes dtc_escapes.test.dtb + run_dtc_test -I dts -O dtb -o dtc_char_literal.test.dtb char_literal.dts + run_test char_literal dtc_char_literal.test.dtb + run_dtc_test -I dts -O dtb -o dtc_extra-terminating-null.test.dtb extra-terminating-null.dts run_test extra-terminating-null dtc_extra-terminating-null.test.dtb diff --git a/tests/testdata.h b/tests/testdata.h index 5b5a9a3..d4c6759 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -19,6 +19,12 @@ #define TEST_STRING_2 "nastystring: \a\b\t\n\v\f\r\\\"" #define TEST_STRING_3 "\xde\xad\xbe\xef" +#define TEST_CHAR1 '\r' +#define TEST_CHAR2 'b' +#define TEST_CHAR3 '\0' +#define TEST_CHAR4 '\'' +#define TEST_CHAR5 '\xff' + #ifndef __ASSEMBLY__ extern struct fdt_header _test_tree1; extern struct fdt_header _truncated_property; From 9ebd9b4a56e54656431111e5ea7cd74e651910bf Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 21 Sep 2011 13:32:44 -0700 Subject: [PATCH 0325/1198] Create Makefile.utils and move ftdump into it We want to avoid a separate Makefile include for each utility, so this sets up a general one for utilities. Acked-by: David Gibson Signed-off-by: Simon Glass --- Makefile | 2 +- Makefile.ftdump | 13 ------------- Makefile.utils | 10 ++++++++++ 3 files changed, 11 insertions(+), 14 deletions(-) delete mode 100644 Makefile.ftdump create mode 100644 Makefile.utils diff --git a/Makefile b/Makefile index 2172d9a..380a705 100644 --- a/Makefile +++ b/Makefile @@ -105,7 +105,7 @@ endef include Makefile.convert-dtsv0 include Makefile.dtc -include Makefile.ftdump +include Makefile.utils BIN += convert-dtsv0 BIN += dtc diff --git a/Makefile.ftdump b/Makefile.ftdump deleted file mode 100644 index 2744a18..0000000 --- a/Makefile.ftdump +++ /dev/null @@ -1,13 +0,0 @@ -# -# This is not a complete Makefile of itself. -# Instead, it is designed to be easily embeddable -# into other systems of Makefiles. -# - -FTDUMP_SRCS = \ - ftdump.c \ - util.c - -FTDUMP_GEN_SRCS = - -FTDUMP_OBJS = $(FTDUMP_SRCS:%.c=%.o) $(FTDUMP_GEN_SRCS:%.c=%.o) diff --git a/Makefile.utils b/Makefile.utils new file mode 100644 index 0000000..0ed9297 --- /dev/null +++ b/Makefile.utils @@ -0,0 +1,10 @@ +# +# This is not a complete Makefile of itself. Instead, it is designed to +# be easily embeddable into other systems of Makefiles. +# + +FTDUMP_SRCS = \ + ftdump.c \ + util.c + +FTDUMP_OBJS = $(FTDUMP_SRCS:%.c=%.o) From 36204fdf742cabc074617648a5b2cf62409dc40b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 22 Sep 2011 10:11:02 -0700 Subject: [PATCH 0326/1198] Add fdt read/write utility functions This adds higher-level libfdt operations for reading/writing an fdt blob from/to a file, as well as a function to decode a data type string as will be used by fdtget, fdtput. This also adds a few tests for the simple type argument supported by utilfdt_decode_type. Signed-off-by: Simon Glass Acked-by: David Gibson --- Makefile | 2 +- tests/Makefile.tests | 5 +- tests/run_tests.sh | 9 ++- tests/tests.h | 18 +----- tests/utilfdt_test.c | 128 ++++++++++++++++++++++++++++++++++++++ util.c | 142 +++++++++++++++++++++++++++++++++++++++++++ util.h | 68 +++++++++++++++++++++ 7 files changed, 352 insertions(+), 20 deletions(-) create mode 100644 tests/utilfdt_test.c diff --git a/Makefile b/Makefile index 380a705..b32409b 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = -CPPFLAGS = -I libfdt +CPPFLAGS = -I libfdt -I . WARNINGS = -Werror -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \ -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls CFLAGS = -g -Os -fPIC -Werror $(WARNINGS) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index e718b63..41695df 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -16,7 +16,8 @@ LIB_TESTS_L = get_mem_rsv \ extra-terminating-null \ dtbs_equal_ordered \ dtb_reverse dtbs_equal_unordered \ - add_subnode_with_nops path_offset_aliases + add_subnode_with_nops path_offset_aliases \ + utilfdt_test LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property @@ -42,7 +43,7 @@ TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) .PHONY: tests tests: $(TESTS) $(TESTS_TREES) -$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_archive) +$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive) $(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o $(LIBFDT_archive) @$(VECHO) LD [libdl] $@ diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 1246df1..e2c3046 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -391,6 +391,10 @@ dtbs_equal_tests () { cmp_tests test_tree1.dtb $WRONG_TREE1 } +utilfdt_tests () { + run_test utilfdt_test +} + while getopts "vt:m" ARG ; do case $ARG in "v") @@ -406,7 +410,7 @@ while getopts "vt:m" ARG ; do done if [ -z "$TESTSETS" ]; then - TESTSETS="libfdt dtc dtbs_equal" + TESTSETS="libfdt utilfdt dtc dtbs_equal" fi # Make sure we don't have stale blobs lying around @@ -417,6 +421,9 @@ for set in $TESTSETS; do "libfdt") libfdt_tests ;; + "utilfdt") + utilfdt_tests + ;; "dtc") dtc_tests ;; diff --git a/tests/tests.h b/tests/tests.h index fcb2b2a..a51556d 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -93,22 +93,6 @@ void cleanup(void); exit(RC_BUG); \ } while (0) -static inline void *xmalloc(size_t size) -{ - void *p = malloc(size); - if (! p) - FAIL("malloc() failure"); - return p; -} - -static inline void *xrealloc(void *p, size_t size) -{ - p = realloc(p, size); - if (! p) - FAIL("realloc() failure"); - return p; -} - void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size); void check_property(void *fdt, int nodeoffset, const char *name, @@ -135,4 +119,6 @@ void *load_blob_arg(int argc, char *argv[]); void save_blob(const char *filename, void *blob); void *open_blob_rw(void *blob); +#include "util.h" + #endif /* _TESTS_H */ diff --git a/tests/utilfdt_test.c b/tests/utilfdt_test.c new file mode 100644 index 0000000..36b4aa5 --- /dev/null +++ b/tests/utilfdt_test.c @@ -0,0 +1,128 @@ +/* + * Copyright 2011 The Chromium Authors, All Rights Reserved. + * + * utilfdt_test - Tests for utilfdt library + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "tests.h" +#include "testdata.h" + +static void check(const char *fmt, int expect_type, int expect_size) +{ + int type; + int size; + + if (utilfdt_decode_type(fmt, &type, &size)) + FAIL("format '%s': valid format string returned failure", fmt); + if (expect_type != type) + FAIL("format '%s': expected type='%c', got type='%c'", fmt, + expect_type, type); + if (expect_size != size) + FAIL("format '%s': expected size=%d, got size=%d", fmt, + expect_size, size); +} + +static void checkfail(const char *fmt) +{ + int type; + int size; + + if (!utilfdt_decode_type(fmt, &type, &size)) + FAIL("format '%s': invalid format string returned success", + 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 expected_size The size (in bytes) that we expect (ignored for + * strings) + */ +static void check_sizes(char *modifier, int expected_size) +{ + char fmt[10], *ptr; + + /* set up a string with a hole in it for the format character */ + if (strlen(modifier) + 2 >= sizeof(fmt)) + FAIL("modifier string '%s' too long", modifier); + strcpy(fmt, modifier); + ptr = fmt + strlen(fmt); + ptr[1] = '\0'; + + /* now try each format character in turn */ + *ptr = 'i'; + check(fmt, 'i', expected_size); + + *ptr = 'u'; + check(fmt, 'u', expected_size); + + *ptr = 'x'; + check(fmt, 'x', expected_size); + + *ptr = 's'; + check(fmt, 's', -1); +} + +static void test_utilfdt_decode_type(void) +{ + char fmt[10]; + int ch; + + /* check all the valid modifiers and sizes */ + check_sizes("", -1); + check_sizes("b", 1); + check_sizes("hh", 1); + check_sizes("h", 2); + check_sizes("l", 4); + + /* try every other character */ + checkfail(""); + for (ch = ' '; ch < 127; ch++) { + if (!strchr("iuxs", ch)) { + *fmt = ch; + fmt[1] = '\0'; + checkfail(fmt); + } + } + + /* try a few modifiers at the end */ + checkfail("sx"); + checkfail("ihh"); + checkfail("xb"); + + /* and one for the doomsday archives */ + checkfail("He has all the virtues I dislike and none of the vices " + "I admire."); +} + +int main(int argc, char *argv[]) +{ + test_utilfdt_decode_type(); + PASS(); +} diff --git a/util.c b/util.c index 6d07292..d82d41f 100644 --- a/util.c +++ b/util.c @@ -1,4 +1,5 @@ /* + * Copyright 2011 The Chromium Authors, All Rights Reserved. * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. * * util_is_printable_string contributed by @@ -27,6 +28,11 @@ #include #include +#include +#include +#include + +#include "libfdt.h" #include "util.h" char *xstrdup(const char *s) @@ -184,3 +190,139 @@ char get_escape_char(const char *s, int *i) (*i) = j; return val; } + +int utilfdt_read_err(const char *filename, char **buffp) +{ + int fd = 0; /* assume stdin */ + char *buf = NULL; + off_t bufsize = 1024, offset = 0; + int ret = 0; + + *buffp = NULL; + if (strcmp(filename, "-") != 0) { + fd = open(filename, O_RDONLY); + if (fd < 0) + return errno; + } + + /* Loop until we have read everything */ + buf = malloc(bufsize); + do { + /* Expand the buffer to hold the next chunk */ + if (offset == bufsize) { + bufsize *= 2; + buf = realloc(buf, bufsize); + if (!buf) { + ret = ENOMEM; + break; + } + } + + ret = read(fd, &buf[offset], bufsize - offset); + if (ret < 0) { + ret = errno; + break; + } + offset += ret; + } while (ret != 0); + + /* Clean up, including closing stdin; return errno on error */ + close(fd); + if (ret) + free(buf); + else + *buffp = buf; + return ret; +} + +char *utilfdt_read(const char *filename) +{ + char *buff; + int ret = utilfdt_read_err(filename, &buff); + + if (ret) { + fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, + strerror(ret)); + return NULL; + } + /* Successful read */ + return buff; +} + +int utilfdt_write_err(const char *filename, const void *blob) +{ + int fd = 1; /* assume stdout */ + int totalsize; + int offset; + int ret = 0; + const char *ptr = blob; + + if (strcmp(filename, "-") != 0) { + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd < 0) + return errno; + } + + totalsize = fdt_totalsize(blob); + offset = 0; + + while (offset < totalsize) { + ret = write(fd, ptr + offset, totalsize - offset); + if (ret < 0) { + ret = -errno; + break; + } + offset += ret; + } + /* Close the file/stdin; return errno on error */ + if (fd != 1) + close(fd); + return ret < 0 ? -ret : 0; +} + + +int utilfdt_write(const char *filename, const void *blob) +{ + int ret = utilfdt_write_err(filename, blob); + + if (ret) { + fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename, + strerror(ret)); + } + return ret ? -1 : 0; +} + +int utilfdt_decode_type(const char *fmt, int *type, int *size) +{ + int qualifier = 0; + + /* get the conversion qualifier */ + *size = -1; + if (strchr("hlLb", *fmt)) { + qualifier = *fmt++; + if (qualifier == *fmt) { + switch (*fmt++) { +/* TODO: case 'l': qualifier = 'L'; break;*/ + case 'h': + qualifier = 'b'; + break; + } + } + } + + /* we should now have a type */ + if (!strchr("iuxs", *fmt)) + return -1; + + /* convert qualifier (bhL) to byte size */ + if (*fmt != 's') + *size = qualifier == 'b' ? 1 : + qualifier == 'h' ? 2 : + qualifier == 'l' ? 4 : -1; + *type = *fmt++; + + /* that should be it! */ + if (*fmt) + return -1; + return 0; +} diff --git a/util.h b/util.h index f251480..730918e 100644 --- a/util.h +++ b/util.h @@ -4,6 +4,7 @@ #include /* + * Copyright 2011 The Chromium Authors, All Rights Reserved. * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or @@ -72,4 +73,71 @@ int util_is_printable_string(const void *data, int len); */ char get_escape_char(const char *s, int *i); +/** + * Read a device tree file into a buffer. This will report any errors on + * stderr. + * + * @param filename The filename to read, or - for stdin + * @return Pointer to allocated buffer containing fdt, or NULL on error + */ +char *utilfdt_read(const char *filename); + +/** + * Read a device tree file into a buffer. Does not report errors, but only + * returns them. The value returned can be passed to strerror() to obtain + * an error message for the user. + * + * @param filename The filename to read, or - for stdin + * @param buffp Returns pointer to buffer containing fdt + * @return 0 if ok, else an errno value representing the error + */ +int utilfdt_read_err(const char *filename, char **buffp); + + +/** + * Write a device tree buffer to a file. This will report any errors on + * stderr. + * + * @param filename The filename to write, or - for stdout + * @param blob Poiner to buffer containing fdt + * @return 0 if ok, -1 on error + */ +int utilfdt_write(const char *filename, const void *blob); + +/** + * Write a device tree buffer to a file. Does not report errors, but only + * returns them. The value returned can be passed to strerror() to obtain + * an error message for the user. + * + * @param filename The filename to write, or - for stdout + * @param blob Poiner to buffer containing fdt + * @return 0 if ok, else an errno value representing the error + */ +int utilfdt_write_err(const char *filename, const void *blob); + +/** + * Decode a data type string. The purpose of this string + * + * The string consists of an optional character followed by the type: + * Modifier characters: + * hh or b 1 byte + * h 2 byte + * l 4 byte, default + * + * Type character: + * s string + * i signed integer + * u unsigned integer + * x hex + * + * TODO: Implement ll modifier (8 bytes) + * TODO: Implement o type (octal) + * + * @param fmt Format string to process + * @param type Returns type found(s/d/u/x), or 0 if none + * @param size Returns size found(1,2,4,8) or 4 if none + * @return 0 if ok, -1 on error (no type given, or other invalid format) + */ +int utilfdt_decode_type(const char *fmt, int *type, int *size); + #endif /* _UTIL_H */ From 1c25c0d520dee58bfd86626a07036fe9febfebe6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 22 Sep 2011 10:11:03 -0700 Subject: [PATCH 0327/1198] Make testutils use utilfdt The load_blob() and save_blob() functions are very similar to the utilfdt versions. This removes the duplicated code. Signed-off-by: Simon Glass Acked-by: David Gibson --- tests/Makefile.tests | 5 ++-- tests/testutils.c | 55 ++++++++------------------------------------ 2 files changed, 12 insertions(+), 48 deletions(-) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 41695df..cae8390 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -45,11 +45,12 @@ tests: $(TESTS) $(TESTS_TREES) $(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive) -$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o $(LIBFDT_archive) +$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive) @$(VECHO) LD [libdl] $@ $(LINK.c) -o $@ $^ -ldl -$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o $(LIBFDT_archive) +$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \ + util.o $(LIBFDT_archive) $(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o diff --git a/tests/testutils.c b/tests/testutils.c index b0a2230..f185133 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -159,33 +159,13 @@ int nodename_eq(const char *s1, const char *s2) void *load_blob(const char *filename) { - int fd; - int offset = 0; - int bufsize = 1024; - char *p = NULL; - int ret; + char *blob; + int ret = utilfdt_read_err(filename, &blob); - fd = open(filename, O_RDONLY); - if (fd < 0) + if (ret) CONFIG("Couldn't open blob from \"%s\": %s", filename, - strerror(errno)); - - p = xmalloc(bufsize); - do { - if (offset == bufsize) { - bufsize *= 2; - p = xrealloc(p, bufsize); - } - - ret = read(fd, &p[offset], bufsize - offset); - if (ret < 0) - CONFIG("Couldn't read from \"%s\": %s", filename, - strerror(errno)); - - offset += ret; - } while (ret != 0); - - return p; + strerror(ret)); + return blob; } void *load_blob_arg(int argc, char *argv[]) @@ -197,28 +177,11 @@ void *load_blob_arg(int argc, char *argv[]) void save_blob(const char *filename, void *fdt) { - int fd; - int totalsize; - int offset; - char *p; - int ret; + int ret = utilfdt_write_err(filename, fdt); - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (fd < 0) - CONFIG("Couldn't open \"%s\" to write blob: %s", filename, - strerror(errno)); - - totalsize = fdt_totalsize(fdt); - offset = 0; - p = fdt; - - while (offset < totalsize) { - ret = write(fd, p + offset, totalsize - offset); - if (ret < 0) - CONFIG("Couldn't write to \"%s\": %s", filename, - strerror(errno)); - offset += ret; - } + if (ret) + CONFIG("Couldn't write blob to \"%s\": %s", filename, + strerror(ret)); } void *open_blob_rw(void *blob) From 07a8691fbbeb2a7e0cff85fb24435e2dc71facaf Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 22 Sep 2011 10:11:04 -0700 Subject: [PATCH 0328/1198] ftdump: use utilfdt to read blob Now that we have utilfdt_read(), ftdump should use it too. Signed-off-by: Simon Glass Acked-by: David Gibson --- ftdump.c | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/ftdump.c b/ftdump.c index db932e3..cc55fe2 100644 --- a/ftdump.c +++ b/ftdump.c @@ -13,8 +13,6 @@ #include "util.h" -#define FTDUMP_BUF_SIZE 65536 - #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) #define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) #define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) @@ -147,40 +145,18 @@ static void dump_blob(void *blob) int main(int argc, char *argv[]) { - FILE *fp; char *buf; - int size; if (argc < 2) { fprintf(stderr, "supply input filename\n"); return 5; } - if (strcmp(argv[1], "-") == 0) { - fp = stdin; - } else { - fp = fopen(argv[1], "rb"); - if (fp == NULL) { - fprintf(stderr, "unable to open %s\n", argv[1]); - return 10; - } - } - - buf = malloc(FTDUMP_BUF_SIZE); - if (!buf) { - fprintf(stderr, "Couldn't allocate %d byte buffer\n", FTDUMP_BUF_SIZE); + buf = utilfdt_read(argv[1]); + if (buf) + dump_blob(buf); + else return 10; - } - - size = fread(buf, 1, FTDUMP_BUF_SIZE, fp); - if (size == FTDUMP_BUF_SIZE) { - fprintf(stderr, "file too large (maximum is %d bytes)\n", FTDUMP_BUF_SIZE); - return 10; - } - - dump_blob(buf); - - fclose(fp); return 0; } From 2cd4c8d27d6b5ea83723754da4eba5d51aa71b95 Mon Sep 17 00:00:00 2001 From: Anton Staaf Date: Tue, 11 Oct 2011 10:22:27 -0700 Subject: [PATCH 0329/1198] libfdt: Add fdt16_to_cpu utility function This utility routine will be used in the variable size cell literal append code. It is a straightforward adaptation of the fdt32_to_cpu function. Signed-off-by: Anton Staaf Acked-by: David Gibson --- libfdt/libfdt_env.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h index 449bf60..da952e7 100644 --- a/libfdt/libfdt_env.h +++ b/libfdt/libfdt_env.h @@ -6,6 +6,12 @@ #include #define _B(n) ((unsigned long long)((uint8_t *)&x)[n]) +static inline uint16_t fdt16_to_cpu(uint16_t x) +{ + return (_B(0) << 8) | _B(1); +} +#define cpu_to_fdt16(x) fdt16_to_cpu(x) + static inline uint32_t fdt32_to_cpu(uint32_t x) { return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3); From a4b515c03804dbc0eff5bbf281bd22438717e773 Mon Sep 17 00:00:00 2001 From: Anton Staaf Date: Tue, 11 Oct 2011 10:22:28 -0700 Subject: [PATCH 0330/1198] dtc: Add data_append_integer function This function deals with appending integers of various sizes (8, 16 32, and 64 bit currently). It handles endianess conversions. If the integer will not fit in the requested number of bits of storage it will have it's high bits ignored. This patch also rewrites data_append_cell and data_append_addr to use data_append_integer. Signed-off-by: Anton Staaf Acked-by: David Gibson --- data.c | 37 +++++++++++++++++++++++++++++++------ dtc.h | 1 + 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/data.c b/data.c index b5f3066..4a40c5b 100644 --- a/data.c +++ b/data.c @@ -168,11 +168,33 @@ struct data data_merge(struct data d1, struct data d2) return d; } -struct data data_append_cell(struct data d, cell_t word) +struct data data_append_integer(struct data d, uint64_t value, int bits) { - cell_t beword = cpu_to_fdt32(word); + uint8_t value_8; + uint16_t value_16; + uint32_t value_32; + uint64_t value_64; - return data_append_data(d, &beword, sizeof(beword)); + switch (bits) { + case 8: + value_8 = value; + return data_append_data(d, &value_8, 1); + + case 16: + value_16 = cpu_to_fdt16(value); + return data_append_data(d, &value_16, 2); + + case 32: + value_32 = cpu_to_fdt32(value); + return data_append_data(d, &value_32, 4); + + case 64: + value_64 = cpu_to_fdt64(value); + return data_append_data(d, &value_64, 8); + + default: + die("Invalid literal size (%d)\n", bits); + } } struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) @@ -185,11 +207,14 @@ struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) return data_append_data(d, &bere, sizeof(bere)); } +struct data data_append_cell(struct data d, cell_t word) +{ + return data_append_integer(d, word, sizeof(word) * 8); +} + struct data data_append_addr(struct data d, uint64_t addr) { - uint64_t beaddr = cpu_to_fdt64(addr); - - return data_append_data(d, &beaddr, sizeof(beaddr)); + return data_append_integer(d, addr, sizeof(addr) * 8); } struct data data_append_byte(struct data d, uint8_t byte) diff --git a/dtc.h b/dtc.h index f37c97e..7b4c65b 100644 --- a/dtc.h +++ b/dtc.h @@ -109,6 +109,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m, const void *p, int len); struct data data_merge(struct data d1, struct data d2); struct data data_append_cell(struct data d, cell_t word); +struct data data_append_integer(struct data d, uint64_t word, int bits); struct data data_append_re(struct data d, const struct fdt_reserve_entry *re); struct data data_append_addr(struct data d, uint64_t addr); struct data data_append_byte(struct data d, uint8_t byte); From 033089f29099bdfd5c2d6986cdb9fd07b16cfde0 Mon Sep 17 00:00:00 2001 From: Anton Staaf Date: Tue, 11 Oct 2011 10:22:29 -0700 Subject: [PATCH 0331/1198] dtc: Add support for variable sized elements Elements of size 8, 16, 32, and 64 bits are supported. The new /bits/ syntax was selected so as to not pollute the reserved keyword space with uint8/uint16/... type names. With this patch the following property assignment: property = /bits/ 16 <0x1234 0x5678 0x0 0xffff>; is equivalent to: property = <0x12345678 0x0000ffff>; It is now also possible to directly specify a 64 bit literal in a cell list, also known as an array using: property = /bits/ 64 <0xdeadbeef00000000>; It is an error to attempt to store a literal into an element that is too small to hold the literal, and the compiler will generate an error when it detects this. For instance: property = /bits/ 8 <256>; Will fail to compile. It is also an error to attempt to place a reference in a non 32-bit element. The documentation has been changed to reflect that the cell list is now an array of elements that can be of sizes other than the default 32-bit cell size. The sized_cells test tests the creation and access of 8, 16, 32, and 64-bit sized elements. It also tests that the creation of two properties, one with 16 bit elements and one with 32 bit elements result in the same property contents. Signed-off-by: Anton Staaf Acked-by: David Gibson --- Documentation/dts-format.txt | 34 ++++++++++----- dtc-lexer.l | 6 +++ dtc-parser.y | 84 +++++++++++++++++++++++------------- tests/.gitignore | 1 + tests/Makefile.tests | 1 + tests/run_tests.sh | 3 ++ tests/sized_cells.c | 84 ++++++++++++++++++++++++++++++++++++ tests/sized_cells.dts | 11 +++++ 8 files changed, 184 insertions(+), 40 deletions(-) create mode 100644 tests/sized_cells.c create mode 100644 tests/sized_cells.dts diff --git a/Documentation/dts-format.txt b/Documentation/dts-format.txt index eae8b76..41741df 100644 --- a/Documentation/dts-format.txt +++ b/Documentation/dts-format.txt @@ -29,18 +29,28 @@ except for properties with empty (zero length) value which have the form: [label:] property-name; -Property values may be defined as an array of 32-bit integer cells, as -NUL-terminated strings, as bytestrings or a combination of these. +Property values may be defined as an array of 8, 16, 32, or 64-bit integer +elements, as NUL-terminated strings, as bytestrings or a combination of these. -* Arrays of cells are represented by angle brackets surrounding a - space separated list of C-style integers or character literals. +* Arrays are represented by angle brackets surrounding a space separated list + of C-style integers or character literals. Array elements default to 32-bits + in size. An array of 32-bit elements is also known as a cell list or a list + of cells. A cell being an unsigned 32-bit integer. e.g. interrupts = <17 0xc>; -* A 64-bit value is represented with two 32-bit cells. +* A 64-bit value can be represented with two 32-bit elements. e.g. clock-frequency = <0x00000001 0x00000000>; +* The storage size of an element can be changed using the /bits/ prefix. The + /bits/ prefix allows for the creation of 8, 16, 32, and 64-bit elements. + The resulting array will not be padded to a multiple of the default 32-bit + element size. + + e.g. interrupts = /bits/ 8 <17 0xc>; + e.g. clock-frequency = /bits/ 64 <0x0000000100000000>; + * A NUL-terminated string value is represented using double quotes (the property value is considered to include the terminating NUL character). @@ -59,19 +69,20 @@ NUL-terminated strings, as bytestrings or a combination of these. e.g. compatible = "ns16550", "ns8250"; example = <0xf00f0000 19>, "a strange property format"; -* In a cell array a reference to another node will be expanded to that - node's phandle. References may by '&' followed by a node's label: +* In an array a reference to another node will be expanded to that node's + phandle. References may by '&' followed by a node's label: e.g. interrupt-parent = < &mpic >; or they may be '&' followed by a node's full path in braces: e.g. interrupt-parent = < &{/soc/interrupt-controller@40000} >; + References are only permitted in arrays that have an element size of + 32-bits. -* Outside a cell array, a reference to another node will be expanded - to that node's full path. +* Outside an array, a reference to another node will be expanded to that + node's full path. e.g. ethernet0 = &EMAC0; * Labels may also appear before or after any component of a property - value, or between cells of a cell array, or between bytes of a - bytestring. + value, or between elements of an array, or between bytes of a bytestring. e.g. reg = reglabel: <0 sizelabel: 0x1000000>; e.g. prop = [ab cd ef byte4: 00 ff fe]; e.g. str = start: "string value" end: ; @@ -108,3 +119,4 @@ Version 1 DTS files have the overall layout: -- David Gibson -- Yoder Stuart + -- Anton Staaf diff --git a/dtc-lexer.l b/dtc-lexer.l index 494e342..73d190c 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -97,6 +97,12 @@ static int pop_input_file(void); return DT_MEMRESERVE; } +<*>"/bits/" { + DPRINT("Keyword: /bits/\n"); + BEGIN_DEFAULT(); + return DT_BITS; + } + <*>{LABEL}: { DPRINT("Label: %s\n", yytext); yylval.labelref = xstrdup(yytext); diff --git a/dtc-parser.y b/dtc-parser.y index 554f11a..348616b 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -45,8 +45,12 @@ static unsigned char eval_char_literal(const char *s); uint8_t byte; struct data data; + struct { + struct data data; + int bits; + } array; + uint64_t addr; - cell_t cell; struct property *prop; struct property *proplist; struct node *node; @@ -56,6 +60,7 @@ static unsigned char eval_char_literal(const char *s); %token DT_V1 %token DT_MEMRESERVE +%token DT_BITS %token DT_PROPNODENAME %token DT_LITERAL %token DT_CHAR_LITERAL @@ -71,8 +76,7 @@ static unsigned char eval_char_literal(const char *s); %type memreserve %type memreserves %type addr -%type celllist -%type cellval +%type arrayprefix %type bytestring %type propdef %type proplist @@ -182,9 +186,9 @@ propdata: { $$ = data_merge($1, $2); } - | propdataprefix '<' celllist '>' + | propdataprefix arrayprefix '>' { - $$ = data_merge($1, $3); + $$ = data_merge($1, $2.data); } | propdataprefix '[' bytestring ']' { @@ -242,34 +246,56 @@ propdataprefix: } ; -celllist: - /* empty */ +arrayprefix: + DT_BITS DT_LITERAL '<' { - $$ = empty_data; - } - | celllist cellval - { - $$ = data_append_cell($1, $2); - } - | celllist DT_REF - { - $$ = data_append_cell(data_add_marker($1, REF_PHANDLE, - $2), -1); - } - | celllist DT_LABEL - { - $$ = data_add_marker($1, LABEL, $2); - } - ; + $$.data = empty_data; + $$.bits = eval_literal($2, 0, 7); -cellval: - DT_LITERAL - { - $$ = eval_literal($1, 0, 32); + if (($$.bits != 8) && + ($$.bits != 16) && + ($$.bits != 32) && + ($$.bits != 64)) + { + print_error("Only 8, 16, 32 and 64-bit elements" + " are currently supported"); + $$.bits = 32; + } } - | DT_CHAR_LITERAL + | '<' { - $$ = eval_char_literal($1); + $$.data = empty_data; + $$.bits = 32; + } + | arrayprefix DT_LITERAL + { + uint64_t val = eval_literal($2, 0, $1.bits); + + $$.data = data_append_integer($1.data, val, $1.bits); + } + | arrayprefix DT_CHAR_LITERAL + { + uint64_t val = eval_char_literal($2); + + $$.data = data_append_integer($1.data, val, $1.bits); + } + | arrayprefix DT_REF + { + uint64_t val = ~0ULL >> (64 - $1.bits); + + if ($1.bits == 32) + $1.data = data_add_marker($1.data, + REF_PHANDLE, + $2); + else + print_error("References are only allowed in " + "arrays with 32-bit elements."); + + $$.data = data_append_integer($1.data, val, $1.bits); + } + | arrayprefix DT_LABEL + { + $$.data = data_add_marker($1.data, LABEL, $2); } ; diff --git a/tests/.gitignore b/tests/.gitignore index a3e9bd1..9e062c3 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -40,6 +40,7 @@ /set_name /setprop /setprop_inplace +/sized_cells /string_escapes /subnode_offset /supernode_atdepth_offset diff --git a/tests/Makefile.tests b/tests/Makefile.tests index cae8390..215a8c5 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -6,6 +6,7 @@ LIB_TESTS_L = get_mem_rsv \ node_check_compatible node_offset_by_compatible \ get_alias \ char_literal \ + sized_cells \ notfound \ setprop_inplace nop_property nop_node \ sw_tree1 \ diff --git a/tests/run_tests.sh b/tests/run_tests.sh index e2c3046..da6f970 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -209,6 +209,9 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_char_literal.test.dtb char_literal.dts run_test char_literal dtc_char_literal.test.dtb + run_dtc_test -I dts -O dtb -o dtc_sized_cells.test.dtb sized_cells.dts + run_test sized_cells dtc_sized_cells.test.dtb + run_dtc_test -I dts -O dtb -o dtc_extra-terminating-null.test.dtb extra-terminating-null.dts run_test extra-terminating-null dtc_extra-terminating-null.test.dtb diff --git a/tests/sized_cells.c b/tests/sized_cells.c new file mode 100644 index 0000000..847ec96 --- /dev/null +++ b/tests/sized_cells.c @@ -0,0 +1,84 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for variable sized cells in dtc + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright (C) 2011 The Chromium Authors. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +static void check_compare_properties(void *fdt, + char const *name_one, + char const *name_two) +{ + const void *propval; + int proplen; + + propval = fdt_getprop(fdt, 0, name_one, &proplen); + + if (!propval) + FAIL("fdt_getprop(\"%s\"): %s", + name_one, + fdt_strerror(proplen)); + + check_getprop(fdt, 0, name_two, proplen, propval); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + uint8_t expected_8[6] = {TEST_CHAR1, + TEST_CHAR2, + TEST_CHAR3, + TEST_CHAR4, + TEST_CHAR5, + TEST_VALUE_1 >> 24}; + uint16_t expected_16[6]; + uint32_t expected_32[6]; + uint64_t expected_64[6]; + int i; + + for (i = 0; i < 5; ++i) { + expected_16[i] = cpu_to_fdt16(expected_8[i]); + expected_32[i] = cpu_to_fdt32(expected_8[i]); + expected_64[i] = cpu_to_fdt64(expected_8[i]); + } + + expected_16[5] = cpu_to_fdt16(TEST_VALUE_1 >> 16); + expected_32[5] = cpu_to_fdt32(TEST_VALUE_1); + expected_64[5] = cpu_to_fdt64(TEST_ADDR_1); + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_getprop(fdt, 0, "cells-8b", sizeof(expected_8), expected_8); + check_getprop(fdt, 0, "cells-16b", sizeof(expected_16), expected_16); + check_getprop(fdt, 0, "cells-32b", sizeof(expected_32), expected_32); + check_getprop(fdt, 0, "cells-64b", sizeof(expected_64), expected_64); + + check_compare_properties(fdt, "cells-one-16b", "cells-one-32b"); + + PASS(); +} diff --git a/tests/sized_cells.dts b/tests/sized_cells.dts new file mode 100644 index 0000000..efea9f5 --- /dev/null +++ b/tests/sized_cells.dts @@ -0,0 +1,11 @@ +/dts-v1/; + +/ { + cells-8b = /bits/ 8 <'\r' 'b' '\0' '\'' '\xff' 0xde>; + cells-16b = /bits/ 16 <'\r' 'b' '\0' '\'' '\xff' 0xdead>; + cells-32b = /bits/ 32 <'\r' 'b' '\0' '\'' '\xff' 0xdeadbeef>; + cells-64b = /bits/ 64 <'\r' 'b' '\0' '\'' '\xff' 0xdeadbeef00000000>; + + cells-one-16b = /bits/ 16 <0x1234 0x5678 0x0 0xffff>; + cells-one-32b = <0x12345678 0x0000ffff>; +}; From 8f459c5d72673e1a3a119ac58a7eee56236fca73 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 25 Oct 2011 17:29:24 -0400 Subject: [PATCH 0332/1198] fdtdump: rename from ftdump The freetype package already installs a binary named "ftdump", so the dtc package conflicts with that. So rename the newer dtc tool to "fdtdump". This even makes a bit more sense: ftdump: [F]lat device [T]ree [dump] fdtdump: [F]lat [D]evice [T]ree [dump] Signed-off-by: Mike Frysinger Acked-by: David Gibson --- .gitignore | 2 +- Documentation/manual.txt | 10 +++++----- Makefile | 6 +++--- Makefile.utils | 6 +++--- ftdump.c => fdtdump.c | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) rename ftdump.c => fdtdump.c (97%) diff --git a/.gitignore b/.gitignore index ae7a46a..74714cd 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,6 @@ lex.yy.c *.lex.c /dtc -/ftdump +/fdtdump /convert-dtsv0 /version_gen.h diff --git a/Documentation/manual.txt b/Documentation/manual.txt index f8a8a7b..14508f3 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -21,7 +21,7 @@ III - libfdt IV - Utility Tools 1) convert-dtsv0 -- Conversion to Version 1 - 1) ftdump + 1) fdtdump I - "dtc", the device tree compiler @@ -643,10 +643,10 @@ a new file with a "v1" appended the filename. Comments, empty lines, etc. are preserved. -2) ftdump -- Flat Tree dumping utility +2) fdtdump -- Flat Device Tree dumping utility -The ftdump program prints a readable version of a flat device tree file. +The fdtdump program prints a readable version of a flat device tree file. -The syntax of the ftdump command line is: +The syntax of the fdtdump command line is: - ftdump + fdtdump diff --git a/Makefile b/Makefile index b32409b..4582f5d 100644 --- a/Makefile +++ b/Makefile @@ -109,7 +109,7 @@ include Makefile.utils BIN += convert-dtsv0 BIN += dtc -BIN += ftdump +BIN += fdtdump SCRIPTS = dtdiff @@ -119,7 +119,7 @@ all: $(BIN) libfdt ifneq ($(DEPTARGETS),) -include $(DTC_OBJS:%.o=%.d) -include $(CONVERT_OBJS:%.o=%.d) --include $(FTDUMP_OBJS:%.o=%.d) +-include $(FDTDUMP_OBJS:%.o=%.d) endif @@ -178,7 +178,7 @@ convert-dtsv0: $(CONVERT_OBJS) @$(VECHO) LD $@ $(LINK.c) -o $@ $^ -ftdump: $(FTDUMP_OBJS) +fdtdump: $(FDTDUMP_OBJS) # diff --git a/Makefile.utils b/Makefile.utils index 0ed9297..fae5b00 100644 --- a/Makefile.utils +++ b/Makefile.utils @@ -3,8 +3,8 @@ # be easily embeddable into other systems of Makefiles. # -FTDUMP_SRCS = \ - ftdump.c \ +FDTDUMP_SRCS = \ + fdtdump.c \ util.c -FTDUMP_OBJS = $(FTDUMP_SRCS:%.c=%.o) +FDTDUMP_OBJS = $(FDTDUMP_SRCS:%.c=%.o) diff --git a/ftdump.c b/fdtdump.c similarity index 97% rename from ftdump.c rename to fdtdump.c index cc55fe2..207a46d 100644 --- a/ftdump.c +++ b/fdtdump.c @@ -1,5 +1,5 @@ /* - * ftdump.c - Contributed by Pantelis Antoniou + * fdtdump.c - Contributed by Pantelis Antoniou */ #include From a31e3ef83bfce62d07695355e5f06cd4d0e44b86 Mon Sep 17 00:00:00 2001 From: Minghuan Lian Date: Mon, 5 Dec 2011 12:22:07 +1100 Subject: [PATCH 0333/1198] libfdt: Add support for appending the values to a existing property Some properties may contain multiple values, these values may need to be added to the property respectively. this patch provides this functionality. The main purpose of fdt_append_prop() is to append the values to a existing property, or create a new property if it dose not exist. Signed-off-by: Minghuan Lian Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 27 +++++++++++++ libfdt/libfdt.h | 95 ++++++++++++++++++++++++++++++++++++++++++++ tests/appendprop.dts | 7 ++++ tests/appendprop1.c | 70 ++++++++++++++++++++++++++++++++ tests/appendprop2.c | 64 +++++++++++++++++++++++++++++ 5 files changed, 263 insertions(+) create mode 100644 tests/appendprop.dts create mode 100644 tests/appendprop1.c create mode 100644 tests/appendprop2.c diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 994037b..24437df 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -289,6 +289,33 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, return 0; } +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + struct fdt_property *prop; + int err, oldlen, newlen; + + FDT_RW_CHECK_HEADER(fdt); + + prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); + if (prop) { + newlen = len + oldlen; + err = _fdt_splice_struct(fdt, prop->data, + FDT_TAGALIGN(oldlen), + FDT_TAGALIGN(newlen)); + if (err) + return err; + prop->len = cpu_to_fdt32(newlen); + memcpy(prop->data + oldlen, val, len); + } else { + err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); + if (err) + return err; + memcpy(prop->data, val, len); + } + return 0; +} + int fdt_delprop(void *fdt, int nodeoffset, const char *name) { struct fdt_property *prop; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 55f3eb3..060479e 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1133,6 +1133,101 @@ 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_appendprop - append to or create a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to append to + * @val: pointer to data to append to the property value + * @len: length of the data to append to the property value + * + * fdt_appendprop() appends the value to the named property in the + * given node, creating the property if it does not already exist. + * + * This function may insert data into 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_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len); + +/** + * 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) + * + * fdt_appendprop_cell() appends the given cell value (converting to + * big-endian if necessary) 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. + * + * This function may insert data into 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 + */ +static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + val = cpu_to_fdt32(val); + return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val)); +} + +/** + * fdt_appendprop_string - append a string 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 + * @str: string value to append to the property + * + * fdt_appendprop_string() appends the given string 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. + * + * This function may insert data into 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_appendprop_string(fdt, nodeoffset, name, str) \ + fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + /** * fdt_delprop - delete a property * @fdt: pointer to the device tree blob diff --git a/tests/appendprop.dts b/tests/appendprop.dts new file mode 100644 index 0000000..6e3a3eb --- /dev/null +++ b/tests/appendprop.dts @@ -0,0 +1,7 @@ +/dts-v1/; + +/ { + prop-str = "hello world", "nastystring: \a\b\t\n\v\f\r\\\""; + prop-int = <0xdeadbeef 123456789>; + prop-bytes = [00010203040001020304]; +}; diff --git a/tests/appendprop1.c b/tests/appendprop1.c new file mode 100644 index 0000000..180d296 --- /dev/null +++ b/tests/appendprop1.c @@ -0,0 +1,70 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_appendprop() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +#define SPACE 65536 + +#define CHECK(code) \ + { \ + err = (code); \ + if (err) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } + +int main(int argc, char *argv[]) +{ + void *fdt; + int err; + uint8_t bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04}; + + test_init(argc, argv); + + /* Create an empty tree first */ + fdt = xmalloc(SPACE); + CHECK(fdt_create(fdt, SPACE)); + CHECK(fdt_finish_reservemap(fdt)); + CHECK(fdt_begin_node(fdt, "")); + CHECK(fdt_end_node(fdt)); + CHECK(fdt_finish(fdt)); + + /* Now use appendprop to add properties */ + CHECK(fdt_open_into(fdt, fdt, SPACE)); + + CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes))); + CHECK(fdt_appendprop_cell(fdt, 0, "prop-int", TEST_VALUE_1)); + CHECK(fdt_appendprop_string(fdt, 0, "prop-str", TEST_STRING_1)); + + CHECK(fdt_pack(fdt)); + + save_blob("appendprop1.test.dtb", fdt); + + PASS(); +} diff --git a/tests/appendprop2.c b/tests/appendprop2.c new file mode 100644 index 0000000..d651a89 --- /dev/null +++ b/tests/appendprop2.c @@ -0,0 +1,64 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_appendprop() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "tests.h" +#include "testdata.h" + +#define SPACE 65536 + +#define CHECK(code) \ + { \ + err = (code); \ + if (err) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } + +int main(int argc, char *argv[]) +{ + void *fdt, *buf; + int err; + uint8_t bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04}; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + buf = xmalloc(SPACE); + CHECK(fdt_open_into(fdt, buf, SPACE)); + fdt = buf; + + CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes))); + CHECK(fdt_appendprop_cell(fdt, 0, "prop-int", TEST_VALUE_2)); + CHECK(fdt_appendprop_string(fdt, 0, "prop-str", TEST_STRING_2)); + + CHECK(fdt_pack(fdt)); + + save_blob("appendprop2.test.dtb", fdt); + + PASS(); +} From 97b909f852039daaae267a66f5df2c90ed05b586 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 11 Jan 2012 23:41:32 +1100 Subject: [PATCH 0334/1198] libfdt: Activate testcase for appending properties Commit a31e3ef83bfce62d07695355e5f06cd4d0e44b86 introduced new libfdt functions to append to existing properties. It also included a test case for this, but neglected to update the Makefile and run_tests.sh script to actually build and execute this testcase. This patch corrects the oversight. Signed-off-by: David Gibson --- tests/Makefile.tests | 1 + tests/run_tests.sh | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 215a8c5..3f92074 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -12,6 +12,7 @@ LIB_TESTS_L = get_mem_rsv \ sw_tree1 \ move_and_save mangle-layout nopulate \ open_pack rw_tree1 set_name setprop del_property del_node \ + appendprop1 appendprop2 \ string_escapes references path-references phandle_format \ boot-cpuid incbin \ extra-terminating-null \ diff --git a/tests/run_tests.sh b/tests/run_tests.sh index da6f970..c72b9d2 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -178,6 +178,10 @@ libfdt_tests () { run_test rw_tree1 tree1_tests rw_tree1.test.dtb tree1_tests_rw rw_tree1.test.dtb + run_test appendprop1 + run_test appendprop2 appendprop1.test.dtb + run_dtc_test -I dts -O dtb -o appendprop.test.dtb appendprop.dts + run_test dtbs_equal_ordered appendprop2.test.dtb appendprop.test.dtb for basetree in test_tree1.dtb sw_tree1.test.dtb rw_tree1.test.dtb; do run_test nopulate $basetree From 69df9f0de25db1c37970850115cdf48335d41802 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 12 Jan 2012 11:31:00 -0700 Subject: [PATCH 0335/1198] dtc: Implement -d option to write out a dependency file This will allow callers to rebuild .dtb files when any of the /include/d .dtsi files are modified, not just the top-level .dts file. Signed-off-by: Stephen Warren Acked-by: David Gibson --- Documentation/manual.txt | 3 +++ dtc.c | 20 +++++++++++++++++++- srcpos.c | 4 ++++ srcpos.h | 1 + tests/dependencies.cmp | 1 + tests/dependencies.dts | 6 ++++++ tests/deps_inc1.dtsi | 1 + tests/deps_inc2.dtsi | 1 + tests/run_tests.sh | 4 ++++ 9 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/dependencies.cmp create mode 100644 tests/dependencies.dts create mode 100644 tests/deps_inc1.dtsi create mode 100644 tests/deps_inc2.dtsi diff --git a/Documentation/manual.txt b/Documentation/manual.txt index 14508f3..989c589 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -106,6 +106,9 @@ Options: -O The generated output format, as listed above. + -d + Generate a dependency file during compilation. + -q Quiet: -q suppress warnings, -qq errors, -qqq all diff --git a/dtc.c b/dtc.c index 15d2fc2..7a0c605 100644 --- a/dtc.c +++ b/dtc.c @@ -71,6 +71,7 @@ static void __attribute__ ((noreturn)) usage(void) fprintf(stderr, "\t\t\tasm - assembler source\n"); fprintf(stderr, "\t-V \n"); fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION); + fprintf(stderr, "\t-d \n"); fprintf(stderr, "\t-R \n"); fprintf(stderr, "\t\tMake space for reserve map entries (relevant for \n\t\tdtb and asm output only)\n"); fprintf(stderr, "\t-S \n"); @@ -99,6 +100,7 @@ int main(int argc, char *argv[]) const char *inform = "dts"; const char *outform = "dts"; const char *outname = "-"; + const char *depname = NULL; int force = 0, sort = 0; const char *arg; int opt; @@ -111,7 +113,7 @@ int main(int argc, char *argv[]) minsize = 0; padsize = 0; - while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fqb:vH:s")) != EOF) { + while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:vH:s")) != EOF) { switch (opt) { case 'I': inform = optarg; @@ -125,6 +127,9 @@ int main(int argc, char *argv[]) case 'V': outversion = strtol(optarg, NULL, 0); break; + case 'd': + depname = optarg; + break; case 'R': reservenum = strtol(optarg, NULL, 0); break; @@ -185,6 +190,14 @@ int main(int argc, char *argv[]) fprintf(stderr, "DTC: %s->%s on file \"%s\"\n", inform, outform, arg); + if (depname) { + depfile = fopen(depname, "w"); + if (!depfile) + die("Couldn't open dependency file %s: %s\n", depname, + strerror(errno)); + fprintf(depfile, "%s:", outname); + } + if (streq(inform, "dts")) bi = dt_from_source(arg); else if (streq(inform, "fs")) @@ -194,6 +207,11 @@ int main(int argc, char *argv[]) else die("Unknown input format \"%s\"\n", inform); + if (depfile) { + fputc('\n', depfile); + fclose(depfile); + } + if (cmdline_boot_cpuid != -1) bi->boot_cpuid_phys = cmdline_boot_cpuid; diff --git a/srcpos.c b/srcpos.c index 2dbc874..36a38e9 100644 --- a/srcpos.c +++ b/srcpos.c @@ -40,6 +40,7 @@ static char *dirname(const char *path) return NULL; } +FILE *depfile; /* = NULL */ struct srcfile_state *current_srcfile; /* = NULL */ /* Detect infinite include recursion. */ @@ -67,6 +68,9 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep) strerror(errno)); } + if (depfile) + fprintf(depfile, " %s", fullname); + if (fullnamep) *fullnamep = fullname; else diff --git a/srcpos.h b/srcpos.h index bd7966e..ce980ca 100644 --- a/srcpos.h +++ b/srcpos.h @@ -30,6 +30,7 @@ struct srcfile_state { struct srcfile_state *prev; }; +extern FILE *depfile; /* = NULL */ extern struct srcfile_state *current_srcfile; /* = NULL */ FILE *srcfile_relative_open(const char *fname, char **fullnamep); diff --git a/tests/dependencies.cmp b/tests/dependencies.cmp new file mode 100644 index 0000000..bcd9432 --- /dev/null +++ b/tests/dependencies.cmp @@ -0,0 +1 @@ +dependencies.test.dtb: dependencies.dts deps_inc1.dtsi deps_inc2.dtsi diff --git a/tests/dependencies.dts b/tests/dependencies.dts new file mode 100644 index 0000000..2cfe31b --- /dev/null +++ b/tests/dependencies.dts @@ -0,0 +1,6 @@ +/dts-v1/; + +/include/ "deps_inc1.dtsi" + +/ { +}; diff --git a/tests/deps_inc1.dtsi b/tests/deps_inc1.dtsi new file mode 100644 index 0000000..5c607dc --- /dev/null +++ b/tests/deps_inc1.dtsi @@ -0,0 +1 @@ +/include/ "deps_inc2.dtsi" diff --git a/tests/deps_inc2.dtsi b/tests/deps_inc2.dtsi new file mode 100644 index 0000000..710cecc --- /dev/null +++ b/tests/deps_inc2.dtsi @@ -0,0 +1 @@ +/* Empty */ diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c72b9d2..e42154b 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -357,6 +357,10 @@ dtc_tests () { run_sh_test dtc-fatal.sh -I dts -O dtb nosuchfile.dts run_sh_test dtc-fatal.sh -I dtb -O dtb nosuchfile.dtb run_sh_test dtc-fatal.sh -I fs -O dtb nosuchfile + + # Dependencies + run_dtc_test -I dts -O dtb -o dependencies.test.dtb -d dependencies.test.d dependencies.dts + run_wrap_test cmp dependencies.test.d dependencies.cmp } cmp_tests () { From 68d057f20d7c3a93b441d2892c4749392bc83b45 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 21 Jan 2012 10:14:47 -0800 Subject: [PATCH 0336/1198] Add fdtget utility to read property values from a device tree This simply utility makes it easy for scripts to read values from the device tree. It is written in C and uses the same libfdt as the rest of the dtc package. What is it for: - Reading fdt values from scripts - Extracting fdt information within build systems - Looking at particular values without having to dump the entire tree To use it, specify the fdt binary file on command line followed by a list of node, property pairs. The utility then looks up each node, finds the property and displays the value. Each value is printed on a new line. fdtget tries to guess the type of each property based on its contents. This is not always reliable, so you can use the -t option to force fdtget to decode the value as a string, or byte, etc. To read from stdin, use - as the file. Usage: fdtget
[ ]... Options: -t Type of data -h Print this help s=string, i=int, u=unsigned, x=hex Optional modifier prefix: hh or b=byte, h=2 byte, l=4 byte (default) Signed-off-by: Simon Glass --- .gitignore | 1 + Makefile | 4 + Makefile.utils | 7 ++ fdtget.c | 226 ++++++++++++++++++++++++++++++++++++++++ tests/fdtget-runtest.sh | 35 +++++++ tests/run_tests.sh | 43 +++++++- tests/tests.sh | 1 + util.h | 10 ++ 8 files changed, 326 insertions(+), 1 deletion(-) create mode 100644 fdtget.c create mode 100755 tests/fdtget-runtest.sh diff --git a/.gitignore b/.gitignore index 74714cd..2d82b71 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ lex.yy.c /fdtdump /convert-dtsv0 /version_gen.h +/fdtget diff --git a/Makefile b/Makefile index 4582f5d..a54a209 100644 --- a/Makefile +++ b/Makefile @@ -110,6 +110,7 @@ include Makefile.utils BIN += convert-dtsv0 BIN += dtc BIN += fdtdump +BIN += fdtget SCRIPTS = dtdiff @@ -120,6 +121,7 @@ ifneq ($(DEPTARGETS),) -include $(DTC_OBJS:%.o=%.d) -include $(CONVERT_OBJS:%.o=%.d) -include $(FDTDUMP_OBJS:%.o=%.d) +-include $(FDTGET_OBJS:%.o=%.d) endif @@ -180,6 +182,8 @@ convert-dtsv0: $(CONVERT_OBJS) fdtdump: $(FDTDUMP_OBJS) +fdtget: $(FDTGET_OBJS) $(LIBFDT_archive) + # # Testsuite rules diff --git a/Makefile.utils b/Makefile.utils index fae5b00..38efa3c 100644 --- a/Makefile.utils +++ b/Makefile.utils @@ -8,3 +8,10 @@ FDTDUMP_SRCS = \ util.c FDTDUMP_OBJS = $(FDTDUMP_SRCS:%.c=%.o) + + +FDTGET_SRCS = \ + fdtget.c \ + util.c + +FDTGET_OBJS = $(FDTGET_SRCS:%.c=%.o) diff --git a/fdtget.c b/fdtget.c new file mode 100644 index 0000000..48ab615 --- /dev/null +++ b/fdtget.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include + +#include "util.h" + +/* Holds information which controls our output and options */ +struct display_info { + int type; /* data type (s/i/u/x or 0 for default) */ + int size; /* data size (1/2/4) */ +}; + +static void report_error(const char *where, int err) +{ + fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err)); +} + +/** + * Displays data of a given length according to selected options + * + * If a specific data type is provided in disp, then this is used. Otherwise + * we try to guess the data type / size from the contents. + * + * @param disp Display information / options + * @param data Data to display + * @param len Maximum length of buffer + * @return 0 if ok, -1 if data does not match format + */ +static int show_data(struct display_info *disp, const char *data, int len) +{ + int i, size; + const uint8_t *p = (const uint8_t *)data; + const char *s; + int value; + int is_string; + char fmt[3]; + + /* no data, don't print */ + if (len == 0) + return 0; + + is_string = (disp->type) == 's' || + (!disp->type && util_is_printable_string(data, len)); + if (is_string) { + if (data[len - 1] != '\0') { + fprintf(stderr, "Unterminated string\n"); + return -1; + } + for (s = data; s - data < len; s += strlen(s) + 1) { + if (s != data) + printf(" "); + printf("%s", (const char *)s); + } + return 0; + } + size = disp->size; + if (size == -1) + size = (len % 4) == 0 ? 4 : 1; + else if (len % size) { + fprintf(stderr, "Property length must be a multiple of " + "selected data size\n"); + return -1; + } + fmt[0] = '%'; + fmt[1] = disp->type ? disp->type : 'd'; + fmt[2] = '\0'; + for (i = 0; i < len; i += size, p += size) { + if (i) + printf(" "); + value = size == 4 ? fdt32_to_cpu(*(const uint32_t *)p) : + size == 2 ? (*p << 8) | p[1] : *p; + printf(fmt, value); + } + return 0; +} + +/** + * Show the data for a given node (and perhaps property) according to the + * display option provided. + * + * @param blob FDT blob + * @param disp Display information / options + * @param node Node to display + * @param property Name of property to display, or NULL if none + * @return 0 if ok, -ve on error + */ +static int show_data_for_item(const void *blob, struct display_info *disp, + int node, const char *property) +{ + const void *value = NULL; + int len, err = 0; + + value = fdt_getprop(blob, node, property, &len); + if (value) { + if (show_data(disp, value, len)) + err = -1; + else + printf("\n"); + } else { + report_error(property, len); + err = -1; + } + return err; +} + +/** + * Run the main fdtget operation, given a filename and valid arguments + * + * @param disp Display information / options + * @param filename Filename of blob file + * @param arg List of arguments to process + * @param arg_count Number of arguments + * @param return 0 if ok, -ve on error + */ +static int do_fdtget(struct display_info *disp, const char *filename, + char **arg, int arg_count) +{ + char *blob; + int i, node; + + blob = utilfdt_read(filename); + if (!blob) + return -1; + + for (i = 0; i + 2 <= arg_count; i += 2) { + node = fdt_path_offset(blob, arg[0]); + if (node < 0) { + report_error(arg[0], node); + return -1; + } + + if (show_data_for_item(blob, disp, node, arg[1])) + return -1; + } + return 0; +} + +static const char *usage_msg = + "fdtget - read values from device tree\n" + "\n" + "Each value is printed on a new line.\n\n" + "Usage:\n" + " fdtget
[ ]...\n" + "Options:\n" + "\t-t \tType of data\n" + "\t-h\t\tPrint this help\n\n" + USAGE_TYPE_MSG; + +static void usage(const char *msg) +{ + if (msg) + fprintf(stderr, "Error: %s\n\n", msg); + + fprintf(stderr, "%s", usage_msg); + exit(2); +} + +int main(int argc, char *argv[]) +{ + char *filename = NULL; + struct display_info disp; + + /* set defaults */ + memset(&disp, '\0', sizeof(disp)); + disp.size = -1; + for (;;) { + int c = getopt(argc, argv, "ht:"); + if (c == -1) + break; + + switch (c) { + case 'h': + case '?': + usage(NULL); + + case 't': + if (utilfdt_decode_type(optarg, &disp.type, + &disp.size)) + usage("Invalid type string"); + break; + } + } + + if (optind < argc) + filename = argv[optind++]; + if (!filename) + usage("Missing filename"); + + argv += optind; + argc -= optind; + + /* Allow no arguments, and silently succeed */ + if (!argc) + return 0; + + /* Check for node, property arguments */ + if (argc % 2) + usage("Must have an even number of arguments"); + + if (do_fdtget(&disp, filename, argv, argc)) + return 1; + return 0; +} diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh new file mode 100755 index 0000000..f38184f --- /dev/null +++ b/tests/fdtget-runtest.sh @@ -0,0 +1,35 @@ +#! /bin/sh + +. ./tests.sh + +LOG="tmp.log.$$" +EXPECT="tmp.expect.$$" + +rm -f $TMPFILE $LOG + +expect="$1" +echo "$expect" >$EXPECT +shift + +verbose_run_log "$LOG" $VALGRIND "$DTGET" "$@" +ret="$?" + +if [ "$ret" -ne 0 -a "$expect" = "ERR" ]; then + PASS +fi + +if [ "$ret" -gt 127 ]; then + signame=$(kill -l $[ret - 128]) + FAIL "Killed by SIG$signame" +fi + +diff $EXPECT $LOG +ret="$?" + +rm -f $LOG $EXPECT + +if [ "$ret" -eq 0 ]; then + PASS +else + FAIL +fi diff --git a/tests/run_tests.sh b/tests/run_tests.sh index e42154b..e6184df 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -83,6 +83,13 @@ asm_to_so_test () { run_wrap_test asm_to_so "$@" } +run_fdtget_test () { + # run_fdtget_test name expected_output dtb_file args... + echo -n "$1: " + shift + base_run_test sh fdtget-runtest.sh "$@" +} + tree1_tests () { TREE=$1 @@ -402,6 +409,37 @@ dtbs_equal_tests () { cmp_tests test_tree1.dtb $WRONG_TREE1 } +fdtget_tests () { + file=label01.dtb + $DTC -O dtb -o $file ${file%.dtb}.dts 2>/dev/null + + # run_fdtget_test ... + run_fdtget_test "Simple string" "MyBoardName" $file / model + run_fdtget_test "Multiple string i" "77 121 66 111 \ +97 114 100 78 97 109 101 0 77 121 66 111 97 114 100 70 97 109 105 \ +108 121 78 97 109 101 0" $file / compatible + run_fdtget_test "Multiple string s" "MyBoardName MyBoardFamilyName" \ + -t s $file / compatible + run_fdtget_test "Integer" "32768" $file /cpus/PowerPC,970@1 d-cache-size + run_fdtget_test "Integer hex" "8000" -tx $file \ + /cpus/PowerPC,970@1 d-cache-size + run_fdtget_test "Integer list" "61 62 63 0" -tbx $file \ + /randomnode tricky1 + run_fdtget_test "Byte list short" "a b c d de ea ad be ef" -tbx \ + $file /randomnode blob + + # Here the property size is not a multiple of 4 bytes, so it should fail + run_fdtget_test "Integer list invalid" ERR -tlx \ + $file /randomnode mixed + run_fdtget_test "Integer list halfword" "6162 6300 1234 0 a 0 b 0 c" -thx \ + $file /randomnode mixed + run_fdtget_test "Integer list byte" \ + "61 62 63 0 12 34 0 0 0 a 0 0 0 b 0 0 0 c" -thhx \ + $file /randomnode mixed + run_fdtget_test "Missing property" ERR -ts \ + $file /randomnode doctor-who +} + utilfdt_tests () { run_test utilfdt_test } @@ -421,7 +459,7 @@ while getopts "vt:m" ARG ; do done if [ -z "$TESTSETS" ]; then - TESTSETS="libfdt utilfdt dtc dtbs_equal" + TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget" fi # Make sure we don't have stale blobs lying around @@ -441,6 +479,9 @@ for set in $TESTSETS; do "dtbs_equal") dtbs_equal_tests ;; + "fdtget") + fdtget_tests + ;; esac done diff --git a/tests/tests.sh b/tests/tests.sh index 30ffead..d9a0524 100644 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -11,6 +11,7 @@ FAIL () { } DTC=../dtc +DTGET=../fdtget verbose_run () { if [ -z "$QUIET_TEST" ]; then diff --git a/util.h b/util.h index 730918e..c8eb45d 100644 --- a/util.h +++ b/util.h @@ -140,4 +140,14 @@ int utilfdt_write_err(const char *filename, const void *blob); */ int utilfdt_decode_type(const char *fmt, int *type, int *size); +/* + * This is a usage message fragment for the -t option. It is the format + * supported by utilfdt_decode_type. + */ + +#define USAGE_TYPE_MSG \ + "\ts=string, i=int, u=unsigned, x=hex\n" \ + "\tOptional modifier prefix:\n" \ + "\t\thh or b=byte, h=2 byte, l=4 byte (default)\n"; + #endif /* _UTIL_H */ From 1ede50c3559bbfca79fadcbfd8acb9388f4aac87 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 21 Jan 2012 10:14:48 -0800 Subject: [PATCH 0337/1198] Add fdtput utility to write property values to a device tree This simple utility allows writing of values into a device tree from the command line. It aimes to be the opposite of fdtget. What is it for: - Updating fdt values when a binary blob already exists (even though source may be available it might be easier to use this utility rather than sed, etc.) - Writing machine-specific fdt values within a build system To use it, specify the fdt binary file on command line followed by the node and property to set. Then, provide a list of values to put into that property. Often there will be just one, but fdtput also supports arrays and string lists. fdtput does not try to guess the type of the property based on looking at the arguments. Instead it always assumes that an integer is provided. To indicate that you want to write a string, use -ts. You can also provide hex values with -tx. The command line arguments are joined together into a single value. For strings, a nul terminator is placed between each string when it is packed into the property. To avoid this, pass the string as a single argument. Usage: fdtput
< [...] Options: -t Type of data -v Verbose: display each value decoded from command line -h Print this help s=string, i=int, u=unsigned, x=hex Optional modifier prefix: hh or b=byte, h=2 byte, l=4 byte (default) To read from stdin and write to stdout, use - as the file. So you can do: cat somefile.dtb | fdtput -ts - /node prop "My string value" > newfile.dtb This commit also adds basic tests to verify the major features. Signed-off-by: Simon Glass --- .gitignore | 1 + Makefile | 4 + Makefile.utils | 7 ++ fdtput.c | 235 ++++++++++++++++++++++++++++++++++++++++ tests/fdtput-runtest.sh | 55 ++++++++++ tests/run_tests.sh | 73 ++++++++++++- tests/tests.sh | 1 + 7 files changed, 375 insertions(+), 1 deletion(-) create mode 100644 fdtput.c create mode 100644 tests/fdtput-runtest.sh diff --git a/.gitignore b/.gitignore index 2d82b71..5074980 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ lex.yy.c /convert-dtsv0 /version_gen.h /fdtget +/fdtput diff --git a/Makefile b/Makefile index a54a209..510caa6 100644 --- a/Makefile +++ b/Makefile @@ -111,6 +111,7 @@ BIN += convert-dtsv0 BIN += dtc BIN += fdtdump BIN += fdtget +BIN += fdtput SCRIPTS = dtdiff @@ -122,6 +123,7 @@ ifneq ($(DEPTARGETS),) -include $(CONVERT_OBJS:%.o=%.d) -include $(FDTDUMP_OBJS:%.o=%.d) -include $(FDTGET_OBJS:%.o=%.d) +-include $(FDTPUT_OBJS:%.o=%.d) endif @@ -184,6 +186,8 @@ fdtdump: $(FDTDUMP_OBJS) fdtget: $(FDTGET_OBJS) $(LIBFDT_archive) +fdtput: $(FDTPUT_OBJS) $(LIBFDT_archive) + # # Testsuite rules diff --git a/Makefile.utils b/Makefile.utils index 38efa3c..48ece49 100644 --- a/Makefile.utils +++ b/Makefile.utils @@ -15,3 +15,10 @@ FDTGET_SRCS = \ util.c FDTGET_OBJS = $(FDTGET_SRCS:%.c=%.o) + + +FDTPUT_SRCS = \ + fdtput.c \ + util.c + +FDTPUT_OBJS = $(FDTPUT_SRCS:%.c=%.o) diff --git a/fdtput.c b/fdtput.c new file mode 100644 index 0000000..f6ebd24 --- /dev/null +++ b/fdtput.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "util.h" + +struct display_info { + int type; /* data type (s/i/u/x or 0 for default) */ + int size; /* data size (1/2/4) */ + int verbose; /* verbose output */ +}; + +static void report_error(const char *where, int err) +{ + fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err)); +} + +/** + * Encode a series of arguments in a property value. + * + * @param disp Display information / options + * @param arg List of arguments from command line + * @param arg_count Number of arguments (may be 0) + * @param valuep Returns buffer containing value + * @param *value_len Returns length of value encoded + */ +static int encode_value(struct display_info *disp, char **arg, int arg_count, + char **valuep, int *value_len) +{ + char *value = NULL; /* holding area for value */ + int value_size = 0; /* size of holding area */ + char *ptr; /* pointer to current value position */ + 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') + len = strlen(*arg) + 1; + else + len = disp->size == -1 ? 4 : disp->size; + + /* enlarge our value buffer by a suitable margin if needed */ + if (upto + len > value_size) { + value_size = (upto + len) + 500; + value = realloc(value, value_size); + if (!value) { + fprintf(stderr, "Out of mmory: cannot alloc " + "%d bytes\n", value_size); + return -1; + } + } + + ptr = value + upto; + if (disp->type == 's') { + memcpy(ptr, *arg, len); + if (disp->verbose) + fprintf(stderr, "\tstring: '%s'\n", ptr); + } else { + int *iptr = (int *)ptr; + sscanf(*arg, fmt, &ival); + if (len == 4) + *iptr = cpu_to_fdt32(ival); + else + *ptr = (uint8_t)ival; + if (disp->verbose) { + fprintf(stderr, "\t%s: %d\n", + disp->size == 1 ? "byte" : + disp->size == 2 ? "short" : "int", + ival); + } + } + } + *value_len = upto; + *valuep = value; + if (disp->verbose) + fprintf(stderr, "Value size %d\n", upto); + return 0; +} + +static int store_key_value(void *blob, const char *node_name, + const char *property, const char *buf, int len) +{ + int node; + int err; + + node = fdt_path_offset(blob, node_name); + if (node < 0) { + report_error(node_name, node); + return -1; + } + + err = fdt_setprop(blob, node, property, buf, len); + if (err) { + report_error(property, err); + return -1; + } + return 0; +} + +static int do_fdtput(struct display_info *disp, const char *filename, + char **arg, int arg_count) +{ + char *value; + char *blob; + int len, ret = 0; + + blob = utilfdt_read(filename); + if (!blob) + return -1; + + /* convert the arguments into a single binary value, then store */ + assert(arg_count >= 2); + if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) || + store_key_value(blob, *arg, arg[1], value, len)) + ret = -1; + + if (!ret) + ret = utilfdt_write(filename, blob); + + free(blob); + return ret; +} + +static const char *usage_msg = + "fdtput - write a property value to a device tree\n" + "\n" + "The command line arguments are joined together into a single value.\n" + "\n" + "Usage:\n" + " fdtput
< [...]\n" + "Options:\n" + "\t-t \tType of data\n" + "\t-v\t\tVerbose: display each value decoded from command line\n" + "\t-h\t\tPrint this help\n\n" + USAGE_TYPE_MSG; + +static void usage(const char *msg) +{ + if (msg) + fprintf(stderr, "Error: %s\n\n", msg); + + fprintf(stderr, "%s", usage_msg); + exit(2); +} + +int main(int argc, char *argv[]) +{ + struct display_info disp; + char *filename = NULL; + + memset(&disp, '\0', sizeof(disp)); + disp.size = -1; + for (;;) { + int c = getopt(argc, argv, "ht:v"); + if (c == -1) + break; + + /* + * TODO: add options to: + * - delete property + * - delete node (optionally recursively) + * - rename node + * - pack fdt before writing + * - set amount of free space when writing + * - expand fdt if value doesn't fit + */ + switch (c) { + case 'h': + case '?': + usage(NULL); + + case 't': + if (utilfdt_decode_type(optarg, &disp.type, + &disp.size)) + usage("Invalid type string"); + break; + + case 'v': + disp.verbose = 1; + break; + } + } + + if (optind < argc) + filename = argv[optind++]; + if (!filename) + usage("Missing filename"); + + argv += optind; + argc -= optind; + + if (argc < 1) + usage("Missing node"); + if (argc < 2) + usage("Missing property"); + + if (do_fdtput(&disp, filename, argv, argc)) + return 1; + return 0; +} diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh new file mode 100644 index 0000000..ea51569 --- /dev/null +++ b/tests/fdtput-runtest.sh @@ -0,0 +1,55 @@ +#! /bin/sh + +# Run script for fdtput tests +# We run fdtput to update the device tree, thn fdtget to check it + +# Usage +# fdtput-runtest.sh name expected_output dtb_file node property flags value + +. ./tests.sh + +LOG="tmp.log.$$" +EXPECT="tmp.expect.$$" + +rm -f $TMPFILE $LOG + +expect="$1" +echo "$expect" >$EXPECT +dtb="$2" +node="$3" +property="$4" +flags="$5" +shift 5 +value="$@" + +# First run fdtput +verbose_run $VALGRIND "$DTPUT" "$dtb" "$node" "$property" $value $flags +ret="$?" + +if [ "$ret" -ne 0 -a "$expect" = "ERR" ]; then + PASS +fi +if [ "$ret" -gt 127 ]; then + signame=$(kill -l $[ret - 128]) + FAIL "Killed by SIG$signame" +fi + +# Now fdtget to read the value +verbose_run_log "$LOG" $VALGRIND "$DTGET" "$dtb" "$node" "$property" $flags +ret="$?" + +if [ "$ret" -gt 127 ]; then + signame=$(kill -l $[ret - 128]) + FAIL "Killed by SIG$signame" +fi + +diff $EXPECT $LOG +ret="$?" + +rm -f $LOG $EXPECT + +if [ "$ret" -eq 0 ]; then + PASS +else + FAIL +fi diff --git a/tests/run_tests.sh b/tests/run_tests.sh index e6184df..2650559 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -90,6 +90,21 @@ run_fdtget_test () { base_run_test sh fdtget-runtest.sh "$@" } +run_fdtput_test () { + # run_fdtput_test name expected_output dtb_file node property flags value... + echo -n "$1: " + shift + output="$1" + dtb="$2" + node="$3" + property="$4" + flags="$5" + shift 5 + base_run_test sh fdtput-runtest.sh "$output" "$dtb" "$node" "$property" \ + "$flags" $@ +# base_run_test sh fdtput-runtest.sh "$@" +} + tree1_tests () { TREE=$1 @@ -440,6 +455,59 @@ fdtget_tests () { $file /randomnode doctor-who } +fdtput_tests () { + file=label01.dtb + src=label01.dts + + # Create some test files containing useful strings + base=tmp.test0 + file1=tmp.test1 + file2=tmp.test2 + bigfile1=tmp.test3 + bigfile2=tmp.test4 + + # Filter out anything the shell might not like + cat $src | tr -d "'\"\n\;/\.\*{}\-" | tr -s "[:blank:]" " " >$base + + # Make two small files + head -5 $base >$file1 + cat $file1 | tr a-z A-Z | cut -c10-30 | sort -r >$file2 + + # and two larger ones + cat $base > $bigfile1 + tac $base | tr a-z A-Z | sort -r >$bigfile2 + + # Allow just enough space for both file1 and file2 + (( space = $(stat -c %s $file1) + $(stat -c %s $file2) )) + $DTC -O dtb -p $space -o $file ${file%.dtb}.dts 2>/dev/null + + # run_fdtput_test + # ... + run_fdtput_test "Simple string" "a_model" $file / model -ts "a_model" + run_fdtput_test "Multiple string s" "board1 board2" \ + $file / compatible -ts board1 board2 + run_fdtput_test "Single string with spaces" "board1 board2" \ + $file / compatible -ts "board1 board2" + run_fdtput_test "Integer" "32768" \ + $file /cpus/PowerPC,970@1 d-cache-size "" "32768" + run_fdtput_test "Integer hex" "8001" \ + $file /cpus/PowerPC,970@1 d-cache-size -tx 0x8001 + run_fdtput_test "Integer list" "2 3 12" \ + $file /randomnode tricky1 -tbi "02 003 12" + run_fdtput_test "Byte list short" "a b c ea ad be ef" \ + $file /randomnode blob -tbx "a b c ea ad be ef" + run_fdtput_test "Integer list short" "a0b0c0d deeaae ef000000" \ + $file /randomnode blob -tx "a0b0c0d deeaae ef000000" + run_fdtput_test "Large string list" "`cat $file1 $file2`" \ + $file /randomnode blob -ts "`cat $file1`" "`cat $file2`" + + # This should be larger than available space in the fdt ($space) + run_fdtput_test "Enormous string list" ERR \ + $file /randomnode blob -ts "`cat $bigfile1`" "`cat $bigfile2`" + + # TODO: Add tests for verbose mode? +} + utilfdt_tests () { run_test utilfdt_test } @@ -459,7 +527,7 @@ while getopts "vt:m" ARG ; do done if [ -z "$TESTSETS" ]; then - TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget" + TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget fdtput" fi # Make sure we don't have stale blobs lying around @@ -482,6 +550,9 @@ for set in $TESTSETS; do "fdtget") fdtget_tests ;; + "fdtput") + fdtput_tests + ;; esac done diff --git a/tests/tests.sh b/tests/tests.sh index d9a0524..6e5e76a 100644 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -12,6 +12,7 @@ FAIL () { DTC=../dtc DTGET=../fdtget +DTPUT=../fdtput verbose_run () { if [ -z "$QUIET_TEST" ]; then From 1456da7e2d3054882b20c120d817096bea21571e Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 21 Jan 2012 15:24:51 -0600 Subject: [PATCH 0338/1198] Introduce ${TESTS_BIN} in Makefiles to identify tested executables. --- Makefile | 6 ++++++ tests/Makefile.tests | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 510caa6..1169e6c 100644 --- a/Makefile +++ b/Makefile @@ -193,6 +193,12 @@ fdtput: $(FDTPUT_OBJS) $(LIBFDT_archive) # Testsuite rules # TESTS_PREFIX=tests/ + +TESTS_BIN += dtc +TESTS_BIN += convert-dtsv0 +TESTS_BIN += fdtput +TESTS_BIN += fdtget + include tests/Makefile.tests # diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 3f92074..2eee708 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -65,13 +65,13 @@ tests_clean: rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%) rm -f $(TESTS_CLEANFILES) -check: tests dtc convert-dtsv0 +check: tests ${TESTS_BIN} cd $(TESTS_PREFIX); ./run_tests.sh -checkm: tests dtc convert-dtsv0 +checkm: tests ${TESTS_BIN} cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$ -checkv: tests dtc convert-dtsv0 +checkv: tests ${TESTS_BIN} cd $(TESTS_PREFIX); ./run_tests.sh -v ifneq ($(DEPTARGETS),) From 81f11f4f109cc16e1ec31a85c222a1caabea5654 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Feb 2012 16:12:00 +1100 Subject: [PATCH 0339/1198] Update .gitignore for tests We've add some test (generated) binaries that aren't currently listed in .gitignore, in addition more scripts now generate various tmp.* files during operation. This adds them all to .gitignore. Signed-off-by: David Gibson --- tests/.gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/.gitignore b/tests/.gitignore index 9e062c3..0b71bcf 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,7 +1,9 @@ *.dtb *.dtb.test.dts *.dts.test.s +tmp.* /add_subnode_with_nops +/appendprop[12] /asm_tree_dump /boot-cpuid /char_literal @@ -46,6 +48,7 @@ /supernode_atdepth_offset /sw_tree1 /truncated_property +/utilfdt_test /value-labels /dtb_reverse /dtbs_equal_unordered From 9cf26ffa4a9dfa477971f989dcd7392bedbaaaed Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Feb 2012 16:12:01 +1100 Subject: [PATCH 0340/1198] Add quilt files to .gitignore For the benefit of quilt users (such as myself, sometimes) have git ignore the quilt control and patches files. Signed-off-by: David Gibson --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 5074980..7cabc49 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ lex.yy.c /version_gen.h /fdtget /fdtput +/patches +/.pc From 53d6ca639d1e95d0d62e84b25f3d22d721d1f4a3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Feb 2012 16:12:02 +1100 Subject: [PATCH 0341/1198] Trivial style fixup Having braces on an if branch but not the else branch, or vice versa is ugly and can trick you when reading the code. Signed-off-by: David Gibson --- fdtget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fdtget.c b/fdtget.c index 48ab615..2c384b6 100644 --- a/fdtget.c +++ b/fdtget.c @@ -77,9 +77,9 @@ static int show_data(struct display_info *disp, const char *data, int len) return 0; } size = disp->size; - if (size == -1) + if (size == -1) { size = (len % 4) == 0 ? 4 : 1; - else if (len % size) { + } else if (len % size) { fprintf(stderr, "Property length must be a multiple of " "selected data size\n"); return -1; From 9a50d82c4e3a44ca004ada288f7c37004da0b0cc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Feb 2012 16:12:03 +1100 Subject: [PATCH 0342/1198] Remove unused variable from test scripts Several of the test scripts remove $TMPFILE, without ever having set the TMPFILE variable. This patch fixes it. Signed-off-by: David Gibson --- tests/dtc-checkfails.sh | 2 +- tests/fdtget-runtest.sh | 2 +- tests/fdtput-runtest.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh index c58694f..e7aa25e 100755 --- a/tests/dtc-checkfails.sh +++ b/tests/dtc-checkfails.sh @@ -12,7 +12,7 @@ done LOG="tmp.log.$$" -rm -f $TMPFILE $LOG +rm -f $LOG verbose_run_log "$LOG" $VALGRIND "$DTC" -o /dev/null "$@" ret="$?" diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh index f38184f..c17c8f9 100755 --- a/tests/fdtget-runtest.sh +++ b/tests/fdtget-runtest.sh @@ -5,7 +5,7 @@ LOG="tmp.log.$$" EXPECT="tmp.expect.$$" -rm -f $TMPFILE $LOG +rm -f $LOG expect="$1" echo "$expect" >$EXPECT diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh index ea51569..8e4cd95 100644 --- a/tests/fdtput-runtest.sh +++ b/tests/fdtput-runtest.sh @@ -11,7 +11,7 @@ LOG="tmp.log.$$" EXPECT="tmp.expect.$$" -rm -f $TMPFILE $LOG +rm -f $LOG expect="$1" echo "$expect" >$EXPECT From 2ca83614e78f32e68202100e94668b0bb62f1ba6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Feb 2012 16:12:04 +1100 Subject: [PATCH 0343/1198] Use 'trap' builtin to clean up temporaries in test scripts Some of the test scripts create temporary files, which we remove at the end. Except that we usually forgot to remove them on some exit paths. To avoid this problem in future, this modifies the scripts to use the shell's trap 0 functionality to automatically remove the temporaries on any exit. Signed-off-by: David Gibson --- tests/dtc-checkfails.sh | 6 ++---- tests/fdtget-runtest.sh | 10 ++++------ tests/fdtput-runtest.sh | 10 ++++------ 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh index e7aa25e..87992a0 100755 --- a/tests/dtc-checkfails.sh +++ b/tests/dtc-checkfails.sh @@ -10,9 +10,9 @@ for x; do CHECKS="$CHECKS $x" done -LOG="tmp.log.$$" - +LOG=tmp.log.$$ rm -f $LOG +trap "rm -f $LOG" 0 verbose_run_log "$LOG" $VALGRIND "$DTC" -o /dev/null "$@" ret="$?" @@ -28,6 +28,4 @@ for c in $CHECKS; do fi done -rm -f $LOG - PASS diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh index c17c8f9..44c3529 100755 --- a/tests/fdtget-runtest.sh +++ b/tests/fdtget-runtest.sh @@ -2,10 +2,10 @@ . ./tests.sh -LOG="tmp.log.$$" -EXPECT="tmp.expect.$$" - -rm -f $LOG +LOG=tmp.log.$$ +EXPECT=tmp.expect.$$ +rm -f $LOG $EXPECT +trap "rm -f $LOG $EXPECT" 0 expect="$1" echo "$expect" >$EXPECT @@ -26,8 +26,6 @@ fi diff $EXPECT $LOG ret="$?" -rm -f $LOG $EXPECT - if [ "$ret" -eq 0 ]; then PASS else diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh index 8e4cd95..c4b2135 100644 --- a/tests/fdtput-runtest.sh +++ b/tests/fdtput-runtest.sh @@ -8,10 +8,10 @@ . ./tests.sh -LOG="tmp.log.$$" -EXPECT="tmp.expect.$$" - -rm -f $LOG +LOG=tmp.log.$$ +EXPECT=tmp.expect.$$ +rm -f $LOG $EXPECT +trap "rm -f $LOG $EXPECT" 0 expect="$1" echo "$expect" >$EXPECT @@ -46,8 +46,6 @@ fi diff $EXPECT $LOG ret="$?" -rm -f $LOG $EXPECT - if [ "$ret" -eq 0 ]; then PASS else From a90b5b149197a8b38bd569c6a8abc9fc0363fa4b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Feb 2012 16:12:05 +1100 Subject: [PATCH 0344/1198] Remove bashism from run_tests.sh The patches introducing fdtget and fdtput inserted a peculiar bashism to run_tests.sh using non-portable assignment within an (( )) expression. This patch fixes it. 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 2650559..37c173c 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -478,7 +478,7 @@ fdtput_tests () { tac $base | tr a-z A-Z | sort -r >$bigfile2 # Allow just enough space for both file1 and file2 - (( space = $(stat -c %s $file1) + $(stat -c %s $file2) )) + space=$(( $(stat -c %s $file1) + $(stat -c %s $file2) )) $DTC -O dtb -p $space -o $file ${file%.dtb}.dts 2>/dev/null # run_fdtput_test From c879a8a28b168b3b448ca8a107e3386eda6829c7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Feb 2012 16:12:06 +1100 Subject: [PATCH 0345/1198] Factor signal checks out of test scripts Several test scripts now have some code to check for a program returning a signal, and reporting a suitable failure. This patch moves this duplicated code into a helper function in tests.sh. At the same time we remove a bashism found in the current copies (using the non portablr $[ ] construct for arithmetic). Signed-off-by: David Gibson --- tests/dtc-checkfails.sh | 5 +---- tests/fdtget-runtest.sh | 5 +---- tests/fdtput-runtest.sh | 11 +++-------- tests/tests.sh | 8 ++++++++ 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh index 87992a0..3f77b13 100755 --- a/tests/dtc-checkfails.sh +++ b/tests/dtc-checkfails.sh @@ -17,10 +17,7 @@ trap "rm -f $LOG" 0 verbose_run_log "$LOG" $VALGRIND "$DTC" -o /dev/null "$@" ret="$?" -if [ "$ret" -gt 127 ]; then - signame=$(kill -l $[ret - 128]) - FAIL "Killed by SIG$signame" -fi +FAIL_IF_SIGNAL $ret for c in $CHECKS; do if ! grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh index 44c3529..42dc00c 100755 --- a/tests/fdtget-runtest.sh +++ b/tests/fdtget-runtest.sh @@ -18,10 +18,7 @@ if [ "$ret" -ne 0 -a "$expect" = "ERR" ]; then PASS fi -if [ "$ret" -gt 127 ]; then - signame=$(kill -l $[ret - 128]) - FAIL "Killed by SIG$signame" -fi +FAIL_IF_SIGNAL $ret diff $EXPECT $LOG ret="$?" diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh index c4b2135..9178d2f 100644 --- a/tests/fdtput-runtest.sh +++ b/tests/fdtput-runtest.sh @@ -29,19 +29,14 @@ ret="$?" if [ "$ret" -ne 0 -a "$expect" = "ERR" ]; then PASS fi -if [ "$ret" -gt 127 ]; then - signame=$(kill -l $[ret - 128]) - FAIL "Killed by SIG$signame" -fi + +FAIL_IF_SIGNAL $ret # Now fdtget to read the value verbose_run_log "$LOG" $VALGRIND "$DTGET" "$dtb" "$node" "$property" $flags ret="$?" -if [ "$ret" -gt 127 ]; then - signame=$(kill -l $[ret - 128]) - FAIL "Killed by SIG$signame" -fi +FAIL_IF_SIGNAL $ret diff $EXPECT $LOG ret="$?" diff --git a/tests/tests.sh b/tests/tests.sh index 6e5e76a..3b7c6c8 100644 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -10,6 +10,14 @@ FAIL () { exit 2 } +FAIL_IF_SIGNAL () { + ret="$1" + if [ "$ret" -gt 127 ]; then + signame=$(kill -l $((ret - 128))) + FAIL "Killed by SIG$signame" + fi +} + DTC=../dtc DTGET=../fdtget DTPUT=../fdtput From 15b23d21a62b5a0295ee08b54d0842889ce94c92 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Feb 2012 16:12:07 +1100 Subject: [PATCH 0346/1198] Clean up invocation of fdt{get,put} tests This patch cleans up how the fdtget and fdtput tests are invoked. Specifically we no longer hide the full command lines with a wrapper function - this makes it possible to distinguish fdtget from similar fdtput tests and makes it easier to work out how to manually invoke an individual failing test. In addition, we remove the testing for errors from the fdt{get,put}-runtest.sh script, instead using an internal wrapper analagous to run_wrap_test which can test for any program invocation that's expected to return an error. For a couple of the fdtput tests this would result in printing out ludicrously large command lines. Therefore we introduce a new mechanism to cut those down to something reasonable. Signed-off-by: David Gibson --- tests/fdtget-runtest.sh | 11 +--- tests/fdtput-runtest.sh | 16 +---- tests/run_tests.sh | 142 ++++++++++++++++++++++------------------ tests/tests.sh | 19 ++++++ 4 files changed, 103 insertions(+), 85 deletions(-) diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh index 42dc00c..75e7503 100755 --- a/tests/fdtget-runtest.sh +++ b/tests/fdtget-runtest.sh @@ -8,17 +8,10 @@ rm -f $LOG $EXPECT trap "rm -f $LOG $EXPECT" 0 expect="$1" -echo "$expect" >$EXPECT +echo $expect >$EXPECT shift -verbose_run_log "$LOG" $VALGRIND "$DTGET" "$@" -ret="$?" - -if [ "$ret" -ne 0 -a "$expect" = "ERR" ]; then - PASS -fi - -FAIL_IF_SIGNAL $ret +verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@" diff $EXPECT $LOG ret="$?" diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh index 9178d2f..dbd9c0d 100644 --- a/tests/fdtput-runtest.sh +++ b/tests/fdtput-runtest.sh @@ -14,7 +14,7 @@ rm -f $LOG $EXPECT trap "rm -f $LOG $EXPECT" 0 expect="$1" -echo "$expect" >$EXPECT +echo $expect >$EXPECT dtb="$2" node="$3" property="$4" @@ -23,20 +23,10 @@ shift 5 value="$@" # First run fdtput -verbose_run $VALGRIND "$DTPUT" "$dtb" "$node" "$property" $value $flags -ret="$?" - -if [ "$ret" -ne 0 -a "$expect" = "ERR" ]; then - PASS -fi - -FAIL_IF_SIGNAL $ret +verbose_run_check $VALGRIND "$DTPUT" "$dtb" "$node" "$property" $value $flags # Now fdtget to read the value -verbose_run_log "$LOG" $VALGRIND "$DTGET" "$dtb" "$node" "$property" $flags -ret="$?" - -FAIL_IF_SIGNAL $ret +verbose_run_log_check "$LOG" $VALGRIND "$DTGET" "$dtb" "$node" "$property" $flags diff $EXPECT $LOG ret="$?" diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 37c173c..999c882 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -36,6 +36,20 @@ base_run_test() { fi } +shorten_echo () { + limit=32 + echo -n "$1" + shift + for x; do + if [ ${#x} -le $limit ]; then + echo -n " $x" + else + short=$(echo "$x" | head -c$limit) + echo -n " \"$short\"...<${#x} bytes>" + fi + done +} + run_test () { echo -n "$@: " if [ -n "$VALGRIND" -a -f $1.supp ]; then @@ -70,6 +84,28 @@ run_wrap_test () { base_run_test wrap_test "$@" } +wrap_error () { + ( + if verbose_run "$@"; then + FAIL "Expected non-zero return code" + else + ret="$?" + if [ "$ret" -gt 127 ]; then + signame=$(kill -l $((ret - 128))) + FAIL "Killed by SIG$signame" + else + PASS + fi + fi + ) +} + +run_wrap_error_test () { + shorten_echo "$@" + echo -n " {!= 0}: " + base_run_test wrap_error "$@" +} + run_dtc_test () { echo -n "dtc $@: " base_run_test wrap_test $VALGRIND $DTC "$@" @@ -84,25 +120,18 @@ asm_to_so_test () { } run_fdtget_test () { - # run_fdtget_test name expected_output dtb_file args... - echo -n "$1: " + expect="$1" shift - base_run_test sh fdtget-runtest.sh "$@" + echo -n "fdtget-runtest.sh "$expect" $@: " + base_run_test sh fdtget-runtest.sh "$expect" "$@" } run_fdtput_test () { - # run_fdtput_test name expected_output dtb_file node property flags value... - echo -n "$1: " + expect="$1" shift - output="$1" - dtb="$2" - node="$3" - property="$4" - flags="$5" - shift 5 - base_run_test sh fdtput-runtest.sh "$output" "$dtb" "$node" "$property" \ - "$flags" $@ -# base_run_test sh fdtput-runtest.sh "$@" + shorten_echo fdtput-runtest.sh "$expect" "$@" + echo -n ": " + base_run_test sh fdtput-runtest.sh "$expect" "$@" } tree1_tests () { @@ -425,39 +454,32 @@ dtbs_equal_tests () { } fdtget_tests () { - file=label01.dtb - $DTC -O dtb -o $file ${file%.dtb}.dts 2>/dev/null + dts=label01.dts + dtb=$dts.fdtget.test.dtb + run_dtc_test -O dtb -o $dtb $dts - # run_fdtget_test ... - run_fdtget_test "Simple string" "MyBoardName" $file / model - run_fdtget_test "Multiple string i" "77 121 66 111 \ + # run_fdtget_test [] + run_fdtget_test "MyBoardName" $dtb / model + run_fdtget_test "77 121 66 111 \ 97 114 100 78 97 109 101 0 77 121 66 111 97 114 100 70 97 109 105 \ -108 121 78 97 109 101 0" $file / compatible - run_fdtget_test "Multiple string s" "MyBoardName MyBoardFamilyName" \ - -t s $file / compatible - run_fdtget_test "Integer" "32768" $file /cpus/PowerPC,970@1 d-cache-size - run_fdtget_test "Integer hex" "8000" -tx $file \ - /cpus/PowerPC,970@1 d-cache-size - run_fdtget_test "Integer list" "61 62 63 0" -tbx $file \ - /randomnode tricky1 - run_fdtget_test "Byte list short" "a b c d de ea ad be ef" -tbx \ - $file /randomnode blob +108 121 78 97 109 101 0" $dtb / compatible + run_fdtget_test "MyBoardName MyBoardFamilyName" -t s $dtb / compatible + run_fdtget_test 32768 $dtb /cpus/PowerPC,970@1 d-cache-size + 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 # Here the property size is not a multiple of 4 bytes, so it should fail - run_fdtget_test "Integer list invalid" ERR -tlx \ - $file /randomnode mixed - run_fdtget_test "Integer list halfword" "6162 6300 1234 0 a 0 b 0 c" -thx \ - $file /randomnode mixed - run_fdtget_test "Integer list byte" \ - "61 62 63 0 12 34 0 0 0 a 0 0 0 b 0 0 0 c" -thhx \ - $file /randomnode mixed - run_fdtget_test "Missing property" ERR -ts \ - $file /randomnode doctor-who + run_wrap_error_test $DTGET -tlx $dtb /randomnode mixed + run_fdtget_test "6162 6300 1234 0 a 0 b 0 c" -thx $dtb /randomnode mixed + run_fdtget_test "61 62 63 0 12 34 0 0 0 a 0 0 0 b 0 0 0 c" \ + -thhx $dtb /randomnode mixed + run_wrap_error_test $DTGET -ts $dtb /randomnode doctor-who } fdtput_tests () { - file=label01.dtb - src=label01.dts + dts=label01.dts + dtb=$dts.fdtput.test.dtb # Create some test files containing useful strings base=tmp.test0 @@ -467,7 +489,7 @@ fdtput_tests () { bigfile2=tmp.test4 # Filter out anything the shell might not like - cat $src | tr -d "'\"\n\;/\.\*{}\-" | tr -s "[:blank:]" " " >$base + cat $dts | tr -d "'\"\n\;/\.\*{}\-" | tr -s "[:blank:]" " " >$base # Make two small files head -5 $base >$file1 @@ -479,31 +501,25 @@ fdtput_tests () { # Allow just enough space for both file1 and file2 space=$(( $(stat -c %s $file1) + $(stat -c %s $file2) )) - $DTC -O dtb -p $space -o $file ${file%.dtb}.dts 2>/dev/null + run_dtc_test -O dtb -p $space -o $dtb $dts - # run_fdtput_test - # ... - run_fdtput_test "Simple string" "a_model" $file / model -ts "a_model" - run_fdtput_test "Multiple string s" "board1 board2" \ - $file / compatible -ts board1 board2 - run_fdtput_test "Single string with spaces" "board1 board2" \ - $file / compatible -ts "board1 board2" - run_fdtput_test "Integer" "32768" \ - $file /cpus/PowerPC,970@1 d-cache-size "" "32768" - run_fdtput_test "Integer hex" "8001" \ - $file /cpus/PowerPC,970@1 d-cache-size -tx 0x8001 - run_fdtput_test "Integer list" "2 3 12" \ - $file /randomnode tricky1 -tbi "02 003 12" - run_fdtput_test "Byte list short" "a b c ea ad be ef" \ - $file /randomnode blob -tbx "a b c ea ad be ef" - run_fdtput_test "Integer list short" "a0b0c0d deeaae ef000000" \ - $file /randomnode blob -tx "a0b0c0d deeaae ef000000" - run_fdtput_test "Large string list" "`cat $file1 $file2`" \ - $file /randomnode blob -ts "`cat $file1`" "`cat $file2`" + # run_fdtput_test + run_fdtput_test "a_model" $dtb / model -ts "a_model" + run_fdtput_test "board1 board2" $dtb / compatible -ts board1 board2 + run_fdtput_test "board1 board2" $dtb / compatible -ts "board1 board2" + run_fdtput_test "32768" $dtb /cpus/PowerPC,970@1 d-cache-size "" "32768" + run_fdtput_test "8001" $dtb /cpus/PowerPC,970@1 d-cache-size -tx 0x8001 + run_fdtput_test "2 3 12" $dtb /randomnode tricky1 -tbi "02 003 12" + run_fdtput_test "a b c ea ad be ef" $dtb /randomnode blob \ + -tbx "a b c ea ad be ef" + run_fdtput_test "a0b0c0d deeaae ef000000" $dtb /randomnode blob \ + -tx "a0b0c0d deeaae ef000000" + run_fdtput_test "`cat $file1 $file2`" $dtb /randomnode blob \ + -ts "`cat $file1`" "`cat $file2`" # This should be larger than available space in the fdt ($space) - run_fdtput_test "Enormous string list" ERR \ - $file /randomnode blob -ts "`cat $bigfile1`" "`cat $bigfile2`" + run_wrap_error_test $DTPUT $dtb /randomnode blob \ + -ts "`cat $bigfile1`" "`cat $bigfile2`" # TODO: Add tests for verbose mode? } diff --git a/tests/tests.sh b/tests/tests.sh index 3b7c6c8..31530d5 100644 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -30,6 +30,15 @@ verbose_run () { fi } +verbose_run_check () { + verbose_run "$@" + ret="$?" + FAIL_IF_SIGNAL $ret + if [ $ret != 0 ]; then + FAIL "Returned error code $ret" + fi +} + verbose_run_log () { LOG="$1" shift @@ -40,3 +49,13 @@ verbose_run_log () { fi return $ret } + +verbose_run_log_check () { + verbose_run_log "$@" + ret="$?" + FAIL_IF_SIGNAL $ret + if [ $ret != 0 ]; then + FAIL "Returned error code $ret" + fi +} + From c34e88354a07099dbc15a41621c81f71325d25fd Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Feb 2012 16:12:08 +1100 Subject: [PATCH 0347/1198] Don't use diff to check fdt{get,put} results Currently the fdt{get,put}-runtest.sh scripts invoke diff to check if fdt{get,put} did the right thing. This isn't great though: it's not obvious from the diff output which is the expected and which is the actual result; diff's line by line behaviour is useless here, since all the results are a single line and finally, when there is a difference it always prints information even when the tests are supposed to be running in quiet mode. This patch uses cmp instead, and explicitly prints the expected results, when running in verbose mode (the invocation of fdtget itself will have already displayed the actual results in this mode. Signed-off-by: David Gibson --- tests/fdtget-runtest.sh | 13 +++++++------ tests/fdtput-runtest.sh | 13 +++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh index 75e7503..dac7f9a 100755 --- a/tests/fdtget-runtest.sh +++ b/tests/fdtget-runtest.sh @@ -13,11 +13,12 @@ shift verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@" -diff $EXPECT $LOG -ret="$?" - -if [ "$ret" -eq 0 ]; then - PASS +if cmp $EXPECT $LOG>/dev/null; then + PASS else - FAIL + if [ -z "$QUIET_TEST" ]; then + echo "EXPECTED :-:" + cat $EXPECT + fi + FAIL "Results differ from expected" fi diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh index dbd9c0d..527a968 100644 --- a/tests/fdtput-runtest.sh +++ b/tests/fdtput-runtest.sh @@ -28,11 +28,12 @@ verbose_run_check $VALGRIND "$DTPUT" "$dtb" "$node" "$property" $value $flags # Now fdtget to read the value verbose_run_log_check "$LOG" $VALGRIND "$DTGET" "$dtb" "$node" "$property" $flags -diff $EXPECT $LOG -ret="$?" - -if [ "$ret" -eq 0 ]; then - PASS +if cmp $EXPECT $LOG >/dev/null; then + PASS else - FAIL + if [ -z "$QUIET_TEST" ]; then + echo "EXPECTED :-:" + cat $EXPECT + fi + FAIL "Results differ from expected" fi From 0b3b46e019f546a24927bb7ca009670762c00107 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Feb 2012 16:12:09 +1100 Subject: [PATCH 0348/1198] Generate test data for fdtput more sensibly Currently run_tests.sh generates several files of text test data. The procedure it uses for this is somewhat torturous and has several problems: * Since the test data is derived from a dts file, a cursory glance at the test output suggests something is wrong with the processing of that dts. This is misleading since in fact it's just being used as an arbirary string. * Since the base input has linefeeds removed, the head and sort commands used later have no effect. * Although an attempt is made to get rid of characters which the shell will mangle, it's not thorough enough. Specifically it leaves in \ which means that some string escapes found in the input data can get expanded somewhere along the line in some shells. This patch, therefore, replaces this generation of test data with a pre-canned "Lorem ipsum" of approximately 2k. On my system, where /bin/sh is dash, this fixes a test failure due to the aforementioned string escapes being evaluated on one but not the other of the two comparison paths (I haven't tracked down exactly where the expansion is happening). Signed-off-by: David Gibson --- tests/lorem.txt | 35 +++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 32 ++++++-------------------------- 2 files changed, 41 insertions(+), 26 deletions(-) create mode 100644 tests/lorem.txt diff --git a/tests/lorem.txt b/tests/lorem.txt new file mode 100644 index 0000000..acff698 --- /dev/null +++ b/tests/lorem.txt @@ -0,0 +1,35 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris eros +arcu, egestas non pellentesque non, euismod eu nibh. Proin arcu metus, +dapibus vitae sodales rhoncus, suscipit vel nulla. Etiam lorem est, +aliquam ut fringilla sit amet, condimentum et quam. Duis eu arcu odio, +at pulvinar nisi. Morbi condimentum eros ut turpis rhoncus +pharetra. Pellentesque habitant morbi tristique senectus et netus et +malesuada fames ac turpis egestas. Nam et nulla enim. Etiam fringilla +eleifend neque, at posuere ante lacinia a. Duis orci tortor, dictum ac +gravida ac, euismod eu leo. Sed eget dolor tortor. Pellentesque +venenatis, lectus eu vulputate porta, libero ipsum convallis mi, sit +amet vehicula arcu elit sit amet odio. + +Fusce iaculis massa metus, id sagittis diam. Praesent molestie ante +vel odio tincidunt auctor. Cum sociis natoque penatibus et magnis dis +parturient montes, nascetur ridiculus mus. Duis rutrum vehicula nisl +eget condimentum. In in justo nisl. Nullam id arcu at nisl eleifend +pretium. Nulla interdum ligula id elit mollis dictum a sit amet +quam. Nullam iaculis laoreet ipsum at tempus. Vestibulum in cursus +dui. Curabitur porta lectus eget urna bibendum congue eget elementum +nisi. Proin sit amet lectus ut neque iaculis consectetur eu sit amet +nibh. Maecenas rhoncus dolor ac nunc gravida blandit. Fusce sem felis, +aliquam a porttitor a, porta quis odio. + +Nunc purus lorem, sollicitudin non ultricies id, porta vitae +enim. Nulla tristique gravida leo ut suscipit. Phasellus vitae turpis +libero. Proin ac purus dolor, in suscipit magna. Sed et enim +arcu. Morbi semper aliquet suscipit. Aenean laoreet condimentum massa, +eu pharetra magna fermentum ut. Morbi euismod convallis tortor, eget +fringilla lacus sagittis non. Nullam bibendum posuere feugiat. + +In at pulvinar massa. Mauris nunc lectus, mollis et malesuada +pharetra, cursus sed lacus. Integer dolor urna, interdum a mollis at, +vestibulum non nisl. Sed in urna tortor. Mauris arcu felis, volutpat +quis euismod vel, congue sit amet ipsum. Morbi in aliquet purus. Duis +cras amet. diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 999c882..a561433 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -480,28 +480,10 @@ fdtget_tests () { fdtput_tests () { dts=label01.dts dtb=$dts.fdtput.test.dtb + text=lorem.txt - # Create some test files containing useful strings - base=tmp.test0 - file1=tmp.test1 - file2=tmp.test2 - bigfile1=tmp.test3 - bigfile2=tmp.test4 - - # Filter out anything the shell might not like - cat $dts | tr -d "'\"\n\;/\.\*{}\-" | tr -s "[:blank:]" " " >$base - - # Make two small files - head -5 $base >$file1 - cat $file1 | tr a-z A-Z | cut -c10-30 | sort -r >$file2 - - # and two larger ones - cat $base > $bigfile1 - tac $base | tr a-z A-Z | sort -r >$bigfile2 - - # Allow just enough space for both file1 and file2 - space=$(( $(stat -c %s $file1) + $(stat -c %s $file2) )) - run_dtc_test -O dtb -p $space -o $dtb $dts + # Allow just enough space for $text + run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts # run_fdtput_test run_fdtput_test "a_model" $dtb / model -ts "a_model" @@ -514,12 +496,10 @@ fdtput_tests () { -tbx "a b c ea ad be ef" run_fdtput_test "a0b0c0d deeaae ef000000" $dtb /randomnode blob \ -tx "a0b0c0d deeaae ef000000" - run_fdtput_test "`cat $file1 $file2`" $dtb /randomnode blob \ - -ts "`cat $file1`" "`cat $file2`" + run_fdtput_test "$(cat $text)" $dtb /randomnode blob -ts "$(cat $text)" - # This should be larger than available space in the fdt ($space) - run_wrap_error_test $DTPUT $dtb /randomnode blob \ - -ts "`cat $bigfile1`" "`cat $bigfile2`" + # This should be larger than available space in the fdt + run_wrap_error_test $DTPUT $dtb /randomnode blob -ts "$(cat $text $text)" # TODO: Add tests for verbose mode? } From e280442e08fcbe8431dc85d836ff3ecc489932fb Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Feb 2012 17:06:12 +1100 Subject: [PATCH 0349/1198] Fix uninitialized access bug in utilfdt_decode_type I just found this little bug with valgrind. strchr() will return true if the given character is '\0'. This meant that utilfdt_decode_type() could take a path which accesses uninitialized data when given the (invalid) format string "L". Signed-off-by: David Gibson --- util.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/util.c b/util.c index d82d41f..2422c34 100644 --- a/util.c +++ b/util.c @@ -296,6 +296,9 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size) { int qualifier = 0; + if (!*fmt) + return -1; + /* get the conversion qualifier */ *size = -1; if (strchr("hlLb", *fmt)) { @@ -311,7 +314,7 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size) } /* we should now have a type */ - if (!strchr("iuxs", *fmt)) + if ((*fmt == '\0') || !strchr("iuxs", *fmt)) return -1; /* convert qualifier (bhL) to byte size */ From a6e6c60e3a97a6b3a033cd052bb3740fd53cbf4c Mon Sep 17 00:00:00 2001 From: Horst Kronstorfer Date: Tue, 7 Feb 2012 10:02:53 +0100 Subject: [PATCH 0350/1198] dtc: Fix zero-length input segfault This patch fixes a segmentation fault caused by dereferencing a NULL pointer (pos->file aka yylloc.file) in srcpos_string when the input length is 0 (fe 'dtc --- treesource.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/treesource.c b/treesource.c index c09aafa..33eeba5 100644 --- a/treesource.c +++ b/treesource.c @@ -23,6 +23,7 @@ extern FILE *yyin; extern int yyparse(void); +extern YYLTYPE yylloc; struct boot_info *the_boot_info; int treesource_error; @@ -34,6 +35,7 @@ struct boot_info *dt_from_source(const char *fname) srcfile_push(fname); yyin = current_srcfile->f; + yylloc.file = current_srcfile; if (yyparse() != 0) die("Unable to parse input tree\n"); From 097ec97c1a35685957210adb93692c3e210bc82c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 2 Mar 2012 17:12:07 -0800 Subject: [PATCH 0351/1198] fdtget: Fix multiple arg bug and add test for it There is a rather unfortunate bug in fdtget in that if multiple argument sets are provided, it just repeats displaying the first set ones for each set. Fix this bug and add a test for it. Signed-off-by: Simon Glass Acked-by: David Gibson --- fdtget.c | 6 +++--- tests/fdtget-runtest.sh | 2 +- tests/run_tests.sh | 3 +++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/fdtget.c b/fdtget.c index 2c384b6..9783e04 100644 --- a/fdtget.c +++ b/fdtget.c @@ -146,13 +146,13 @@ static int do_fdtget(struct display_info *disp, const char *filename, return -1; for (i = 0; i + 2 <= arg_count; i += 2) { - node = fdt_path_offset(blob, arg[0]); + node = fdt_path_offset(blob, arg[i]); if (node < 0) { - report_error(arg[0], node); + report_error(arg[i], node); return -1; } - if (show_data_for_item(blob, disp, node, arg[1])) + if (show_data_for_item(blob, disp, node, arg[i + 1])) return -1; } return 0; diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh index dac7f9a..982fbe1 100755 --- a/tests/fdtget-runtest.sh +++ b/tests/fdtget-runtest.sh @@ -8,7 +8,7 @@ rm -f $LOG $EXPECT trap "rm -f $LOG $EXPECT" 0 expect="$1" -echo $expect >$EXPECT +echo -e $expect >$EXPECT shift verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@" diff --git a/tests/run_tests.sh b/tests/run_tests.sh index a561433..ac6fa17 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -475,6 +475,9 @@ fdtget_tests () { run_fdtget_test "61 62 63 0 12 34 0 0 0 a 0 0 0 b 0 0 0 c" \ -thhx $dtb /randomnode mixed run_wrap_error_test $DTGET -ts $dtb /randomnode doctor-who + + # Test multiple arguments + run_fdtget_test "MyBoardName\nmemory" -ts $dtb / model /memory device_type } fdtput_tests () { From 30eb201adae2132c36874c89d4c6cf3195659d71 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 2 Mar 2012 17:12:08 -0800 Subject: [PATCH 0352/1198] fdtget: Add -p to list the properties of a node This option lists the properties of each node given as a parameter, one property per line. Signed-off-by: Simon Glass Acked-by: David Gibson --- fdtget.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/fdtget.c b/fdtget.c index 9783e04..874bcbf 100644 --- a/fdtget.c +++ b/fdtget.c @@ -1,6 +1,12 @@ /* * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. * + * Portions from U-Boot cmd_fdt.c (C) Copyright 2007 + * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com + * Based on code written by: + * Pantelis Antoniou and + * Matthew McClintock + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of @@ -17,6 +23,7 @@ * MA 02111-1307 USA */ +#include #include #include #include @@ -27,10 +34,16 @@ #include "util.h" +enum display_mode { + MODE_SHOW_VALUE, /* show values for node properties */ + MODE_LIST_PROPS, /* list the properties for a node */ +}; + /* Holds information which controls our output and options */ struct display_info { int type; /* data type (s/i/u/x or 0 for default) */ int size; /* data size (1/2/4) */ + enum display_mode mode; /* display mode that we are using */ }; static void report_error(const char *where, int err) @@ -97,6 +110,32 @@ static int show_data(struct display_info *disp, const char *data, int len) return 0; } +/** + * List all properties in a node, one per line. + * + * @param blob FDT blob + * @param node Node to display + * @return 0 if ok, or FDT_ERR... if not. + */ +static int list_properties(const void *blob, int node) +{ + const struct fdt_property *data; + const char *name; + int prop; + + prop = fdt_first_property_offset(blob, node); + do { + /* Stop silently when there are no more properties */ + if (prop < 0) + return prop == -FDT_ERR_NOTFOUND ? 0 : prop; + data = fdt_get_property_by_offset(blob, prop, NULL); + name = fdt_string(blob, fdt32_to_cpu(data->nameoff)); + if (name) + puts(name); + prop = fdt_next_property_offset(blob, prop); + } while (1); +} + /** * Show the data for a given node (and perhaps property) according to the * display option provided. @@ -113,6 +152,10 @@ static int show_data_for_item(const void *blob, struct display_info *disp, const void *value = NULL; int len, err = 0; + if (disp->mode == MODE_LIST_PROPS) + return list_properties(blob, node); + + assert(property); value = fdt_getprop(blob, node, property, &len); if (value) { if (show_data(disp, value, len)) @@ -136,23 +179,25 @@ static int show_data_for_item(const void *blob, struct display_info *disp, * @param return 0 if ok, -ve on error */ static int do_fdtget(struct display_info *disp, const char *filename, - char **arg, int arg_count) + char **arg, int arg_count, int args_per_step) { char *blob; + const char *prop; int i, node; blob = utilfdt_read(filename); if (!blob) return -1; - for (i = 0; i + 2 <= arg_count; i += 2) { + for (i = 0; i + args_per_step <= arg_count; i += args_per_step) { node = fdt_path_offset(blob, arg[i]); if (node < 0) { report_error(arg[i], node); return -1; } + prop = args_per_step == 1 ? NULL : arg[i + 1]; - if (show_data_for_item(blob, disp, node, arg[i + 1])) + if (show_data_for_item(blob, disp, node, prop)) return -1; } return 0; @@ -164,8 +209,10 @@ static const char *usage_msg = "Each value is printed on a new line.\n\n" "Usage:\n" " fdtget
[ ]...\n" + " fdtget -p
[ ]...\n" "Options:\n" "\t-t \tType of data\n" + "\t-p\t\tList properties for each node\n" "\t-h\t\tPrint this help\n\n" USAGE_TYPE_MSG; @@ -182,12 +229,14 @@ int main(int argc, char *argv[]) { char *filename = NULL; struct display_info disp; + int args_per_step = 2; /* set defaults */ memset(&disp, '\0', sizeof(disp)); disp.size = -1; + disp.mode = MODE_SHOW_VALUE; for (;;) { - int c = getopt(argc, argv, "ht:"); + int c = getopt(argc, argv, "hpt:"); if (c == -1) break; @@ -201,6 +250,11 @@ int main(int argc, char *argv[]) &disp.size)) usage("Invalid type string"); break; + + case 'p': + disp.mode = MODE_LIST_PROPS; + args_per_step = 1; + break; } } @@ -217,10 +271,10 @@ int main(int argc, char *argv[]) return 0; /* Check for node, property arguments */ - if (argc % 2) + if (args_per_step == 2 && (argc % 2)) usage("Must have an even number of arguments"); - if (do_fdtget(&disp, filename, argv, argc)) + if (do_fdtget(&disp, filename, argv, argc, args_per_step)) return 1; return 0; } From 16c99ee8e3e60fb47b5eaa1778996fe6ef11c611 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Mar 2012 16:41:46 -0800 Subject: [PATCH 0353/1198] fdtget: Add -l to list the subnodes of a node This option lists the subnodes of each node given as a parameter, one subnode per line. Signed-off-by: Simon Glass Acked-by: David Gibson --- fdtget.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 12 deletions(-) diff --git a/fdtget.c b/fdtget.c index 874bcbf..2c7d238 100644 --- a/fdtget.c +++ b/fdtget.c @@ -37,6 +37,7 @@ enum display_mode { MODE_SHOW_VALUE, /* show values for node properties */ MODE_LIST_PROPS, /* list the properties for a node */ + MODE_LIST_SUBNODES, /* list the subnodes of a node */ }; /* Holds information which controls our output and options */ @@ -136,6 +137,61 @@ static int list_properties(const void *blob, int node) } while (1); } +#define MAX_LEVEL 32 /* how deeply nested we will go */ + +/** + * List all subnodes in a node, one per line + * + * @param blob FDT blob + * @param node Node to display + * @return 0 if ok, or FDT_ERR... if not. + */ +static int list_subnodes(const void *blob, int node) +{ + int nextoffset; /* next node offset from libfdt */ + uint32_t tag; /* current tag */ + int level = 0; /* keep track of nesting level */ + const char *pathp; + int depth = 1; /* the assumed depth of this node */ + + while (level >= 0) { + tag = fdt_next_tag(blob, node, &nextoffset); + switch (tag) { + case FDT_BEGIN_NODE: + pathp = fdt_get_name(blob, node, NULL); + if (level <= depth) { + if (pathp == NULL) + pathp = "/* NULL pointer error */"; + if (*pathp == '\0') + pathp = "/"; /* root is nameless */ + if (level == 1) + puts(pathp); + } + level++; + if (level >= MAX_LEVEL) { + printf("Nested too deep, aborting.\n"); + return 1; + } + break; + case FDT_END_NODE: + level--; + if (level == 0) + level = -1; /* exit the loop */ + break; + case FDT_END: + return 1; + case FDT_PROP: + break; + default: + if (level <= depth) + printf("Unknown tag 0x%08X\n", tag); + return 1; + } + node = nextoffset; + } + return 0; +} + /** * Show the data for a given node (and perhaps property) according to the * display option provided. @@ -152,20 +208,30 @@ static int show_data_for_item(const void *blob, struct display_info *disp, const void *value = NULL; int len, err = 0; - if (disp->mode == MODE_LIST_PROPS) - return list_properties(blob, node); + switch (disp->mode) { + case MODE_LIST_PROPS: + err = list_properties(blob, node); + break; - assert(property); - value = fdt_getprop(blob, node, property, &len); - if (value) { - if (show_data(disp, value, len)) + case MODE_LIST_SUBNODES: + err = list_subnodes(blob, node); + break; + + default: + assert(property); + value = fdt_getprop(blob, node, property, &len); + if (value) { + if (show_data(disp, value, len)) + err = -1; + else + printf("\n"); + } else { + report_error(property, len); err = -1; - else - printf("\n"); - } else { - report_error(property, len); - err = -1; + } + break; } + return err; } @@ -213,6 +279,7 @@ static const char *usage_msg = "Options:\n" "\t-t \tType of data\n" "\t-p\t\tList properties for each node\n" + "\t-l\t\tList subnodes for each node\n" "\t-h\t\tPrint this help\n\n" USAGE_TYPE_MSG; @@ -236,7 +303,7 @@ int main(int argc, char *argv[]) disp.size = -1; disp.mode = MODE_SHOW_VALUE; for (;;) { - int c = getopt(argc, argv, "hpt:"); + int c = getopt(argc, argv, "hlpt:"); if (c == -1) break; @@ -255,6 +322,11 @@ int main(int argc, char *argv[]) disp.mode = MODE_LIST_PROPS; args_per_step = 1; break; + + case 'l': + disp.mode = MODE_LIST_SUBNODES; + args_per_step = 1; + break; } } From 7fcbef275741793064268cf0a1bdcd59144a9a10 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Mar 2012 16:41:47 -0800 Subject: [PATCH 0354/1198] fdtget: Add -d to provide a default value Sometimes the requested node or property is not present in the device tree. This option provides a way of reporting a default value in this case, rather than halting with an error. Signed-off-by: Simon Glass Acked-by: David Gibson --- fdtget.c | 20 +++++++++++++++++--- tests/run_tests.sh | 6 ++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/fdtget.c b/fdtget.c index 2c7d238..c2fbab2 100644 --- a/fdtget.c +++ b/fdtget.c @@ -45,6 +45,7 @@ struct display_info { int type; /* data type (s/i/u/x or 0 for default) */ int size; /* data size (1/2/4) */ enum display_mode mode; /* display mode that we are using */ + const char *default_val; /* default value if node/property not found */ }; static void report_error(const char *where, int err) @@ -225,6 +226,8 @@ static int show_data_for_item(const void *blob, struct display_info *disp, err = -1; else printf("\n"); + } else if (disp->default_val) { + puts(disp->default_val); } else { report_error(property, len); err = -1; @@ -258,8 +261,13 @@ static int do_fdtget(struct display_info *disp, const char *filename, for (i = 0; i + args_per_step <= arg_count; i += args_per_step) { node = fdt_path_offset(blob, arg[i]); if (node < 0) { - report_error(arg[i], node); - return -1; + if (disp->default_val) { + puts(disp->default_val); + continue; + } else { + report_error(arg[i], node); + return -1; + } } prop = args_per_step == 1 ? NULL : arg[i + 1]; @@ -280,6 +288,8 @@ static const char *usage_msg = "\t-t \tType of data\n" "\t-p\t\tList properties for each node\n" "\t-l\t\tList subnodes for each node\n" + "\t-d\t\tDefault value to display when the property is " + "missing\n" "\t-h\t\tPrint this help\n\n" USAGE_TYPE_MSG; @@ -303,7 +313,7 @@ int main(int argc, char *argv[]) disp.size = -1; disp.mode = MODE_SHOW_VALUE; for (;;) { - int c = getopt(argc, argv, "hlpt:"); + int c = getopt(argc, argv, "d:hlpt:"); if (c == -1) break; @@ -327,6 +337,10 @@ int main(int argc, char *argv[]) disp.mode = MODE_LIST_SUBNODES; args_per_step = 1; break; + + case 'd': + disp.default_val = optarg; + break; } } diff --git a/tests/run_tests.sh b/tests/run_tests.sh index ac6fa17..deffae3 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -478,6 +478,12 @@ fdtget_tests () { # Test multiple arguments run_fdtget_test "MyBoardName\nmemory" -ts $dtb / model /memory device_type + + # Test defaults + run_wrap_error_test $DTGET -tx $dtb /randomnode doctor-who + run_fdtget_test "" -tx \ + -d "" $dtb /randomnode doctor-who + run_fdtget_test "" -tx -d "" $dtb /memory doctor-who } fdtput_tests () { From de6b76240e91b9288cdce63ab81e51a7232d0927 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 14 Mar 2012 20:04:13 -0700 Subject: [PATCH 0355/1198] dtc: Add -i option to support search paths It is often inconvenient to place device tree files in the same directory as their includes, or to specify the full path to include files. An example of this is in U-Boot where we have a .dtsi file for each SOC type, and this is included by the board .dts file. We need to either use a mechanism like: /include/ ARCH_CPU_DTS with sed or cpp to perform the replacement with the correct path, or we must specify the full path in the file: /include/ "../../arch/arm/dts/tegra20.dtsi" The first option is not desirable since it requires anyone compiling the file to first pre-process it. The second is not desirable since it introduces a path which is project-specific into a file which is supposed to be a hardware description. For example Linux and U-Boot are unlikely to put these include files in the same place. It is much more convenient to specify the search patch on the command line as is done with C pre-processors, for example. Introduce a -i option to add to the list of search paths used to find source and include files. We cannot use -I as it is already in use. Other suggestions welcome. Signed-off-by: Simon Glass --- dtc.c | 8 +- srcpos.c | 92 ++++++++++++++++++++-- srcpos.h | 29 +++++++ tests/run_tests.sh | 11 +++ tests/search_dir/search_test.dtsi | 4 + tests/search_dir/search_test2.dtsi | 3 + tests/search_dir_b/search_paths_subdir.dts | 6 ++ tests/search_dir_b/search_test_b.dtsi | 4 + tests/search_dir_b/search_test_b2.dtsi | 5 ++ tests/search_dir_b/search_test_c.dtsi | 2 + tests/search_paths.dts | 6 ++ tests/search_paths_b.dts | 6 ++ 12 files changed, 168 insertions(+), 8 deletions(-) create mode 100644 tests/search_dir/search_test.dtsi create mode 100644 tests/search_dir/search_test2.dtsi create mode 100644 tests/search_dir_b/search_paths_subdir.dts create mode 100644 tests/search_dir_b/search_test_b.dtsi create mode 100644 tests/search_dir_b/search_test_b2.dtsi create mode 100644 tests/search_dir_b/search_test_c.dtsi create mode 100644 tests/search_paths.dts create mode 100644 tests/search_paths_b.dts diff --git a/dtc.c b/dtc.c index 7a0c605..83aef32 100644 --- a/dtc.c +++ b/dtc.c @@ -82,6 +82,8 @@ static void __attribute__ ((noreturn)) usage(void) fprintf(stderr, "\t\tSet the physical boot cpu\n"); fprintf(stderr, "\t-f\n"); fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n"); + fprintf(stderr, "\t-i\n"); + fprintf(stderr, "\t\tAdd a path to search for include files\n"); fprintf(stderr, "\t-s\n"); fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n"); fprintf(stderr, "\t-v\n"); @@ -113,7 +115,8 @@ int main(int argc, char *argv[]) minsize = 0; padsize = 0; - while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:vH:s")) != EOF) { + while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:s")) + != EOF) { switch (opt) { case 'I': inform = optarg; @@ -148,6 +151,9 @@ int main(int argc, char *argv[]) case 'b': cmdline_boot_cpuid = strtoll(optarg, NULL, 0); break; + case 'i': + srcfile_add_search_path(optarg); + break; case 'v': printf("Version: %s\n", DTC_VERSION); exit(0); diff --git a/srcpos.c b/srcpos.c index 36a38e9..3ee523d 100644 --- a/srcpos.c +++ b/srcpos.c @@ -24,6 +24,15 @@ #include "dtc.h" #include "srcpos.h" +/* A node in our list of directories to search for source/include files */ +struct search_path { + struct search_path *next; /* next node in list, NULL for end */ + const char *dirname; /* name of directory to search */ +}; + +/* This is the list of directories that we search for source files */ +static struct search_path *search_path_head, **search_path_tail; + static char *dirname(const char *path) { @@ -47,6 +56,64 @@ struct srcfile_state *current_srcfile; /* = NULL */ #define MAX_SRCFILE_DEPTH (100) static int srcfile_depth; /* = 0 */ + +/** + * Try to open a file in a given directory. + * + * If the filename is an absolute path, then dirname is ignored. If it is a + * relative path, then we look in that directory for the file. + * + * @param dirname Directory to look in, or NULL for none + * @param fname Filename to look for + * @param fp Set to NULL if file did not open + * @return allocated filename on success (caller must free), NULL on failure + */ +static char *try_open(const char *dirname, const char *fname, FILE **fp) +{ + char *fullname; + + if (!dirname || fname[0] == '/') + fullname = xstrdup(fname); + else + fullname = join_path(dirname, fname); + + *fp = fopen(fullname, "r"); + if (!*fp) { + free(fullname); + fullname = NULL; + } + + return fullname; +} + +/** + * Open a file for read access + * + * If it is a relative filename, we search the full search path for it. + * + * @param fname Filename to open + * @param fp Returns pointer to opened FILE, or NULL on failure + * @return pointer to allocated filename, which caller must free + */ +static char *fopen_any_on_path(const char *fname, FILE **fp) +{ + const char *cur_dir = NULL; + struct search_path *node; + char *fullname; + + /* Try current directory first */ + assert(fp); + if (current_srcfile) + cur_dir = current_srcfile->dir; + fullname = try_open(cur_dir, fname, fp); + + /* Failing that, try each search path in turn */ + for (node = search_path_head; !*fp && node; node = node->next) + fullname = try_open(node->dirname, fname, fp); + + return fullname; +} + FILE *srcfile_relative_open(const char *fname, char **fullnamep) { FILE *f; @@ -56,13 +123,7 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep) f = stdin; fullname = xstrdup(""); } else { - if (!current_srcfile || !current_srcfile->dir - || (fname[0] == '/')) - fullname = xstrdup(fname); - else - fullname = join_path(current_srcfile->dir, fname); - - f = fopen(fullname, "r"); + fullname = fopen_any_on_path(fname, &f); if (!f) die("Couldn't open \"%s\": %s\n", fname, strerror(errno)); @@ -119,6 +180,23 @@ int srcfile_pop(void) return current_srcfile ? 1 : 0; } +void srcfile_add_search_path(const char *dirname) +{ + struct search_path *node; + + /* Create the node */ + node = xmalloc(sizeof(*node)); + node->next = NULL; + node->dirname = xstrdup(dirname); + + /* Add to the end of our list */ + if (search_path_tail) + *search_path_tail = node; + else + search_path_head = node; + search_path_tail = &node->next; +} + /* * The empty source position. */ diff --git a/srcpos.h b/srcpos.h index ce980ca..5617916 100644 --- a/srcpos.h +++ b/srcpos.h @@ -33,10 +33,39 @@ struct srcfile_state { extern FILE *depfile; /* = NULL */ extern struct srcfile_state *current_srcfile; /* = NULL */ +/** + * Open a source file. + * + * If the source file is a relative pathname, then it is searched for in the + * current directory (the directory of the last source file read) and after + * that in the search path. + * + * We work through the search path in order from the first path specified to + * the last. + * + * If the file is not found, then this function does not return, but calls + * die(). + * + * @param fname Filename to search + * @param fullnamep If non-NULL, it is set to the allocated filename of the + * file that was opened. The caller is then responsible + * for freeing the pointer. + * @return pointer to opened FILE + */ FILE *srcfile_relative_open(const char *fname, char **fullnamep); + void srcfile_push(const char *fname); int srcfile_pop(void); +/** + * Add a new directory to the search path for input files + * + * The new path is added at the end of the list. + * + * @param dirname Directory to add + */ +void srcfile_add_search_path(const char *dirname); + struct srcpos { int first_line; int first_column; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index deffae3..e470b82 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -412,6 +412,17 @@ dtc_tests () { # Dependencies run_dtc_test -I dts -O dtb -o dependencies.test.dtb -d dependencies.test.d dependencies.dts run_wrap_test cmp dependencies.test.d dependencies.cmp + + # Search paths + run_wrap_error_test $DTC -I dts -O dtb -o search_paths.dtb search_paths.dts + run_dtc_test -i search_dir -I dts -O dtb -o search_paths.dtb \ + search_paths.dts + run_wrap_error_test $DTC -i search_dir_b -I dts -O dtb \ + -o search_paths_b.dtb search_paths_b.dts + run_dtc_test -i search_dir_b -i search_dir -I dts -O dtb \ + -o search_paths_b.dtb search_paths_b.dts + run_dtc_test -I dts -O dtb -o search_paths_subdir.dtb \ + search_dir_b/search_paths_subdir.dts } cmp_tests () { diff --git a/tests/search_dir/search_test.dtsi b/tests/search_dir/search_test.dtsi new file mode 100644 index 0000000..217fb80 --- /dev/null +++ b/tests/search_dir/search_test.dtsi @@ -0,0 +1,4 @@ +/include/ "search_test2.dtsi" + +/ { +}; diff --git a/tests/search_dir/search_test2.dtsi b/tests/search_dir/search_test2.dtsi new file mode 100644 index 0000000..7b9099e --- /dev/null +++ b/tests/search_dir/search_test2.dtsi @@ -0,0 +1,3 @@ + +/ { +}; diff --git a/tests/search_dir_b/search_paths_subdir.dts b/tests/search_dir_b/search_paths_subdir.dts new file mode 100644 index 0000000..5c5c962 --- /dev/null +++ b/tests/search_dir_b/search_paths_subdir.dts @@ -0,0 +1,6 @@ +/dts-v1/; + +/include/ "search_test_c.dtsi" + +/ { +}; diff --git a/tests/search_dir_b/search_test_b.dtsi b/tests/search_dir_b/search_test_b.dtsi new file mode 100644 index 0000000..b06a7d6 --- /dev/null +++ b/tests/search_dir_b/search_test_b.dtsi @@ -0,0 +1,4 @@ +/include/ "search_test_b2.dtsi" + +/ { +}; diff --git a/tests/search_dir_b/search_test_b2.dtsi b/tests/search_dir_b/search_test_b2.dtsi new file mode 100644 index 0000000..2526b43 --- /dev/null +++ b/tests/search_dir_b/search_test_b2.dtsi @@ -0,0 +1,5 @@ + +/include/ "search_test.dtsi" + +/ { +}; diff --git a/tests/search_dir_b/search_test_c.dtsi b/tests/search_dir_b/search_test_c.dtsi new file mode 100644 index 0000000..336d7a2 --- /dev/null +++ b/tests/search_dir_b/search_test_c.dtsi @@ -0,0 +1,2 @@ +/ { +}; diff --git a/tests/search_paths.dts b/tests/search_paths.dts new file mode 100644 index 0000000..a2bf179 --- /dev/null +++ b/tests/search_paths.dts @@ -0,0 +1,6 @@ +/dts-v1/; + +/include/ "search_test.dtsi" + +/ { +}; diff --git a/tests/search_paths_b.dts b/tests/search_paths_b.dts new file mode 100644 index 0000000..6ace6e2 --- /dev/null +++ b/tests/search_paths_b.dts @@ -0,0 +1,6 @@ +/dts-v1/; + +/include/ "search_test_b.dtsi" + +/ { +}; From eaec1dbc5946d5fd01a9ef7120f8461c74d759a0 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 20 Mar 2012 20:23:46 -0600 Subject: [PATCH 0356/1198] fdtget-runtest.sh: Fix failures when /bin/sh isn't bash On Ubuntu, /bin/sh is dash (at least by default), and dash's echo doesn't accept the -e option. This means that fdtget-runtest.sh's EXPECT file will contain "-e foo" rather than just "foo", which causes a test failure. To work around this, run /bin/echo instead of (builtin) echo, which has more chance of supporting the -e option. Another possible fix is to change all the #! lines to /bin/bash rather than /bin/sh, and change run_tests.sh to invoke sub-scripts using $SHELL instead of just "sh". However, that would require bash specifically, which may not be desirable. Signed-off-by: Stephen Warren Acked-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 982fbe1..c3a3559 100755 --- a/tests/fdtget-runtest.sh +++ b/tests/fdtget-runtest.sh @@ -8,7 +8,7 @@ rm -f $LOG $EXPECT trap "rm -f $LOG $EXPECT" 0 expect="$1" -echo -e $expect >$EXPECT +/bin/echo -e $expect >$EXPECT shift verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@" From 5f0c3b2d6235dec65fff1628a97f45e21680b36d Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 3 Apr 2012 20:56:00 -0600 Subject: [PATCH 0357/1198] dtc: Basic integer expressions Written by David Gibson . Additions by me: * Ported to ToT dtc. * Renamed cell to integer throughout. * Implemented value range checks. * Allow U/L/UL/LL/ULL suffix on literals. * Enabled the commented test. Signed-off-by: Stephen Warren --- dtc-lexer.l | 11 ++- dtc-parser.y | 154 ++++++++++++++++++++++++++++++------ tests/Makefile.tests | 3 +- tests/integer-expressions.c | 117 +++++++++++++++++++++++++++ tests/run_tests.sh | 5 ++ 5 files changed, 265 insertions(+), 25 deletions(-) create mode 100644 tests/integer-expressions.c diff --git a/dtc-lexer.l b/dtc-lexer.l index 73d190c..4715f31 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -110,7 +110,7 @@ static int pop_input_file(void); return DT_LABEL; } -[0-9]+|0[xX][0-9a-fA-F]+ { +([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? { yylval.literal = xstrdup(yytext); DPRINT("Literal: '%s'\n", yylval.literal); return DT_LITERAL; @@ -164,6 +164,15 @@ static int pop_input_file(void); <*>{COMMENT}+ /* eat C-style comments */ <*>{LINECOMMENT}+ /* eat C++-style comments */ +<*>"<<" { return DT_LSHIFT; }; +<*>">>" { return DT_RSHIFT; }; +<*>"<=" { return DT_LE; }; +<*>">=" { return DT_GE; }; +<*>"==" { return DT_EQ; }; +<*>"!=" { return DT_NE; }; +<*>"&&" { return DT_AND; }; +<*>"||" { return DT_OR; }; + <*>. { DPRINT("Char: %c (\\x%02x)\n", yytext[0], (unsigned)yytext[0]); diff --git a/dtc-parser.y b/dtc-parser.y index 348616b..6d5c2c2 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -50,16 +50,17 @@ static unsigned char eval_char_literal(const char *s); int bits; } array; - uint64_t addr; struct property *prop; struct property *proplist; struct node *node; struct node *nodelist; struct reserve_info *re; + uint64_t integer; } %token DT_V1 %token DT_MEMRESERVE +%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR %token DT_BITS %token DT_PROPNODENAME %token DT_LITERAL @@ -75,7 +76,6 @@ static unsigned char eval_char_literal(const char *s); %type propdataprefix %type memreserve %type memreserves -%type addr %type arrayprefix %type bytestring %type propdef @@ -86,6 +86,21 @@ static unsigned char eval_char_literal(const char *s); %type subnode %type subnodes +%type integer_prim +%type integer_unary +%type integer_mul +%type integer_add +%type integer_shift +%type integer_rela +%type integer_eq +%type integer_bitand +%type integer_bitxor +%type integer_bitor +%type integer_and +%type integer_or +%type integer_trinary +%type integer_expr + %% sourcefile: @@ -108,7 +123,7 @@ memreserves: ; memreserve: - DT_MEMRESERVE addr addr ';' + DT_MEMRESERVE integer_prim integer_prim ';' { $$ = build_reserve_entry($2, $3); } @@ -119,13 +134,6 @@ memreserve: } ; -addr: - DT_LITERAL - { - $$ = eval_literal($1, 0, 64); - } - ; - devicetree: '/' nodedef { @@ -198,7 +206,7 @@ propdata: { $$ = data_add_marker($1, REF_PATH, $2); } - | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')' + | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' { FILE *f = srcfile_relative_open($4.val, NULL); struct data d; @@ -267,17 +275,25 @@ arrayprefix: $$.data = empty_data; $$.bits = 32; } - | arrayprefix DT_LITERAL + | arrayprefix integer_prim { - uint64_t val = eval_literal($2, 0, $1.bits); + if ($1.bits < 64) { + uint64_t mask = (1ULL << $1.bits) - 1; + /* + * Bits above mask must either be all zero + * (positive within range of mask) or all one + * (negative and sign-extended). The second + * condition is true if when we set all bits + * within the mask to one (i.e. | in the + * mask), all bits are one. + */ + if (($2 > mask) && (($2 | mask) != -1ULL)) + print_error( + "integer value out of range " + "%016lx (%d bits)", $1.bits); + } - $$.data = data_append_integer($1.data, val, $1.bits); - } - | arrayprefix DT_CHAR_LITERAL - { - uint64_t val = eval_char_literal($2); - - $$.data = data_append_integer($1.data, val, $1.bits); + $$.data = data_append_integer($1.data, $2, $1.bits); } | arrayprefix DT_REF { @@ -299,6 +315,95 @@ arrayprefix: } ; +integer_prim: + DT_LITERAL + { + $$ = eval_literal($1, 0, 64); + } + | DT_CHAR_LITERAL + { + $$ = eval_char_literal($1); + } + | '(' integer_expr ')' + { + $$ = $2; + } + ; + +integer_expr: + integer_trinary + ; + +integer_trinary: + integer_or + | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; } + ; + +integer_or: + integer_and + | integer_or DT_OR integer_and { $$ = $1 || $3; } + ; + +integer_and: + integer_bitor + | integer_and DT_AND integer_bitor { $$ = $1 && $3; } + ; + +integer_bitor: + integer_bitxor + | integer_bitor '|' integer_bitxor { $$ = $1 | $3; } + ; + +integer_bitxor: + integer_bitand + | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; } + ; + +integer_bitand: + integer_eq + | integer_bitand '&' integer_eq { $$ = $1 & $3; } + ; + +integer_eq: + integer_rela + | integer_eq DT_EQ integer_rela { $$ = $1 == $3; } + | integer_eq DT_NE integer_rela { $$ = $1 != $3; } + ; + +integer_rela: + integer_shift + | integer_rela '<' integer_shift { $$ = $1 < $3; } + | integer_rela '>' integer_shift { $$ = $1 > $3; } + | integer_rela DT_LE integer_shift { $$ = $1 <= $3; } + | integer_rela DT_GE integer_shift { $$ = $1 >= $3; } + ; + +integer_shift: + integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; } + | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; } + | integer_add + ; + +integer_add: + integer_add '+' integer_mul { $$ = $1 + $3; } + | integer_add '-' integer_mul { $$ = $1 - $3; } + | integer_mul + ; + +integer_mul: + integer_mul '*' integer_unary { $$ = $1 * $3; } + | integer_mul '/' integer_unary { $$ = $1 / $3; } + | integer_mul '%' integer_unary { $$ = $1 % $3; } + | integer_unary + ; + +integer_unary: + integer_prim + | '-' integer_unary { $$ = -$2; } + | '~' integer_unary { $$ = ~$2; } + | '!' integer_unary { $$ = !$2; } + ; + bytestring: /* empty */ { @@ -366,9 +471,12 @@ static unsigned long long eval_literal(const char *s, int base, int bits) errno = 0; val = strtoull(s, &e, base); - if (*e) - print_error("bad characters in literal"); - else if ((errno == ERANGE) + if (*e) { + size_t uls = strspn(e, "UL"); + if (e[uls]) + print_error("bad characters in literal"); + } + if ((errno == ERANGE) || ((bits < 64) && (val >= (1ULL << bits)))) print_error("literal out of range"); else if (errno != 0) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 2eee708..1795466 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -19,7 +19,8 @@ LIB_TESTS_L = get_mem_rsv \ dtbs_equal_ordered \ dtb_reverse dtbs_equal_unordered \ add_subnode_with_nops path_offset_aliases \ - utilfdt_test + utilfdt_test \ + integer-expressions LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property diff --git a/tests/integer-expressions.c b/tests/integer-expressions.c new file mode 100644 index 0000000..5ba1566 --- /dev/null +++ b/tests/integer-expressions.c @@ -0,0 +1,117 @@ +/* + * Testcase for dtc expression support + * + * Copyright (C) 2008 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + + +#include +#include + +#include "tests.h" +#include "testdata.h" + +struct test_expr { + const char *expr; + uint32_t result; +} expr_table[] = { +#define TE(expr) { #expr, (expr) } + TE(0xdeadbeef), + TE(-0x21524111), + TE(1+1), + TE(2*3), + TE(4/2), + TE(10/3), + TE(19%4), + TE(1 << 13), + TE(0x1000 >> 4), + TE(3*2+1), TE(3*(2+1)), + TE(1+2*3), TE((1+2)*3), + TE(1 < 2), TE(2 < 1), TE(1 < 1), + TE(1 <= 2), TE(2 <= 1), TE(1 <= 1), + TE(1 > 2), TE(2 > 1), TE(1 > 1), + TE(1 >= 2), TE(2 >= 1), TE(1 >= 1), + TE(1 == 1), TE(1 == 2), + TE(1 != 1), TE(1 != 2), + TE(0xabcdabcd & 0xffff0000), + TE(0xdead4110 ^ 0xf0f0f0f0), + TE(0xabcd0000 | 0x0000abcd), + TE(~0x21524110), + TE(~~0xdeadbeef), + TE(0 && 0), TE(17 && 0), TE(0 && 17), TE(17 && 17), + TE(0 || 0), TE(17 || 0), TE(0 || 17), TE(17 || 17), + TE(!0), TE(!1), TE(!17), TE(!!0), TE(!!17), + TE(0 ? 17 : 39), TE(1 ? 17 : 39), TE(17 ? 0xdeadbeef : 0xabcd1234), + TE(11 * 257 * 1321517ULL), + TE(123456790 - 4/2 + 17%4), +}; + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +int main(int argc, char *argv[]) +{ + void *fdt; + const uint32_t *res; + int reslen; + int i; + + test_init(argc, argv); + + if ((argc == 3) && (strcmp(argv[1], "-g") == 0)) { + FILE *f = fopen(argv[2], "w"); + + if (!f) + FAIL("Couldn't open \"%s\" for output: %s\n", + argv[2], strerror(errno)); + + fprintf(f, "/dts-v1/;\n"); + fprintf(f, "/ {\n"); + fprintf(f, "\texpressions = <\n"); + for (i = 0; i < ARRAY_SIZE(expr_table); i++) + fprintf(f, "\t\t(%s)\n", expr_table[i].expr); + fprintf(f, "\t>;\n"); + fprintf(f, "};\n"); + fclose(f); + } else { + fdt = load_blob_arg(argc, argv); + + res = fdt_getprop(fdt, 0, "expressions", &reslen); + + if (!res) + FAIL("Error retreiving expression results: %s\n", + fdt_strerror(reslen)); + + if (reslen != (ARRAY_SIZE(expr_table) * sizeof(uint32_t))) + FAIL("Unexpected length of results %d instead of %zd\n", + reslen, ARRAY_SIZE(expr_table) * sizeof(uint32_t)); + + for (i = 0; i < ARRAY_SIZE(expr_table); i++) + if (fdt32_to_cpu(res[i]) != expr_table[i].result) + FAIL("Incorrect result for expression \"%s\"," + " 0x%x instead of 0x%x\n", + expr_table[i].expr, fdt32_to_cpu(res[i]), + expr_table[i].result); + } + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index e470b82..ab8133c 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -404,6 +404,11 @@ 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 + 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 + # Check for graceful failure in some error conditions run_sh_test dtc-fatal.sh -I dts -O dtb nosuchfile.dts run_sh_test dtc-fatal.sh -I dtb -O dtb nosuchfile.dtb From 37b167f68afa21fbecb3077839f9c037a1459701 Mon Sep 17 00:00:00 2001 From: Bert Kenward Date: Tue, 10 Apr 2012 08:00:15 -0700 Subject: [PATCH 0358/1198] Remove invalid macro starting with _ from libfdt_env.h libfdt_env.h in the device tree compiler currently defines a _B() macro. This is in the namespace reserved for the implementation, and Cygwin's ctype.h actually defines a macro with this name. This renames _B to EXTRACT_BYTE. Signed-off-by: Bert Kenward --- libfdt/libfdt_env.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h index da952e7..213d7fb 100644 --- a/libfdt/libfdt_env.h +++ b/libfdt/libfdt_env.h @@ -5,25 +5,25 @@ #include #include -#define _B(n) ((unsigned long long)((uint8_t *)&x)[n]) +#define EXTRACT_BYTE(n) ((unsigned long long)((uint8_t *)&x)[n]) static inline uint16_t fdt16_to_cpu(uint16_t x) { - return (_B(0) << 8) | _B(1); + return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1); } #define cpu_to_fdt16(x) fdt16_to_cpu(x) static inline uint32_t fdt32_to_cpu(uint32_t x) { - return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3); + return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3); } #define cpu_to_fdt32(x) fdt32_to_cpu(x) static inline uint64_t fdt64_to_cpu(uint64_t x) { - return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32) - | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7); + return (EXTRACT_BYTE(0) << 56) | (EXTRACT_BYTE(1) << 48) | (EXTRACT_BYTE(2) << 40) | (EXTRACT_BYTE(3) << 32) + | (EXTRACT_BYTE(4) << 24) | (EXTRACT_BYTE(5) << 16) | (EXTRACT_BYTE(6) << 8) | EXTRACT_BYTE(7); } #define cpu_to_fdt64(x) fdt64_to_cpu(x) -#undef _B +#undef EXTRACT_BYTE #endif /* _LIBFDT_ENV_H */ From 3cbf82987425f0bfcdd898a24db9647b35ee7351 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 11 Apr 2012 16:32:26 -0700 Subject: [PATCH 0359/1198] dtc: Remove spurious output on stderr Outputing to stderr is best avoided unless there is an error or warning to display. At present dtc always displays the name of the file it is compiling and the input/output formats. For example: DTC: dts->dts on file "-" This can cause problems in some build systems. For example, U-Boot shows build errors for any boards which use dtc at present. It is typically the only message output during such a build. The C compiler does not output anything in general. The current dtc behaviour makes it difficult to provide a silent build in the normal case where nothing went wrong. Remove the message entirely. Signed-off-by: Simon Glass Acked-by: David Gibson --- dtc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/dtc.c b/dtc.c index 83aef32..bee5085 100644 --- a/dtc.c +++ b/dtc.c @@ -193,9 +193,6 @@ int main(int argc, char *argv[]) if (minsize) fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n"); - fprintf(stderr, "DTC: %s->%s on file \"%s\"\n", - inform, outform, arg); - if (depname) { depfile = fopen(depname, "w"); if (!depfile) From 84a94f6ffcab762f44e44cba3409b7bc5fa46a89 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 19 Apr 2012 09:33:35 -0700 Subject: [PATCH 0360/1198] dtc: Adjust .gitignore to be in alphabetical order This is the intent, so correct it. Signed-off-by: Simon Glass --- tests/.gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/.gitignore b/tests/.gitignore index 0b71bcf..cca3dbc 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -10,6 +10,8 @@ tmp.* /del_node /del_property /dtbs_equal_ordered +/dtbs_equal_unordered +/dtb_reverse /dumptrees /extra-terminating-null /find_property @@ -50,5 +52,3 @@ tmp.* /truncated_property /utilfdt_test /value-labels -/dtb_reverse -/dtbs_equal_unordered From 3ec9cb570333769295774e4fd0e2000d35cf6eda Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 19 Apr 2012 09:33:36 -0700 Subject: [PATCH 0361/1198] Add integer expressions files to .gitignore Several files were added, and should be in .gitignore. The *.test.dts pattern should catch future source files which are generated by tests. It also subsumes the old *.dtb.test.dts pattern. Signed-off-by: Simon Glass --- tests/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/.gitignore b/tests/.gitignore index cca3dbc..f8e1af0 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,6 +1,6 @@ *.dtb -*.dtb.test.dts *.dts.test.s +*.test.dts tmp.* /add_subnode_with_nops /appendprop[12] @@ -22,6 +22,7 @@ tmp.* /get_phandle /getprop /incbin +/integer-expressions /mangle-layout /move_and_save /node_check_compatible From 4adbb5336b0eed99f30c852d9dcf3cd125cae921 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Jun 2012 14:12:36 +1000 Subject: [PATCH 0362/1198] Remove test_tree1_dts0 testcases The testcases based on test_tree1_dts0.dts were added purely to test dtc's backwards compatibility handling of the old dts-v0 format. Since that support has been removed, the dts has been updated to use the current dts-v1 syntax, which makes the testcases pass, but be completely useless. This patch removes the now obsolete testcases. Signed-off-by: David Gibson --- tests/run_tests.sh | 4 ---- tests/test_tree1_dts0.dts | 37 ------------------------------------- 2 files changed, 41 deletions(-) delete mode 100644 tests/test_tree1_dts0.dts diff --git a/tests/run_tests.sh b/tests/run_tests.sh index ab8133c..9a2a7d9 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -254,10 +254,6 @@ dtc_tests () { tree1_tests_rw dtc_tree1.test.dtb run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb - run_dtc_test -I dts -O dtb -o dtc_tree1_dts0.test.dtb test_tree1_dts0.dts - tree1_tests dtc_tree1_dts0.test.dtb - tree1_tests_rw dtc_tree1_dts0.test.dtb - run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts run_test string_escapes dtc_escapes.test.dtb diff --git a/tests/test_tree1_dts0.dts b/tests/test_tree1_dts0.dts deleted file mode 100644 index 032d540..0000000 --- a/tests/test_tree1_dts0.dts +++ /dev/null @@ -1,37 +0,0 @@ -/dts-v1/; - -/memreserve/ 0xdeadbeef00000000 0x0000000000100000; -/memreserve/ 0x00000000075bcd15 0x0000000000001000; - -/ { - compatible = "test_tree1"; - prop-int = <0xdeadbeef>; - prop-str = "hello world"; - - subnode@1 { - compatible = "subnode1"; - prop-int = [deadbeef]; - - subsubnode { - compatible = "subsubnode1", "subsubnode"; - prop-int = < 0xdeadbeef>; - }; - - ss1 { - }; - }; - - subnode@2 { - linux,phandle = <0x2000>; - prop-int = < 123456789>; - - subsubnode@0 { - linux,phandle = <0x2001>; - compatible = "subsubnode2", "subsubnode"; - prop-int = < 0726746425>; - }; - - ss2 { - }; - }; -}; From cbf1410eab4b7ce7be1b15f985ef71bfc1f5886d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Jun 2012 14:12:37 +1000 Subject: [PATCH 0363/1198] libfdt: Add helpers for 64-bit integer properties In device trees in the world, properties consisting of a single 64-bit integer are not as common as those consisting of a single 32-bit, cell sized integer, but they're common enough that they're worth including convenience functions for. This patch adds helper wrappers of fdt_setprop_inplace(), fdt_setprop() and fdt_appendprop() for handling 64-bit integer quantities in properties. For better consistency with the names of these new *_u64() functions we also add *_u32() functions as alternative names for the existing *_cell() functions handling 32-bit integers. Signed-off-by: David Gibson --- libfdt/libfdt.h | 193 ++++++++++++++++++++++++---- tests/appendprop.dts | 1 + tests/appendprop1.c | 1 + tests/appendprop2.c | 1 + tests/include1.dts | 1 + tests/include5a.dts | 1 + tests/rw_tree1.c | 3 +- tests/setprop.c | 18 +++ tests/setprop_inplace.c | 15 +++ tests/sw_tree1.c | 3 +- tests/test_tree1.dts | 1 + tests/test_tree1_merge.dts | 1 + tests/test_tree1_merge_labelled.dts | 1 + tests/test_tree1_merge_path.dts | 1 + tests/testdata.h | 2 + tests/tests.h | 5 + tests/trees.S | 6 + 17 files changed, 229 insertions(+), 25 deletions(-) create mode 100644 tests/include5a.dts diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 060479e..35d78b8 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -852,17 +852,17 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len); /** - * fdt_setprop_inplace_cell - change the value of a single-cell property + * fdt_setprop_inplace_u32 - change the value of a 32-bit integer 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: cell (32-bit integer) value to replace the property with + * @val: 32-bit integer value to replace the property with * - * fdt_setprop_inplace_cell() replaces the value of a given property - * with the 32-bit integer cell value in val, converting val to - * big-endian if necessary. This function cannot change the size of a - * property, and so will only work if the property already exists and - * has length 4. + * fdt_setprop_inplace_u32() replaces the value of a given property + * with the 32-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 4. * * This function will alter only the bytes in the blob which contain * the given property value, and will not alter or move any other part @@ -871,7 +871,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, * returns: * 0, on success * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 - * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_NOTFOUND, node does not have the named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, @@ -879,13 +879,59 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ -static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, - const char *name, uint32_t val) +static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) { val = cpu_to_fdt32(val); return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); } +/** + * fdt_setprop_inplace_u64 - change the value of a 64-bit integer 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: 64-bit integer value to replace the property with + * + * fdt_setprop_inplace_u64() replaces the value of a given property + * with the 64-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 8. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + val = cpu_to_fdt64(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); +} + +/** + * fdt_setprop_inplace_cell - change the value of a single-cell property + * + * This is an alternative name for fdt_setprop_inplace_u32() + */ +static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); +} + /** * fdt_nop_property - replace a property with nop tags * @fdt: pointer to the device tree blob @@ -945,11 +991,20 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); int fdt_finish_reservemap(void *fdt); int fdt_begin_node(void *fdt, const char *name); int fdt_property(void *fdt, const char *name, const void *val, int len); -static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) +static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) { val = cpu_to_fdt32(val); return fdt_property(fdt, name, &val, sizeof(val)); } +static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) +{ + val = cpu_to_fdt64(val); + return fdt_property(fdt, name, &val, sizeof(val)); +} +static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) +{ + return fdt_property_u32(fdt, name, val); +} #define fdt_property_string(fdt, name, str) \ fdt_property(fdt, name, str, strlen(str)+1) int fdt_end_node(void *fdt); @@ -1068,14 +1123,14 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len); /** - * fdt_setprop_cell - set a property to a single cell value + * fdt_setprop_u32 - set a property to a 32-bit integer * @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) * - * fdt_setprop_cell() sets the value of the named property in the - * given node to the given cell value (converting to big-endian if + * fdt_setprop_u32() sets the value of the named property in the given + * node to the given 32-bit integer value (converting to big-endian if * necessary), or creates a new property with that value if it does * not already exist. * @@ -1095,13 +1150,59 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ -static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, - uint32_t val) +static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, + uint32_t val) { val = cpu_to_fdt32(val); return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); } +/** + * fdt_setprop_u64 - set a property to a 64-bit integer + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value for the property (native endian) + * + * fdt_setprop_u64() sets the value of the named property in the given + * node to the given 64-bit integer value (converting to big-endian if + * necessary), 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 + */ +static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, + uint64_t val) +{ + val = cpu_to_fdt64(val); + return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); +} + +/** + * fdt_setprop_cell - set a property to a single cell value + * + * This is an alternative name for fdt_setprop_u32() + */ +static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, + uint32_t val) +{ + return fdt_setprop_u32(fdt, nodeoffset, name, val); +} + /** * fdt_setprop_string - set a property to a string value * @fdt: pointer to the device tree blob @@ -1164,16 +1265,16 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name, const void *val, int len); /** - * fdt_appendprop_cell - append a single cell value to a property + * fdt_appendprop_u32 - append a 32-bit integer 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) * - * fdt_appendprop_cell() appends the given cell value (converting to - * big-endian if necessary) 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. + * fdt_appendprop_u32() appends the given 32-bit integer value + * (converting to big-endian if necessary) 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. * * This function may insert data into the blob, and will therefore * change the offsets of some existing nodes. @@ -1191,13 +1292,59 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ -static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, - const char *name, uint32_t val) +static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) { val = cpu_to_fdt32(val); return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val)); } +/** + * fdt_appendprop_u64 - append a 64-bit integer 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: 64-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u64() appends the given 64-bit integer value + * (converting to big-endian if necessary) 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. + * + * This function may insert data into 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 + */ +static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + val = cpu_to_fdt64(val); + return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val)); +} + +/** + * fdt_appendprop_cell - append a single cell value to a property + * + * This is an alternative name for fdt_appendprop_u32() + */ +static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_appendprop_u32(fdt, nodeoffset, name, val); +} + /** * fdt_appendprop_string - append a string to a property * @fdt: pointer to the device tree blob diff --git a/tests/appendprop.dts b/tests/appendprop.dts index 6e3a3eb..f4bc730 100644 --- a/tests/appendprop.dts +++ b/tests/appendprop.dts @@ -2,6 +2,7 @@ / { prop-str = "hello world", "nastystring: \a\b\t\n\v\f\r\\\""; + prop-int64 = /bits/ 64 <0xdeadbeef01abcdef 0xdeadbeef01abcdef>; prop-int = <0xdeadbeef 123456789>; prop-bytes = [00010203040001020304]; }; diff --git a/tests/appendprop1.c b/tests/appendprop1.c index 180d296..d716f7a 100644 --- a/tests/appendprop1.c +++ b/tests/appendprop1.c @@ -60,6 +60,7 @@ int main(int argc, char *argv[]) CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes))); CHECK(fdt_appendprop_cell(fdt, 0, "prop-int", TEST_VALUE_1)); + CHECK(fdt_appendprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1)); CHECK(fdt_appendprop_string(fdt, 0, "prop-str", TEST_STRING_1)); CHECK(fdt_pack(fdt)); diff --git a/tests/appendprop2.c b/tests/appendprop2.c index d651a89..7eb243d 100644 --- a/tests/appendprop2.c +++ b/tests/appendprop2.c @@ -54,6 +54,7 @@ int main(int argc, char *argv[]) CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes))); CHECK(fdt_appendprop_cell(fdt, 0, "prop-int", TEST_VALUE_2)); + CHECK(fdt_appendprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1)); CHECK(fdt_appendprop_string(fdt, 0, "prop-str", TEST_STRING_2)); CHECK(fdt_pack(fdt)); diff --git a/tests/include1.dts b/tests/include1.dts index 5d59d83..893aaff 100644 --- a/tests/include1.dts +++ b/tests/include1.dts @@ -6,6 +6,7 @@ / { /include/ "include4.dts" /include/ "include5.dts" = <0xdeadbeef>; + prop-int64 /include/ "include5a.dts"; prop-str = /include/ "include6.dts"; /include/ "include7.dts" diff --git a/tests/include5a.dts b/tests/include5a.dts new file mode 100644 index 0000000..39ddba4 --- /dev/null +++ b/tests/include5a.dts @@ -0,0 +1 @@ += /bits/ 64 <0xdeadbeef01abcdef> \ No newline at end of file diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c index f0bce88..f4965ec 100644 --- a/tests/rw_tree1.c +++ b/tests/rw_tree1.c @@ -73,7 +73,8 @@ int main(int argc, char *argv[]) CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2)); CHECK(fdt_setprop_string(fdt, 0, "compatible", "test_tree1")); - CHECK(fdt_setprop_cell(fdt, 0, "prop-int", TEST_VALUE_1)); + CHECK(fdt_setprop_u32(fdt, 0, "prop-int", TEST_VALUE_1)); + CHECK(fdt_setprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1)); CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1)); OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@1")); diff --git a/tests/setprop.c b/tests/setprop.c index 386b87b..9f2bc88 100644 --- a/tests/setprop.c +++ b/tests/setprop.c @@ -74,5 +74,23 @@ int main(int argc, char *argv[]) check_getprop(fdt, 0, "prop-str", 0, NULL); + err = fdt_setprop_u32(fdt, 0, "prop-u32", TEST_VALUE_2); + if (err) + FAIL("Failed to set \"prop-u32\" to 0x%08x: %s", + TEST_VALUE_2, fdt_strerror(err)); + check_getprop_cell(fdt, 0, "prop-u32", TEST_VALUE_2); + + err = fdt_setprop_cell(fdt, 0, "prop-cell", TEST_VALUE_2); + if (err) + FAIL("Failed to set \"prop-cell\" to 0x%08x: %s", + TEST_VALUE_2, fdt_strerror(err)); + check_getprop_cell(fdt, 0, "prop-cell", TEST_VALUE_2); + + err = fdt_setprop_u64(fdt, 0, "prop-u64", TEST_VALUE64_1); + if (err) + FAIL("Failed to set \"prop-u64\" to 0x%016llx: %s", + TEST_VALUE64_1, fdt_strerror(err)); + check_getprop_64(fdt, 0, "prop-u64", TEST_VALUE64_1); + PASS(); } diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c index aa0cd96..30a1cf3 100644 --- a/tests/setprop_inplace.c +++ b/tests/setprop_inplace.c @@ -34,6 +34,7 @@ int main(int argc, char *argv[]) { void *fdt; const uint32_t *intp; + const uint64_t *int64p; const char *strp; char *xstr; int xlen, i; @@ -52,6 +53,20 @@ int main(int argc, char *argv[]) intp = check_getprop_cell(fdt, 0, "prop-int", ~TEST_VALUE_1); verbose_printf("New int value is 0x%08x\n", *intp); + strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, + TEST_STRING_1); + + + int64p = check_getprop_64(fdt, 0, "prop-int64", TEST_VALUE64_1); + + verbose_printf("Old int64 value was 0x%016llx\n", *int64p); + err = fdt_setprop_inplace_u64(fdt, 0, "prop-int64", ~TEST_VALUE64_1); + if (err) + FAIL("Failed to set \"prop-int64\" to 0x016%llx: %s", + ~TEST_VALUE64_1, fdt_strerror(err)); + int64p = check_getprop_64(fdt, 0, "prop-int64", ~TEST_VALUE64_1); + verbose_printf("New int64 value is 0x%016llx\n", *int64p); + strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1); diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index f2c430a..5c71414 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -55,7 +55,8 @@ int main(int argc, char *argv[]) CHECK(fdt_begin_node(fdt, "")); CHECK(fdt_property_string(fdt, "compatible", "test_tree1")); - CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1)); + CHECK(fdt_property_u32(fdt, "prop-int", TEST_VALUE_1)); + CHECK(fdt_property_u64(fdt, "prop-int64", TEST_VALUE64_1)); CHECK(fdt_property_string(fdt, "prop-str", TEST_STRING_1)); CHECK(fdt_begin_node(fdt, "subnode@1")); diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts index 4f0ce45..cf530ce 100644 --- a/tests/test_tree1.dts +++ b/tests/test_tree1.dts @@ -6,6 +6,7 @@ / { compatible = "test_tree1"; prop-int = <0xdeadbeef>; + prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; prop-str = "hello world"; subnode@1 { diff --git a/tests/test_tree1_merge.dts b/tests/test_tree1_merge.dts index fc191fd..ded08d8 100644 --- a/tests/test_tree1_merge.dts +++ b/tests/test_tree1_merge.dts @@ -30,6 +30,7 @@ / { prop-int = <0xdeadbeef>; + prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; subnode@1 { prop-int = [deadbeef]; }; diff --git a/tests/test_tree1_merge_labelled.dts b/tests/test_tree1_merge_labelled.dts index 46a6840..29953b0 100644 --- a/tests/test_tree1_merge_labelled.dts +++ b/tests/test_tree1_merge_labelled.dts @@ -6,6 +6,7 @@ / { compatible = "test_tree1"; prop-int = <0xdeadbeef>; + prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; prop-str = "hello world"; subnode@1 { diff --git a/tests/test_tree1_merge_path.dts b/tests/test_tree1_merge_path.dts index d68713b..168d066 100644 --- a/tests/test_tree1_merge_path.dts +++ b/tests/test_tree1_merge_path.dts @@ -6,6 +6,7 @@ / { compatible = "test_tree1"; prop-int = <0xdeadbeef>; + prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; prop-str = "hello world"; subnode@1 { diff --git a/tests/testdata.h b/tests/testdata.h index d4c6759..ce715e4 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -12,6 +12,8 @@ #define TEST_VALUE_1 0xdeadbeef #define TEST_VALUE_2 123456789 +#define TEST_VALUE64_1 ASM_CONST_LL(0xdeadbeef01abcdef) + #define PHANDLE_1 0x2000 #define PHANDLE_2 0x2001 diff --git a/tests/tests.h b/tests/tests.h index a51556d..56a843c 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -111,6 +111,11 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name, uint32_t x = cpu_to_fdt32(val); \ check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \ }) +#define check_getprop_64(fdt, nodeoffset, name, val) \ + ({ \ + uint64_t x = cpu_to_fdt64(val); \ + check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \ + }) #define check_getprop_string(fdt, nodeoffset, name, s) \ check_getprop((fdt), (nodeoffset), (name), strlen(s)+1, (s)) int nodename_eq(const char *s1, const char *s2); diff --git a/tests/trees.S b/tests/trees.S index 66adf3f..cae0187 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -52,6 +52,10 @@ tree##_rsvmap_end: ; PROPHDR(tree, name, 4) \ FDTLONG(val) ; +#define PROP_INT64(tree, name, val) \ + PROPHDR(tree, name, 8) \ + FDTQUAD(val) ; + #define PROP_STR(tree, name, str) \ PROPHDR(tree, name, 55f - 54f) \ 54: \ @@ -86,6 +90,7 @@ 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_1) PROP_STR(test_tree1, prop_str, TEST_STRING_1) BEGIN_NODE("subnode@1") @@ -124,6 +129,7 @@ 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") From be6026838e45b67800ac803f4ad8cca3cde57d6d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Jun 2012 14:12:38 +1000 Subject: [PATCH 0364/1198] libfdt: Add helper function to create a trivial, empty tree The libfdt read/write functions are now usable enough that it's become a moderately common pattern to use them to build and manipulate a device tree from scratch. For example, we do so ourself in our rw_tree1 testcase, and qemu is starting to use this model when building device trees for some targets such as e500. However, the read/write functions require some sort of valid tree to begin with, so this necessitates either having a trivial canned dtb to begin with or, more commonly, creating an empty tree using the serial-write functions first. This patch adds a helper function which uses the serial-write functions to create a trivial, empty but complete and valid tree in a supplied buffer, ready for manipulation with the read/write functions. Signed-off-by: David Gibson --- libfdt/Makefile.libfdt | 2 +- libfdt/fdt_empty_tree.c | 84 +++++++++++++++++++++++++++++++++++++++++ libfdt/libfdt.h | 1 + tests/rw_tree1.c | 12 +----- 4 files changed, 87 insertions(+), 12 deletions(-) create mode 100644 libfdt/fdt_empty_tree.c diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index d55a6f8..4366627 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -6,5 +6,5 @@ LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 LIBFDT_INCLUDES = fdt.h libfdt.h LIBFDT_VERSION = version.lds -LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c +LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) diff --git a/libfdt/fdt_empty_tree.c b/libfdt/fdt_empty_tree.c new file mode 100644 index 0000000..f72d13b --- /dev/null +++ b/libfdt/fdt_empty_tree.c @@ -0,0 +1,84 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2012 David Gibson, IBM Corporation. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +int fdt_create_empty_tree(void *buf, int bufsize) +{ + int err; + + err = fdt_create(buf, bufsize); + if (err) + return err; + + err = fdt_finish_reservemap(buf); + if (err) + return err; + + err = fdt_begin_node(buf, ""); + if (err) + return err; + + err = fdt_end_node(buf); + if (err) + return err; + + err = fdt_finish(buf); + if (err) + return err; + + return fdt_open_into(buf, buf, bufsize); +} + diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 35d78b8..73f4975 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1014,6 +1014,7 @@ int fdt_finish(void *fdt); /* Read-write functions */ /**********************************************************************/ +int fdt_create_empty_tree(void *buf, int bufsize); int fdt_open_into(const void *fdt, void *buf, int bufsize); int fdt_pack(void *fdt); diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c index f4965ec..103a24d 100644 --- a/tests/rw_tree1.c +++ b/tests/rw_tree1.c @@ -57,17 +57,7 @@ int main(int argc, char *argv[]) fdt = xmalloc(SPACE); /* First create empty tree with SW */ - CHECK(fdt_create(fdt, SPACE)); - - CHECK(fdt_finish_reservemap(fdt)); - CHECK(fdt_begin_node(fdt, "")); - CHECK(fdt_end_node(fdt)); - CHECK(fdt_finish(fdt)); - - verbose_printf("Built empty tree, totalsize = %d\n", - fdt_totalsize(fdt)); - - CHECK(fdt_open_into(fdt, fdt, SPACE)); + CHECK(fdt_create_empty_tree(fdt, SPACE)); CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_1, TEST_SIZE_1)); CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2)); From 942b3c065fb1c8788d2317977945c7283f1db7e2 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 12 Jun 2012 14:48:12 -0600 Subject: [PATCH 0365/1198] Fix compilation warning/error in setprop_inplace.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling the current code-base with gcc 4.6.1, the following warning is raised, which is interpreted as an error: cc1: warnings being treated as errors tests/setprop_inplace.c: In function ‘main’: tests/setprop_inplace.c:62: error: format ‘%016llx’ expects type ‘long long unsigned int’, but argument 2 has type ‘uint64_t’ tests/setprop_inplace.c:68: error: format ‘%016llx’ expects type ‘long long unsigned int’, but argument 2 has type ‘uint64_t’ Use printf format specifiers from to solve this. Signed-off-by: Stephen Warren Acked-by: David Gibson --- tests/setprop_inplace.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c index 30a1cf3..82d8951 100644 --- a/tests/setprop_inplace.c +++ b/tests/setprop_inplace.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include @@ -48,7 +49,7 @@ int main(int argc, char *argv[]) verbose_printf("Old int value was 0x%08x\n", *intp); err = fdt_setprop_inplace_cell(fdt, 0, "prop-int", ~TEST_VALUE_1); if (err) - FAIL("Failed to set \"prop-int\" to 0x08%x: %s", + FAIL("Failed to set \"prop-int\" to 0x%08x: %s", ~TEST_VALUE_1, fdt_strerror(err)); intp = check_getprop_cell(fdt, 0, "prop-int", ~TEST_VALUE_1); verbose_printf("New int value is 0x%08x\n", *intp); @@ -59,13 +60,13 @@ int main(int argc, char *argv[]) int64p = check_getprop_64(fdt, 0, "prop-int64", TEST_VALUE64_1); - verbose_printf("Old int64 value was 0x%016llx\n", *int64p); + verbose_printf("Old int64 value was 0x%016" PRIx64 "\n", *int64p); err = fdt_setprop_inplace_u64(fdt, 0, "prop-int64", ~TEST_VALUE64_1); if (err) - FAIL("Failed to set \"prop-int64\" to 0x016%llx: %s", + FAIL("Failed to set \"prop-int64\" to 0x%016llx: %s", ~TEST_VALUE64_1, fdt_strerror(err)); int64p = check_getprop_64(fdt, 0, "prop-int64", ~TEST_VALUE64_1); - verbose_printf("New int64 value is 0x%016llx\n", *int64p); + verbose_printf("New int64 value is 0x%016" PRIx64 "\n", *int64p); strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1); From f67dfe845930b32ea14df6ff18d69799828a5909 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 3 Jul 2012 14:09:30 -0600 Subject: [PATCH 0366/1198] Add test for re-defining an identical label When merging one device tree over the top of a previous tree, it is possible to define a duplicate label that has the same name and points to the same property or node. This is currently allowed by the duplicate label checking code. However, alternative duplicate label checking algorithms might not allow this. Add an explicit test to ensure this capability is maintained. Signed-off-by: Stephen Warren Acked-by: David Gibson --- tests/label_repeated.dts | 15 +++++++++++++++ tests/run_tests.sh | 2 ++ 2 files changed, 17 insertions(+) create mode 100644 tests/label_repeated.dts diff --git a/tests/label_repeated.dts b/tests/label_repeated.dts new file mode 100644 index 0000000..34225d3 --- /dev/null +++ b/tests/label_repeated.dts @@ -0,0 +1,15 @@ +/dts-v1/; + +/ { + l0: prop = "foo"; + + l1: node { + }; +}; + +/ { + l0: prop = "foo"; + + l1: node { + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 9a2a7d9..e0299e3 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -281,6 +281,8 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o multilabel.test.dtb multilabel.dts run_test references multilabel.test.dtb + run_dtc_test -I dts -O dtb -o label_repeated.test.dtb label_repeated.dts + run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb comments.dts run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb From 511dedd40f0372cd7c85e3d4c66553f5829142b7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 8 Jul 2012 23:25:21 +1000 Subject: [PATCH 0367/1198] Re-work level setting on checks code Currently each of the semantic checks in checks.c has a "level" between IGNORE and ERROR. This single level makes it awkward to implement the semantics we want for toggling the checks on the command line. This patch reworks the code to instead have separate boolean flags for warning and error. At present having both flags set will have the same effect as having just the error flag set, but this can change in the future. Signed-off-by: David Gibson --- checks.c | 115 +++++++++++++++++++++++++++++-------------------------- dtc.h | 1 + 2 files changed, 62 insertions(+), 54 deletions(-) diff --git a/checks.c b/checks.c index a662a00..3080439 100644 --- a/checks.c +++ b/checks.c @@ -31,12 +31,6 @@ #define TRACE(c, fmt, ...) do { } while (0) #endif -enum checklevel { - IGNORE = 0, - WARN = 1, - ERROR = 2, -}; - enum checkstatus { UNCHECKED = 0, PREREQ, @@ -57,14 +51,14 @@ struct check { node_check_fn node_fn; prop_check_fn prop_fn; void *data; - enum checklevel level; + bool warn, error; enum checkstatus status; int inprogress; int num_prereqs; struct check **prereq; }; -#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \ +#define CHECK(nm, tfn, nfn, pfn, d, w, e, ...) \ static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \ static struct check nm = { \ .name = #nm, \ @@ -72,20 +66,29 @@ struct check { .node_fn = (nfn), \ .prop_fn = (pfn), \ .data = (d), \ - .level = (lvl), \ + .warn = (w), \ + .error = (e), \ .status = UNCHECKED, \ .num_prereqs = ARRAY_SIZE(nm##_prereqs), \ .prereq = nm##_prereqs, \ }; +#define WARNING(nm, tfn, nfn, pfn, d, ...) \ + CHECK(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__) +#define ERROR(nm, tfn, nfn, pfn, d, ...) \ + CHECK(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__) -#define TREE_CHECK(nm, d, lvl, ...) \ - CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__) -#define NODE_CHECK(nm, d, lvl, ...) \ - CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__) -#define PROP_CHECK(nm, d, lvl, ...) \ - CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__) -#define BATCH_CHECK(nm, lvl, ...) \ - CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__) +#define TREE_WARNING(nm, d, ...) \ + WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) +#define TREE_ERROR(nm, d, ...) \ + ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) +#define NODE_WARNING(nm, d, ...) \ + WARNING(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) +#define NODE_ERROR(nm, d, ...) \ + ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) +#define PROP_WARNING(nm, d, ...) \ + WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) +#define PROP_ERROR(nm, d, ...) \ + ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) #ifdef __GNUC__ static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); @@ -95,13 +98,13 @@ static inline void check_msg(struct check *c, const char *fmt, ...) va_list ap; va_start(ap, fmt); - if ((c->level < WARN) || (c->level <= quiet)) - return; /* Suppress message */ - - fprintf(stderr, "%s (%s): ", - (c->level == ERROR) ? "ERROR" : "Warning", c->name); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + if ((c->warn && (quiet < 1)) + || (c->error && (quiet < 2))) { + fprintf(stderr, "%s (%s): ", + (c->error) ? "ERROR" : "Warning", c->name); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + } } #define FAIL(c, ...) \ @@ -167,7 +170,7 @@ static int run_check(struct check *c, struct node *dt) out: c->inprogress = 0; - if ((c->status != PASSED) && (c->level == ERROR)) + if ((c->status != PASSED) && (c->error)) error = 1; return error; } @@ -190,8 +193,10 @@ static void check_is_string(struct check *c, struct node *root, FAIL(c, "\"%s\" property in %s is not a string", propname, node->fullpath); } -#define CHECK_IS_STRING(nm, propname, lvl) \ - CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl)) +#define WARNING_IF_NOT_STRING(nm, propname) \ + WARNING(nm, NULL, check_is_string, NULL, (propname)) +#define ERROR_IF_NOT_STRING(nm, propname) \ + ERROR(nm, NULL, check_is_string, NULL, (propname)) static void check_is_cell(struct check *c, struct node *root, struct node *node) @@ -207,8 +212,10 @@ static void check_is_cell(struct check *c, struct node *root, FAIL(c, "\"%s\" property in %s is not a single cell", propname, node->fullpath); } -#define CHECK_IS_CELL(nm, propname, lvl) \ - CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl)) +#define WARNING_IF_NOT_CELL(nm, propname) \ + WARNING(nm, NULL, check_is_cell, NULL, (propname)) +#define ERROR_IF_NOT_CELL(nm, propname) \ + ERROR(nm, NULL, check_is_cell, NULL, (propname)) /* * Structural check functions @@ -227,7 +234,7 @@ static void check_duplicate_node_names(struct check *c, struct node *dt, FAIL(c, "Duplicate node name %s", child->fullpath); } -NODE_CHECK(duplicate_node_names, NULL, ERROR); +NODE_ERROR(duplicate_node_names, NULL); static void check_duplicate_property_names(struct check *c, struct node *dt, struct node *node) @@ -240,7 +247,7 @@ static void check_duplicate_property_names(struct check *c, struct node *dt, FAIL(c, "Duplicate property name %s in %s", prop->name, node->fullpath); } -NODE_CHECK(duplicate_property_names, NULL, ERROR); +NODE_ERROR(duplicate_property_names, NULL); #define LOWERCASE "abcdefghijklmnopqrstuvwxyz" #define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -256,7 +263,7 @@ static void check_node_name_chars(struct check *c, struct node *dt, FAIL(c, "Bad character '%c' in node %s", node->name[n], node->fullpath); } -NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR); +NODE_ERROR(node_name_chars, PROPNODECHARS "@"); static void check_node_name_format(struct check *c, struct node *dt, struct node *node) @@ -265,7 +272,7 @@ static void check_node_name_format(struct check *c, struct node *dt, FAIL(c, "Node %s has multiple '@' characters in name", node->fullpath); } -NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars); +NODE_ERROR(node_name_format, NULL, &node_name_chars); static void check_property_name_chars(struct check *c, struct node *dt, struct node *node, struct property *prop) @@ -276,7 +283,7 @@ static void check_property_name_chars(struct check *c, struct node *dt, FAIL(c, "Bad character '%c' in property name \"%s\", node %s", prop->name[n], prop->name, node->fullpath); } -PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR); +PROP_ERROR(property_name_chars, PROPNODECHARS); #define DESCLABEL_FMT "%s%s%s%s%s" #define DESCLABEL_ARGS(node,prop,mark) \ @@ -331,8 +338,8 @@ static void check_duplicate_label_prop(struct check *c, struct node *dt, for_each_marker_of_type(m, LABEL) check_duplicate_label(c, dt, m->ref, node, prop, m); } -CHECK(duplicate_label, NULL, check_duplicate_label_node, - check_duplicate_label_prop, NULL, ERROR); +ERROR(duplicate_label, NULL, check_duplicate_label_node, + check_duplicate_label_prop, NULL); static void check_explicit_phandles(struct check *c, struct node *root, struct node *node, struct property *prop) @@ -391,7 +398,7 @@ static void check_explicit_phandles(struct check *c, struct node *root, node->phandle = phandle; } -PROP_CHECK(explicit_phandles, NULL, ERROR); +PROP_ERROR(explicit_phandles, NULL); static void check_name_properties(struct check *c, struct node *root, struct node *node) @@ -420,8 +427,8 @@ static void check_name_properties(struct check *c, struct node *root, free(prop); } } -CHECK_IS_STRING(name_is_string, "name", ERROR); -NODE_CHECK(name_properties, NULL, ERROR, &name_is_string); +ERROR_IF_NOT_STRING(name_is_string, "name"); +NODE_ERROR(name_properties, NULL, &name_is_string); /* * Reference fixup functions @@ -448,7 +455,7 @@ static void fixup_phandle_references(struct check *c, struct node *dt, *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); } } -CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR, +ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL, &duplicate_node_names, &explicit_phandles); static void fixup_path_references(struct check *c, struct node *dt, @@ -473,19 +480,19 @@ static void fixup_path_references(struct check *c, struct node *dt, strlen(path) + 1); } } -CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR, +ERROR(path_references, NULL, NULL, fixup_path_references, NULL, &duplicate_node_names); /* * Semantic checks */ -CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN); -CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN); -CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN); +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"); -CHECK_IS_STRING(device_type_is_string, "device_type", WARN); -CHECK_IS_STRING(model_is_string, "model", WARN); -CHECK_IS_STRING(status_is_string, "status", WARN); +WARNING_IF_NOT_STRING(device_type_is_string, "device_type"); +WARNING_IF_NOT_STRING(model_is_string, "model"); +WARNING_IF_NOT_STRING(status_is_string, "status"); static void fixup_addr_size_cells(struct check *c, struct node *dt, struct node *node) @@ -503,8 +510,8 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt, if (prop) node->size_cells = propval_cell(prop); } -CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN, - &address_cells_is_cell, &size_cells_is_cell); +WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, + &address_cells_is_cell, &size_cells_is_cell); #define node_addr_cells(n) \ (((n)->addr_cells == -1) ? 2 : (n)->addr_cells) @@ -538,7 +545,7 @@ static void check_reg_format(struct check *c, struct node *dt, "(#address-cells == %d, #size-cells == %d)", node->fullpath, prop->val.len, addr_cells, size_cells); } -NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells); +NODE_WARNING(reg_format, NULL, &addr_size_cells); static void check_ranges_format(struct check *c, struct node *dt, struct node *node) @@ -579,7 +586,7 @@ static void check_ranges_format(struct check *c, struct node *dt, p_addr_cells, c_addr_cells, c_size_cells); } } -NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells); +NODE_WARNING(ranges_format, NULL, &addr_size_cells); /* * Style checks @@ -606,7 +613,7 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt, FAIL(c, "Relying on default #size-cells value for %s", node->fullpath); } -NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells); +NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells); static void check_obsolete_chosen_interrupt_controller(struct check *c, struct node *dt) @@ -623,7 +630,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c, FAIL(c, "/chosen has obsolete \"interrupt-controller\" " "property"); } -TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN); +TREE_WARNING(obsolete_chosen_interrupt_controller, NULL); static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, @@ -653,7 +660,7 @@ void process_checks(int force, struct boot_info *bi) for (i = 0; i < ARRAY_SIZE(check_table); i++) { struct check *c = check_table[i]; - if (c->level != IGNORE) + if (c->warn || c->error) error = error || run_check(c, dt); } diff --git a/dtc.h b/dtc.h index 7b4c65b..d57fbfc 100644 --- a/dtc.h +++ b/dtc.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include From d5399197e9e0d8bad13de5c41df3b93804c0558a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 8 Jul 2012 23:25:22 +1000 Subject: [PATCH 0368/1198] Allow toggling of semantic checks This patch adds -W and -E options to dtc which allow toggling on and off of the various built in semantic checks on the tree. Signed-off-by: David Gibson --- checks.c | 84 +++++++++++++++++++++++++++++++++++++++-- dtc.c | 13 ++++++- dtc.h | 1 + tests/dtc-checkfails.sh | 20 +++++++++- tests/dtc-fails.sh | 30 +++++++++++++++ tests/run_tests.sh | 12 ++++++ 6 files changed, 154 insertions(+), 6 deletions(-) create mode 100755 tests/dtc-fails.sh diff --git a/checks.c b/checks.c index 3080439..9061237 100644 --- a/checks.c +++ b/checks.c @@ -58,7 +58,7 @@ struct check { struct check **prereq; }; -#define CHECK(nm, tfn, nfn, pfn, d, w, e, ...) \ +#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...) \ static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \ static struct check nm = { \ .name = #nm, \ @@ -73,22 +73,30 @@ struct check { .prereq = nm##_prereqs, \ }; #define WARNING(nm, tfn, nfn, pfn, d, ...) \ - CHECK(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__) + CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__) #define ERROR(nm, tfn, nfn, pfn, d, ...) \ - CHECK(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__) + CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__) +#define CHECK(nm, tfn, nfn, pfn, d, ...) \ + CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__) #define TREE_WARNING(nm, d, ...) \ WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) #define TREE_ERROR(nm, d, ...) \ ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) +#define TREE_CHECK(nm, d, ...) \ + CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) #define NODE_WARNING(nm, d, ...) \ WARNING(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) #define NODE_ERROR(nm, d, ...) \ ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) +#define NODE_CHECK(nm, d, ...) \ + CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) #define PROP_WARNING(nm, d, ...) \ WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) #define PROP_ERROR(nm, d, ...) \ ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) +#define PROP_CHECK(nm, d, ...) \ + CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) #ifdef __GNUC__ static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); @@ -179,6 +187,13 @@ out: * Utility check functions */ +/* A check which always fails, for testing purposes only */ +static inline void check_always_fail(struct check *c, struct node *dt) +{ + FAIL(c, "always_fail check"); +} +TREE_CHECK(always_fail, NULL); + static void check_is_string(struct check *c, struct node *root, struct node *node) { @@ -649,8 +664,71 @@ static struct check *check_table[] = { &avoid_default_addr_size, &obsolete_chosen_interrupt_controller, + + &always_fail, }; +static void enable_warning_error(struct check *c, bool warn, bool error) +{ + int i; + + /* Raising level, also raise it for prereqs */ + if ((warn && !c->warn) || (error && !c->error)) + for (i = 0; i < c->num_prereqs; i++) + enable_warning_error(c->prereq[i], warn, error); + + c->warn = c->warn || warn; + c->error = c->error || error; +} + +static void disable_warning_error(struct check *c, bool warn, bool error) +{ + int i; + + /* Lowering level, also lower it for things this is the prereq + * for */ + if ((warn && c->warn) || (error && c->error)) { + for (i = 0; i < ARRAY_SIZE(check_table); i++) { + struct check *cc = check_table[i]; + int j; + + for (j = 0; j < cc->num_prereqs; j++) + if (cc->prereq[j] == c) + disable_warning_error(cc, warn, error); + } + } + + c->warn = c->warn && !warn; + c->error = c->error && !error; +} + +void parse_checks_option(bool warn, bool error, const char *optarg) +{ + int i; + const char *name = optarg; + bool enable = true; + + if ((strncmp(optarg, "no-", 3) == 0) + || (strncmp(optarg, "no_", 3) == 0)) { + name = optarg + 3; + enable = false; + } + + for (i = 0; i < ARRAY_SIZE(check_table); i++) { + struct check *c = check_table[i]; + + if (streq(c->name, name)) { + if (enable) + enable_warning_error(c, warn, error); + else + disable_warning_error(c, warn, error); + return; + } + } + + die("Unrecognized check name \"%s\"\n", name); +} + void process_checks(int force, struct boot_info *bi) { struct node *dt = bi->dt; diff --git a/dtc.c b/dtc.c index bee5085..a375683 100644 --- a/dtc.c +++ b/dtc.c @@ -93,6 +93,9 @@ static void __attribute__ ((noreturn)) usage(void) fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n"); fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n"); fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n"); + fprintf(stderr, "\t-W [no-]\n"); + fprintf(stderr, "\t-E [no-]\n"); + fprintf(stderr, "\t\t\tenable or disable warnings and errors\n"); exit(3); } @@ -115,7 +118,7 @@ int main(int argc, char *argv[]) minsize = 0; padsize = 0; - while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:s")) + while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:")) != EOF) { switch (opt) { case 'I': @@ -173,6 +176,14 @@ int main(int argc, char *argv[]) sort = 1; break; + case 'W': + parse_checks_option(true, false, optarg); + break; + + case 'E': + parse_checks_option(false, true, optarg); + break; + case 'h': default: usage(); diff --git a/dtc.h b/dtc.h index d57fbfc..7ee2d54 100644 --- a/dtc.h +++ b/dtc.h @@ -226,6 +226,7 @@ void sort_tree(struct boot_info *bi); /* Checks */ +void parse_checks_option(bool warn, bool error, const char *optarg); void process_checks(int force, struct boot_info *bi); /* Flattened trees */ diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh index 3f77b13..76ded15 100755 --- a/tests/dtc-checkfails.sh +++ b/tests/dtc-checkfails.sh @@ -4,10 +4,20 @@ for x; do shift + if [ "$x" = "-n" ]; then + for x; do + shift + if [ "$x" = "--" ]; then + break; + fi + NOCHECKS="$NOCHECKS $x" + done + break; + fi if [ "$x" = "--" ]; then break; fi - CHECKS="$CHECKS $x" + YESCHECKS="$YESCHECKS $x" done LOG=tmp.log.$$ @@ -19,10 +29,16 @@ ret="$?" FAIL_IF_SIGNAL $ret -for c in $CHECKS; do +for c in $YESCHECKS; do if ! grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then FAIL "Failed to trigger check \"$c\"" fi done +for c in $NOCHECKS; do + if grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then + FAIL "Incorrectly triggered check \"$c\"" + fi +done + PASS diff --git a/tests/dtc-fails.sh b/tests/dtc-fails.sh new file mode 100755 index 0000000..4ddcb27 --- /dev/null +++ b/tests/dtc-fails.sh @@ -0,0 +1,30 @@ +#! /bin/sh + +. ./tests.sh + +if [ "$1" = "-n" ]; then + NEG="$1" + shift +fi + +OUTPUT="$1" +shift + +verbose_run $VALGRIND "$DTC" -o "$OUTPUT" "$@" +ret="$?" + +FAIL_IF_SIGNAL $ret + +if [ -n "$NEG" ]; then + if [ ! -e "$OUTPUT" ]; then + FAIL "Produced no output" + fi +else + if [ -e "$OUTPUT" ]; then + FAIL "Incorrectly produced output" + fi +fi + +rm -f "$OUTPUT" + +PASS diff --git a/tests/run_tests.sh b/tests/run_tests.sh index e0299e3..169a829 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -396,6 +396,18 @@ dtc_tests () { run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label5.dts run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label6.dts + # Check warning options + run_sh_test 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 bad-ncells.dts + run_sh_test dtc-fails.sh -n test-warn-output.test.dtb -I dts -O dtb bad-ncells.dts + run_sh_test dtc-fails.sh test-error-output.test.dtb -I dts -O dtb bad-ncells.dts -Esize_cells_is_cell + run_sh_test dtc-checkfails.sh always_fail -- -Walways_fail -I dts -O dtb test_tree1.dts + run_sh_test dtc-checkfails.sh -n always_fail -- -Walways_fail -Wno_always_fail -I dts -O dtb test_tree1.dts + run_sh_test dtc-fails.sh test-negation-1.test.dtb -Ealways_fail -I dts -O dtb test_tree1.dts + run_sh_test dtc-fails.sh -n test-negation-2.test.dtb -Ealways_fail -Eno_always_fail -I dts -O dtb test_tree1.dts + run_sh_test dtc-fails.sh test-negation-3.test.dtb -Ealways_fail -Wno_always_fail -I dts -O dtb test_tree1.dts + run_sh_test dtc-fails.sh -n test-negation-4.test.dtb -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb bad-ncells.dts + run_sh_test dtc-checkfails.sh size_cells_is_cell -- -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb bad-ncells.dts + # Check for proper behaviour reading from stdin run_dtc_test -I dts -O dtb -o stdin_dtc_tree1.test.dtb - < test_tree1.dts run_wrap_test cmp stdin_dtc_tree1.test.dtb dtc_tree1.test.dtb From bb21f0a766056114e4d9336324b4c294f640d9d1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 10 Jul 2012 05:56:44 -0700 Subject: [PATCH 0369/1198] fdtput: Fix nit in help message There was an extra < in the help message, so fix it. Signed-off-by: Simon Glass Acked-by: David Gibson --- fdtput.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdtput.c b/fdtput.c index f6ebd24..244d1f1 100644 --- a/fdtput.c +++ b/fdtput.c @@ -162,7 +162,7 @@ static const char *usage_msg = "The command line arguments are joined together into a single value.\n" "\n" "Usage:\n" - " fdtput
< [...]\n" + " fdtput
[...]\n" "Options:\n" "\t-t \tType of data\n" "\t-v\t\tVerbose: display each value decoded from command line\n" From f58dff50407c0ee56b372ab201469c18dc042f56 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 12 Jul 2012 08:52:48 -0700 Subject: [PATCH 0370/1198] fdtput: Prepare to support multiple operations We want to add new options to this tool. In preparation for this, add the concept of a current operation. Signed-off-by: Simon Glass --- fdtput.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/fdtput.c b/fdtput.c index 244d1f1..da63539 100644 --- a/fdtput.c +++ b/fdtput.c @@ -28,7 +28,13 @@ #include "util.h" +/* These are the operations we support */ +enum oper_type { + OPER_WRITE_PROP, /* Write a property in a node */ +}; + struct display_info { + enum oper_type oper; /* operation to perform */ int type; /* data type (s/i/u/x or 0 for default) */ int size; /* data size (1/2/4) */ int verbose; /* verbose output */ @@ -143,13 +149,19 @@ static int do_fdtput(struct display_info *disp, const char *filename, if (!blob) return -1; - /* convert the arguments into a single binary value, then store */ - assert(arg_count >= 2); - if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) || - store_key_value(blob, *arg, arg[1], value, len)) - ret = -1; - - if (!ret) + switch (disp->oper) { + case OPER_WRITE_PROP: + /* + * Convert the arguments into a single binary value, then + * store them into the property. + */ + assert(arg_count >= 2); + if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) || + store_key_value(blob, *arg, arg[1], value, len)) + ret = -1; + break; + } + if (ret >= 0) ret = utilfdt_write(filename, blob); free(blob); @@ -185,6 +197,7 @@ int main(int argc, char *argv[]) memset(&disp, '\0', sizeof(disp)); disp.size = -1; + disp.oper = OPER_WRITE_PROP; for (;;) { int c = getopt(argc, argv, "ht:v"); if (c == -1) @@ -224,10 +237,12 @@ int main(int argc, char *argv[]) argv += optind; argc -= optind; - if (argc < 1) - usage("Missing node"); - if (argc < 2) - usage("Missing property"); + if (disp.oper == OPER_WRITE_PROP) { + if (argc < 1) + usage("Missing node"); + if (argc < 2) + usage("Missing property"); + } if (do_fdtput(&disp, filename, argv, argc)) return 1; From d46c2de5700fd8d43de67ca3709c276beba39b39 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 12 Jul 2012 08:52:49 -0700 Subject: [PATCH 0371/1198] fdtput: Add -c option to create nodes This option allows the creation of new nodes in a dtb file. The syntax is: fdtput -c The node_path contains the path of the node to be created. All path components up to the final one must exist already. The final one must not exist already. Signed-off-by: Simon Glass Acked-by: David Gibson --- fdtput.c | 52 +++++++++++++++++++++++++++++++++++++++++++++- tests/run_tests.sh | 13 ++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/fdtput.c b/fdtput.c index da63539..a414fe9 100644 --- a/fdtput.c +++ b/fdtput.c @@ -31,6 +31,7 @@ /* These are the operations we support */ enum oper_type { OPER_WRITE_PROP, /* Write a property in a node */ + OPER_CREATE_NODE, /* Create a new node */ }; struct display_info { @@ -138,6 +139,46 @@ static int store_key_value(void *blob, const char *node_name, return 0; } +/** + * Create a new node in the fdt. + * + * This will overwrite the node_name string. Any error is reported. + * + * TODO: Perhaps create fdt_path_offset_namelen() so we don't need to do this. + * + * @param blob FDT blob to write into + * @param node_name Name of node to create + * @return new node offset if found, or -1 on failure + */ +static int create_node(void *blob, const char *node_name) +{ + int node = 0; + char *p; + + p = strrchr(node_name, '/'); + if (!p) { + report_error(node_name, -FDT_ERR_BADPATH); + return -1; + } + *p = '\0'; + + if (p > node_name) { + node = fdt_path_offset(blob, node_name); + if (node < 0) { + report_error(node_name, node); + return -1; + } + } + + node = fdt_add_subnode(blob, node, p + 1); + if (node < 0) { + report_error(p + 1, node); + return -1; + } + + return 0; +} + static int do_fdtput(struct display_info *disp, const char *filename, char **arg, int arg_count) { @@ -160,6 +201,10 @@ static int do_fdtput(struct display_info *disp, const char *filename, store_key_value(blob, *arg, arg[1], value, len)) ret = -1; break; + case OPER_CREATE_NODE: + for (; ret >= 0 && arg_count--; arg++) + ret = create_node(blob, *arg); + break; } if (ret >= 0) ret = utilfdt_write(filename, blob); @@ -175,7 +220,9 @@ static const char *usage_msg = "\n" "Usage:\n" " fdtput
[...]\n" + " fdtput -c
[...]\n" "Options:\n" + "\t-c\t\tCreate nodes if they don't already exist\n" "\t-t \tType of data\n" "\t-v\t\tVerbose: display each value decoded from command line\n" "\t-h\t\tPrint this help\n\n" @@ -199,7 +246,7 @@ int main(int argc, char *argv[]) disp.size = -1; disp.oper = OPER_WRITE_PROP; for (;;) { - int c = getopt(argc, argv, "ht:v"); + int c = getopt(argc, argv, "cht:v"); if (c == -1) break; @@ -213,6 +260,9 @@ int main(int argc, char *argv[]) * - expand fdt if value doesn't fit */ switch (c) { + case 'c': + disp.oper = OPER_CREATE_NODE; + break; case 'h': case '?': usage(NULL); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 169a829..617372d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -536,6 +536,19 @@ fdtput_tests () { # This should be larger than available space in the fdt run_wrap_error_test $DTPUT $dtb /randomnode blob -ts "$(cat $text $text)" + # Start again with a fresh dtb + run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts + + # Node creation + run_wrap_error_test $DTPUT $dtb -c /baldrick sod + run_wrap_test $DTPUT $dtb -c /chosen/son /chosen/daughter + run_fdtput_test "eva" $dtb /chosen/daughter name "" -ts "eva" + run_fdtput_test "adam" $dtb /chosen/son name "" -ts "adam" + + # Not allowed to create an existing node + run_wrap_error_test $DTPUT $dtb -c /chosen + run_wrap_error_test $DTPUT $dtb -c /chosen/son + # TODO: Add tests for verbose mode? } From 3553dfac224435233f2c0d33169194098e979c88 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 10 Jul 2012 05:56:47 -0700 Subject: [PATCH 0372/1198] fdtput: Adjust report_error() to use name, namelen params As with many fdt functions, report_error() should permit a namelen to be specified, thus obviating the need for nul termination in strings passed to it. Signed-off-by: Simon Glass Acked-by: David Gibson --- fdtput.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/fdtput.c b/fdtput.c index a414fe9..1f048a8 100644 --- a/fdtput.c +++ b/fdtput.c @@ -41,9 +41,20 @@ struct display_info { int verbose; /* verbose output */ }; -static void report_error(const char *where, int err) + +/** + * Report an error with a particular node. + * + * @param name Node name to report error on + * @param namelen Length of node name, or -1 to use entire string + * @param err Error number to report (-FDT_ERR_...) + */ +static void report_error(const char *name, int namelen, int err) { - fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err)); + if (namelen == -1) + namelen = strlen(name); + fprintf(stderr, "Error at '%1.*s': %s\n", namelen, name, + fdt_strerror(err)); } /** @@ -127,13 +138,13 @@ static int store_key_value(void *blob, const char *node_name, node = fdt_path_offset(blob, node_name); if (node < 0) { - report_error(node_name, node); + report_error(node_name, -1, node); return -1; } err = fdt_setprop(blob, node, property, buf, len); if (err) { - report_error(property, err); + report_error(property, -1, err); return -1; } return 0; @@ -157,7 +168,7 @@ static int create_node(void *blob, const char *node_name) p = strrchr(node_name, '/'); if (!p) { - report_error(node_name, -FDT_ERR_BADPATH); + report_error(node_name, -1, -FDT_ERR_BADPATH); return -1; } *p = '\0'; @@ -165,14 +176,14 @@ static int create_node(void *blob, const char *node_name) if (p > node_name) { node = fdt_path_offset(blob, node_name); if (node < 0) { - report_error(node_name, node); + report_error(node_name, -1, node); return -1; } } node = fdt_add_subnode(blob, node, p + 1); if (node < 0) { - report_error(p + 1, node); + report_error(p + 1, -1, node); return -1; } From f807af192828222dee7a5c9f94d999673bb4d8a1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 12 Jul 2012 08:52:51 -0700 Subject: [PATCH 0373/1198] fdtput: Add -p option to create subnodes along entire path This option mimics mkdir's -p option. It automatically creates nodes as needed along the path provided. If the node already exists, no error is given. Signed-off-by: Simon Glass --- fdtput.c | 59 ++++++++++++++++++++++++++++++++++++++++++---- tests/run_tests.sh | 13 ++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/fdtput.c b/fdtput.c index 1f048a8..f2197f5 100644 --- a/fdtput.c +++ b/fdtput.c @@ -39,6 +39,7 @@ struct display_info { int type; /* data type (s/i/u/x or 0 for default) */ int size; /* data size (1/2/4) */ int verbose; /* verbose output */ + int auto_path; /* automatically create all path components */ }; @@ -150,6 +151,47 @@ static int store_key_value(void *blob, const char *node_name, return 0; } +/** + * Create paths as needed for all components of a path + * + * Any components of the path that do not exist are created. Errors are + * reported. + * + * @param blob FDT blob to write into + * @param in_path Path to process + * @return 0 if ok, -1 on error + */ +static int create_paths(void *blob, const char *in_path) +{ + const char *path = in_path; + const char *sep; + int node, offset = 0; + + /* skip leading '/' */ + while (*path == '/') + path++; + + for (sep = path; *sep; path = sep + 1, offset = node) { + /* equivalent to strchrnul(), but it requires _GNU_SOURCE */ + sep = strchr(path, '/'); + if (!sep) + sep = path + strlen(path); + + node = fdt_subnode_offset_namelen(blob, offset, path, + sep - path); + if (node == -FDT_ERR_NOTFOUND) { + node = fdt_add_subnode_namelen(blob, offset, path, + sep - path); + } + if (node < 0) { + report_error(path, sep - path, node); + return -1; + } + } + + return 0; +} + /** * Create a new node in the fdt. * @@ -208,13 +250,19 @@ static int do_fdtput(struct display_info *disp, const char *filename, * store them into the property. */ assert(arg_count >= 2); + if (disp->auto_path && create_paths(blob, *arg)) + return -1; if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) || store_key_value(blob, *arg, arg[1], value, len)) ret = -1; break; case OPER_CREATE_NODE: - for (; ret >= 0 && arg_count--; arg++) - ret = create_node(blob, *arg); + for (; ret >= 0 && arg_count--; arg++) { + if (disp->auto_path) + ret = create_paths(blob, *arg); + else + ret = create_node(blob, *arg); + } break; } if (ret >= 0) @@ -234,6 +282,7 @@ static const char *usage_msg = " fdtput -c
[...]\n" "Options:\n" "\t-c\t\tCreate nodes if they don't already exist\n" + "\t-p\t\tAutomatically create nodes as needed for the node path\n" "\t-t \tType of data\n" "\t-v\t\tVerbose: display each value decoded from command line\n" "\t-h\t\tPrint this help\n\n" @@ -257,7 +306,7 @@ int main(int argc, char *argv[]) disp.size = -1; disp.oper = OPER_WRITE_PROP; for (;;) { - int c = getopt(argc, argv, "cht:v"); + int c = getopt(argc, argv, "chpt:v"); if (c == -1) break; @@ -277,7 +326,9 @@ int main(int argc, char *argv[]) case 'h': case '?': usage(NULL); - + case 'p': + disp.auto_path = 1; + break; case 't': if (utilfdt_decode_type(optarg, &disp.type, &disp.size)) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 617372d..f5eebd6 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -549,6 +549,19 @@ fdtput_tests () { run_wrap_error_test $DTPUT $dtb -c /chosen run_wrap_error_test $DTPUT $dtb -c /chosen/son + # Automatic node creation + run_wrap_test $DTPUT $dtb -cp /blackadder/the-second/turnip \ + /blackadder/the-second/potato + run_fdtput_test 1000 $dtb /blackadder/the-second/turnip cost "" 1000 + run_fdtput_test "fine wine" $dtb /blackadder/the-second/potato drink \ + "-ts" "fine wine" + run_wrap_test $DTPUT $dtb -p /you/are/drunk/sir/winston slurp -ts twice + run_wrap_error_test $DTPUT $dtb -cp "$(cat $text $text)/longish" + + # Allowed to create an existing node with -p + run_wrap_test $DTPUT $dtb -cp /chosen + run_wrap_test $DTPUT $dtb -cp /chosen/son + # TODO: Add tests for verbose mode? } From 8716901d2215a314504b7df6282aedfcf89da1ea Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Wed, 22 Aug 2012 01:48:17 +0200 Subject: [PATCH 0374/1198] dtc/libfdt: install missing header Previously, only two headers were installed: libfdt.h and fdt.h. But libfdt.h also #includes libfdt_env.h, which was not installed. Install this missing header too. Signed-off-by: "Yann E. MORIN" Acked-by: David Gibson --- libfdt/Makefile.libfdt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index 4366627..91126c0 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -4,7 +4,7 @@ # be easily embeddable into other systems of Makefiles. # LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 -LIBFDT_INCLUDES = fdt.h libfdt.h +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 LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) From 45013d86197fea96810a7ae1b920d22b4c887688 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 7 Aug 2012 22:50:15 -0600 Subject: [PATCH 0375/1198] dtc: Add ability to delete nodes and properties dtc currently allows the contents of properties to be changed, and the contents of nodes to be added to. There are situations where removing properties or nodes may be useful. This change implements the following syntax to do that: / { /delete-property/ propname; /delete-node/ nodename; }; or: /delete-node/ &noderef; Signed-off-by: Stephen Warren Acked-by: David Gibson --- checks.c | 8 ++- dtc-lexer.l | 14 ++++ dtc-parser.y | 21 ++++++ dtc.h | 48 +++++++++++++- flattree.c | 3 + livetree.c | 125 ++++++++++++++++++++++++++++++++---- tests/run_tests.sh | 4 ++ tests/test_tree1.dts | 37 +---------- tests/test_tree1_body.dtsi | 36 +++++++++++ tests/test_tree1_delete.dts | 68 ++++++++++++++++++++ 10 files changed, 312 insertions(+), 52 deletions(-) create mode 100644 tests/test_tree1_body.dtsi create mode 100644 tests/test_tree1_delete.dts diff --git a/checks.c b/checks.c index 9061237..ee96a25 100644 --- a/checks.c +++ b/checks.c @@ -256,11 +256,15 @@ static void check_duplicate_property_names(struct check *c, struct node *dt, { struct property *prop, *prop2; - for_each_property(node, prop) - for (prop2 = prop->next; prop2; prop2 = prop2->next) + for_each_property(node, prop) { + for (prop2 = prop->next; prop2; prop2 = prop2->next) { + if (prop2->deleted) + continue; if (streq(prop->name, prop2->name)) FAIL(c, "Duplicate property name %s in %s", prop->name, node->fullpath); + } + } } NODE_ERROR(duplicate_property_names, NULL); diff --git a/dtc-lexer.l b/dtc-lexer.l index 4715f31..91c4930 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -103,6 +103,20 @@ static int pop_input_file(void); return DT_BITS; } +<*>"/delete-property/" { + DPRINT("Keyword: /delete-property/\n"); + DPRINT("\n"); + BEGIN(PROPNODENAME); + return DT_DEL_PROP; + } + +<*>"/delete-node/" { + DPRINT("Keyword: /delete-node/\n"); + DPRINT("\n"); + BEGIN(PROPNODENAME); + return DT_DEL_NODE; + } + <*>{LABEL}: { DPRINT("Label: %s\n", yytext); yylval.labelref = xstrdup(yytext); diff --git a/dtc-parser.y b/dtc-parser.y index 6d5c2c2..f412460 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -62,6 +62,8 @@ static unsigned char eval_char_literal(const char *s); %token DT_MEMRESERVE %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR %token DT_BITS +%token DT_DEL_PROP +%token DT_DEL_NODE %token DT_PROPNODENAME %token DT_LITERAL %token DT_CHAR_LITERAL @@ -153,6 +155,17 @@ devicetree: print_error("label or path, '%s', not found", $2); $$ = $1; } + | devicetree DT_DEL_NODE DT_REF ';' + { + struct node *target = get_node_by_ref($1, $3); + + if (!target) + print_error("label or path, '%s', not found", $3); + else + delete_node(target); + + $$ = $1; + } ; nodedef: @@ -182,6 +195,10 @@ propdef: { $$ = build_property($1, empty_data); } + | DT_DEL_PROP DT_PROPNODENAME ';' + { + $$ = build_property_delete($2); + } | DT_LABEL propdef { add_label(&$2->labels, $1); @@ -440,6 +457,10 @@ subnode: { $$ = name_node($2, $1); } + | DT_DEL_NODE DT_PROPNODENAME ';' + { + $$ = name_node(build_node_delete(), $2); + } | DT_LABEL subnode { add_label(&$2->labels, $1); diff --git a/dtc.h b/dtc.h index 7ee2d54..d501c86 100644 --- a/dtc.h +++ b/dtc.h @@ -128,11 +128,13 @@ int data_is_one_string(struct data d); /* Live trees */ struct label { + int deleted; char *label; struct label *next; }; struct property { + int deleted; char *name; struct data val; @@ -142,6 +144,7 @@ struct property { }; struct node { + int deleted; char *name; struct property *proplist; struct node *children; @@ -158,28 +161,71 @@ struct node { struct label *labels; }; +static inline struct label *for_each_label_next(struct label *l) +{ + do { + l = l->next; + } while (l && l->deleted); + + return l; +} + #define for_each_label(l0, l) \ + for ((l) = (l0); (l); (l) = for_each_label_next(l)) + +#define for_each_label_withdel(l0, l) \ for ((l) = (l0); (l); (l) = (l)->next) +static inline struct property *for_each_property_next(struct property *p) +{ + do { + p = p->next; + } while (p && p->deleted); + + return p; +} + #define for_each_property(n, p) \ + for ((p) = (n)->proplist; (p); (p) = for_each_property_next(p)) + +#define for_each_property_withdel(n, p) \ for ((p) = (n)->proplist; (p); (p) = (p)->next) -#define for_each_child(n, c) \ +static inline struct node *for_each_child_next(struct node *c) +{ + do { + c = c->next_sibling; + } while (c && c->deleted); + + return c; +} + +#define for_each_child(n, c) \ + for ((c) = (n)->children; (c); (c) = for_each_child_next(c)) + +#define for_each_child_withdel(n, c) \ for ((c) = (n)->children; (c); (c) = (c)->next_sibling) 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_delete(char *name); struct property *chain_property(struct property *first, struct property *list); struct property *reverse_properties(struct property *first); struct node *build_node(struct property *proplist, struct node *children); +struct node *build_node_delete(void); struct node *name_node(struct node *node, char *name); struct node *chain_node(struct node *first, struct node *list); struct node *merge_nodes(struct node *old_node, struct node *new_node); void add_property(struct node *node, struct property *prop); +void delete_property_by_name(struct node *node, char *name); +void delete_property(struct property *prop); void add_child(struct node *parent, struct node *child); +void delete_node_by_name(struct node *parent, char *name); +void delete_node(struct node *node); const char *get_unitname(struct node *node); struct property *get_property(struct node *node, const char *propname); diff --git a/flattree.c b/flattree.c index 28d0b23..665dad7 100644 --- a/flattree.c +++ b/flattree.c @@ -263,6 +263,9 @@ static void flatten_tree(struct node *tree, struct emitter *emit, struct node *child; int seen_name_prop = 0; + if (tree->deleted) + return; + emit->beginnode(etarget, tree->labels); if (vi->flags & FTF_FULLPATH) diff --git a/livetree.c b/livetree.c index c9209d5..e856662 100644 --- a/livetree.c +++ b/livetree.c @@ -29,9 +29,11 @@ void add_label(struct label **labels, char *label) struct label *new; /* Make sure the label isn't already there */ - for_each_label(*labels, new) - if (streq(new->label, label)) + for_each_label_withdel(*labels, new) + if (streq(new->label, label)) { + new->deleted = 0; return; + } new = xmalloc(sizeof(*new)); new->label = label; @@ -39,6 +41,14 @@ void add_label(struct label **labels, char *label) *labels = new; } +void delete_labels(struct label **labels) +{ + struct label *label; + + for_each_label(*labels, label) + label->deleted = 1; +} + struct property *build_property(char *name, struct data val) { struct property *new = xmalloc(sizeof(*new)); @@ -51,6 +61,18 @@ struct property *build_property(char *name, struct data val) return new; } +struct property *build_property_delete(char *name) +{ + struct property *new = xmalloc(sizeof(*new)); + + memset(new, 0, sizeof(*new)); + + new->name = name; + new->deleted = 1; + + return new; +} + struct property *chain_property(struct property *first, struct property *list) { assert(first->next == NULL); @@ -91,6 +113,17 @@ struct node *build_node(struct property *proplist, struct node *children) return new; } +struct node *build_node_delete(void) +{ + struct node *new = xmalloc(sizeof(*new)); + + memset(new, 0, sizeof(*new)); + + new->deleted = 1; + + return new; +} + struct node *name_node(struct node *node, char *name) { assert(node->name == NULL); @@ -106,8 +139,10 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) struct node *new_child, *old_child; struct label *l; + old_node->deleted = 0; + /* Add new node labels to old node */ - for_each_label(new_node->labels, l) + for_each_label_withdel(new_node->labels, l) add_label(&old_node->labels, l->label); /* Move properties from the new node to the old node. If there @@ -118,14 +153,21 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) new_node->proplist = new_prop->next; new_prop->next = NULL; + if (new_prop->deleted) { + delete_property_by_name(old_node, new_prop->name); + free(new_prop); + continue; + } + /* Look for a collision, set new value if there is */ - for_each_property(old_node, old_prop) { + for_each_property_withdel(old_node, old_prop) { if (streq(old_prop->name, new_prop->name)) { /* Add new labels to old property */ - for_each_label(new_prop->labels, l) + for_each_label_withdel(new_prop->labels, l) add_label(&old_prop->labels, l->label); old_prop->val = new_prop->val; + old_prop->deleted = 0; free(new_prop); new_prop = NULL; break; @@ -146,8 +188,14 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) new_child->parent = NULL; new_child->next_sibling = NULL; + if (new_child->deleted) { + delete_node_by_name(old_node, new_child->name); + free(new_child); + continue; + } + /* Search for a collision. Merge if there is */ - for_each_child(old_node, old_child) { + for_each_child_withdel(old_node, old_child) { if (streq(old_child->name, new_child->name)) { merge_nodes(old_child, new_child); new_child = NULL; @@ -188,6 +236,25 @@ void add_property(struct node *node, struct property *prop) *p = prop; } +void delete_property_by_name(struct node *node, char *name) +{ + struct property *prop = node->proplist; + + while (prop) { + if (!strcmp(prop->name, name)) { + delete_property(prop); + return; + } + prop = prop->next; + } +} + +void delete_property(struct property *prop) +{ + prop->deleted = 1; + delete_labels(&prop->labels); +} + void add_child(struct node *parent, struct node *child) { struct node **p; @@ -202,6 +269,32 @@ void add_child(struct node *parent, struct node *child) *p = child; } +void delete_node_by_name(struct node *parent, char *name) +{ + struct node *node = parent->children; + + while (node) { + if (!strcmp(node->name, name)) { + delete_node(node); + return; + } + node = node->next_sibling; + } +} + +void delete_node(struct node *node) +{ + struct property *prop; + struct node *child; + + node->deleted = 1; + for_each_child(node, child) + delete_node(child); + for_each_property(node, prop) + delete_property(prop); + delete_labels(&node->labels); +} + struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) { struct reserve_info *new = xmalloc(sizeof(*new)); @@ -353,8 +446,11 @@ struct node *get_node_by_path(struct node *tree, const char *path) const char *p; struct node *child; - if (!path || ! (*path)) + if (!path || ! (*path)) { + if (tree->deleted) + return NULL; return tree; + } while (path[0] == '/') path++; @@ -397,8 +493,11 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle) assert((phandle != 0) && (phandle != -1)); - if (tree->phandle == phandle) + if (tree->phandle == phandle) { + if (tree->deleted) + return NULL; return tree; + } for_each_child(tree, child) { node = get_node_by_phandle(child, phandle); @@ -535,7 +634,7 @@ static void sort_properties(struct node *node) int n = 0, i = 0; struct property *prop, **tbl; - for_each_property(node, prop) + for_each_property_withdel(node, prop) n++; if (n == 0) @@ -543,7 +642,7 @@ static void sort_properties(struct node *node) tbl = xmalloc(n * sizeof(*tbl)); - for_each_property(node, prop) + for_each_property_withdel(node, prop) tbl[i++] = prop; qsort(tbl, n, sizeof(*tbl), cmp_prop); @@ -571,7 +670,7 @@ static void sort_subnodes(struct node *node) int n = 0, i = 0; struct node *subnode, **tbl; - for_each_child(node, subnode) + for_each_child_withdel(node, subnode) n++; if (n == 0) @@ -579,7 +678,7 @@ static void sort_subnodes(struct node *node) tbl = xmalloc(n * sizeof(*tbl)); - for_each_child(node, subnode) + for_each_child_withdel(node, subnode) tbl[i++] = subnode; qsort(tbl, n, sizeof(*tbl), cmp_subnode); @@ -598,7 +697,7 @@ static void sort_node(struct node *node) sort_properties(node); sort_subnodes(node); - for_each_child(node, c) + for_each_child_withdel(node, c) sort_node(c); } diff --git a/tests/run_tests.sh b/tests/run_tests.sh index f5eebd6..e2158f7 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -367,6 +367,10 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_tree1_merge_path.test.dtb test_tree1_merge_path.dts tree1_tests dtc_tree1_merge_path.test.dtb test_tree1.dtb + # Check prop/node delete functionality + run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb test_tree1_delete.dts + tree1_tests dtc_tree1_delete.test.dtb + # Check some checks check_tests dup-nodename.dts duplicate_node_names check_tests dup-propname.dts duplicate_property_names diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts index cf530ce..c7b170c 100644 --- a/tests/test_tree1.dts +++ b/tests/test_tree1.dts @@ -1,38 +1,3 @@ /dts-v1/; -/memreserve/ 0xdeadbeef00000000 0x100000; -/memreserve/ 123456789 010000; - -/ { - compatible = "test_tree1"; - prop-int = <0xdeadbeef>; - prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; - prop-str = "hello world"; - - subnode@1 { - compatible = "subnode1"; - prop-int = [deadbeef]; - - subsubnode { - compatible = "subsubnode1", "subsubnode"; - prop-int = <0xdeadbeef>; - }; - - ss1 { - }; - }; - - subnode@2 { - linux,phandle = <0x2000>; - prop-int = <123456789>; - - ssn0: subsubnode@0 { - phandle = <0x2001>; - compatible = "subsubnode2", "subsubnode"; - prop-int = <0726746425>; - }; - - ss2 { - }; - }; -}; +/include/ "test_tree1_body.dtsi" diff --git a/tests/test_tree1_body.dtsi b/tests/test_tree1_body.dtsi new file mode 100644 index 0000000..1446191 --- /dev/null +++ b/tests/test_tree1_body.dtsi @@ -0,0 +1,36 @@ +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; + +/ { + compatible = "test_tree1"; + prop-int = <0xdeadbeef>; + prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; + prop-str = "hello world"; + + subnode@1 { + compatible = "subnode1"; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + linux,phandle = <0x2000>; + prop-int = <123456789>; + + ssn0: subsubnode@0 { + phandle = <0x2001>; + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; + }; + + ss2 { + }; + }; +}; diff --git a/tests/test_tree1_delete.dts b/tests/test_tree1_delete.dts new file mode 100644 index 0000000..a2f1bfd --- /dev/null +++ b/tests/test_tree1_delete.dts @@ -0,0 +1,68 @@ +/dts-v1/; + +/include/ "test_tree1_body.dtsi" + +/ { + nonexistant-property = <0xdeadbeef>; + + nonexistant-subnode { + prop-int = <1>; + }; + + dellabel: deleted-by-label { + prop-int = <1>; + }; + + subnode@1 { + delete-this-str = "deadbeef"; + }; + +}; + +/ { + /delete-property/ nonexistant-property; + + /delete-node/ nonexistant-subnode; + + subnode@1 { + /delete-property/ delete-this-str; + }; +}; + +/delete-node/ &dellabel; + +/ { + /delete-property/ prop-str; +}; + +/ { + prop-str = "hello world"; +}; + +/ { + subnode@1 { + /delete-node/ ss1; + }; +}; + +/ { + subnode@1 { + ss1 { + }; + }; +}; + +/{ + duplabel1: foo1 = "bar"; + duplabel2: foo2 = "bar"; +}; + +/{ + duplabel1: baz1 = "qux"; + duplabel2: baz2 = "qux"; +}; + +/{ + /delete-property/ foo1; + /delete-property/ baz2; +}; From 1ff3d3f8de701ed107e908030b5c1fed9d17125a Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 27 Sep 2012 17:11:04 -0600 Subject: [PATCH 0376/1198] dtc: cpp co-existence: allow names starting with # to be escaped The device tree language as currently defined conflicts with the C pre- processor in one aspect - when a property or node name begins with a # character, a pre-processor would attempt to interpret it as a directive, fail, and most likely error out. This change allows a property/node name to be prefixed with \. This prevents a pre-processor from seeing # as the first non-whitespace character on the line, and hence prevents the conflict. \ was previously an illegal character in property/node names, so this change is backwards compatible. The \ is stripped from the name during parsing by dtc. Signed-off-by: Stephen Warren Acked-by: David Gibson --- dtc-lexer.l | 5 +++-- tests/.gitignore | 1 + tests/Makefile.tests | 2 +- tests/propname_escapes.c | 43 ++++++++++++++++++++++++++++++++++++++ tests/propname_escapes.dts | 6 ++++++ tests/run_tests.sh | 3 +++ 6 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 tests/propname_escapes.c create mode 100644 tests/propname_escapes.dts diff --git a/dtc-lexer.l b/dtc-lexer.l index 91c4930..edbeb86 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -162,9 +162,10 @@ static int pop_input_file(void); return ']'; } -{PROPNODECHAR}+ { +\\?{PROPNODECHAR}+ { DPRINT("PropNodeName: %s\n", yytext); - yylval.propnodename = xstrdup(yytext); + yylval.propnodename = xstrdup((yytext[0] == '\\') ? + yytext + 1 : yytext); BEGIN_DEFAULT(); return DT_PROPNODENAME; } diff --git a/tests/.gitignore b/tests/.gitignore index f8e1af0..e2aa24a 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -39,6 +39,7 @@ tmp.* /path_offset /path_offset_aliases /phandle_format +/propname_escapes /references /root_node /rw_tree1 diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 1795466..d59bff8 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -12,7 +12,7 @@ LIB_TESTS_L = get_mem_rsv \ sw_tree1 \ move_and_save mangle-layout nopulate \ open_pack rw_tree1 set_name setprop del_property del_node \ - appendprop1 appendprop2 \ + appendprop1 appendprop2 propname_escapes \ string_escapes references path-references phandle_format \ boot-cpuid incbin \ extra-terminating-null \ diff --git a/tests/propname_escapes.c b/tests/propname_escapes.c new file mode 100644 index 0000000..3aec28f --- /dev/null +++ b/tests/propname_escapes.c @@ -0,0 +1,43 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_getprop() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "tests.h" + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_getprop_cell(fdt, 0, "#address-cells", 1); + check_getprop_cell(fdt, 0, "#gpio-cells", 2); + + PASS(); +} diff --git a/tests/propname_escapes.dts b/tests/propname_escapes.dts new file mode 100644 index 0000000..9f70618 --- /dev/null +++ b/tests/propname_escapes.dts @@ -0,0 +1,6 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + \#gpio-cells = <2>; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index e2158f7..7d7a5f7 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -254,6 +254,9 @@ dtc_tests () { tree1_tests_rw dtc_tree1.test.dtb run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb + run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb propname_escapes.dts + run_test propname_escapes dtc_escapes.test.dtb + run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts run_test string_escapes dtc_escapes.test.dtb From 1b6d1941dc5b589632c254ee6e960404d7cef5f2 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 27 Sep 2012 17:11:05 -0600 Subject: [PATCH 0377/1198] dtc: cpp co-existence: add support for #line directives Line control directives of the following formats are supported: #line LINE "FILE" # LINE "FILE" [FLAGS] This allows dtc to consume the output of pre-processors, and to provide error messages that refer to the original filename, including taking into account any #include directives that the pre-processor may have performed. Signed-off-by: Stephen Warren Acked-by: David Gibson --- dtc-lexer.l | 21 +++++++++++++++++++++ srcpos.c | 6 ++++++ srcpos.h | 2 ++ tests/line_directives.dts | 11 +++++++++++ tests/run_tests.sh | 2 ++ 5 files changed, 42 insertions(+) create mode 100644 tests/line_directives.dts diff --git a/dtc-lexer.l b/dtc-lexer.l index edbeb86..254d5af 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -71,6 +71,27 @@ static int pop_input_file(void); push_input_file(name); } +<*>^"#"(line)?{WS}+[0-9]+{WS}+{STRING}({WS}+[0-9]+)? { + char *line, *tmp, *fn; + /* skip text before line # */ + line = yytext; + while (!isdigit(*line)) + line++; + /* skip digits in line # */ + tmp = line; + while (!isspace(*tmp)) + tmp++; + /* "NULL"-terminate line # */ + *tmp = '\0'; + /* start of filename */ + fn = strchr(tmp + 1, '"') + 1; + /* strip trailing " from filename */ + tmp = strchr(fn, '"'); + *tmp = 0; + /* -1 since #line is the number of the next line */ + srcpos_set_line(xstrdup(fn), atoi(line) - 1); + } + <*><> { if (!pop_input_file()) { yyterminate(); diff --git a/srcpos.c b/srcpos.c index 3ee523d..246ab4b 100644 --- a/srcpos.c +++ b/srcpos.c @@ -328,3 +328,9 @@ srcpos_warn(struct srcpos *pos, char const *fmt, ...) va_end(va); } + +void srcpos_set_line(char *f, int l) +{ + current_srcfile->name = f; + current_srcfile->lineno = l; +} diff --git a/srcpos.h b/srcpos.h index 5617916..93a2712 100644 --- a/srcpos.h +++ b/srcpos.h @@ -113,4 +113,6 @@ extern void srcpos_error(struct srcpos *pos, char const *, ...) extern void srcpos_warn(struct srcpos *pos, char const *, ...) __attribute__((format(printf, 2, 3))); +extern void srcpos_set_line(char *f, int l); + #endif /* _SRCPOS_H_ */ diff --git a/tests/line_directives.dts b/tests/line_directives.dts new file mode 100644 index 0000000..e9d0800 --- /dev/null +++ b/tests/line_directives.dts @@ -0,0 +1,11 @@ +/dts-v1/; + +/* common format */ +#line 3 "foo.dts" +/* newer gcc format */ +# 9 "baz.dts" 1 +/* flags are optional */ +# 6 "bar.dts" + +/ { +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 7d7a5f7..9ca45c9 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -257,6 +257,8 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb propname_escapes.dts run_test propname_escapes dtc_escapes.test.dtb + run_dtc_test -I dts -O dtb -o line_directives.test.dtb line_directives.dts + run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts run_test string_escapes dtc_escapes.test.dtb From 317a5d92bc357aba2c993ee78b4c089b7539fcc6 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 28 Sep 2012 12:39:22 -0600 Subject: [PATCH 0378/1198] dtc: zero out new label objects Without this, new->deleted may be left set to some random value, which may then cause future label references to fail to locate the label. The code that allocates properties and nodes already contains the equivalent memset(). Signed-off-by: Stephen Warren --- livetree.c | 1 + 1 file changed, 1 insertion(+) diff --git a/livetree.c b/livetree.c index e856662..b61465f 100644 --- a/livetree.c +++ b/livetree.c @@ -36,6 +36,7 @@ void add_label(struct label **labels, char *label) } new = xmalloc(sizeof(*new)); + memset(new, 0, sizeof(*new)); new->label = label; new->next = *labels; *labels = new; From c6fb1d239191daa3323fb6caeff56d48c4777793 Mon Sep 17 00:00:00 2001 From: Anders Hedlund Date: Mon, 10 Sep 2012 13:50:56 +0200 Subject: [PATCH 0379/1198] libfdt: Added missing functions to shared library Some API function symbols were set as 'local' causing linking errors, now they are set as global (external). Signed-off-by: Anders Hedlund Acked-by: David Gibson --- libfdt/version.lds | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libfdt/version.lds b/libfdt/version.lds index 3c3994e..80b322b 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -48,6 +48,12 @@ LIBFDT_1.2 { fdt_strerror; fdt_offset_ptr; fdt_next_tag; + fdt_appendprop; + fdt_create_empty_tree; + fdt_first_property_offset; + fdt_get_property_by_offset; + fdt_getprop_by_offset; + fdt_next_property_offset; local: *; From 1762ab42ef77db7ab2776d0d6cba3515150f518a Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 5 Oct 2012 09:57:41 -0600 Subject: [PATCH 0380/1198] dtc: fix for_each_*() to skip first object if deleted The previous definition of for_each_*() would always include the very first object within the list, irrespective of whether it was marked deleted, since the deleted flag was not checked on the first object, but only on any "next" object. Fix for_each_*() to check the deleted flag in the loop body every iteration to correct this. Incidentally, this change is why commit 45013d8 dtc: "Add ability to delete nodes and properties" only caused two "make checkm" failures; only two tests actually use multiple labels on the same property or node. With this current change applied, but commit 317a5d9 "dtc: zero out new label objects" reverted, "make checkm" fails 29 times; i.e. for every test that uses any labels at all. Signed-off-by: Stephen Warren Acked-by: David Gibson --- dtc.h | 44 ++++++----------------- tests/delete_reinstate_multilabel.dts | 37 +++++++++++++++++++ tests/delete_reinstate_multilabel_ref.dts | 9 +++++ tests/run_tests.sh | 3 ++ 4 files changed, 59 insertions(+), 34 deletions(-) create mode 100644 tests/delete_reinstate_multilabel.dts create mode 100644 tests/delete_reinstate_multilabel_ref.dts diff --git a/dtc.h b/dtc.h index d501c86..3e42a07 100644 --- a/dtc.h +++ b/dtc.h @@ -161,51 +161,27 @@ struct node { struct label *labels; }; -static inline struct label *for_each_label_next(struct label *l) -{ - do { - l = l->next; - } while (l && l->deleted); - - return l; -} - -#define for_each_label(l0, l) \ - for ((l) = (l0); (l); (l) = for_each_label_next(l)) - #define for_each_label_withdel(l0, l) \ for ((l) = (l0); (l); (l) = (l)->next) -static inline struct property *for_each_property_next(struct property *p) -{ - do { - p = p->next; - } while (p && p->deleted); - - return p; -} - -#define for_each_property(n, p) \ - for ((p) = (n)->proplist; (p); (p) = for_each_property_next(p)) +#define for_each_label(l0, l) \ + for_each_label_withdel(l0, l) \ + if (!(l)->deleted) #define for_each_property_withdel(n, p) \ for ((p) = (n)->proplist; (p); (p) = (p)->next) -static inline struct node *for_each_child_next(struct node *c) -{ - do { - c = c->next_sibling; - } while (c && c->deleted); - - return c; -} - -#define for_each_child(n, c) \ - for ((c) = (n)->children; (c); (c) = for_each_child_next(c)) +#define for_each_property(n, p) \ + for_each_property_withdel(n, p) \ + if (!(p)->deleted) #define for_each_child_withdel(n, c) \ for ((c) = (n)->children; (c); (c) = (c)->next_sibling) +#define for_each_child(n, c) \ + for_each_child_withdel(n, c) \ + if (!(c)->deleted) + void add_label(struct label **labels, char *label); void delete_labels(struct label **labels); diff --git a/tests/delete_reinstate_multilabel.dts b/tests/delete_reinstate_multilabel.dts new file mode 100644 index 0000000..281a6b2 --- /dev/null +++ b/tests/delete_reinstate_multilabel.dts @@ -0,0 +1,37 @@ +/dts-v1/; + +/* Create some nodes and properties with multiple labels */ + +/ { + label1: label2: prop = "value"; + + label3: label4: node { + label5: label6: prop = "value"; + }; +}; + +/* Delete them, and everything that's part of them, i.e. the labels */ + +/ { + /delete-property/ prop; + /delete-node/ node; +}; + +/* + * Re-instate them. None of the old labels should come back + * + * Note: Do not add any new/extra labels here. As of the time of writing, + * when dtc adds labels to an object, they are added to the head of the list + * of labels, and this test is specifically about ensuring the correct + * handling of lists of labels where the first label in the list is marked as + * deleted. Failure to observe this note may result in the test passing when + * it should not. + */ + +/ { + prop = "value"; + + node { + prop = "value"; + }; +}; diff --git a/tests/delete_reinstate_multilabel_ref.dts b/tests/delete_reinstate_multilabel_ref.dts new file mode 100644 index 0000000..28fa117 --- /dev/null +++ b/tests/delete_reinstate_multilabel_ref.dts @@ -0,0 +1,9 @@ +/dts-v1/; + +/ { + prop = "value"; + + node { + prop = "value"; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 9ca45c9..dd7f217 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -376,6 +376,9 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb test_tree1_delete.dts tree1_tests dtc_tree1_delete.test.dtb + run_dtc_test -I dts -O dts -o delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel.dts + run_wrap_test cmp delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel_ref.dts + # Check some checks check_tests dup-nodename.dts duplicate_node_names check_tests dup-propname.dts duplicate_property_names From 8dec4d86ad3f44ef5011f86394d8f3061a09237a Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 16 Oct 2012 17:58:56 +1100 Subject: [PATCH 0381/1198] dtc: srcpos_verror() should print to stderr Errors should go to stderr. Signed-off-by: Michael Ellerman Acked-by: David Gibson --- srcpos.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srcpos.c b/srcpos.c index 246ab4b..c20bc53 100644 --- a/srcpos.c +++ b/srcpos.c @@ -297,9 +297,9 @@ srcpos_verror(struct srcpos *pos, char const *fmt, va_list va) srcstr = srcpos_string(pos); - fprintf(stdout, "Error: %s ", srcstr); - vfprintf(stdout, fmt, va); - fprintf(stdout, "\n"); + fprintf(stderr, "Error: %s ", srcstr); + vfprintf(stderr, fmt, va); + fprintf(stderr, "\n"); } void From e4b497f367a3b2ae99cc52089a14a221b13a76ef Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 16 Oct 2012 18:04:20 +1100 Subject: [PATCH 0382/1198] Add documentation on how to submit patches Signed-off-by: Michael Ellerman Acked-by: David Gibson --- Documentation/manual.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/manual.txt b/Documentation/manual.txt index 989c589..65c8540 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -3,6 +3,7 @@ Device Tree Compiler Manual I - "dtc", the device tree compiler 1) Obtaining Sources + 1.1) Submitting Patches 2) Description 3) Command Line 4) Source File @@ -44,6 +45,10 @@ Tarballs of the 1.0.0 and latest releases are here: http://www.jdl.com/software/dtc-v1.2.0.tgz http://www.jdl.com/software/dtc-latest.tgz +1.1) Submitting Patches + +Patches should be sent to jdl@jdl.com, and CC'ed to +devicetree-discuss@lists.ozlabs.org. 2) Description From 94a4799b200451d4037ec9219023becfe8c45ef1 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Fri, 4 Jan 2013 21:12:46 +0200 Subject: [PATCH 0383/1198] fdtdump: properly handle multi-string properties Device tree can store multiple strings in a single property. We didn't handle that case properly. Signed-off-by: Pantelis Antoniou Acked-by: David Gibson --- fdtdump.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/fdtdump.c b/fdtdump.c index 207a46d..d4fa6d7 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -21,13 +21,23 @@ static void print_data(const char *data, int len) { int i; const char *p = data; + const char *s; /* no data, don't print */ if (len == 0) return; if (util_is_printable_string(data, len)) { - printf(" = \"%s\"", (const char *)data); + printf(" = "); + + s = data; + do { + printf("\"%s\"", s); + s += strlen(s) + 1; + if (s < data + len) + printf(", "); + } while (s < data + len); + } else if ((len % 4) == 0) { printf(" = <"); for (i = 0; i < len; i += 4) From 1c1efd69545a101d7181fc8e5df2b9a3545a58e8 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Fri, 4 Jan 2013 21:12:58 +0200 Subject: [PATCH 0384/1198] Fix util_is_printable_string The method used did not account for multi-part strings. Signed-off-by: Pantelis Antoniou Acked-by: David Gibson --- util.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/util.c b/util.c index 2422c34..45f186b 100644 --- a/util.c +++ b/util.c @@ -72,7 +72,7 @@ char *join_path(const char *path, const char *name) int util_is_printable_string(const void *data, int len) { const char *s = data; - const char *ss; + const char *ss, *se; /* zero length is not */ if (len == 0) @@ -82,13 +82,19 @@ int util_is_printable_string(const void *data, int len) if (s[len - 1] != '\0') return 0; - ss = s; - while (*s && isprint(*s)) - s++; + se = s + len; - /* not zero, or not done yet */ - if (*s != '\0' || (s + 1 - ss) < len) - return 0; + while (s < se) { + ss = s; + while (s < se && *s && isprint(*s)) + s++; + + /* not zero, or not done yet */ + if (*s != '\0' || s == ss) + return 0; + + s++; + } return 1; } From 38ad79d33946590c862567c7cbdf25b5a46d8149 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Tue, 13 Nov 2012 18:34:01 -0600 Subject: [PATCH 0385/1198] dtc/tests: don't include fdt.h prior to libfdt.h tests will need fdt type definitions provided in a subsequent patch to libfdt_env.h. Since libfdt.h includes libfdt_env.h in the right order anyway, just remove the fdt.h include. Signed-off-by: Kim Phillips Acked-by: David Gibson --- tests/add_subnode_with_nops.c | 1 - tests/appendprop1.c | 1 - tests/appendprop2.c | 1 - tests/asm_tree_dump.c | 1 - tests/boot-cpuid.c | 1 - tests/char_literal.c | 1 - tests/del_node.c | 1 - tests/del_property.c | 1 - tests/dtb_reverse.c | 1 - tests/dtbs_equal_ordered.c | 1 - tests/dtbs_equal_unordered.c | 1 - tests/dumptrees.c | 2 -- tests/extra-terminating-null.c | 1 - tests/find_property.c | 1 - tests/get_alias.c | 1 - tests/get_mem_rsv.c | 1 - tests/get_name.c | 1 - tests/get_path.c | 1 - tests/get_phandle.c | 1 - tests/getprop.c | 1 - tests/incbin.c | 1 - tests/integer-expressions.c | 1 - tests/mangle-layout.c | 1 - tests/move_and_save.c | 1 - tests/node_check_compatible.c | 1 - tests/node_offset_by_compatible.c | 1 - tests/node_offset_by_phandle.c | 1 - tests/node_offset_by_prop_value.c | 1 - tests/nop_node.c | 1 - tests/nop_property.c | 1 - tests/nopulate.c | 1 - tests/notfound.c | 1 - tests/open_pack.c | 1 - tests/parent_offset.c | 1 - tests/path-references.c | 1 - tests/path_offset.c | 1 - tests/path_offset_aliases.c | 1 - tests/phandle_format.c | 1 - tests/propname_escapes.c | 1 - tests/references.c | 1 - tests/root_node.c | 1 - tests/rw_tree1.c | 1 - tests/set_name.c | 1 - tests/setprop.c | 1 - tests/setprop_inplace.c | 1 - tests/sized_cells.c | 1 - tests/string_escapes.c | 1 - tests/subnode_offset.c | 1 - tests/supernode_atdepth_offset.c | 1 - tests/sw_tree1.c | 1 - tests/truncated_property.c | 1 - tests/utilfdt_test.c | 1 - tests/value-labels.c | 1 - 53 files changed, 54 deletions(-) diff --git a/tests/add_subnode_with_nops.c b/tests/add_subnode_with_nops.c index 4fb8f02..95ddf6a 100644 --- a/tests/add_subnode_with_nops.c +++ b/tests/add_subnode_with_nops.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/appendprop1.c b/tests/appendprop1.c index d716f7a..9d6b3ad 100644 --- a/tests/appendprop1.c +++ b/tests/appendprop1.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/appendprop2.c b/tests/appendprop2.c index 7eb243d..ca1446c 100644 --- a/tests/appendprop2.c +++ b/tests/appendprop2.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/asm_tree_dump.c b/tests/asm_tree_dump.c index 5ff5087..bd12eda 100644 --- a/tests/asm_tree_dump.c +++ b/tests/asm_tree_dump.c @@ -26,7 +26,6 @@ #include -#include #include #include "tests.h" diff --git a/tests/boot-cpuid.c b/tests/boot-cpuid.c index 7b5433d..ca39f4b 100644 --- a/tests/boot-cpuid.c +++ b/tests/boot-cpuid.c @@ -21,7 +21,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/char_literal.c b/tests/char_literal.c index 150f2a0..d7a4773 100644 --- a/tests/char_literal.c +++ b/tests/char_literal.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/del_node.c b/tests/del_node.c index afad502..45cb060 100644 --- a/tests/del_node.c +++ b/tests/del_node.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/del_property.c b/tests/del_property.c index 449eca6..42fd7cb 100644 --- a/tests/del_property.c +++ b/tests/del_property.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/dtb_reverse.c b/tests/dtb_reverse.c index 25e1eef..527fd71 100644 --- a/tests/dtb_reverse.c +++ b/tests/dtb_reverse.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/dtbs_equal_ordered.c b/tests/dtbs_equal_ordered.c index 1db25f4..12495de 100644 --- a/tests/dtbs_equal_ordered.c +++ b/tests/dtbs_equal_ordered.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/dtbs_equal_unordered.c b/tests/dtbs_equal_unordered.c index df53318..20b4356 100644 --- a/tests/dtbs_equal_unordered.c +++ b/tests/dtbs_equal_unordered.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/dumptrees.c b/tests/dumptrees.c index fa1f563..bebf553 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -25,9 +25,7 @@ #include #include -#include #include -#include #include "testdata.h" diff --git a/tests/extra-terminating-null.c b/tests/extra-terminating-null.c index 8a2043f..dc1fe89 100644 --- a/tests/extra-terminating-null.c +++ b/tests/extra-terminating-null.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/find_property.c b/tests/find_property.c index 74a6965..4dc3030 100644 --- a/tests/find_property.c +++ b/tests/find_property.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/get_alias.c b/tests/get_alias.c index 1e0faf4..5060795 100644 --- a/tests/get_alias.c +++ b/tests/get_alias.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/get_mem_rsv.c b/tests/get_mem_rsv.c index 554c788..1812639 100644 --- a/tests/get_mem_rsv.c +++ b/tests/get_mem_rsv.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/get_name.c b/tests/get_name.c index 0262a12..c6ca9f9 100644 --- a/tests/get_name.c +++ b/tests/get_name.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/get_path.c b/tests/get_path.c index 1e05f7c..7352976 100644 --- a/tests/get_path.c +++ b/tests/get_path.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/get_phandle.c b/tests/get_phandle.c index 5735733..2079591 100644 --- a/tests/get_phandle.c +++ b/tests/get_phandle.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/getprop.c b/tests/getprop.c index 239856e..6255bad 100644 --- a/tests/getprop.c +++ b/tests/getprop.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/incbin.c b/tests/incbin.c index 76d8626..4100ba0 100644 --- a/tests/incbin.c +++ b/tests/incbin.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/integer-expressions.c b/tests/integer-expressions.c index 5ba1566..57e2ff6 100644 --- a/tests/integer-expressions.c +++ b/tests/integer-expressions.c @@ -25,7 +25,6 @@ #include -#include #include #include "tests.h" diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c index 3b19788..a76e51e 100644 --- a/tests/mangle-layout.c +++ b/tests/mangle-layout.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/move_and_save.c b/tests/move_and_save.c index 410ccb3..393b60a 100644 --- a/tests/move_and_save.c +++ b/tests/move_and_save.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/node_check_compatible.c b/tests/node_check_compatible.c index 23abbf5..4bdf091 100644 --- a/tests/node_check_compatible.c +++ b/tests/node_check_compatible.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/node_offset_by_compatible.c b/tests/node_offset_by_compatible.c index 2317930..f62b591 100644 --- a/tests/node_offset_by_compatible.c +++ b/tests/node_offset_by_compatible.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/node_offset_by_phandle.c b/tests/node_offset_by_phandle.c index a8442f1..becff0f 100644 --- a/tests/node_offset_by_phandle.c +++ b/tests/node_offset_by_phandle.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/node_offset_by_prop_value.c b/tests/node_offset_by_prop_value.c index 0f2a345..9212a4e 100644 --- a/tests/node_offset_by_prop_value.c +++ b/tests/node_offset_by_prop_value.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/nop_node.c b/tests/nop_node.c index ea3a18f..c316444 100644 --- a/tests/nop_node.c +++ b/tests/nop_node.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/nop_property.c b/tests/nop_property.c index e6ef4d9..644b0a6 100644 --- a/tests/nop_property.c +++ b/tests/nop_property.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/nopulate.c b/tests/nopulate.c index 3cbbe21..cd79872 100644 --- a/tests/nopulate.c +++ b/tests/nopulate.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/notfound.c b/tests/notfound.c index 4d55b88..dc623d6 100644 --- a/tests/notfound.c +++ b/tests/notfound.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/open_pack.c b/tests/open_pack.c index 0a5a3fc..407ef6c 100644 --- a/tests/open_pack.c +++ b/tests/open_pack.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/parent_offset.c b/tests/parent_offset.c index e7affcc..d4ab3cf 100644 --- a/tests/parent_offset.c +++ b/tests/parent_offset.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/path-references.c b/tests/path-references.c index 9f363b3..0746b3f 100644 --- a/tests/path-references.c +++ b/tests/path-references.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/path_offset.c b/tests/path_offset.c index d3e1f8e..4e5b7a1 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/path_offset_aliases.c b/tests/path_offset_aliases.c index 3682da4..78d5a46 100644 --- a/tests/path_offset_aliases.c +++ b/tests/path_offset_aliases.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/phandle_format.c b/tests/phandle_format.c index 7e4d816..5874ae7 100644 --- a/tests/phandle_format.c +++ b/tests/phandle_format.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/propname_escapes.c b/tests/propname_escapes.c index 3aec28f..e91bd99 100644 --- a/tests/propname_escapes.c +++ b/tests/propname_escapes.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/references.c b/tests/references.c index b20f21f..c9d05a2 100644 --- a/tests/references.c +++ b/tests/references.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/root_node.c b/tests/root_node.c index 3f47829..58aebf6 100644 --- a/tests/root_node.c +++ b/tests/root_node.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c index 103a24d..efd4718 100644 --- a/tests/rw_tree1.c +++ b/tests/rw_tree1.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/set_name.c b/tests/set_name.c index 5d1149e..9861587 100644 --- a/tests/set_name.c +++ b/tests/set_name.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/setprop.c b/tests/setprop.c index 9f2bc88..d089f8d 100644 --- a/tests/setprop.c +++ b/tests/setprop.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c index 82d8951..daef182 100644 --- a/tests/setprop_inplace.c +++ b/tests/setprop_inplace.c @@ -25,7 +25,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/sized_cells.c b/tests/sized_cells.c index 847ec96..94da03b 100644 --- a/tests/sized_cells.c +++ b/tests/sized_cells.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/string_escapes.c b/tests/string_escapes.c index 30eb6a8..8cdee4b 100644 --- a/tests/string_escapes.c +++ b/tests/string_escapes.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c index e58c192..231fcb5 100644 --- a/tests/subnode_offset.c +++ b/tests/subnode_offset.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/supernode_atdepth_offset.c b/tests/supernode_atdepth_offset.c index 73f41ae..43e120d 100644 --- a/tests/supernode_atdepth_offset.c +++ b/tests/supernode_atdepth_offset.c @@ -22,7 +22,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 5c71414..8eb6e5f 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/truncated_property.c b/tests/truncated_property.c index 56daa22..f820d99 100644 --- a/tests/truncated_property.c +++ b/tests/truncated_property.c @@ -23,7 +23,6 @@ #include #include -#include #include #include "tests.h" diff --git a/tests/utilfdt_test.c b/tests/utilfdt_test.c index 36b4aa5..274c3d6 100644 --- a/tests/utilfdt_test.c +++ b/tests/utilfdt_test.c @@ -24,7 +24,6 @@ #include #include -#include #include #include diff --git a/tests/value-labels.c b/tests/value-labels.c index abe2721..dcf2059 100644 --- a/tests/value-labels.c +++ b/tests/value-labels.c @@ -26,7 +26,6 @@ #include -#include #include #include "tests.h" From 20b866a7ce1651c4ca3f28cf380df66d9ed35719 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Tue, 13 Nov 2012 18:34:09 -0600 Subject: [PATCH 0386/1198] dtc/fdtdump: include libfdt_env.h prior to fdt.h in order to get the upcoming fdt type definitions. Signed-off-by: Kim Phillips Acked-by: David Gibson --- fdtdump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdtdump.c b/fdtdump.c index d4fa6d7..b2c5b37 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -8,8 +8,8 @@ #include #include -#include #include +#include #include "util.h" From feafcd972cb744750a65728440c99526e6199a6d Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Wed, 28 Nov 2012 17:33:01 -0600 Subject: [PATCH 0387/1198] dtc/libfdt: introduce fdt types for annotation by endian checkers Projects such as linux and u-boot run sparse on libfdt. libfdt contains the notion of endianness via usage of endian conversion functions such as fdt32_to_cpu. As such, in order to pass endian checks, libfdt has to annotate its fdt variables such that sparse can warn when mixing bitwise and regular integers. This patch adds these new fdtXX_t types and, ifdef __CHECKER__ (a symbol sparse defines), includes the bitwise annotation. Signed-off-by: Kim Phillips Acked-by: David Gibson --- libfdt/fdt.h | 42 +++++++++++++++---------------- libfdt/libfdt_env.h | 61 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 67 insertions(+), 36 deletions(-) diff --git a/libfdt/fdt.h b/libfdt/fdt.h index 48ccfd9..45dd134 100644 --- a/libfdt/fdt.h +++ b/libfdt/fdt.h @@ -4,45 +4,45 @@ #ifndef __ASSEMBLY__ struct fdt_header { - uint32_t magic; /* magic word FDT_MAGIC */ - uint32_t totalsize; /* total size of DT block */ - uint32_t off_dt_struct; /* offset to structure */ - uint32_t off_dt_strings; /* offset to strings */ - uint32_t off_mem_rsvmap; /* offset to memory reserve map */ - uint32_t version; /* format version */ - uint32_t last_comp_version; /* last compatible version */ + fdt32_t magic; /* magic word FDT_MAGIC */ + fdt32_t totalsize; /* total size of DT block */ + fdt32_t off_dt_struct; /* offset to structure */ + fdt32_t off_dt_strings; /* offset to strings */ + fdt32_t off_mem_rsvmap; /* offset to memory reserve map */ + fdt32_t version; /* format version */ + fdt32_t last_comp_version; /* last compatible version */ /* version 2 fields below */ - uint32_t boot_cpuid_phys; /* Which physical CPU id we're + fdt32_t boot_cpuid_phys; /* Which physical CPU id we're booting on */ /* version 3 fields below */ - uint32_t size_dt_strings; /* size of the strings block */ + fdt32_t size_dt_strings; /* size of the strings block */ /* version 17 fields below */ - uint32_t size_dt_struct; /* size of the structure block */ + fdt32_t size_dt_struct; /* size of the structure block */ }; struct fdt_reserve_entry { - uint64_t address; - uint64_t size; + fdt64_t address; + fdt64_t size; }; struct fdt_node_header { - uint32_t tag; + fdt32_t tag; char name[0]; }; struct fdt_property { - uint32_t tag; - uint32_t len; - uint32_t nameoff; + fdt32_t tag; + fdt32_t len; + fdt32_t nameoff; char data[0]; }; #endif /* !__ASSEMBLY */ #define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ -#define FDT_TAGSIZE sizeof(uint32_t) +#define FDT_TAGSIZE sizeof(fdt32_t) #define FDT_BEGIN_NODE 0x1 /* Start node: full name */ #define FDT_END_NODE 0x2 /* End node */ @@ -51,10 +51,10 @@ struct fdt_property { #define FDT_NOP 0x4 /* nop */ #define FDT_END 0x9 -#define FDT_V1_SIZE (7*sizeof(uint32_t)) -#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(uint32_t)) -#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(uint32_t)) +#define FDT_V1_SIZE (7*sizeof(fdt32_t)) +#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t)) +#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) #define FDT_V16_SIZE FDT_V3_SIZE -#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(uint32_t)) +#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) #endif /* _FDT_H */ diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h index 213d7fb..956b4ae 100644 --- a/libfdt/libfdt_env.h +++ b/libfdt/libfdt_env.h @@ -5,25 +5,56 @@ #include #include -#define EXTRACT_BYTE(n) ((unsigned long long)((uint8_t *)&x)[n]) -static inline uint16_t fdt16_to_cpu(uint16_t x) -{ - return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1); -} -#define cpu_to_fdt16(x) fdt16_to_cpu(x) +#ifdef __CHECKER__ +#define __force __attribute__((force)) +#define __bitwise __attribute__((bitwise)) +#else +#define __force +#define __bitwise +#endif -static inline uint32_t fdt32_to_cpu(uint32_t x) -{ - return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3); -} -#define cpu_to_fdt32(x) fdt32_to_cpu(x) +typedef uint16_t __bitwise fdt16_t; +typedef uint32_t __bitwise fdt32_t; +typedef uint64_t __bitwise fdt64_t; -static inline uint64_t fdt64_to_cpu(uint64_t x) +#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n]) +#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) +#define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \ + (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3)) +#define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \ + (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \ + (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \ + (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7)) + +static inline uint16_t fdt16_to_cpu(fdt16_t x) { - return (EXTRACT_BYTE(0) << 56) | (EXTRACT_BYTE(1) << 48) | (EXTRACT_BYTE(2) << 40) | (EXTRACT_BYTE(3) << 32) - | (EXTRACT_BYTE(4) << 24) | (EXTRACT_BYTE(5) << 16) | (EXTRACT_BYTE(6) << 8) | EXTRACT_BYTE(7); + return (__force uint16_t)CPU_TO_FDT16(x); } -#define cpu_to_fdt64(x) fdt64_to_cpu(x) +static inline fdt16_t cpu_to_fdt16(uint16_t x) +{ + return (__force fdt16_t)CPU_TO_FDT16(x); +} + +static inline uint32_t fdt32_to_cpu(fdt32_t x) +{ + return (__force uint32_t)CPU_TO_FDT32(x); +} +static inline fdt32_t cpu_to_fdt32(uint32_t x) +{ + return (__force fdt32_t)CPU_TO_FDT32(x); +} + +static inline uint64_t fdt64_to_cpu(fdt64_t x) +{ + return (__force uint64_t)CPU_TO_FDT64(x); +} +static inline fdt64_t cpu_to_fdt64(uint64_t x) +{ + return (__force fdt64_t)CPU_TO_FDT64(x); +} +#undef CPU_TO_FDT64 +#undef CPU_TO_FDT32 +#undef CPU_TO_FDT16 #undef EXTRACT_BYTE #endif /* _LIBFDT_ENV_H */ From 142419e43c99e88cbe72a760a72cdbf520690eb6 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Tue, 13 Nov 2012 18:34:30 -0600 Subject: [PATCH 0388/1198] dtc/libfdt: sparse fixes libfdt/fdt.c:104:28: warning: incorrect type in argument 1 (different base types) libfdt/fdt.c:104:28: expected restricted fdt32_t [usertype] x libfdt/fdt.c:104:28: got unsigned int const [unsigned] [usertype] libfdt/fdt.c:124:40: warning: incorrect type in argument 1 (different base types) libfdt/fdt.c:124:40: expected restricted fdt32_t [usertype] x libfdt/fdt.c:124:40: got unsigned int const [unsigned] [usertype] libfdt/fdt_ro.c:337:29: warning: incorrect type in argument 1 (different base types) libfdt/fdt_ro.c:337:29: expected restricted fdt32_t [usertype] x libfdt/fdt_ro.c:337:29: got unsigned int const [unsigned] [usertype] libfdt/fdt_rw.c:370:17: warning: incorrect type in assignment (different base types) libfdt/fdt_rw.c:370:17: expected unsigned int [unsigned] [usertype] libfdt/fdt_rw.c:370:17: got restricted fdt32_t libfdt/fdt_sw.c:164:13: warning: incorrect type in assignment (different base types) libfdt/fdt_sw.c:164:13: expected unsigned int [unsigned] [usertype] libfdt/fdt_sw.c:164:13: got restricted fdt32_t libfdt/fdt_sw.c:227:14: warning: incorrect type in assignment (different base types) libfdt/fdt_sw.c:227:14: expected unsigned int [unsigned] [usertype] libfdt/fdt_sw.c:227:14: got restricted fdt32_t libfdt/fdt_wip.c:80:20: warning: incorrect type in assignment (different base types) libfdt/fdt_wip.c:80:20: expected unsigned int [unsigned] [usertype] libfdt/fdt_wip.c:80:20: got restricted fdt32_t libfdt/libfdt.h:1001:13: warning: incorrect type in assignment (different base types) libfdt/libfdt.h:1001:13: expected unsigned long [unsigned] [usertype] val libfdt/libfdt.h:1001:13: got restricted fdt64_t libfdt/libfdt.h:1157:13: warning: incorrect type in assignment (different base types) libfdt/libfdt.h:1157:13: expected unsigned int [unsigned] [usertype] val libfdt/libfdt.h:1157:13: got restricted fdt32_t libfdt/libfdt.h:1192:13: warning: incorrect type in assignment (different base types) libfdt/libfdt.h:1192:13: expected unsigned long [unsigned] [usertype] val libfdt/libfdt.h:1192:13: got restricted fdt64_t libfdt/libfdt.h:1299:13: warning: incorrect type in assignment (different base types) libfdt/libfdt.h:1299:13: expected unsigned int [unsigned] [usertype] val libfdt/libfdt.h:1299:13: got restricted fdt32_t libfdt/libfdt.h:1334:13: warning: incorrect type in assignment (different base types) libfdt/libfdt.h:1334:13: expected unsigned long [unsigned] [usertype] val libfdt/libfdt.h:1334:13: got restricted fdt64_t libfdt/libfdt.h:885:13: warning: incorrect type in assignment (different base types) libfdt/libfdt.h:885:13: expected unsigned int [unsigned] [usertype] val libfdt/libfdt.h:885:13: got restricted fdt32_t libfdt/libfdt.h:920:13: warning: incorrect type in assignment (different base types) libfdt/libfdt.h:920:13: expected unsigned long [unsigned] [usertype] val libfdt/libfdt.h:920:13: got restricted fdt64_t libfdt/libfdt.h:996:13: warning: incorrect type in assignment (different base types) libfdt/libfdt.h:996:13: expected unsigned int [unsigned] [usertype] val libfdt/libfdt.h:996:13: got restricted fdt32_t Signed-off-by: Kim Phillips --- libfdt/fdt.c | 2 +- libfdt/fdt_ro.c | 2 +- libfdt/fdt_rw.c | 4 ++-- libfdt/fdt_sw.c | 4 ++-- libfdt/fdt_wip.c | 2 +- libfdt/libfdt.h | 32 ++++++++++++++++---------------- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index e56833a..57faba3 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -92,7 +92,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 uint32_t *tagp, *lenp; + const fdt32_t *tagp, *lenp; uint32_t tag; int offset = startoffset; const char *p; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 02b6d68..42da2bd 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -322,7 +322,7 @@ const void *fdt_getprop(const void *fdt, int nodeoffset, uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) { - const uint32_t *php; + const fdt32_t *php; int len; /* FIXME: This is a bit sub-optimal, since we potentially scan diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 24437df..fdba618 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -339,7 +339,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, int nodelen; int err; uint32_t tag; - uint32_t *endtag; + fdt32_t *endtag; FDT_RW_CHECK_HEADER(fdt); @@ -366,7 +366,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); memcpy(nh->name, name, namelen); - endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE); + endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE); *endtag = cpu_to_fdt32(FDT_END_NODE); return offset; diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 55ebebf..f422754 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -153,7 +153,7 @@ int fdt_begin_node(void *fdt, const char *name) int fdt_end_node(void *fdt) { - uint32_t *en; + fdt32_t *en; FDT_SW_CHECK_HEADER(fdt); @@ -213,7 +213,7 @@ int fdt_property(void *fdt, const char *name, const void *val, int len) int fdt_finish(void *fdt) { char *p = (char *)fdt; - uint32_t *end; + fdt32_t *end; int oldstroffset, newstroffset; uint32_t tag; int offset, nextoffset; diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c index 6025fa1..c5bbb68 100644 --- a/libfdt/fdt_wip.c +++ b/libfdt/fdt_wip.c @@ -74,7 +74,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, static void _fdt_nop_region(void *start, int len) { - uint32_t *p; + fdt32_t *p; for (p = start; (char *)p < ((char *)start + len); p++) *p = cpu_to_fdt32(FDT_NOP); diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 73f4975..8e57a06 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -882,8 +882,8 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, const char *name, uint32_t val) { - val = cpu_to_fdt32(val); - return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** @@ -917,8 +917,8 @@ static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, const char *name, uint64_t val) { - val = cpu_to_fdt64(val); - return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** @@ -993,13 +993,13 @@ int fdt_begin_node(void *fdt, const char *name); 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) { - val = cpu_to_fdt32(val); - return fdt_property(fdt, name, &val, sizeof(val)); + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_property(fdt, name, &tmp, sizeof(tmp)); } static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) { - val = cpu_to_fdt64(val); - return fdt_property(fdt, name, &val, sizeof(val)); + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_property(fdt, name, &tmp, sizeof(tmp)); } static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) { @@ -1154,8 +1154,8 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, uint32_t val) { - val = cpu_to_fdt32(val); - return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** @@ -1189,8 +1189,8 @@ static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, uint64_t val) { - val = cpu_to_fdt64(val); - return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** @@ -1296,8 +1296,8 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name, static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, const char *name, uint32_t val) { - val = cpu_to_fdt32(val); - return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val)); + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** @@ -1331,8 +1331,8 @@ static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, const char *name, uint64_t val) { - val = cpu_to_fdt64(val); - return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val)); + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** From 19cd5ead0b692c8c10e286252a7f4a725133d8f4 Mon Sep 17 00:00:00 2001 From: KRONSTORFER Horst Date: Tue, 11 Dec 2012 21:12:14 +0000 Subject: [PATCH 0389/1198] dtc: Drop the '-S is deprecated' warning The 'deprecated' warning is in there for more than 4 years now and nobody seemed to be confused enough to vote it out. Let's drop the warning then. This reverts commit 315c5d095ebdf29f1912186e76ab9f95e694b18a. Signed-off-by: Horst Kronstorfer --- dtc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/dtc.c b/dtc.c index a375683..d40e220 100644 --- a/dtc.c +++ b/dtc.c @@ -201,9 +201,6 @@ int main(int argc, char *argv[]) if (minsize && padsize) die("Can't set both -p and -S\n"); - if (minsize) - fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n"); - if (depname) { depfile = fopen(depname, "w"); if (!depfile) From 1760e7ca03894689118646e229ca9487158cd0e8 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 11 Dec 2012 10:05:51 -0700 Subject: [PATCH 0390/1198] fdtget-runtest.sh: use printf instead of /bin/echo -e Not all /bin/echo implementations support the -e option. Instead, use printf, which appears to be more widely available than /bin/echo -e. See commit eaec1db "fdtget-runtest.sh: Fix failures when /bin/sh isn't bash" for history. I have tested this on Ubuntu 10.04 with /bin/sh pointing to both dash and bash. Reported-by: Mike Frysinger # and implemented-by Signed-off-by: Stephen Warren Acked-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 c3a3559..8d8b058 100755 --- a/tests/fdtget-runtest.sh +++ b/tests/fdtget-runtest.sh @@ -8,7 +8,7 @@ rm -f $LOG $EXPECT trap "rm -f $LOG $EXPECT" 0 expect="$1" -/bin/echo -e $expect >$EXPECT +printf '%b\n' "$expect" > $EXPECT shift verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@" From 8055d77a5be3a4204b3aa5cd73ce5cc03362e193 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 27 Jan 2013 11:13:11 -0800 Subject: [PATCH 0391/1198] Adjust util_is_printable_string() comment and fix test This commit which changed the behaviour of this function broke one of the tests. Also the comment should be updated to reflect its new behaviour. Signed-off-by: Simon Glass Acked-by: David Gibson --- tests/run_tests.sh | 3 ++- util.h | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index dd7f217..b56b626 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -498,9 +498,10 @@ fdtget_tests () { # run_fdtget_test [] run_fdtget_test "MyBoardName" $dtb / model + run_fdtget_test "MyBoardName MyBoardFamilyName" $dtb / compatible run_fdtget_test "77 121 66 111 \ 97 114 100 78 97 109 101 0 77 121 66 111 97 114 100 70 97 109 105 \ -108 121 78 97 109 101 0" $dtb / compatible +108 121 78 97 109 101 0" -t bu $dtb / compatible run_fdtget_test "MyBoardName MyBoardFamilyName" -t s $dtb / compatible run_fdtget_test 32768 $dtb /cpus/PowerPC,970@1 d-cache-size run_fdtget_test 8000 -tx $dtb /cpus/PowerPC,970@1 d-cache-size diff --git a/util.h b/util.h index c8eb45d..e9043be 100644 --- a/util.h +++ b/util.h @@ -57,12 +57,14 @@ extern char *xstrdup(const char *s); extern char *join_path(const char *path, const char *name); /** - * Check a string of a given length to see if it is all printable and - * has a valid terminator. + * Check a property of a given length to see if it is all printable and + * has a valid terminator. The property can contain either a single string, + * or multiple strings each of non-zero length. * * @param data The string to check * @param len The string length including terminator - * @return 1 if a valid printable string, 0 if not */ + * @return 1 if a valid printable string, 0 if not + */ int util_is_printable_string(const void *data, int len); /* From d20391d6ff45c8fa7281e945491817c35f42b51b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Jan 2013 12:59:16 -0800 Subject: [PATCH 0392/1198] Move property-printing into util The function that prints a property can be useful to other programs, so move it into util. Signed-off-by: Simon Glass Acked-by: David Gibson --- fdtdump.c | 37 +------------------------------------ util.c | 37 +++++++++++++++++++++++++++++++++++++ util.h | 14 ++++++++++++++ 3 files changed, 52 insertions(+), 36 deletions(-) diff --git a/fdtdump.c b/fdtdump.c index b2c5b37..03ea429 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -17,41 +17,6 @@ #define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) #define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) -static void print_data(const char *data, int len) -{ - int i; - const char *p = data; - const char *s; - - /* no data, don't print */ - if (len == 0) - return; - - if (util_is_printable_string(data, len)) { - printf(" = "); - - s = data; - do { - printf("\"%s\"", s); - s += strlen(s) + 1; - if (s < data + len) - printf(", "); - } while (s < data + len); - - } else if ((len % 4) == 0) { - printf(" = <"); - for (i = 0; i < len; i += 4) - printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)), - i < (len - 4) ? " " : ""); - printf(">"); - } else { - printf(" = ["); - for (i = 0; i < len; i++) - printf("%02x%s", *p++, i < len - 1 ? " " : ""); - printf("]"); - } -} - static void dump_blob(void *blob) { struct fdt_header *bph = blob; @@ -147,7 +112,7 @@ static void dump_blob(void *blob) p = PALIGN(p + sz, 4); printf("%*s%s", depth * shift, "", s); - print_data(t, sz); + utilfdt_print_data(t, sz); printf(";\n"); } } diff --git a/util.c b/util.c index 45f186b..b081fa8 100644 --- a/util.c +++ b/util.c @@ -335,3 +335,40 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size) return -1; return 0; } + +void utilfdt_print_data(const char *data, int len) +{ + int i; + const char *p = data; + const char *s; + + /* no data, don't print */ + if (len == 0) + return; + + if (util_is_printable_string(data, len)) { + printf(" = "); + + s = data; + do { + printf("\"%s\"", s); + s += strlen(s) + 1; + if (s < data + len) + printf(", "); + } while (s < data + len); + + } else if ((len % 4) == 0) { + const uint32_t *cell = (const uint32_t *)data; + + printf(" = <"); + for (i = 0; i < len; i += 4) + printf("0x%08x%s", fdt32_to_cpu(cell[i]), + i < (len - 4) ? " " : ""); + printf(">"); + } else { + printf(" = ["); + for (i = 0; i < len; i++) + printf("%02x%s", *p++, i < len - 1 ? " " : ""); + printf("]"); + } +} diff --git a/util.h b/util.h index e9043be..543a173 100644 --- a/util.h +++ b/util.h @@ -152,4 +152,18 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size); "\tOptional modifier prefix:\n" \ "\t\thh or b=byte, h=2 byte, l=4 byte (default)\n"; +/** + * Print property data in a readable format to stdout + * + * Properties that look like strings will be printed as strings. Otherwise + * the data will be displayed either as cells (if len is a multiple of 4 + * bytes) or bytes. + * + * If len is 0 then this function does nothing. + * + * @param data Pointers to property data + * @param len Length of property data + */ +void utilfdt_print_data(const char *data, int len); + #endif /* _UTIL_H */ From d59b8078bd79a3ed0cd4bdb9bb92de4475bc1a84 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Jan 2013 12:59:17 -0800 Subject: [PATCH 0393/1198] .gitignore: Add rule for *.patch Ignore any patch files that we find, since these are likely to be used when sending patches upstream. Signed-off-by: Simon Glass Acked-by: David Gibson --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7cabc49..545b899 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.o *.d *.a +*.patch *.so *~ *.tab.[ch] From b7aa300eee001872134345416e73e0f81159798f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Jan 2013 12:59:18 -0800 Subject: [PATCH 0394/1198] Export fdt_stringlist_contains() This function is useful outside libfdt, so export it. Signed-off-by: Simon Glass Acked-by: David Gibson --- libfdt/fdt_ro.c | 5 ++--- libfdt/libfdt.h | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 42da2bd..50007f6 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -515,8 +515,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) return offset; /* error from fdt_next_node() */ } -static int _fdt_stringlist_contains(const char *strlist, int listlen, - const char *str) +int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) { int len = strlen(str); const char *p; @@ -542,7 +541,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); if (!prop) return len; - if (_fdt_stringlist_contains(prop, len, compatible)) + if (fdt_stringlist_contains(prop, len, compatible)) return 0; else return 1; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 8e57a06..c0075e7 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -816,6 +816,20 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible); +/** + * fdt_stringlist_contains - check a string list property for a string + * @strlist: Property containing a list of strings to check + * @listlen: Length of property + * @str: String to search for + * + * This is a utility function provided for convenience. The list contains + * 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 + */ +int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); + /**********************************************************************/ /* Write-in-place functions */ /**********************************************************************/ From cc11e522a3f50ad3ad289d1313cd0bf0ba491e24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Sun, 3 Feb 2013 00:52:21 +0100 Subject: [PATCH 0395/1198] Fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: François Revol --- libfdt/libfdt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index c0075e7..130789a 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -582,7 +582,7 @@ const char *fdt_get_alias_namelen(const void *fdt, * value of the property named 'name' in the node /aliases. * * returns: - * a pointer to the expansion of the alias named 'name', of it exists + * a pointer to the expansion of the alias named 'name', if it exists * NULL, if the given alias or the /aliases node does not exist */ const char *fdt_get_alias(const void *fdt, const char *name); From 27cdc1b16f86f970c3c049795d4e71ad531cca3d Mon Sep 17 00:00:00 2001 From: Justin Sobota Date: Fri, 15 Feb 2013 11:06:10 -0500 Subject: [PATCH 0396/1198] Added license header to dtc/libfdt/fdt.h and libfdt_env.h This commit adds a license header to fdt.h and libfdt_env.h because the license was omitted. Signed-off-by: Justin Sobota Acked-by: David Gibson --- libfdt/fdt.h | 51 +++++++++++++++++++++++++++++++++++++++++++++ libfdt/libfdt_env.h | 51 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/libfdt/fdt.h b/libfdt/fdt.h index 45dd134..526aedb 100644 --- a/libfdt/fdt.h +++ b/libfdt/fdt.h @@ -1,5 +1,56 @@ #ifndef _FDT_H #define _FDT_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef __ASSEMBLY__ diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h index 956b4ae..9dea97d 100644 --- a/libfdt/libfdt_env.h +++ b/libfdt/libfdt_env.h @@ -1,5 +1,56 @@ #ifndef _LIBFDT_ENV_H #define _LIBFDT_ENV_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include #include From f8cb5dd94903a5cfa1609695328b8f1d5557367f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 10 Apr 2013 14:29:06 -0400 Subject: [PATCH 0397/1198] utilfdt_read_err: use xmalloc funcs We've got these handy helpers, so let's use them. Acked-by: David Gibson Signed-off-by: Mike Frysinger --- util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util.c b/util.c index b081fa8..12f0614 100644 --- a/util.c +++ b/util.c @@ -212,12 +212,12 @@ int utilfdt_read_err(const char *filename, char **buffp) } /* Loop until we have read everything */ - buf = malloc(bufsize); + buf = xmalloc(bufsize); do { /* Expand the buffer to hold the next chunk */ if (offset == bufsize) { bufsize *= 2; - buf = realloc(buf, bufsize); + buf = xrealloc(buf, bufsize); if (!buf) { ret = ENOMEM; break; From cc2c178727cdeca4eb9756637c2e09e50e0856e7 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 10 Apr 2013 14:29:07 -0400 Subject: [PATCH 0398/1198] utilfdt_read: pass back up the length of data read For a follow up commit, we want to be able to scan the buffer that was returned to us. In order to do that safely, we need to know how big the buffer actually is, so pass that back if requested. Signed-off-by: Mike Frysinger --- fdtget.c | 2 +- fdtput.c | 2 +- tests/testutils.c | 2 +- util.c | 8 +++++--- util.h | 6 ++++-- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/fdtget.c b/fdtget.c index c2fbab2..374bee2 100644 --- a/fdtget.c +++ b/fdtget.c @@ -254,7 +254,7 @@ static int do_fdtget(struct display_info *disp, const char *filename, const char *prop; int i, node; - blob = utilfdt_read(filename); + blob = utilfdt_read(filename, NULL); if (!blob) return -1; diff --git a/fdtput.c b/fdtput.c index f2197f5..572d6da 100644 --- a/fdtput.c +++ b/fdtput.c @@ -239,7 +239,7 @@ static int do_fdtput(struct display_info *disp, const char *filename, char *blob; int len, ret = 0; - blob = utilfdt_read(filename); + blob = utilfdt_read(filename, NULL); if (!blob) return -1; diff --git a/tests/testutils.c b/tests/testutils.c index f185133..67b39b0 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -160,7 +160,7 @@ int nodename_eq(const char *s1, const char *s2) void *load_blob(const char *filename) { char *blob; - int ret = utilfdt_read_err(filename, &blob); + int ret = utilfdt_read_err(filename, &blob, NULL); if (ret) CONFIG("Couldn't open blob from \"%s\": %s", filename, diff --git a/util.c b/util.c index 12f0614..c689ea7 100644 --- a/util.c +++ b/util.c @@ -197,7 +197,7 @@ char get_escape_char(const char *s, int *i) return val; } -int utilfdt_read_err(const char *filename, char **buffp) +int utilfdt_read_err(const char *filename, char **buffp, off_t *len) { int fd = 0; /* assume stdin */ char *buf = NULL; @@ -238,13 +238,15 @@ int utilfdt_read_err(const char *filename, char **buffp) free(buf); else *buffp = buf; + if (len) + *len = bufsize; return ret; } -char *utilfdt_read(const char *filename) +char *utilfdt_read(const char *filename, off_t *len) { char *buff; - int ret = utilfdt_read_err(filename, &buff); + int ret = utilfdt_read_err(filename, &buff, len); if (ret) { fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, diff --git a/util.h b/util.h index 543a173..3c20b15 100644 --- a/util.h +++ b/util.h @@ -80,9 +80,10 @@ char get_escape_char(const char *s, int *i); * stderr. * * @param filename The filename to read, or - for stdin + * @param len If non-NULL, the amount of data we managed to read * @return Pointer to allocated buffer containing fdt, or NULL on error */ -char *utilfdt_read(const char *filename); +char *utilfdt_read(const char *filename, off_t *len); /** * Read a device tree file into a buffer. Does not report errors, but only @@ -91,9 +92,10 @@ char *utilfdt_read(const char *filename); * * @param filename The filename to read, or - for stdin * @param buffp Returns pointer to buffer containing fdt + * @param len If non-NULL, the amount of data we managed to read * @return 0 if ok, else an errno value representing the error */ -int utilfdt_read_err(const char *filename, char **buffp); +int utilfdt_read_err(const char *filename, char **buffp, off_t *len); /** From 97c122eacc8636b26992cf6e080775f7c28660f9 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 10 Apr 2013 14:29:08 -0400 Subject: [PATCH 0399/1198] die: constify format string arg We only display this string, so there's no need for it to be writable. Constify away! Acked-by: David Gibson Signed-off-by: Mike Frysinger --- util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.h b/util.h index 3c20b15..d856eb9 100644 --- a/util.h +++ b/util.h @@ -23,7 +23,7 @@ * USA */ -static inline void __attribute__((noreturn)) die(char * str, ...) +static inline void __attribute__((noreturn)) die(const char *str, ...) { va_list ap; From 31be4ce7ca550a6fd9c4eb39abdd2f9f5ac8db44 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 10 Apr 2013 14:29:09 -0400 Subject: [PATCH 0400/1198] util_version: new helper for displaying version info This is so all utilities can have this flag and not just dtc. Acked-by: David Gibson Signed-off-by: Mike Frysinger --- dtc.c | 5 +---- util.c | 7 +++++++ util.h | 5 +++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/dtc.c b/dtc.c index d40e220..e4e1b84 100644 --- a/dtc.c +++ b/dtc.c @@ -21,8 +21,6 @@ #include "dtc.h" #include "srcpos.h" -#include "version_gen.h" - /* * Command line options */ @@ -158,8 +156,7 @@ int main(int argc, char *argv[]) srcfile_add_search_path(optarg); break; case 'v': - printf("Version: %s\n", DTC_VERSION); - exit(0); + util_version(); case 'H': if (streq(optarg, "legacy")) phandle_format = PHANDLE_LEGACY; diff --git a/util.c b/util.c index c689ea7..a9b118c 100644 --- a/util.c +++ b/util.c @@ -34,6 +34,7 @@ #include "libfdt.h" #include "util.h" +#include "version_gen.h" char *xstrdup(const char *s) { @@ -374,3 +375,9 @@ void utilfdt_print_data(const char *data, int len) printf("]"); } } + +void util_version(void) +{ + printf("Version: %s\n", DTC_VERSION); + exit(0); +} diff --git a/util.h b/util.h index d856eb9..e09cc25 100644 --- a/util.h +++ b/util.h @@ -168,4 +168,9 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size); */ void utilfdt_print_data(const char *data, int len); +/** + * Show source version and exit + */ +void util_version(void) __attribute__((noreturn)); + #endif /* _UTIL_H */ From 5543b88d5e3047b781552eb431bc2e3bdd9ade06 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Mon, 22 Apr 2013 15:41:41 -0500 Subject: [PATCH 0401/1198] Revert "utilfdt_read: pass back up the length of data read" This reverts commit cc2c178727cdeca4eb9756637c2e09e50e0856e7. It was the wrong version of the patch. --- fdtget.c | 2 +- fdtput.c | 2 +- tests/testutils.c | 2 +- util.c | 8 +++----- util.h | 6 ++---- 5 files changed, 8 insertions(+), 12 deletions(-) diff --git a/fdtget.c b/fdtget.c index 374bee2..c2fbab2 100644 --- a/fdtget.c +++ b/fdtget.c @@ -254,7 +254,7 @@ static int do_fdtget(struct display_info *disp, const char *filename, const char *prop; int i, node; - blob = utilfdt_read(filename, NULL); + blob = utilfdt_read(filename); if (!blob) return -1; diff --git a/fdtput.c b/fdtput.c index 572d6da..f2197f5 100644 --- a/fdtput.c +++ b/fdtput.c @@ -239,7 +239,7 @@ static int do_fdtput(struct display_info *disp, const char *filename, char *blob; int len, ret = 0; - blob = utilfdt_read(filename, NULL); + blob = utilfdt_read(filename); if (!blob) return -1; diff --git a/tests/testutils.c b/tests/testutils.c index 67b39b0..f185133 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -160,7 +160,7 @@ int nodename_eq(const char *s1, const char *s2) void *load_blob(const char *filename) { char *blob; - int ret = utilfdt_read_err(filename, &blob, NULL); + int ret = utilfdt_read_err(filename, &blob); if (ret) CONFIG("Couldn't open blob from \"%s\": %s", filename, diff --git a/util.c b/util.c index a9b118c..4cdad10 100644 --- a/util.c +++ b/util.c @@ -198,7 +198,7 @@ char get_escape_char(const char *s, int *i) return val; } -int utilfdt_read_err(const char *filename, char **buffp, off_t *len) +int utilfdt_read_err(const char *filename, char **buffp) { int fd = 0; /* assume stdin */ char *buf = NULL; @@ -239,15 +239,13 @@ int utilfdt_read_err(const char *filename, char **buffp, off_t *len) free(buf); else *buffp = buf; - if (len) - *len = bufsize; return ret; } -char *utilfdt_read(const char *filename, off_t *len) +char *utilfdt_read(const char *filename) { char *buff; - int ret = utilfdt_read_err(filename, &buff, len); + int ret = utilfdt_read_err(filename, &buff); if (ret) { fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, diff --git a/util.h b/util.h index e09cc25..3f02cd8 100644 --- a/util.h +++ b/util.h @@ -80,10 +80,9 @@ char get_escape_char(const char *s, int *i); * stderr. * * @param filename The filename to read, or - for stdin - * @param len If non-NULL, the amount of data we managed to read * @return Pointer to allocated buffer containing fdt, or NULL on error */ -char *utilfdt_read(const char *filename, off_t *len); +char *utilfdt_read(const char *filename); /** * Read a device tree file into a buffer. Does not report errors, but only @@ -92,10 +91,9 @@ char *utilfdt_read(const char *filename, off_t *len); * * @param filename The filename to read, or - for stdin * @param buffp Returns pointer to buffer containing fdt - * @param len If non-NULL, the amount of data we managed to read * @return 0 if ok, else an errno value representing the error */ -int utilfdt_read_err(const char *filename, char **buffp, off_t *len); +int utilfdt_read_err(const char *filename, char **buffp); /** From a6d55e039fd22048687fe061b4609e2807efe764 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 8 Apr 2013 00:56:54 -0400 Subject: [PATCH 0402/1198] utilfdt_read: pass back up the length of data read For a follow up commit, we want to be able to scan the buffer that was returned to us. In order to do that safely, we need to know how big the buffer actually is, so create a new set of funcs to pass that back. Acked-by: David Gibson Signed-off-by: Mike Frysinger --- util.c | 19 ++++++++++++++++--- util.h | 13 +++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/util.c b/util.c index 4cdad10..350cf8b 100644 --- a/util.c +++ b/util.c @@ -198,7 +198,7 @@ char get_escape_char(const char *s, int *i) return val; } -int utilfdt_read_err(const char *filename, char **buffp) +int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len) { int fd = 0; /* assume stdin */ char *buf = NULL; @@ -239,13 +239,20 @@ int utilfdt_read_err(const char *filename, char **buffp) free(buf); else *buffp = buf; + *len = bufsize; return ret; } -char *utilfdt_read(const char *filename) +int utilfdt_read_err(const char *filename, char **buffp) +{ + off_t len; + return utilfdt_read_err_len(filename, buffp, &len); +} + +char *utilfdt_read_len(const char *filename, off_t *len) { char *buff; - int ret = utilfdt_read_err(filename, &buff); + int ret = utilfdt_read_err_len(filename, &buff, len); if (ret) { fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, @@ -256,6 +263,12 @@ char *utilfdt_read(const char *filename) return buff; } +char *utilfdt_read(const char *filename) +{ + off_t len; + return utilfdt_read_len(filename, &len); +} + int utilfdt_write_err(const char *filename, const void *blob) { int fd = 1; /* assume stdout */ diff --git a/util.h b/util.h index 3f02cd8..95ae531 100644 --- a/util.h +++ b/util.h @@ -84,6 +84,13 @@ char get_escape_char(const char *s, int *i); */ char *utilfdt_read(const char *filename); +/** + * Like utilfdt_read(), but also passes back the size of the file read. + * + * @param len If non-NULL, the amount of data we managed to read + */ +char *utilfdt_read_len(const char *filename, off_t *len); + /** * Read a device tree file into a buffer. Does not report errors, but only * returns them. The value returned can be passed to strerror() to obtain @@ -95,6 +102,12 @@ char *utilfdt_read(const char *filename); */ int utilfdt_read_err(const char *filename, char **buffp); +/** + * Like utilfdt_read_err(), but also passes back the size of the file read. + * + * @param len If non-NULL, the amount of data we managed to read + */ +int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len); /** * Write a device tree buffer to a file. This will report any errors on From 4e76ec796c90d44d417f82d9db2d67cfe575f8ed Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 26 Apr 2013 05:43:31 -0700 Subject: [PATCH 0403/1198] libfdt: Add fdt_next_subnode() to permit easy subnode iteration Iterating through subnodes with libfdt is a little painful to write as we need something like this: for (depth = 0, count = 0, offset = fdt_next_node(fdt, parent_offset, &depth); (offset >= 0) && (depth > 0); offset = fdt_next_node(fdt, offset, &depth)) { if (depth == 1) { /* code body */ } } Using fdt_next_subnode() we can instead write this, which is shorter and easier to get right: for (offset = fdt_first_subnode(fdt, parent_offset); offset >= 0; offset = fdt_next_subnode(fdt, offset)) { /* code body */ } Also, it doesn't require two levels of indentation for the loop body. Signed-off-by: Simon Glass Acked-by: David Gibson --- libfdt/fdt.c | 28 ++++++++++++ libfdt/libfdt.h | 22 +++++++++ tests/Makefile.tests | 3 +- tests/run_tests.sh | 3 ++ tests/subnode_iterate.c | 94 +++++++++++++++++++++++++++++++++++++++ tests/subnode_iterate.dts | 44 ++++++++++++++++++ 6 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 tests/subnode_iterate.c create mode 100644 tests/subnode_iterate.dts diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 57faba3..2ce6a44 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -198,6 +198,34 @@ int fdt_next_node(const void *fdt, int offset, int *depth) return offset; } +int fdt_first_subnode(const void *fdt, int offset) +{ + int depth = 0; + + offset = fdt_next_node(fdt, offset, &depth); + if (offset < 0 || depth != 1) + return -FDT_ERR_NOTFOUND; + + return offset; +} + +int fdt_next_subnode(const void *fdt, int offset) +{ + int depth = 1; + + /* + * With respect to the parent, the depth of the next subnode will be + * the same as the last. + */ + do { + offset = fdt_next_node(fdt, offset, &depth); + if (offset < 0 || depth < 1) + return -FDT_ERR_NOTFOUND; + } while (depth > 1); + + return offset; +} + const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) { int len = strlen(s) + 1; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 130789a..02baa84 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -136,6 +136,28 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); 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 + */ +int fdt_first_subnode(const void *fdt, int offset); + +/** + * fdt_next_subnode() - get offset of next direct 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 + */ +int fdt_next_subnode(const void *fdt, int offset); + /**********************************************************************/ /* General functions */ /**********************************************************************/ diff --git a/tests/Makefile.tests b/tests/Makefile.tests index d59bff8..dafb618 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -20,7 +20,8 @@ LIB_TESTS_L = get_mem_rsv \ dtb_reverse dtbs_equal_unordered \ add_subnode_with_nops path_offset_aliases \ utilfdt_test \ - integer-expressions + integer-expressions \ + subnode_iterate LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property diff --git a/tests/run_tests.sh b/tests/run_tests.sh index b56b626..b013761 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -241,6 +241,9 @@ libfdt_tests () { tree1_tests_rw noppy.$basetree done + run_dtc_test -I dts -O dtb -o subnode_iterate.dtb subnode_iterate.dts + run_test subnode_iterate subnode_iterate.dtb + # Tests for behaviour on various sorts of corrupted trees run_test truncated_property diff --git a/tests/subnode_iterate.c b/tests/subnode_iterate.c new file mode 100644 index 0000000..b9f379d --- /dev/null +++ b/tests/subnode_iterate.c @@ -0,0 +1,94 @@ +/* + * libfdt - Flat Device Tree manipulation + * Tests that fdt_next_subnode() works as expected + * + * Copyright (C) 2013 Google, Inc + * + * Copyright (C) 2007 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +static void test_node(void *fdt, int parent_offset) +{ + fdt32_t subnodes; + const fdt32_t *prop; + int offset; + int count; + int len; + + /* This property indicates the number of subnodes to expect */ + prop = fdt_getprop(fdt, parent_offset, "subnodes", &len); + if (!prop || len != sizeof(fdt32_t)) { + FAIL("Missing/invalid subnodes property at '%s'", + fdt_get_name(fdt, parent_offset, NULL)); + } + subnodes = cpu_to_fdt32(*prop); + + count = 0; + for (offset = fdt_first_subnode(fdt, parent_offset); + offset >= 0; + offset = fdt_next_subnode(fdt, offset)) + count++; + + if (count != subnodes) { + FAIL("Node '%s': Expected %d subnodes, got %d\n", + fdt_get_name(fdt, parent_offset, NULL), subnodes, + count); + } +} + +static void check_fdt_next_subnode(void *fdt) +{ + int offset; + int count = 0; + + for (offset = fdt_first_subnode(fdt, 0); + offset >= 0; + offset = fdt_next_subnode(fdt, offset)) { + test_node(fdt, offset); + count++; + } + + if (count != 2) + FAIL("Expected %d tests, got %d\n", 2, count); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + if (argc != 2) + CONFIG("Usage: %s ", argv[0]); + + fdt = load_blob(argv[1]); + if (!fdt) + FAIL("No device tree available"); + + check_fdt_next_subnode(fdt); + + PASS(); +} diff --git a/tests/subnode_iterate.dts b/tests/subnode_iterate.dts new file mode 100644 index 0000000..14a0d3a --- /dev/null +++ b/tests/subnode_iterate.dts @@ -0,0 +1,44 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <0>; + + test1 { + subnodes = <2>; + linux,phandle = <0x1>; + #address-cells = <1>; + #size-cells = <0>; + PowerPC,970@0 { + name = "PowerPC,970"; + device_type = "cpu"; + reg = <0x00000000>; + clock-frequency = <1600000000>; + timebase-frequency = <33333333>; + linux,boot-cpu; + i-cache-size = <65536>; + d-cache-size = <32768>; + another-sub-node { + should-be-ignored; + yet-another { + should-also-be-ignored; + }; + }; + }; + + PowerPC,970@1 { + name = "PowerPC,970"; + device_type = "cpu"; + reg = <0x00000001>; + clock-frequency = <1600000000>; + timebase-frequency = <33333333>; + i-cache-size = <65536>; + d-cache-size = <32768>; + }; + }; + + test2 { + subnodes = <0>; + }; +}; + From be8d1c82cb0a9caeb7e2f804f9a9f845063d7d53 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 15 Apr 2013 22:13:12 -0400 Subject: [PATCH 0404/1198] fdtdump: make usage a bit more friendly This starts a new usage framework and then cuts fdtdump over to it. Now we can do `fdtdump -h` and get something useful back. Signed-off-by: Mike Frysinger Signed-off-by: David Gibson --- fdtdump.c | 31 ++++++++++++++++++++-------- util.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ util.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 8 deletions(-) diff --git a/fdtdump.c b/fdtdump.c index 03ea429..a6e522c 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -117,21 +117,36 @@ static void dump_blob(void *blob) } } +/* Usage related data. */ +static const char usage_synopsis[] = "fdtdump [options] "; +static const char usage_short_opts[] = USAGE_COMMON_SHORT_OPTS; +static struct option const usage_long_opts[] = { + USAGE_COMMON_LONG_OPTS +}; +static const char * const usage_opts_help[] = { + USAGE_COMMON_OPTS_HELP +}; int main(int argc, char *argv[]) { + int opt; + const char *file; char *buf; - if (argc < 2) { - fprintf(stderr, "supply input filename\n"); - return 5; + while ((opt = util_getopt_long()) != EOF) { + switch (opt) { + case_USAGE_COMMON_FLAGS + } } + if (optind != argc - 1) + long_usage("missing input filename"); + file = argv[optind]; - buf = utilfdt_read(argv[1]); - if (buf) - dump_blob(buf); - else - return 10; + buf = utilfdt_read(file); + if (!buf) + die("could not read: %s\n", file); + + dump_blob(buf); return 0; } diff --git a/util.c b/util.c index 350cf8b..d9a823a 100644 --- a/util.c +++ b/util.c @@ -392,3 +392,57 @@ void util_version(void) printf("Version: %s\n", DTC_VERSION); exit(0); } + +void util_long_usage(const char *errmsg, const char *synopsis, + const char *short_opts, struct option const long_opts[], + const char * const opts_help[]) +{ + FILE *fp = errmsg ? stderr : stdout; + const char a_arg[] = ""; + size_t a_arg_len = strlen(a_arg) + 1; + size_t i; + int optlen; + + fprintf(fp, + "Usage: %s\n" + "\n" + "Options: -[%s]\n", synopsis, short_opts); + + /* prescan the --long opt length to auto-align */ + optlen = 0; + for (i = 0; long_opts[i].name; ++i) { + /* +1 is for space between --opt and help text */ + int l = strlen(long_opts[i].name) + 1; + if (long_opts[i].has_arg == a_argument) + l += a_arg_len; + if (optlen < l) + optlen = l; + } + + for (i = 0; long_opts[i].name; ++i) { + /* helps when adding new applets or options */ + assert(opts_help[i] != NULL); + + /* first output the short flag if it has one */ + if (long_opts[i].val > '~') + fprintf(fp, " "); + else + fprintf(fp, " -%c, ", long_opts[i].val); + + /* then the long flag */ + if (long_opts[i].has_arg == no_argument) + fprintf(fp, "--%-*s", optlen, long_opts[i].name); + else + fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg, + (int)(optlen - strlen(long_opts[i].name) - a_arg_len), ""); + + /* finally the help text */ + fprintf(fp, "%s\n", opts_help[i]); + } + + if (errmsg) { + fprintf(fp, "\nError: %s\n", errmsg); + exit(EXIT_FAILURE); + } else + exit(EXIT_SUCCESS); +} diff --git a/util.h b/util.h index 95ae531..1da3bd3 100644 --- a/util.h +++ b/util.h @@ -2,6 +2,7 @@ #define _UTIL_H #include +#include /* * Copyright 2011 The Chromium Authors, All Rights Reserved. @@ -184,4 +185,64 @@ void utilfdt_print_data(const char *data, int len); */ void util_version(void) __attribute__((noreturn)); +/** + * Show usage and exit + * + * This helps standardize the output of various utils. You most likely want + * to use the long_usage() helper below rather than call this. + * + * @param errmsg If non-NULL, an error message to display + * @param synopsis The initial example usage text (and possible examples) + * @param short_opts The string of short options + * @param long_opts The structure of long options + * @param opts_help An array of help strings (should align with long_opts) + */ +void util_long_usage(const char *errmsg, const char *synopsis, + const char *short_opts, struct option const long_opts[], + const char * const opts_help[]) __attribute__((noreturn)); + +/** + * Show usage and exit + * + * If you name all your usage variables with usage_xxx, then you can call this + * help macro rather than expanding all arguments yourself. + * + * @param errmsg If non-NULL, an error message to display + */ +#define long_usage(errmsg) \ + util_long_usage(errmsg, usage_synopsis, usage_short_opts, \ + usage_long_opts, usage_opts_help) + +/** + * Call getopt_long() with standard options + * + * Since all util code runs getopt in the same way, provide a helper. + */ +#define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \ + usage_long_opts, NULL) + +/* Helper for aligning long_opts array */ +#define a_argument required_argument + +/* Helper for usage_short_opts string constant */ +#define USAGE_COMMON_SHORT_OPTS "hV" + +/* Helper for usage_long_opts option array */ +#define USAGE_COMMON_LONG_OPTS \ + {"help", no_argument, NULL, 'h'}, \ + {"version", no_argument, NULL, 'V'}, \ + {NULL, no_argument, NULL, 0x0} + +/* Helper for usage_opts_help array */ +#define USAGE_COMMON_OPTS_HELP \ + "Print this help and exit", \ + "Print version and exit", \ + NULL + +/* Helper for getopt case statements */ +#define case_USAGE_COMMON_FLAGS \ + case 'h': long_usage(NULL); \ + case 'V': util_version(); \ + case '?': long_usage("unknown option"); + #endif /* _UTIL_H */ From fdc7387845420168ee5dd479fbe4391ff93bddab Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 15 Apr 2013 22:13:13 -0400 Subject: [PATCH 0405/1198] fdtdump: add a --scan option Often times, fdts get embedded in other larger files. Rather than force people to `dd` the blob out themselves, make the fdtdump file smarter. It can now scan the blob looking for the fdt magic. Once locate, it does a little validation on the main struct to make sure we didn't hit random binary data. Signed-off-by: Mike Frysinger Signed-off-by: David Gibson --- fdtdump.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/fdtdump.c b/fdtdump.c index a6e522c..c8a3ee7 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -2,12 +2,14 @@ * fdtdump.c - Contributed by Pantelis Antoniou */ +#include #include #include #include #include #include +#include #include #include @@ -119,11 +121,13 @@ static void dump_blob(void *blob) /* Usage related data. */ static const char usage_synopsis[] = "fdtdump [options] "; -static const char usage_short_opts[] = USAGE_COMMON_SHORT_OPTS; +static const char usage_short_opts[] = "s" USAGE_COMMON_SHORT_OPTS; static struct option const usage_long_opts[] = { + {"scan", no_argument, NULL, 's'}, USAGE_COMMON_LONG_OPTS }; static const char * const usage_opts_help[] = { + "Scan for an embedded fdt in file", USAGE_COMMON_OPTS_HELP }; @@ -132,20 +136,58 @@ int main(int argc, char *argv[]) int opt; const char *file; char *buf; + bool scan = false; + off_t len; while ((opt = util_getopt_long()) != EOF) { switch (opt) { case_USAGE_COMMON_FLAGS + + case 's': + scan = true; + break; } } if (optind != argc - 1) long_usage("missing input filename"); file = argv[optind]; - buf = utilfdt_read(file); + buf = utilfdt_read_len(file, &len); if (!buf) die("could not read: %s\n", file); + /* try and locate an embedded fdt in a bigger blob */ + if (scan) { + unsigned char smagic[4]; + char *p = buf; + char *endp = buf + len; + + fdt_set_magic(smagic, FDT_MAGIC); + + /* poor man's memmem */ + while (true) { + p = memchr(p, smagic[0], endp - p - 4); + if (!p) + break; + if (fdt_magic(p) == FDT_MAGIC) { + /* try and validate the main struct */ + off_t this_len = endp - p; + fdt32_t max_version = 17; + if (fdt_version(p) <= max_version && + fdt_last_comp_version(p) < max_version && + fdt_totalsize(p) < this_len && + fdt_off_dt_struct(p) < this_len && + fdt_off_dt_strings(p) < this_len) + break; + } + ++p; + } + if (!p) + die("%s: could not locate fdt magic\n", file); + printf("%s: found fdt at offset %#zx\n", file, p - buf); + buf = p; + } + dump_blob(buf); return 0; From 03449b84c8f9aee2bf2f438bec2c2ec4606bea48 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 24 May 2013 18:02:35 +1000 Subject: [PATCH 0406/1198] dtc/fdt{get, put}/convert-dtsv0-lexer: convert to new usage helpers This helps standardize the flag processing and the usage screens. Only lightly tested; would be great if someone who uses these utils could double check. Signed-off-by: Mike Frysinger Signed-off-by: David Gibson --- convert-dtsv0-lexer.l | 22 ++++++--- dtc.c | 111 ++++++++++++++++++++++-------------------- fdtget.c | 60 ++++++++++------------- fdtput.c | 63 +++++++++++------------- util.h | 2 +- 5 files changed, 131 insertions(+), 127 deletions(-) diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index 89d540a..e62d27a 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -194,11 +194,15 @@ const struct { } %% -static void usage(void) -{ - fprintf(stderr, "convert-dtsv0 ...\n"); - exit(3); -} +/* Usage related data. */ +static const char usage_synopsis[] = "convert-dtsv0 [options] ..."; +static const char usage_short_opts[] = "" USAGE_COMMON_SHORT_OPTS; +static struct option const usage_long_opts[] = { + USAGE_COMMON_LONG_OPTS +}; +static const char * const usage_opts_help[] = { + USAGE_COMMON_OPTS_HELP +}; static void convert_file(const char *fname) { @@ -226,10 +230,16 @@ static void convert_file(const char *fname) int main(int argc, char *argv[]) { + int opt; int i; + while ((opt = util_getopt_long()) != EOF) { + switch (opt) { + case_USAGE_COMMON_FLAGS + } + } if (argc < 2) - usage(); + long_usage("missing filename"); for (i = 1; i < argc; i++) { fprintf(stderr, "Converting %s from dts v0 to dts v1\n", argv[i]); diff --git a/dtc.c b/dtc.c index e4e1b84..d0a1f2d 100644 --- a/dtc.c +++ b/dtc.c @@ -47,55 +47,60 @@ static void fill_fullpaths(struct node *tree, const char *prefix) fill_fullpaths(child, tree->fullpath); } -static void __attribute__ ((noreturn)) usage(void) -{ - fprintf(stderr, "Usage:\n"); - fprintf(stderr, "\tdtc [options] \n"); - fprintf(stderr, "\nOptions:\n"); - fprintf(stderr, "\t-h\n"); - fprintf(stderr, "\t\tThis help text\n"); - fprintf(stderr, "\t-q\n"); - fprintf(stderr, "\t\tQuiet: -q suppress warnings, -qq errors, -qqq all\n"); - fprintf(stderr, "\t-I \n"); - fprintf(stderr, "\t\tInput formats are:\n"); - fprintf(stderr, "\t\t\tdts - device tree source text\n"); - fprintf(stderr, "\t\t\tdtb - device tree blob\n"); - fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n"); - fprintf(stderr, "\t-o \n"); - fprintf(stderr, "\t-O \n"); - fprintf(stderr, "\t\tOutput formats are:\n"); - fprintf(stderr, "\t\t\tdts - device tree source text\n"); - fprintf(stderr, "\t\t\tdtb - device tree blob\n"); - fprintf(stderr, "\t\t\tasm - assembler source\n"); - fprintf(stderr, "\t-V \n"); - fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION); - fprintf(stderr, "\t-d \n"); - fprintf(stderr, "\t-R \n"); - fprintf(stderr, "\t\tMake space for reserve map entries (relevant for \n\t\tdtb and asm output only)\n"); - fprintf(stderr, "\t-S \n"); - fprintf(stderr, "\t\tMake the blob at least long (extra space)\n"); - fprintf(stderr, "\t-p \n"); - fprintf(stderr, "\t\tAdd padding to the blob of long (extra space)\n"); - fprintf(stderr, "\t-b \n"); - fprintf(stderr, "\t\tSet the physical boot cpu\n"); - fprintf(stderr, "\t-f\n"); - fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n"); - fprintf(stderr, "\t-i\n"); - fprintf(stderr, "\t\tAdd a path to search for include files\n"); - fprintf(stderr, "\t-s\n"); - fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n"); - fprintf(stderr, "\t-v\n"); - fprintf(stderr, "\t\tPrint DTC version and exit\n"); - fprintf(stderr, "\t-H \n"); - fprintf(stderr, "\t\tphandle formats are:\n"); - fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n"); - fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n"); - fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n"); - fprintf(stderr, "\t-W [no-]\n"); - fprintf(stderr, "\t-E [no-]\n"); - fprintf(stderr, "\t\t\tenable or disable warnings and errors\n"); - exit(3); -} +/* Usage related data. */ +static const char usage_synopsis[] = "dtc [options] "; +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv"; +static struct option const usage_long_opts[] = { + {"quiet", no_argument, NULL, 'q'}, + {"in-format", a_argument, NULL, 'I'}, + {"out", a_argument, NULL, 'o'}, + {"out-format", a_argument, NULL, 'O'}, + {"out-version", a_argument, NULL, 'V'}, + {"out-dependency", a_argument, NULL, 'd'}, + {"reserve", a_argument, NULL, 'R'}, + {"space", a_argument, NULL, 'S'}, + {"pad", a_argument, NULL, 'p'}, + {"boot-cpu", a_argument, NULL, 'b'}, + {"force", no_argument, NULL, 'f'}, + {"include", a_argument, NULL, 'i'}, + {"sort", no_argument, NULL, 's'}, + {"phandle", a_argument, NULL, 'H'}, + {"warning", a_argument, NULL, 'W'}, + {"error", a_argument, NULL, 'E'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {NULL, no_argument, NULL, 0x0}, +}; +static const char * const usage_opts_help[] = { + "\n\tQuiet: -q suppress warnings, -qq errors, -qqq all", + "\n\tInput formats are:\n" + "\t\tdts - device tree source text\n" + "\t\tdtb - device tree blob\n" + "\t\tfs - /proc/device-tree style directory", + "\n\tOutput file", + "\n\tOutput formats are:\n" + "\t\tdts - device tree source text\n" + "\t\tdtb - device tree blob\n" + "\t\tasm - assembler source", + "\n\tBlob version to produce, defaults to %d (for dtb and asm output)", //, DEFAULT_FDT_VERSION); + "\n\tOutput dependency file", + "\n\ttMake space for reserve map entries (for dtb and asm output)", + "\n\tMake the blob at least long (extra space)", + "\n\tAdd padding to the blob of long (extra space)", + "\n\tSet the physical boot cpu", + "\n\tTry to produce output even if the input tree has errors", + "\n\tAdd a path to search for include files", + "\n\tSort nodes and properties before outputting (useful for comparing trees)", + "\n\tValid phandle formats are:\n" + "\t\tlegacy - \"linux,phandle\" properties only\n" + "\t\tepapr - \"phandle\" properties only\n" + "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties", + "\n\tEnable/disable warnings (prefix with \"no-\")", + "\n\tEnable/disable errors (prefix with \"no-\")", + "\n\tPrint this help and exit", + "\n\tPrint version and exit", + NULL, +}; int main(int argc, char *argv[]) { @@ -116,8 +121,7 @@ int main(int argc, char *argv[]) minsize = 0; padsize = 0; - while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:")) - != EOF) { + while ((opt = util_getopt_long()) != EOF) { switch (opt) { case 'I': inform = optarg; @@ -182,13 +186,14 @@ int main(int argc, char *argv[]) break; case 'h': + long_usage(NULL); default: - usage(); + long_usage("unknown option"); } } if (argc > (optind+1)) - usage(); + long_usage("missing files"); else if (argc < (optind+1)) arg = "-"; else diff --git a/fdtget.c b/fdtget.c index c2fbab2..5008cc1 100644 --- a/fdtget.c +++ b/fdtget.c @@ -277,33 +277,33 @@ static int do_fdtget(struct display_info *disp, const char *filename, return 0; } -static const char *usage_msg = - "fdtget - read values from device tree\n" - "\n" - "Each value is printed on a new line.\n\n" - "Usage:\n" +/* Usage related data. */ +static const char usage_synopsis[] = + "read values from device tree\n" " fdtget
[ ]...\n" " fdtget -p
[ ]...\n" - "Options:\n" - "\t-t \tType of data\n" - "\t-p\t\tList properties for each node\n" - "\t-l\t\tList subnodes for each node\n" - "\t-d\t\tDefault value to display when the property is " - "missing\n" - "\t-h\t\tPrint this help\n\n" + "\n" + "Each value is printed on a new line.\n" USAGE_TYPE_MSG; - -static void usage(const char *msg) -{ - if (msg) - fprintf(stderr, "Error: %s\n\n", msg); - - fprintf(stderr, "%s", usage_msg); - exit(2); -} +static const char usage_short_opts[] = "t:pld:" USAGE_COMMON_SHORT_OPTS; +static struct option const usage_long_opts[] = { + {"type", a_argument, NULL, 't'}, + {"properties", no_argument, NULL, 'p'}, + {"list", no_argument, NULL, 'l'}, + {"default", a_argument, NULL, 'd'}, + USAGE_COMMON_LONG_OPTS, +}; +static const char * const usage_opts_help[] = { + "Type of data", + "List properties for each node", + "List subnodes for each node", + "Default value to display when the property is missing", + USAGE_COMMON_OPTS_HELP +}; int main(int argc, char *argv[]) { + int opt; char *filename = NULL; struct display_info disp; int args_per_step = 2; @@ -312,20 +312,14 @@ int main(int argc, char *argv[]) memset(&disp, '\0', sizeof(disp)); disp.size = -1; disp.mode = MODE_SHOW_VALUE; - for (;;) { - int c = getopt(argc, argv, "d:hlpt:"); - if (c == -1) - break; - - switch (c) { - case 'h': - case '?': - usage(NULL); + while ((opt = util_getopt_long()) != EOF) { + switch (opt) { + case_USAGE_COMMON_FLAGS case 't': if (utilfdt_decode_type(optarg, &disp.type, &disp.size)) - usage("Invalid type string"); + long_usage("invalid type string"); break; case 'p': @@ -347,7 +341,7 @@ int main(int argc, char *argv[]) if (optind < argc) filename = argv[optind++]; if (!filename) - usage("Missing filename"); + long_usage("missing filename"); argv += optind; argc -= optind; @@ -358,7 +352,7 @@ int main(int argc, char *argv[]) /* Check for node, property arguments */ if (args_per_step == 2 && (argc % 2)) - usage("Must have an even number of arguments"); + long_usage("must have an even number of arguments"); if (do_fdtget(&disp, filename, argv, argc, args_per_step)) return 1; diff --git a/fdtput.c b/fdtput.c index f2197f5..99eb05c 100644 --- a/fdtput.c +++ b/fdtput.c @@ -272,44 +272,40 @@ static int do_fdtput(struct display_info *disp, const char *filename, return ret; } -static const char *usage_msg = - "fdtput - write a property value to a device tree\n" - "\n" - "The command line arguments are joined together into a single value.\n" - "\n" - "Usage:\n" +/* Usage related data. */ +static const char usage_synopsis[] = + "write a property value to a device tree\n" " fdtput
[...]\n" " fdtput -c
[...]\n" - "Options:\n" - "\t-c\t\tCreate nodes if they don't already exist\n" - "\t-p\t\tAutomatically create nodes as needed for the node path\n" - "\t-t \tType of data\n" - "\t-v\t\tVerbose: display each value decoded from command line\n" - "\t-h\t\tPrint this help\n\n" + "\n" + "The command line arguments are joined together into a single value.\n" USAGE_TYPE_MSG; - -static void usage(const char *msg) -{ - if (msg) - fprintf(stderr, "Error: %s\n\n", msg); - - fprintf(stderr, "%s", usage_msg); - exit(2); -} +static const char usage_short_opts[] = "cpt:v" USAGE_COMMON_SHORT_OPTS; +static struct option const usage_long_opts[] = { + {"create", no_argument, NULL, 'c'}, + {"auto-path", no_argument, NULL, 'p'}, + {"type", a_argument, NULL, 't'}, + {"verbose", no_argument, NULL, 'v'}, + USAGE_COMMON_LONG_OPTS, +}; +static const char * const usage_opts_help[] = { + "Create nodes if they don't already exist", + "Automatically create nodes as needed for the node path", + "Type of data", + "Display each value decoded from command line", + USAGE_COMMON_OPTS_HELP +}; int main(int argc, char *argv[]) { + int opt; struct display_info disp; char *filename = NULL; memset(&disp, '\0', sizeof(disp)); disp.size = -1; disp.oper = OPER_WRITE_PROP; - for (;;) { - int c = getopt(argc, argv, "chpt:v"); - if (c == -1) - break; - + while ((opt = util_getopt_long()) != EOF) { /* * TODO: add options to: * - delete property @@ -319,20 +315,19 @@ int main(int argc, char *argv[]) * - set amount of free space when writing * - expand fdt if value doesn't fit */ - switch (c) { + switch (opt) { + case_USAGE_COMMON_FLAGS + case 'c': disp.oper = OPER_CREATE_NODE; break; - case 'h': - case '?': - usage(NULL); case 'p': disp.auto_path = 1; break; case 't': if (utilfdt_decode_type(optarg, &disp.type, &disp.size)) - usage("Invalid type string"); + long_usage("Invalid type string"); break; case 'v': @@ -344,16 +339,16 @@ int main(int argc, char *argv[]) if (optind < argc) filename = argv[optind++]; if (!filename) - usage("Missing filename"); + long_usage("missing filename"); argv += optind; argc -= optind; if (disp.oper == OPER_WRITE_PROP) { if (argc < 1) - usage("Missing node"); + long_usage("missing node"); if (argc < 2) - usage("Missing property"); + long_usage("missing property"); } if (do_fdtput(&disp, filename, argv, argc)) diff --git a/util.h b/util.h index 1da3bd3..439b2b3 100644 --- a/util.h +++ b/util.h @@ -164,7 +164,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" \ "\tOptional modifier prefix:\n" \ - "\t\thh or b=byte, h=2 byte, l=4 byte (default)\n"; + "\t\thh or b=byte, h=2 byte, l=4 byte (default)"; /** * Print property data in a readable format to stdout From b9e80656f2de441826ed2ff1cd9c5d43b3ae43d3 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 24 May 2013 18:04:43 +1000 Subject: [PATCH 0407/1198] util: drop "long" from usage helpers Now that all utils have converted to the new usage framework, we can rename to just plain "usage()" and avoid naming conflicts. Signed-off-by: Mike Frysinger Signed-off-by: David Gibson --- convert-dtsv0-lexer.l | 2 +- dtc.c | 6 +++--- fdtdump.c | 2 +- fdtget.c | 6 +++--- fdtput.c | 8 ++++---- util.c | 6 +++--- util.h | 18 +++++++++--------- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index e62d27a..8902648 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -239,7 +239,7 @@ int main(int argc, char *argv[]) } } if (argc < 2) - long_usage("missing filename"); + usage("missing filename"); for (i = 1; i < argc; i++) { fprintf(stderr, "Converting %s from dts v0 to dts v1\n", argv[i]); diff --git a/dtc.c b/dtc.c index d0a1f2d..e3c9653 100644 --- a/dtc.c +++ b/dtc.c @@ -186,14 +186,14 @@ int main(int argc, char *argv[]) break; case 'h': - long_usage(NULL); + usage(NULL); default: - long_usage("unknown option"); + usage("unknown option"); } } if (argc > (optind+1)) - long_usage("missing files"); + usage("missing files"); else if (argc < (optind+1)) arg = "-"; else diff --git a/fdtdump.c b/fdtdump.c index c8a3ee7..c2f16ea 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -149,7 +149,7 @@ int main(int argc, char *argv[]) } } if (optind != argc - 1) - long_usage("missing input filename"); + usage("missing input filename"); file = argv[optind]; buf = utilfdt_read_len(file, &len); diff --git a/fdtget.c b/fdtget.c index 5008cc1..4377419 100644 --- a/fdtget.c +++ b/fdtget.c @@ -319,7 +319,7 @@ int main(int argc, char *argv[]) case 't': if (utilfdt_decode_type(optarg, &disp.type, &disp.size)) - long_usage("invalid type string"); + usage("invalid type string"); break; case 'p': @@ -341,7 +341,7 @@ int main(int argc, char *argv[]) if (optind < argc) filename = argv[optind++]; if (!filename) - long_usage("missing filename"); + usage("missing filename"); argv += optind; argc -= optind; @@ -352,7 +352,7 @@ int main(int argc, char *argv[]) /* Check for node, property arguments */ if (args_per_step == 2 && (argc % 2)) - long_usage("must have an even number of arguments"); + usage("must have an even number of arguments"); if (do_fdtget(&disp, filename, argv, argc, args_per_step)) return 1; diff --git a/fdtput.c b/fdtput.c index 99eb05c..fbb283a 100644 --- a/fdtput.c +++ b/fdtput.c @@ -327,7 +327,7 @@ int main(int argc, char *argv[]) case 't': if (utilfdt_decode_type(optarg, &disp.type, &disp.size)) - long_usage("Invalid type string"); + usage("Invalid type string"); break; case 'v': @@ -339,16 +339,16 @@ int main(int argc, char *argv[]) if (optind < argc) filename = argv[optind++]; if (!filename) - long_usage("missing filename"); + usage("missing filename"); argv += optind; argc -= optind; if (disp.oper == OPER_WRITE_PROP) { if (argc < 1) - long_usage("missing node"); + usage("missing node"); if (argc < 2) - long_usage("missing property"); + usage("missing property"); } if (do_fdtput(&disp, filename, argv, argc)) diff --git a/util.c b/util.c index d9a823a..3055c16 100644 --- a/util.c +++ b/util.c @@ -393,9 +393,9 @@ void util_version(void) exit(0); } -void util_long_usage(const char *errmsg, const char *synopsis, - const char *short_opts, struct option const long_opts[], - const char * const opts_help[]) +void util_usage(const char *errmsg, const char *synopsis, + const char *short_opts, struct option const long_opts[], + const char * const opts_help[]) { FILE *fp = errmsg ? stderr : stdout; const char a_arg[] = ""; diff --git a/util.h b/util.h index 439b2b3..7b9a840 100644 --- a/util.h +++ b/util.h @@ -189,7 +189,7 @@ void util_version(void) __attribute__((noreturn)); * Show usage and exit * * This helps standardize the output of various utils. You most likely want - * to use the long_usage() helper below rather than call this. + * to use the usage() helper below rather than call this. * * @param errmsg If non-NULL, an error message to display * @param synopsis The initial example usage text (and possible examples) @@ -197,9 +197,9 @@ void util_version(void) __attribute__((noreturn)); * @param long_opts The structure of long options * @param opts_help An array of help strings (should align with long_opts) */ -void util_long_usage(const char *errmsg, const char *synopsis, - const char *short_opts, struct option const long_opts[], - const char * const opts_help[]) __attribute__((noreturn)); +void util_usage(const char *errmsg, const char *synopsis, + const char *short_opts, struct option const long_opts[], + const char * const opts_help[]) __attribute__((noreturn)); /** * Show usage and exit @@ -209,9 +209,9 @@ void util_long_usage(const char *errmsg, const char *synopsis, * * @param errmsg If non-NULL, an error message to display */ -#define long_usage(errmsg) \ - util_long_usage(errmsg, usage_synopsis, usage_short_opts, \ - usage_long_opts, usage_opts_help) +#define usage(errmsg) \ + util_usage(errmsg, usage_synopsis, usage_short_opts, \ + usage_long_opts, usage_opts_help) /** * Call getopt_long() with standard options @@ -241,8 +241,8 @@ void util_long_usage(const char *errmsg, const char *synopsis, /* Helper for getopt case statements */ #define case_USAGE_COMMON_FLAGS \ - case 'h': long_usage(NULL); \ + case 'h': usage(NULL); \ case 'V': util_version(); \ - case '?': long_usage("unknown option"); + case '?': usage("unknown option"); #endif /* _UTIL_H */ From 4ad49c3a9cdaccac02cd448c2704ea52ad85d1dc Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 15 Apr 2013 22:13:16 -0400 Subject: [PATCH 0408/1198] util: add common ARRAY_SIZE define I want to use this in more places, so put it in util.h rather than copying & pasting it into another file. Signed-off-by: Mike Frysinger Signed-off-by: David Gibson --- convert-dtsv0-lexer.l | 2 -- dtc.h | 1 - util.h | 2 ++ 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index 8902648..548e719 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -50,8 +50,6 @@ static int saw_hyphen; /* = 0 */ static unsigned long long last_val; static char *last_name; /* = NULL */ -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - const struct { const char *pattern; int obase, width; diff --git a/dtc.h b/dtc.h index 3e42a07..264a20c 100644 --- a/dtc.h +++ b/dtc.h @@ -66,7 +66,6 @@ typedef uint32_t cell_t; #define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) /* Data blobs */ enum markertype { diff --git a/util.h b/util.h index 7b9a840..8f40b44 100644 --- a/util.h +++ b/util.h @@ -24,6 +24,8 @@ * USA */ +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + static inline void __attribute__((noreturn)) die(const char *str, ...) { va_list ap; From 8ec013ae635f36f0a51a21f8b38e3a2669e3b74e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 15 Apr 2013 22:13:17 -0400 Subject: [PATCH 0409/1198] fdtdump: add a debug mode When hacking raw fdt files, it's useful to know the actual offsets into the file each node appears. Add a --debug mode that includes this. Signed-off-by: Mike Frysinger Signed-off-by: David Gibson --- fdtdump.c | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/fdtdump.c b/fdtdump.c index c2f16ea..723770d 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -19,8 +19,29 @@ #define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) #define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) -static void dump_blob(void *blob) +static const char *tagname(uint32_t tag) { + static const char * const names[] = { +#define TN(t) [t] #t + TN(FDT_BEGIN_NODE), + TN(FDT_END_NODE), + TN(FDT_PROP), + TN(FDT_NOP), + TN(FDT_END), +#undef TN + }; + if (tag < ARRAY_SIZE(names)) + if (names[tag]) + return names[tag]; + return "FDT_???"; +} + +#define dumpf(fmt, args...) \ + do { if (debug) printf("// " fmt, ## args); } while (0) + +static void dump_blob(void *blob, bool debug) +{ + uintptr_t blob_off = (uintptr_t)blob; struct fdt_header *bph = blob; uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap); uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct); @@ -74,7 +95,8 @@ static void dump_blob(void *blob) p = p_struct; while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { - /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */ + dumpf("%04zx: tag: 0x%08x (%s)\n", + (uintptr_t)p - blob_off - 4, tag, tagname(tag)); if (tag == FDT_BEGIN_NODE) { s = p; @@ -113,6 +135,8 @@ static void dump_blob(void *blob) p = PALIGN(p + sz, 4); + dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s); + dumpf("%04zx: value\n", (uintptr_t)t - blob_off); printf("%*s%s", depth * shift, "", s); utilfdt_print_data(t, sz); printf(";\n"); @@ -121,12 +145,14 @@ static void dump_blob(void *blob) /* Usage related data. */ static const char usage_synopsis[] = "fdtdump [options] "; -static const char usage_short_opts[] = "s" USAGE_COMMON_SHORT_OPTS; +static const char usage_short_opts[] = "ds" USAGE_COMMON_SHORT_OPTS; static struct option const usage_long_opts[] = { + {"debug", no_argument, NULL, 'd'}, {"scan", no_argument, NULL, 's'}, USAGE_COMMON_LONG_OPTS }; static const char * const usage_opts_help[] = { + "Dump debug information while decoding the file", "Scan for an embedded fdt in file", USAGE_COMMON_OPTS_HELP }; @@ -136,6 +162,7 @@ int main(int argc, char *argv[]) int opt; const char *file; char *buf; + bool debug = false; bool scan = false; off_t len; @@ -143,6 +170,9 @@ int main(int argc, char *argv[]) switch (opt) { case_USAGE_COMMON_FLAGS + case 'd': + debug = true; + break; case 's': scan = true; break; @@ -179,6 +209,9 @@ int main(int argc, char *argv[]) fdt_off_dt_struct(p) < this_len && fdt_off_dt_strings(p) < this_len) break; + if (debug) + printf("%s: skipping fdt magic at offset %#zx\n", + file, p - buf); } ++p; } @@ -188,7 +221,7 @@ int main(int argc, char *argv[]) buf = p; } - dump_blob(buf); + dump_blob(buf, debug); return 0; } From 1c76ec3c090f230fa8a45a5ef84bda600fc4d064 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 29 May 2013 12:39:47 +1000 Subject: [PATCH 0410/1198] Use shorten_echo for wrap_tests We have certain tests which generate extremely long command lines, which are shortened in the testsuite output with the 'shorten_echo' function. Currently that is used in run_fdtput_test and run_wrap_test, this patch uses it for run_wrap_test as well, allowing more general tests with long command lines. 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 b013761..9c87369 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -80,7 +80,7 @@ wrap_test () { } run_wrap_test () { - echo -n "$@: " + shorten_echo "$@: " base_run_test wrap_test "$@" } From a58afe2eb28645641367f4eacdea2c124d291f6e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 29 May 2013 12:44:18 +1000 Subject: [PATCH 0411/1198] Remove some tests for misfeatures There are a couple of fdtput related tests which are rather pointless - they explicitly test for the presence of an undesirable limitation in fdtput, which will cause test failures when we fix it. This patch removes the tests. Signed-off-by: David Gibson --- tests/run_tests.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 9c87369..d0a7f02 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -549,9 +549,6 @@ fdtput_tests () { -tx "a0b0c0d deeaae ef000000" run_fdtput_test "$(cat $text)" $dtb /randomnode blob -ts "$(cat $text)" - # This should be larger than available space in the fdt - run_wrap_error_test $DTPUT $dtb /randomnode blob -ts "$(cat $text $text)" - # Start again with a fresh dtb run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts @@ -572,7 +569,6 @@ fdtput_tests () { run_fdtput_test "fine wine" $dtb /blackadder/the-second/potato drink \ "-ts" "fine wine" run_wrap_test $DTPUT $dtb -p /you/are/drunk/sir/winston slurp -ts twice - run_wrap_error_test $DTPUT $dtb -cp "$(cat $text $text)/longish" # Allowed to create an existing node with -p run_wrap_test $DTPUT $dtb -cp /chosen From d214655904b49938dafcb83797de3f6a0dc725c8 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Wed, 29 May 2013 12:47:38 +1000 Subject: [PATCH 0412/1198] fdtput: expand fdt if value does not fit If you try to insert a new node or extend a property with large value, using fdtput you will notice that it always fails. example: fdtput -v -p -ts ./tst.dtb "/node-1" "property-1" "value-1 Error at 'node-1': FDT_ERR_NOSPACE or fdtput -v -c ./tst.dtb "/node-1" Error at 'node-1': FDT_ERR_NOSPACE or fdtput -v -ts ./tst.dtb "/node" "property" "very big value" Decoding value: string: 'very big value' Value size 15 Error at 'property': FDT_ERR_NOSPACE All these error are returned from libfdt, as the size of the fdt passed has no space to accomdate these new properties. This patch adds realloc functions in fdtput to allocate new space in fdt when it detects a shortage in space for new value or node. With this patch, fdtput can insert a new node or property or extend a property with new value greater than original size. Also it packs the final blob to clean up any extra padding. Without this patch fdtput tool complains with FDT_ERR_NOSPACE when we try to add a node/property or extend the value of a property. Testcases for the new behaviour added by David Gibson. Signed-off-by: Srinivas Kandagatla Signed-off-by: David Gibson --- fdtput.c | 74 ++++++++++++++++++++++++++++++++++++---------- tests/run_tests.sh | 6 ++++ 2 files changed, 65 insertions(+), 15 deletions(-) diff --git a/fdtput.c b/fdtput.c index fbb283a..5226a4e 100644 --- a/fdtput.c +++ b/fdtput.c @@ -131,19 +131,59 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count, return 0; } -static int store_key_value(void *blob, const char *node_name, +#define ALIGN(x) (((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1)) + +static char *_realloc_fdt(char *fdt, int delta) +{ + int new_sz = fdt_totalsize(fdt) + delta; + fdt = xrealloc(fdt, new_sz); + fdt_open_into(fdt, fdt, new_sz); + return fdt; +} + +static char *realloc_node(char *fdt, const char *name) +{ + int delta; + /* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */ + delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1) + + FDT_TAGSIZE; + return _realloc_fdt(fdt, delta); +} + +static char *realloc_property(char *fdt, int nodeoffset, + const char *name, int newlen) +{ + int delta = 0; + int oldlen = 0; + + if (!fdt_get_property(fdt, nodeoffset, name, &oldlen)) + /* strings + property header */ + delta = sizeof(struct fdt_property) + strlen(name) + 1; + + if (newlen > oldlen) + /* actual value in off_struct */ + delta += ALIGN(newlen) - ALIGN(oldlen); + + return _realloc_fdt(fdt, delta); +} + +static int store_key_value(char **blob, const char *node_name, const char *property, const char *buf, int len) { int node; int err; - node = fdt_path_offset(blob, node_name); + node = fdt_path_offset(*blob, node_name); if (node < 0) { report_error(node_name, -1, node); return -1; } - err = fdt_setprop(blob, node, property, buf, len); + err = fdt_setprop(*blob, node, property, buf, len); + if (err == -FDT_ERR_NOSPACE) { + *blob = realloc_property(*blob, node, property, len); + err = fdt_setprop(*blob, node, property, buf, len); + } if (err) { report_error(property, -1, err); return -1; @@ -161,7 +201,7 @@ static int store_key_value(void *blob, const char *node_name, * @param in_path Path to process * @return 0 if ok, -1 on error */ -static int create_paths(void *blob, const char *in_path) +static int create_paths(char **blob, const char *in_path) { const char *path = in_path; const char *sep; @@ -177,10 +217,11 @@ static int create_paths(void *blob, const char *in_path) if (!sep) sep = path + strlen(path); - node = fdt_subnode_offset_namelen(blob, offset, path, + node = fdt_subnode_offset_namelen(*blob, offset, path, sep - path); if (node == -FDT_ERR_NOTFOUND) { - node = fdt_add_subnode_namelen(blob, offset, path, + *blob = realloc_node(*blob, path); + node = fdt_add_subnode_namelen(*blob, offset, path, sep - path); } if (node < 0) { @@ -203,7 +244,7 @@ static int create_paths(void *blob, const char *in_path) * @param node_name Name of node to create * @return new node offset if found, or -1 on failure */ -static int create_node(void *blob, const char *node_name) +static int create_node(char **blob, const char *node_name) { int node = 0; char *p; @@ -215,15 +256,17 @@ static int create_node(void *blob, const char *node_name) } *p = '\0'; + *blob = realloc_node(*blob, p + 1); + if (p > node_name) { - node = fdt_path_offset(blob, node_name); + node = fdt_path_offset(*blob, node_name); if (node < 0) { report_error(node_name, -1, node); return -1; } } - node = fdt_add_subnode(blob, node, p + 1); + node = fdt_add_subnode(*blob, node, p + 1); if (node < 0) { report_error(p + 1, -1, node); return -1; @@ -250,23 +293,25 @@ static int do_fdtput(struct display_info *disp, const char *filename, * store them into the property. */ assert(arg_count >= 2); - if (disp->auto_path && create_paths(blob, *arg)) + if (disp->auto_path && create_paths(&blob, *arg)) return -1; if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) || - store_key_value(blob, *arg, arg[1], value, len)) + store_key_value(&blob, *arg, arg[1], value, len)) ret = -1; break; case OPER_CREATE_NODE: for (; ret >= 0 && arg_count--; arg++) { if (disp->auto_path) - ret = create_paths(blob, *arg); + ret = create_paths(&blob, *arg); else - ret = create_node(blob, *arg); + ret = create_node(&blob, *arg); } break; } - if (ret >= 0) + if (ret >= 0) { + fdt_pack(blob); ret = utilfdt_write(filename, blob); + } free(blob); return ret; @@ -313,7 +358,6 @@ int main(int argc, char *argv[]) * - rename node * - pack fdt before writing * - set amount of free space when writing - * - expand fdt if value doesn't fit */ switch (opt) { case_USAGE_COMMON_FLAGS diff --git a/tests/run_tests.sh b/tests/run_tests.sh index d0a7f02..c0a136b 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -549,6 +549,9 @@ fdtput_tests () { -tx "a0b0c0d deeaae ef000000" run_fdtput_test "$(cat $text)" $dtb /randomnode blob -ts "$(cat $text)" + # Test expansion of the blob when insufficient room for property + run_fdtput_test "$(cat $text $text)" $dtb /randomnode blob -ts "$(cat $text $text)" + # Start again with a fresh dtb run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts @@ -570,6 +573,9 @@ fdtput_tests () { "-ts" "fine wine" run_wrap_test $DTPUT $dtb -p /you/are/drunk/sir/winston slurp -ts twice + # Test expansion of the blob when insufficent room for a new node + run_wrap_test $DTPUT $dtb -cp "$(cat $text $text)/longish" + # Allowed to create an existing node with -p run_wrap_test $DTPUT $dtb -cp /chosen run_wrap_test $DTPUT $dtb -cp /chosen/son From 2e3fc7e9b3a4722a5500afaa9faf7874c61b2e6a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 29 May 2013 12:46:35 +1000 Subject: [PATCH 0413/1198] Add missing test binary to .gitignore The subnode_iterate test binary was missing from .gitignore, this fixes it. Signed-off-by: David Gibson --- tests/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/.gitignore b/tests/.gitignore index e2aa24a..bb5e33a 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -48,6 +48,7 @@ tmp.* /setprop_inplace /sized_cells /string_escapes +/subnode_iterate /subnode_offset /supernode_atdepth_offset /sw_tree1 From a1ee6f068e1c8dbc62873645037a353d7852d5cc Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 31 May 2013 12:33:04 -0600 Subject: [PATCH 0414/1198] dtc: ensure #line directives don't consume data from the next line Previously, the #line parsing regex ended with ({WS}+[0-9]+)?. The {WS} could match line-break characters. If the #line directive did not contain the optional flags field at the end, this could cause any integer data on the next line to be consumed as part of the #line directive parsing. This could cause syntax errors (i.e. #line parsing consuming the leading 0 from a hex literal 0x1234, leaving x1234 to be parsed as cell data, which is a syntax error), or invalid compilation results (i.e. simply consuming literal 1234 as part of the #line processing, thus removing it from the cell data). Fix this by replacing {WS} with [ \t] so that it can't match line-breaks. Convert all instances of {WS}, even though the other instances should be irrelevant for any well-formed #line directive. This is done for consistency and ultimate safety. Reported-by: Ian Campbell Signed-off-by: Stephen Warren Acked-by: David Gibson --- dtc-lexer.l | 2 +- tests/line_directives.dts | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 254d5af..3b41bfc 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -71,7 +71,7 @@ static int pop_input_file(void); push_input_file(name); } -<*>^"#"(line)?{WS}+[0-9]+{WS}+{STRING}({WS}+[0-9]+)? { +<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? { char *line, *tmp, *fn; /* skip text before line # */ line = yytext; diff --git a/tests/line_directives.dts b/tests/line_directives.dts index e9d0800..046ef37 100644 --- a/tests/line_directives.dts +++ b/tests/line_directives.dts @@ -8,4 +8,14 @@ # 6 "bar.dts" / { +/* + * Make sure optional flags don't consume integer data on next line. The issue + * was that the {WS} in the trailing ({WS}+[0-9]+)? could cross the * line- + * break, and consume the leading "0" of the hex constant, leaving "x12345678" + * to be parsed as a number, which is invalid syntax. + */ + prop1 = < +# 10 "qux.dts" + 0x12345678 + >; }; From 65cc4d2748a2c2e6f27f1cf39e07a5dbabd80ebf Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 22 Jun 2013 12:54:28 -0500 Subject: [PATCH 0415/1198] Tag Version 1.4.0 Signed-off-by: Jon Loeliger --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1169e6c..962f94e 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ # CONFIG_LOCALVERSION from some future config system. # VERSION = 1 -PATCHLEVEL = 3 +PATCHLEVEL = 4 SUBLEVEL = 0 EXTRAVERSION = LOCAL_VERSION = From 9476db68b6470ec645d2ee61c263e127147f5073 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 15 Aug 2013 15:49:24 +1000 Subject: [PATCH 0416/1198] Makefile: provide separate install targets Currently `make install` will install the binaries, libraries and includes. This change separates the install target into install-bin, install-lib and install-includes, so we have more flexibility, particularly when we're just using libfdt. Signed-off-by: Jeremy Kerr Signed-off-by: David Gibson --- Makefile | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 962f94e..70abf05 100644 --- a/Makefile +++ b/Makefile @@ -160,18 +160,26 @@ endif # intermediate target and building them again "for real" .SECONDARY: $(DTC_GEN_SRCS) $(CONVERT_GEN_SRCS) -install: all $(SCRIPTS) - @$(VECHO) INSTALL +install-bin: all $(SCRIPTS) + @$(VECHO) INSTALL-BIN $(INSTALL) -d $(DESTDIR)$(BINDIR) $(INSTALL) $(BIN) $(SCRIPTS) $(DESTDIR)$(BINDIR) + +install-lib: all + @$(VECHO) INSTALL-LIB $(INSTALL) -d $(DESTDIR)$(LIBDIR) $(INSTALL) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) ln -sf $(notdir $(LIBFDT_lib)) $(DESTDIR)$(LIBDIR)/$(LIBFDT_soname) ln -sf $(LIBFDT_soname) $(DESTDIR)$(LIBDIR)/libfdt.$(SHAREDLIB_EXT) $(INSTALL) -m 644 $(LIBFDT_archive) $(DESTDIR)$(LIBDIR) + +install-includes: + @$(VECHO) INSTALL-INC $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) $(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR) +install: install-bin install-lib install-includes + $(VERSION_FILE): Makefile FORCE $(call filechk,version) From b290428d711f5a38073ed993a63e6bbf1e6af66d Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 19 Sep 2013 22:15:13 +1000 Subject: [PATCH 0417/1198] Ensure all tests have matching reg and unit address ePAPR 1.1 section 2.2.1.1 "Node Name Requirements" specifies that any node that has a reg property must include a unit address in its name with value matching the first entry in its reg property. Conversely, if a node does not have a reg property, the node name must not include a unit address. Adjust all the dtc test-cases to conform to this rule. Signed-off-by: Stephen Warren Signed-off-by: David Gibson --- tests/aliases.dts | 4 ++++ tests/include1.dts | 5 +++++ tests/include7.dts | 1 + tests/include8.dts | 3 ++- tests/sw_tree1.c | 7 +++++++ tests/test_tree1_body.dtsi | 7 +++++++ tests/test_tree1_merge.dts | 7 +++++++ tests/test_tree1_merge_labelled.dts | 7 +++++++ tests/test_tree1_merge_path.dts | 7 +++++++ tests/test_tree1_wrong1.dts | 7 +++++++ tests/test_tree1_wrong2.dts | 7 +++++++ tests/test_tree1_wrong3.dts | 7 +++++++ tests/test_tree1_wrong4.dts | 7 +++++++ tests/test_tree1_wrong5.dts | 7 +++++++ tests/test_tree1_wrong6.dts | 7 +++++++ tests/test_tree1_wrong7.dts | 7 +++++++ tests/test_tree1_wrong8.dts | 7 +++++++ tests/test_tree1_wrong9.dts | 7 +++++++ tests/trees.S | 10 ++++++++++ 19 files changed, 120 insertions(+), 1 deletion(-) diff --git a/tests/aliases.dts b/tests/aliases.dts index 39d88ff..853479a 100644 --- a/tests/aliases.dts +++ b/tests/aliases.dts @@ -1,6 +1,9 @@ /dts-v1/; / { + #address-cells = <1>; + #size-cells = <0>; + aliases { s1 = &sub1; ss1 = &subsub1; @@ -9,6 +12,7 @@ sub1: subnode@1 { compatible = "subnode1"; + reg = <1>; subsub1: subsubnode { compatible = "subsubnode1", "subsubnode"; diff --git a/tests/include1.dts b/tests/include1.dts index 893aaff..0b4b773 100644 --- a/tests/include1.dts +++ b/tests/include1.dts @@ -8,12 +8,17 @@ /include/ "include5.dts" = <0xdeadbeef>; prop-int64 /include/ "include5a.dts"; prop-str = /include/ "include6.dts"; + #address-cells = <1>; + #size-cells = <0>; /include/ "include7.dts" subnode@2 { + reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; /include/ "include8.dts" phandle = <0x2001>; diff --git a/tests/include7.dts b/tests/include7.dts index dba5e47..2f6eb89 100644 --- a/tests/include7.dts +++ b/tests/include7.dts @@ -1,5 +1,6 @@ subnode@1 { compatible = "subnode1"; + reg = <1>; prop-int = [deadbeef]; subsubnode { diff --git a/tests/include8.dts b/tests/include8.dts index ec70064..7532ef5 100644 --- a/tests/include8.dts +++ b/tests/include8.dts @@ -1 +1,2 @@ -subsubnode@0 { \ No newline at end of file +subsubnode@0 { + reg = <0>; diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 8eb6e5f..e9ea7e7 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -57,9 +57,12 @@ int main(int argc, char *argv[]) CHECK(fdt_property_u32(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_property_u64(fdt, "prop-int64", TEST_VALUE64_1)); CHECK(fdt_property_string(fdt, "prop-str", TEST_STRING_1)); + CHECK(fdt_property_u32(fdt, "#address-cells", 1)); + CHECK(fdt_property_u32(fdt, "#size-cells", 0)); CHECK(fdt_begin_node(fdt, "subnode@1")); CHECK(fdt_property_string(fdt, "compatible", "subnode1")); + CHECK(fdt_property_u32(fdt, "reg", 1)); CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_begin_node(fdt, "subsubnode")); CHECK(fdt_property(fdt, "compatible", "subsubnode1\0subsubnode", @@ -71,9 +74,13 @@ int main(int argc, char *argv[]) CHECK(fdt_end_node(fdt)); CHECK(fdt_begin_node(fdt, "subnode@2")); + CHECK(fdt_property_u32(fdt, "reg", 2)); CHECK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_1)); CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2)); + CHECK(fdt_property_u32(fdt, "#address-cells", 1)); + CHECK(fdt_property_u32(fdt, "#size-cells", 0)); CHECK(fdt_begin_node(fdt, "subsubnode@0")); + CHECK(fdt_property_u32(fdt, "reg", 0)); CHECK(fdt_property_cell(fdt, "phandle", PHANDLE_2)); CHECK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode", 23)); diff --git a/tests/test_tree1_body.dtsi b/tests/test_tree1_body.dtsi index 1446191..24a5e1e 100644 --- a/tests/test_tree1_body.dtsi +++ b/tests/test_tree1_body.dtsi @@ -6,9 +6,12 @@ prop-int = <0xdeadbeef>; prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; subnode@1 { compatible = "subnode1"; + reg = <1>; prop-int = [deadbeef]; subsubnode { @@ -21,10 +24,14 @@ }; subnode@2 { + reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; ssn0: subsubnode@0 { + reg = <0>; phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; diff --git a/tests/test_tree1_merge.dts b/tests/test_tree1_merge.dts index ded08d8..b100c12 100644 --- a/tests/test_tree1_merge.dts +++ b/tests/test_tree1_merge.dts @@ -6,9 +6,12 @@ compatible = "test_tree1"; prop-int = "wrong!"; prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; subnode@1 { compatible = "subnode1"; + reg = <1>; subsubnode { compatible = "subsubnode1", "subsubnode"; @@ -20,8 +23,11 @@ }; subnode@2 { + reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; ss2 { }; @@ -36,6 +42,7 @@ }; subnode@2 { ssn0: subsubnode@0 { + reg = <0>; phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; diff --git a/tests/test_tree1_merge_labelled.dts b/tests/test_tree1_merge_labelled.dts index 29953b0..fcf5dc4 100644 --- a/tests/test_tree1_merge_labelled.dts +++ b/tests/test_tree1_merge_labelled.dts @@ -8,9 +8,12 @@ prop-int = <0xdeadbeef>; prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; subnode@1 { compatible = "subnode1"; + reg = <1>; prop-int = [deadbeef]; subsubnode { @@ -23,10 +26,14 @@ }; subnode@2 { + reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; ssn0: subsubnode@0 { + reg = <0>; phandle = <0x2001>; prop-int = <0xbad>; }; diff --git a/tests/test_tree1_merge_path.dts b/tests/test_tree1_merge_path.dts index 168d066..c2ad829 100644 --- a/tests/test_tree1_merge_path.dts +++ b/tests/test_tree1_merge_path.dts @@ -8,9 +8,12 @@ prop-int = <0xdeadbeef>; prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; subnode@1 { compatible = "subnode1"; + reg = <1>; prop-int = [deadbeef]; subsubnode { @@ -23,10 +26,14 @@ }; subnode@2 { + reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; ssn0: subsubnode@0 { + reg = <0>; phandle = <0x2001>; prop-int = <0xbad>; }; diff --git a/tests/test_tree1_wrong1.dts b/tests/test_tree1_wrong1.dts index d71820a..900d385 100644 --- a/tests/test_tree1_wrong1.dts +++ b/tests/test_tree1_wrong1.dts @@ -6,9 +6,12 @@ compatible = "test_tree1"; prop-int = <0xdeadbeef>; prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; subnode@1 { compatible = "subnode1"; + reg = <1>; prop-int = [deadbeef]; subsubnode { @@ -21,10 +24,14 @@ }; subnode@2 { + reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; subsubnode@0 { + reg = <0>; phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; diff --git a/tests/test_tree1_wrong2.dts b/tests/test_tree1_wrong2.dts index ac27023..099752b 100644 --- a/tests/test_tree1_wrong2.dts +++ b/tests/test_tree1_wrong2.dts @@ -6,9 +6,12 @@ / { compatible = "test_tree1"; prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; subnode@1 { compatible = "subnode1"; + reg = <1>; prop-int = [deadbeef]; subsubnode { @@ -21,10 +24,14 @@ }; subnode@2 { + reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; subsubnode@0 { + reg = <0>; phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; diff --git a/tests/test_tree1_wrong3.dts b/tests/test_tree1_wrong3.dts index 80be2fa..069353a 100644 --- a/tests/test_tree1_wrong3.dts +++ b/tests/test_tree1_wrong3.dts @@ -7,9 +7,12 @@ compatible = "test_tree1"; prop-int = <0xdeadbeef>; prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; subnode@1 { compatible = "subnode1"; + reg = <1>; subsubnode { compatible = "subsubnode1", "subsubnode"; @@ -21,10 +24,14 @@ }; subnode@2 { + reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; subsubnode@0 { + reg = <0>; phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; diff --git a/tests/test_tree1_wrong4.dts b/tests/test_tree1_wrong4.dts index 09bb13b..2c56416 100644 --- a/tests/test_tree1_wrong4.dts +++ b/tests/test_tree1_wrong4.dts @@ -7,9 +7,12 @@ compatible = "test_tree1"; prop-int = <0xdeadbeef>; prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; subnode@1 { compatible = "subnode1"; + reg = <1>; prop-int = [deadbeef]; subsubnode { @@ -22,10 +25,14 @@ }; subnode@2 { + reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; subsubnode@0 { + reg = <0>; phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; diff --git a/tests/test_tree1_wrong5.dts b/tests/test_tree1_wrong5.dts index ef4c4f7..6ddd72d 100644 --- a/tests/test_tree1_wrong5.dts +++ b/tests/test_tree1_wrong5.dts @@ -7,9 +7,12 @@ compatible = "test_tree1"; prop-int = <0xdeadbefe>; prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; subnode@1 { compatible = "subnode1"; + reg = <1>; prop-int = [deadbeef]; subsubnode { @@ -22,10 +25,14 @@ }; subnode@2 { + reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; subsubnode@0 { + reg = <0>; phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; diff --git a/tests/test_tree1_wrong6.dts b/tests/test_tree1_wrong6.dts index 98d6eda..36b4e1f 100644 --- a/tests/test_tree1_wrong6.dts +++ b/tests/test_tree1_wrong6.dts @@ -7,9 +7,12 @@ compatible = "test_tree1"; prop-int = <0xdeadbeef>; prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; subnode@1 { compatible = "subnode1"; + reg = <1>; prop-int = [deadbeef]; subsubnode { @@ -23,10 +26,14 @@ }; subnode@2 { + reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; subsubnode@0 { + reg = <0>; phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; diff --git a/tests/test_tree1_wrong7.dts b/tests/test_tree1_wrong7.dts index f57ace0..54150e6 100644 --- a/tests/test_tree1_wrong7.dts +++ b/tests/test_tree1_wrong7.dts @@ -7,9 +7,12 @@ compatible = "test_tree1"; prop-int = <0xdeadbeef>; prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; subnode@1 { compatible = "subnode1"; + reg = <1>; prop-int = [deadbeef]; subsubnode { @@ -22,10 +25,14 @@ }; subnode@2 { + reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; subsubnode@0 { + reg = <0>; phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; diff --git a/tests/test_tree1_wrong8.dts b/tests/test_tree1_wrong8.dts index 811ce6c..7a28a9f 100644 --- a/tests/test_tree1_wrong8.dts +++ b/tests/test_tree1_wrong8.dts @@ -7,9 +7,12 @@ compatible = "test_tree1"; prop-int = <0xdeadbeef>; prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; subnode@1 { compatible = "subnode1"; + reg = <1>; prop-int = [deadbeef]; subsubnode { @@ -24,8 +27,12 @@ subnode@2 { linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; subsubnode@0 { + reg = <0>; phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; diff --git a/tests/test_tree1_wrong9.dts b/tests/test_tree1_wrong9.dts index 6ff6fab..f6486fa 100644 --- a/tests/test_tree1_wrong9.dts +++ b/tests/test_tree1_wrong9.dts @@ -8,9 +8,12 @@ compatible = "test_tree1"; prop-int = <0xdeadbeef>; prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; subnode@1 { compatible = "subnode1"; + reg = <1>; prop-int = [deadbeef]; subsubnode { @@ -23,10 +26,14 @@ }; subnode@2 { + reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; subsubnode@0 { + reg = <0>; phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; diff --git a/tests/trees.S b/tests/trees.S index cae0187..2389cd3 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -92,9 +92,12 @@ test_tree1_struct: PROP_INT(test_tree1, prop_int, TEST_VALUE_1) PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1) PROP_STR(test_tree1, prop_str, TEST_STRING_1) + PROP_INT(test_tree1, address_cells, 1) + PROP_INT(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) BEGIN_NODE("subsubnode") @@ -108,10 +111,14 @@ test_tree1_struct: END_NODE 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) 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) @@ -133,6 +140,9 @@ test_tree1_strings: 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, address_cells, "#address-cells") + STRING(test_tree1, size_cells, "#size-cells") test_tree1_strings_end: test_tree1_end: From 883238dc508e721db694277c5273a4c3e9a7132f Mon Sep 17 00:00:00 2001 From: Serge Lamikhov-Center Date: Mon, 30 Sep 2013 11:04:26 +0300 Subject: [PATCH 0418/1198] util: Fix out of bounds memory access The change also fixes numeric values output produced by fdtdump. Signed-off-by: Serge Lamikhov-Center --- util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.c b/util.c index 3055c16..e87d6c1 100644 --- a/util.c +++ b/util.c @@ -376,7 +376,7 @@ void utilfdt_print_data(const char *data, int len) printf(" = <"); for (i = 0; i < len; i += 4) - printf("0x%08x%s", fdt32_to_cpu(cell[i]), + printf("0x%08x%s", fdt32_to_cpu(cell[i / 4]), i < (len - 4) ? " " : ""); printf(">"); } else { From 79eebb23dbf1f6eeff1789cd0d6f1c1fe620a487 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sat, 26 Oct 2013 00:17:37 +1100 Subject: [PATCH 0419/1198] libfdt: Add function to resize the buffer for a sequential write tree At present, when using sequential write mode, there's no straightforward means of resizing the buffer the fdt is being built into. This patch adds an fdt_resize() function for this purpose. Signed-off-by: David Gibson --- libfdt/fdt_sw.c | 32 ++++++++++++++++++ libfdt/libfdt.h | 1 + tests/run_tests.sh | 8 +++++ tests/sw_tree1.c | 81 +++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 114 insertions(+), 8 deletions(-) diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index f422754..6a80485 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -107,6 +107,38 @@ int fdt_create(void *buf, int bufsize) return 0; } +int fdt_resize(void *fdt, void *buf, int bufsize) +{ + size_t headsize, tailsize; + char *oldtail, *newtail; + + FDT_SW_CHECK_HEADER(fdt); + + headsize = fdt_off_dt_struct(fdt); + tailsize = fdt_size_dt_strings(fdt); + + if ((headsize + tailsize) > bufsize) + return -FDT_ERR_NOSPACE; + + oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; + newtail = (char *)buf + bufsize - tailsize; + + /* Two cases to avoid clobbering data if the old and new + * buffers partially overlap */ + if (buf <= fdt) { + memmove(buf, fdt, headsize); + memmove(newtail, oldtail, tailsize); + } else { + memmove(newtail, oldtail, tailsize); + memmove(buf, fdt, headsize); + } + + fdt_set_off_dt_strings(buf, bufsize); + fdt_set_totalsize(buf, bufsize); + + return 0; +} + int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) { struct fdt_reserve_entry *re; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 02baa84..c4d5a91 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1023,6 +1023,7 @@ int fdt_nop_node(void *fdt, int nodeoffset); /**********************************************************************/ int fdt_create(void *buf, int bufsize); +int fdt_resize(void *fdt, void *buf, int bufsize); int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); int fdt_finish_reservemap(void *fdt); int fdt_begin_node(void *fdt, const char *name); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c0a136b..a8905a7 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -190,6 +190,14 @@ libfdt_tests () { tree1_tests unfinished_tree1.test.dtb run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb + # Resizing tests + for mode in resize realloc; do + run_test sw_tree1 $mode + tree1_tests sw_tree1.test.dtb + tree1_tests unfinished_tree1.test.dtb + run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb + done + # fdt_move tests for tree in test_tree1.dtb sw_tree1.test.dtb unfinished_tree1.test.dtb; do rm -f moved.$tree shunted.$tree deshunted.$tree diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index e9ea7e7..de00707 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -31,22 +31,87 @@ #define SPACE 65536 -#define CHECK(code) \ - { \ - err = (code); \ - if (err) \ - FAIL(#code ": %s", fdt_strerror(err)); \ +static enum { + FIXED = 0, + RESIZE, + REALLOC, +} alloc_mode; + +static void realloc_fdt(void **fdt, size_t *size) +{ + switch (alloc_mode) { + case FIXED: + if (!(*fdt)) + fdt = xmalloc(*size); + else + FAIL("Ran out of space"); + return; + + case RESIZE: + if (!(*fdt)) { + fdt = xmalloc(SPACE); + } else if (*size < SPACE) { + *size += 1; + fdt_resize(*fdt, *fdt, *size); + } else { + FAIL("Ran out of space"); + } + return; + + case REALLOC: + *size += 1; + *fdt = xrealloc(*fdt, *size); + fdt_resize(*fdt, *fdt, *size); + return; + + default: + CONFIG("Bad allocation mode"); } +} + +#define CHECK(code) \ + do { \ + err = (code); \ + if (err == -FDT_ERR_NOSPACE) \ + realloc_fdt(&fdt, &size); \ + else if (err) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } while (err != 0) int main(int argc, char *argv[]) { - void *fdt; + void *fdt = NULL; + size_t size; int err; test_init(argc, argv); - fdt = xmalloc(SPACE); - CHECK(fdt_create(fdt, SPACE)); + if (argc == 1) { + alloc_mode = FIXED; + size = SPACE; + } else if (argc == 2) { + if (streq(argv[1], "resize")) { + alloc_mode = REALLOC; + size = 0; + } else if (streq(argv[1], "realloc")) { + alloc_mode = REALLOC; + size = 0; + } else { + char *endp; + + size = strtoul(argv[1], &endp, 0); + if (*endp == '\0') + alloc_mode = FIXED; + else + CONFIG("Bad allocation mode \"%s\" specified", + argv[1]); + } + } + + realloc_fdt(&fdt, &size); + + fdt = xmalloc(size); + CHECK(fdt_create(fdt, size)); CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1)); CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_2, TEST_SIZE_2)); From 17625371eeea2fa7257361163c52d336a1a98ebc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 28 Oct 2013 21:06:53 +1100 Subject: [PATCH 0420/1198] Use stdbool more widely We already use the C99 bool type from stdbool.h in a few places. However there are many other places we represent boolean values as plain ints. This patch changes that. Signed-off-by: David Gibson --- checks.c | 16 ++++++++-------- data.c | 10 +++++----- dtc-lexer.l | 8 ++++---- dtc-parser.y | 4 ++-- dtc.c | 6 +++--- dtc.h | 10 +++++----- flattree.c | 4 ++-- srcpos.c | 4 ++-- srcpos.h | 3 ++- treesource.c | 6 +++--- util.c | 2 +- util.h | 3 ++- 12 files changed, 39 insertions(+), 37 deletions(-) diff --git a/checks.c b/checks.c index ee96a25..11a4086 100644 --- a/checks.c +++ b/checks.c @@ -53,7 +53,7 @@ struct check { void *data; bool warn, error; enum checkstatus status; - int inprogress; + bool inprogress; int num_prereqs; struct check **prereq; }; @@ -141,9 +141,9 @@ static void check_nodes_props(struct check *c, struct node *dt, struct node *nod check_nodes_props(c, dt, child); } -static int run_check(struct check *c, struct node *dt) +static bool run_check(struct check *c, struct node *dt) { - int error = 0; + bool error = false; int i; assert(!c->inprogress); @@ -151,11 +151,11 @@ static int run_check(struct check *c, struct node *dt) if (c->status != UNCHECKED) goto out; - c->inprogress = 1; + c->inprogress = true; for (i = 0; i < c->num_prereqs; i++) { struct check *prq = c->prereq[i]; - error |= run_check(prq, dt); + error = error || run_check(prq, dt); if (prq->status != PASSED) { c->status = PREREQ; check_msg(c, "Failed prerequisite '%s'", @@ -177,9 +177,9 @@ static int run_check(struct check *c, struct node *dt) TRACE(c, "\tCompleted, status %d", c->status); out: - c->inprogress = 0; + c->inprogress = false; if ((c->status != PASSED) && (c->error)) - error = 1; + error = true; return error; } @@ -733,7 +733,7 @@ void parse_checks_option(bool warn, bool error, const char *optarg) die("Unrecognized check name \"%s\"\n", name); } -void process_checks(int force, struct boot_info *bi) +void process_checks(bool force, struct boot_info *bi) { struct node *dt = bi->dt; int i; diff --git a/data.c b/data.c index 4a40c5b..4c50b12 100644 --- a/data.c +++ b/data.c @@ -250,20 +250,20 @@ struct data data_add_marker(struct data d, enum markertype type, char *ref) return data_append_markers(d, m); } -int data_is_one_string(struct data d) +bool data_is_one_string(struct data d) { int i; int len = d.len; if (len == 0) - return 0; + return false; for (i = 0; i < len-1; i++) if (d.val[i] == '\0') - return 0; + return false; if (d.val[len-1] != '\0') - return 0; + return false; - return 1; + return true; } diff --git a/dtc-lexer.l b/dtc-lexer.l index 3b41bfc..369407a 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -61,7 +61,7 @@ static int dts_version = 1; BEGIN(V1); \ static void push_input_file(const char *filename); -static int pop_input_file(void); +static bool pop_input_file(void); %} %% @@ -238,13 +238,13 @@ static void push_input_file(const char *filename) } -static int pop_input_file(void) +static bool pop_input_file(void) { if (srcfile_pop() == 0) - return 0; + return false; yypop_buffer_state(); yyin = current_srcfile->f; - return 1; + return true; } diff --git a/dtc-parser.y b/dtc-parser.y index f412460..4864631 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -31,7 +31,7 @@ extern void print_error(char const *fmt, ...); extern void yyerror(char const *s); extern struct boot_info *the_boot_info; -extern int treesource_error; +extern bool treesource_error; static unsigned long long eval_literal(const char *s, int base, int bits); static unsigned char eval_char_literal(const char *s); @@ -478,7 +478,7 @@ void print_error(char const *fmt, ...) srcpos_verror(&yylloc, fmt, va); va_end(va); - treesource_error = 1; + treesource_error = true; } void yyerror(char const *s) { diff --git a/dtc.c b/dtc.c index e3c9653..d36ccdc 100644 --- a/dtc.c +++ b/dtc.c @@ -109,7 +109,7 @@ int main(int argc, char *argv[]) const char *outform = "dts"; const char *outname = "-"; const char *depname = NULL; - int force = 0, sort = 0; + bool force = false, sort = false; const char *arg; int opt; FILE *outf = NULL; @@ -148,7 +148,7 @@ int main(int argc, char *argv[]) padsize = strtol(optarg, NULL, 0); break; case 'f': - force = 1; + force = true; break; case 'q': quiet++; @@ -174,7 +174,7 @@ int main(int argc, char *argv[]) break; case 's': - sort = 1; + sort = true; break; case 'W': diff --git a/dtc.h b/dtc.h index 264a20c..20e4d56 100644 --- a/dtc.h +++ b/dtc.h @@ -118,7 +118,7 @@ struct data data_append_align(struct data d, int align); struct data data_add_marker(struct data d, enum markertype type, char *ref); -int data_is_one_string(struct data d); +bool data_is_one_string(struct data d); /* DT constraints */ @@ -127,13 +127,13 @@ int data_is_one_string(struct data d); /* Live trees */ struct label { - int deleted; + bool deleted; char *label; struct label *next; }; struct property { - int deleted; + bool deleted; char *name; struct data val; @@ -143,7 +143,7 @@ struct property { }; struct node { - int deleted; + bool deleted; char *name; struct property *proplist; struct node *children; @@ -248,7 +248,7 @@ void sort_tree(struct boot_info *bi); /* Checks */ void parse_checks_option(bool warn, bool error, const char *optarg); -void process_checks(int force, struct boot_info *bi); +void process_checks(bool force, struct boot_info *bi); /* Flattened trees */ diff --git a/flattree.c b/flattree.c index 665dad7..bd99fa2 100644 --- a/flattree.c +++ b/flattree.c @@ -261,7 +261,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit, { struct property *prop; struct node *child; - int seen_name_prop = 0; + bool seen_name_prop = false; if (tree->deleted) return; @@ -279,7 +279,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit, int nameoff; if (streq(prop->name, "name")) - seen_name_prop = 1; + seen_name_prop = true; nameoff = stringtable_insert(strbuf, prop->name); diff --git a/srcpos.c b/srcpos.c index c20bc53..294568b 100644 --- a/srcpos.c +++ b/srcpos.c @@ -159,7 +159,7 @@ void srcfile_push(const char *fname) current_srcfile = srcfile; } -int srcfile_pop(void) +bool srcfile_pop(void) { struct srcfile_state *srcfile = current_srcfile; @@ -177,7 +177,7 @@ int srcfile_pop(void) * fix this we could either allocate all the files from a * table, or use a pool allocator. */ - return current_srcfile ? 1 : 0; + return current_srcfile ? true : false; } void srcfile_add_search_path(const char *dirname) diff --git a/srcpos.h b/srcpos.h index 93a2712..57dfa0f 100644 --- a/srcpos.h +++ b/srcpos.h @@ -21,6 +21,7 @@ #define _SRCPOS_H_ #include +#include struct srcfile_state { FILE *f; @@ -55,7 +56,7 @@ extern struct srcfile_state *current_srcfile; /* = NULL */ FILE *srcfile_relative_open(const char *fname, char **fullnamep); void srcfile_push(const char *fname); -int srcfile_pop(void); +bool srcfile_pop(void); /** * Add a new directory to the search path for input files diff --git a/treesource.c b/treesource.c index 33eeba5..ffebb77 100644 --- a/treesource.c +++ b/treesource.c @@ -26,12 +26,12 @@ extern int yyparse(void); extern YYLTYPE yylloc; struct boot_info *the_boot_info; -int treesource_error; +bool treesource_error; struct boot_info *dt_from_source(const char *fname) { the_boot_info = NULL; - treesource_error = 0; + treesource_error = false; srcfile_push(fname); yyin = current_srcfile->f; @@ -54,7 +54,7 @@ static void write_prefix(FILE *f, int level) fputc('\t', f); } -static int isstring(char c) +static bool isstring(char c) { return (isprint(c) || (c == '\0') diff --git a/util.c b/util.c index e87d6c1..2347af9 100644 --- a/util.c +++ b/util.c @@ -70,7 +70,7 @@ char *join_path(const char *path, const char *name) return str; } -int util_is_printable_string(const void *data, int len) +bool util_is_printable_string(const void *data, int len) { const char *s = data; const char *ss, *se; diff --git a/util.h b/util.h index 8f40b44..ccfdf4b 100644 --- a/util.h +++ b/util.h @@ -2,6 +2,7 @@ #define _UTIL_H #include +#include #include /* @@ -68,7 +69,7 @@ extern char *join_path(const char *path, const char *name); * @param len The string length including terminator * @return 1 if a valid printable string, 0 if not */ -int util_is_printable_string(const void *data, int len); +bool util_is_printable_string(const void *data, int len); /* * Parse an escaped character starting at index i in string s. The resulting From 17119ab0a52df5fb30749d038d796d7e78702e3c Mon Sep 17 00:00:00 2001 From: Serge Lamikhov-Center Date: Wed, 25 Dec 2013 15:26:03 +1100 Subject: [PATCH 0421/1198] Pass 'unsigned char' type to isdigit()/isspace()/isprint() functions The isdigit(), isprint(), etc. functions take an int, whose value is required to be in the range of an _unsigned_ char, or EOF. This, horribly, means that systems which have a signed char by default need casts to pass a char variable safely to these functions. We can't do this more nicely by making the variables themselves 'unsigned char *' because then we'll get warnings passing them to the strchr() etc. functions. At least the cygwin version of these functions, are designed to generate warnings if this isn't done, as explained by this comment from ctype.h: These macros are intentionally written in a manner that will trigger a gcc -Wall warning if the user mistakenly passes a 'char' instead of an int containing an 'unsigned char'. Signed-off-by: Serge Lamikhov-Center Signed-off-by: David Gibson --- dtc-lexer.l | 4 ++-- treesource.c | 4 ++-- util.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 369407a..0cd7e67 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -75,11 +75,11 @@ static bool pop_input_file(void); char *line, *tmp, *fn; /* skip text before line # */ line = yytext; - while (!isdigit(*line)) + while (!isdigit((unsigned char)*line)) line++; /* skip digits in line # */ tmp = line; - while (!isspace(*tmp)) + while (!isspace((unsigned char)*tmp)) tmp++; /* "NULL"-terminate line # */ *tmp = '\0'; diff --git a/treesource.c b/treesource.c index ffebb77..bf7a626 100644 --- a/treesource.c +++ b/treesource.c @@ -56,7 +56,7 @@ static void write_prefix(FILE *f, int level) static bool isstring(char c) { - return (isprint(c) + return (isprint((unsigned char)c) || (c == '\0') || strchr("\a\b\t\n\v\f\r", c)); } @@ -119,7 +119,7 @@ static void write_propval_string(FILE *f, struct data val) fprintf(f, "\""); break; default: - if (isprint(c)) + if (isprint((unsigned char)c)) fprintf(f, "%c", c); else fprintf(f, "\\x%02hhx", c); diff --git a/util.c b/util.c index 2347af9..330b594 100644 --- a/util.c +++ b/util.c @@ -87,7 +87,7 @@ bool util_is_printable_string(const void *data, int len) while (s < se) { ss = s; - while (s < se && *s && isprint(*s)) + while (s < se && *s && isprint((unsigned char)*s)) s++; /* not zero, or not done yet */ From edb10bcf1cd5be7251fc87ed5fc622f620008ceb Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 30 Dec 2013 22:42:41 +1100 Subject: [PATCH 0422/1198] Add option to run_tests.sh to stop immediately on a failing test This is a debugging convenience option, which makes it much easier to find the failing tests and fix them one by one. Signed-off-by: David Gibson --- tests/run_tests.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index a8905a7..97e016b 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -7,6 +7,7 @@ if [ -z "$CC" ]; then fi export QUIET_TEST=1 +STOP_ON_FAIL=0 export VALGRIND= VGCODE=126 @@ -24,6 +25,9 @@ base_run_test() { tot_pass=$((tot_pass + 1)) else ret="$?" + if [ "$STOP_ON_FAIL" -eq 1 ]; then + exit 1 + fi if [ "$ret" -eq 1 ]; then tot_config=$((tot_config + 1)) elif [ "$ret" -eq 2 ]; then @@ -595,7 +599,7 @@ utilfdt_tests () { run_test utilfdt_test } -while getopts "vt:m" ARG ; do +while getopts "vt:me" ARG ; do case $ARG in "v") unset QUIET_TEST @@ -606,6 +610,9 @@ while getopts "vt:m" ARG ; do "m") VALGRIND="valgrind --tool=memcheck -q --error-exitcode=$VGCODE" ;; + "e") + STOP_ON_FAIL=1 + ;; esac done From a7ecdb4e751051a31ae8b40333d85c578ce8ea8d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 31 Dec 2013 22:34:05 +1100 Subject: [PATCH 0423/1198] Fix valgrind errors in sw_tree1 The sw_tree1 testcase has accumulated some valgrind errors, at least in the "realloc" mode. * It had both a realloc_fdt() and explicit xmalloc() for the initial allocation which was redundant and caused errors. * It doesn't make sense to call fdt_resize() until after we've created the initial stub tree * Alignment gaps inserted into the tree contain uninitialized data, which trips an error when we write it out. We could zero the buffer, but that would make it easier to miss real bugs, so we add suppressions for the valgrind warnings instead. Signed-off-by: David Gibson --- tests/sw_tree1.c | 13 ++++++++----- tests/sw_tree1.supp | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 tests/sw_tree1.supp diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index de00707..6d4c531 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -37,7 +37,7 @@ static enum { REALLOC, } alloc_mode; -static void realloc_fdt(void **fdt, size_t *size) +static void realloc_fdt(void **fdt, size_t *size, bool created) { switch (alloc_mode) { case FIXED: @@ -61,7 +61,8 @@ static void realloc_fdt(void **fdt, size_t *size) case REALLOC: *size += 1; *fdt = xrealloc(*fdt, *size); - fdt_resize(*fdt, *fdt, *size); + if (created) + fdt_resize(*fdt, *fdt, *size); return; default: @@ -73,7 +74,7 @@ static void realloc_fdt(void **fdt, size_t *size) do { \ err = (code); \ if (err == -FDT_ERR_NOSPACE) \ - realloc_fdt(&fdt, &size); \ + realloc_fdt(&fdt, &size, created); \ else if (err) \ FAIL(#code ": %s", fdt_strerror(err)); \ } while (err != 0) @@ -83,6 +84,7 @@ int main(int argc, char *argv[]) void *fdt = NULL; size_t size; int err; + bool created = false; test_init(argc, argv); @@ -108,12 +110,13 @@ int main(int argc, char *argv[]) } } - realloc_fdt(&fdt, &size); - fdt = xmalloc(size); CHECK(fdt_create(fdt, size)); + created = true; + CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1)); + CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_2, TEST_SIZE_2)); CHECK(fdt_finish_reservemap(fdt)); diff --git a/tests/sw_tree1.supp b/tests/sw_tree1.supp new file mode 100644 index 0000000..279f9e5 --- /dev/null +++ b/tests/sw_tree1.supp @@ -0,0 +1,18 @@ +{ + allocation methods causes uninitialized data in alignment gap + Memcheck:Param + write(buf) + fun:__write_nocancel + fun:utilfdt_write_err + fun:save_blob + fun:main +} +{ + allocation methods causes uninitialized data in alignment gap + Memcheck:Param + write(buf) + fun:__write_nocancel + fun:utilfdt_write_err + fun:save_blob + fun:main +} From 6efd9065e69ee39c45dc4113b3d212bc2757128a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 1 Jan 2014 23:19:35 +1100 Subject: [PATCH 0424/1198] Remove unused srcpos_warn() function This function has no users, and we can replace it more generally later. Signed-off-by: David Gibson --- srcpos.c | 17 ----------------- srcpos.h | 2 -- 2 files changed, 19 deletions(-) diff --git a/srcpos.c b/srcpos.c index 294568b..06ef06d 100644 --- a/srcpos.c +++ b/srcpos.c @@ -312,23 +312,6 @@ srcpos_error(struct srcpos *pos, char const *fmt, ...) va_end(va); } - -void -srcpos_warn(struct srcpos *pos, char const *fmt, ...) -{ - const char *srcstr; - va_list va; - va_start(va, fmt); - - srcstr = srcpos_string(pos); - - fprintf(stderr, "Warning: %s ", srcstr); - vfprintf(stderr, fmt, va); - fprintf(stderr, "\n"); - - va_end(va); -} - void srcpos_set_line(char *f, int l) { current_srcfile->name = f; diff --git a/srcpos.h b/srcpos.h index 57dfa0f..7f0eaea 100644 --- a/srcpos.h +++ b/srcpos.h @@ -111,8 +111,6 @@ extern void srcpos_verror(struct srcpos *pos, char const *, va_list va) __attribute__((format(printf, 2, 0))); extern void srcpos_error(struct srcpos *pos, char const *, ...) __attribute__((format(printf, 2, 3))); -extern void srcpos_warn(struct srcpos *pos, char const *, ...) - __attribute__((format(printf, 2, 3))); extern void srcpos_set_line(char *f, int l); From a1e6da8aed6b945802f851c8df229a264b6b3524 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 1 Jan 2014 23:16:39 +1100 Subject: [PATCH 0425/1198] Fix typo in type of srcpos_verror() et al. The srcpos_verror() and srcpos_error() functions declare the format string as 'char const *' instead of 'const char *'. Fix it. Signed-off-by: David Gibson --- srcpos.c | 4 ++-- srcpos.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/srcpos.c b/srcpos.c index 06ef06d..71a73b8 100644 --- a/srcpos.c +++ b/srcpos.c @@ -291,7 +291,7 @@ srcpos_string(struct srcpos *pos) } void -srcpos_verror(struct srcpos *pos, char const *fmt, va_list va) +srcpos_verror(struct srcpos *pos, const char *fmt, va_list va) { const char *srcstr; @@ -303,7 +303,7 @@ srcpos_verror(struct srcpos *pos, char const *fmt, va_list va) } void -srcpos_error(struct srcpos *pos, char const *fmt, ...) +srcpos_error(struct srcpos *pos, const char *fmt, ...) { va_list va; diff --git a/srcpos.h b/srcpos.h index 7f0eaea..46ea08a 100644 --- a/srcpos.h +++ b/srcpos.h @@ -107,9 +107,9 @@ extern struct srcpos *srcpos_copy(struct srcpos *pos); extern char *srcpos_string(struct srcpos *pos); extern void srcpos_dump(struct srcpos *pos); -extern void srcpos_verror(struct srcpos *pos, char const *, va_list va) +extern void srcpos_verror(struct srcpos *pos, const char *, va_list va) __attribute__((format(printf, 2, 0))); -extern void srcpos_error(struct srcpos *pos, char const *, ...) +extern void srcpos_error(struct srcpos *pos, const char *, ...) __attribute__((format(printf, 2, 3))); extern void srcpos_set_line(char *f, int l); From e19d3b1d6da33b78dec83a9064a1e9a570657dd6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 1 Jan 2014 23:17:39 +1100 Subject: [PATCH 0426/1198] Fix indentation of srcpos_verror() Somehow this function ended up with a 7 space indent, instead of the usual 8 space (1 tab) indent. Signed-off-by: David Gibson --- srcpos.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/srcpos.c b/srcpos.c index 71a73b8..48059aa 100644 --- a/srcpos.c +++ b/srcpos.c @@ -293,13 +293,13 @@ srcpos_string(struct srcpos *pos) void srcpos_verror(struct srcpos *pos, const char *fmt, va_list va) { - const char *srcstr; + const char *srcstr; - srcstr = srcpos_string(pos); + srcstr = srcpos_string(pos); - fprintf(stderr, "Error: %s ", srcstr); - vfprintf(stderr, fmt, va); - fprintf(stderr, "\n"); + fprintf(stderr, "Error: %s ", srcstr); + vfprintf(stderr, fmt, va); + fprintf(stderr, "\n"); } void From 0c0bf8519aab878acb864d84185bd2395b1e3d5b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 1 Jan 2014 23:23:54 +1100 Subject: [PATCH 0427/1198] Fix memory leak in srcpos_verror() Since dtc runs are short, we don't care that much about memory leaks. Still, leaking the source position string every time we print an error messages is pretty nasty. Fix it. Signed-off-by: David Gibson --- srcpos.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/srcpos.c b/srcpos.c index 48059aa..6705fed 100644 --- a/srcpos.c +++ b/srcpos.c @@ -293,13 +293,15 @@ srcpos_string(struct srcpos *pos) void srcpos_verror(struct srcpos *pos, const char *fmt, va_list va) { - const char *srcstr; + char *srcstr; srcstr = srcpos_string(pos); fprintf(stderr, "Error: %s ", srcstr); vfprintf(stderr, fmt, va); fprintf(stderr, "\n"); + + free(srcstr); } void From 0e2d3992258ff4129a8c0f79b660e92994411684 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 1 Jan 2014 23:27:31 +1100 Subject: [PATCH 0428/1198] Make srcpos_{v,}error() more widely useful Allow them to take a prefix argument giving the general type of error, which will be useful in future. Signed-off-by: David Gibson --- dtc-parser.y | 2 +- srcpos.c | 12 ++++++------ srcpos.h | 10 ++++++---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 4864631..2bcef1b 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -475,7 +475,7 @@ void print_error(char const *fmt, ...) va_list va; va_start(va, fmt); - srcpos_verror(&yylloc, fmt, va); + srcpos_verror(&yylloc, "Error", fmt, va); va_end(va); treesource_error = true; diff --git a/srcpos.c b/srcpos.c index 6705fed..3999675 100644 --- a/srcpos.c +++ b/srcpos.c @@ -290,27 +290,27 @@ srcpos_string(struct srcpos *pos) return pos_str; } -void -srcpos_verror(struct srcpos *pos, const char *fmt, va_list va) +void srcpos_verror(struct srcpos *pos, const char *prefix, + const char *fmt, va_list va) { char *srcstr; srcstr = srcpos_string(pos); - fprintf(stderr, "Error: %s ", srcstr); + fprintf(stderr, "%s: %s ", prefix, srcstr); vfprintf(stderr, fmt, va); fprintf(stderr, "\n"); free(srcstr); } -void -srcpos_error(struct srcpos *pos, const char *fmt, ...) +void srcpos_error(struct srcpos *pos, const char *prefix, + const char *fmt, ...) { va_list va; va_start(va, fmt); - srcpos_verror(pos, fmt, va); + srcpos_verror(pos, prefix, fmt, va); va_end(va); } diff --git a/srcpos.h b/srcpos.h index 46ea08a..f81827b 100644 --- a/srcpos.h +++ b/srcpos.h @@ -107,10 +107,12 @@ extern struct srcpos *srcpos_copy(struct srcpos *pos); extern char *srcpos_string(struct srcpos *pos); extern void srcpos_dump(struct srcpos *pos); -extern void srcpos_verror(struct srcpos *pos, const char *, va_list va) - __attribute__((format(printf, 2, 0))); -extern void srcpos_error(struct srcpos *pos, const char *, ...) - __attribute__((format(printf, 2, 3))); +extern void srcpos_verror(struct srcpos *pos, const char *prefix, + const char *fmt, va_list va) + __attribute__((format(printf, 3, 0))); +extern void srcpos_error(struct srcpos *pos, const char *prefix, + const char *fmt, ...) + __attribute__((format(printf, 3, 4))); extern void srcpos_set_line(char *f, int l); From b82b9776140a077db723f13832afd7e279a45184 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Jan 2014 20:00:01 +1100 Subject: [PATCH 0429/1198] Move integer literal processing back to the lexer At the moment integer literals are passed from the lexer to the parser as a string, where it's evaluated into an integer by eval_literal(). That strange approach happened because we needed to know whether we were processing dts-v0 or dts-v1 - only known at the parser level - to know how to interpret the literal properly. dts-v0 support has been gone for some time now, and the base and bits parameters to eval_literal() are essentially useless. So, clean things up by moving the literal interpretation back to the lexer. This also introduces a new lexical_error() function to report malformed literals and set the treesource_error flag so that they'll cause a parse failure at the top level. Signed-off-by: David Gibson --- dtc-lexer.l | 30 ++++++++++++++++++++++++++++-- dtc-parser.y | 42 ++++++++++-------------------------------- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 0cd7e67..ba5d150 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -40,6 +40,7 @@ LINECOMMENT "//".*\n #include "dtc-parser.tab.h" YYLTYPE yylloc; +extern bool treesource_error; /* CAUTION: this will stop working if we ever use yyless() or yyunput() */ #define YY_USER_ACTION \ @@ -62,6 +63,7 @@ static int dts_version = 1; static void push_input_file(const char *filename); static bool pop_input_file(void); +static void lexical_error(const char *fmt, ...); %} %% @@ -146,8 +148,21 @@ static bool pop_input_file(void); } ([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? { - yylval.literal = xstrdup(yytext); - DPRINT("Literal: '%s'\n", yylval.literal); + char *e; + DPRINT("Integer Literal: '%s'\n", yytext); + + errno = 0; + yylval.integer = strtoull(yytext, &e, 0); + + assert(!(*e) || !e[strspn(e, "UL")]); + + if (errno == ERANGE) + lexical_error("Integer literal '%s' out of range", + yytext); + else + /* ERANGE is the only strtoull error triggerable + * by strings matching the pattern */ + assert(errno == 0); return DT_LITERAL; } @@ -248,3 +263,14 @@ static bool pop_input_file(void) return true; } + +static void lexical_error(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + srcpos_verror(&yylloc, "Lexical error", fmt, ap); + va_end(ap); + + treesource_error = true; +} diff --git a/dtc-parser.y b/dtc-parser.y index 2bcef1b..0ce0815 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -33,7 +33,6 @@ extern void yyerror(char const *s); extern struct boot_info *the_boot_info; extern bool treesource_error; -static unsigned long long eval_literal(const char *s, int base, int bits); static unsigned char eval_char_literal(const char *s); %} @@ -65,7 +64,7 @@ static unsigned char eval_char_literal(const char *s); %token DT_DEL_PROP %token DT_DEL_NODE %token DT_PROPNODENAME -%token DT_LITERAL +%token DT_LITERAL %token DT_CHAR_LITERAL %token DT_BASE %token DT_BYTE @@ -274,18 +273,20 @@ propdataprefix: arrayprefix: DT_BITS DT_LITERAL '<' { - $$.data = empty_data; - $$.bits = eval_literal($2, 0, 7); + unsigned long long bits; - if (($$.bits != 8) && - ($$.bits != 16) && - ($$.bits != 32) && - ($$.bits != 64)) + bits = $2; + + if ((bits != 8) && (bits != 16) && + (bits != 32) && (bits != 64)) { print_error("Only 8, 16, 32 and 64-bit elements" " are currently supported"); - $$.bits = 32; + bits = 32; } + + $$.data = empty_data; + $$.bits = bits; } | '<' { @@ -334,9 +335,6 @@ arrayprefix: integer_prim: DT_LITERAL - { - $$ = eval_literal($1, 0, 64); - } | DT_CHAR_LITERAL { $$ = eval_char_literal($1); @@ -485,26 +483,6 @@ void yyerror(char const *s) { print_error("%s", s); } -static unsigned long long eval_literal(const char *s, int base, int bits) -{ - unsigned long long val; - char *e; - - errno = 0; - val = strtoull(s, &e, base); - if (*e) { - size_t uls = strspn(e, "UL"); - if (e[uls]) - print_error("bad characters in literal"); - } - if ((errno == ERANGE) - || ((bits < 64) && (val >= (1ULL << bits)))) - print_error("literal out of range"); - else if (errno != 0) - print_error("bad literal"); - return val; -} - static unsigned char eval_char_literal(const char *s) { int i = 1; From cfc6523619c62d3eee505f53e7a18b253742961a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sat, 4 Jan 2014 10:03:55 +1100 Subject: [PATCH 0430/1198] Move character literal processing to the lexer To match the processing of integer literals, character literals are passed as a string from lexer to parser then interpreted there. This is just as awkward as it was for integer literals, without the excuse that we used to need the information about the dts version to process them correctly. So, move character literal processing back to the lexer as well, cleaning things up. Signed-off-by: David Gibson --- dtc-lexer.l | 20 +++++++++++++++++--- dtc-parser.y | 34 +--------------------------------- 2 files changed, 18 insertions(+), 36 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index ba5d150..0821bde 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -167,9 +167,23 @@ static void lexical_error(const char *fmt, ...); } <*>{CHAR_LITERAL} { - yytext[yyleng-1] = '\0'; - yylval.literal = xstrdup(yytext+1); - DPRINT("Character literal: %s\n", yylval.literal); + struct data d; + DPRINT("Character literal: %s\n", yytext); + + d = data_copy_escape_string(yytext+1, yyleng-2); + if (d.len == 1) { + lexical_error("Empty character literal"); + yylval.integer = 0; + return DT_CHAR_LITERAL; + } + + yylval.integer = (unsigned char)d.val[0]; + + if (d.len > 2) + lexical_error("Character literal has %d" + " characters instead of 1", + d.len - 1); + return DT_CHAR_LITERAL; } diff --git a/dtc-parser.y b/dtc-parser.y index 0ce0815..efe81dd 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -32,13 +32,10 @@ extern void yyerror(char const *s); extern struct boot_info *the_boot_info; extern bool treesource_error; - -static unsigned char eval_char_literal(const char *s); %} %union { char *propnodename; - char *literal; char *labelref; unsigned int cbase; uint8_t byte; @@ -65,7 +62,7 @@ static unsigned char eval_char_literal(const char *s); %token DT_DEL_NODE %token DT_PROPNODENAME %token DT_LITERAL -%token DT_CHAR_LITERAL +%token DT_CHAR_LITERAL %token DT_BASE %token DT_BYTE %token DT_STRING @@ -336,9 +333,6 @@ arrayprefix: integer_prim: DT_LITERAL | DT_CHAR_LITERAL - { - $$ = eval_char_literal($1); - } | '(' integer_expr ')' { $$ = $2; @@ -482,29 +476,3 @@ void print_error(char const *fmt, ...) void yyerror(char const *s) { print_error("%s", s); } - -static unsigned char eval_char_literal(const char *s) -{ - int i = 1; - char c = s[0]; - - if (c == '\0') - { - print_error("empty character literal"); - return 0; - } - - /* - * If the first character in the character literal is a \ then process - * the remaining characters as an escape encoding. If the first - * character is neither an escape or a terminator it should be the only - * character in the literal and will be returned. - */ - if (c == '\\') - c = get_escape_char(s, &i); - - if (s[i] != '\0') - print_error("malformed character literal"); - - return c; -} From 6a15eb2350426d285130e4c9d84c0bdb6575547a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sat, 4 Jan 2014 10:04:19 +1100 Subject: [PATCH 0431/1198] Die on failed /incbin/ seeks Failing to open an input file, with /include/ or /incbin/ is treated as immediately fatal inside srcfile_relative_open(). However, filing to seek() to the requested offset in an /incbin/ is not. This is a bit oddly inconsistent, and leaves us with a strange case that's awkward to deal with down the line. So, get rid of it and have failed seeks on an /incbin/ be immediately fatal. Signed-off-by: David Gibson --- dtc-parser.y | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index efe81dd..bed857e 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -226,10 +226,9 @@ propdata: if ($6 != 0) if (fseek(f, $6, SEEK_SET) != 0) - print_error("Couldn't seek to offset %llu in \"%s\": %s", - (unsigned long long)$6, - $4.val, - strerror(errno)); + die("Couldn't seek to offset %llu in \"%s\": %s", + (unsigned long long)$6, $4.val, + strerror(errno)); d = data_copy_file(f, $8); From c854434dc2e955d2053bccb6c763dcfb75d0842b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Jan 2014 23:23:23 +1100 Subject: [PATCH 0432/1198] Correct locations in parser error messaes The print_error() function used in several places in the parser uses the location information in yylloc to describe the location of the error. This is not correct in most cases. yylloc gives the location of the lookahead token, whereas the error is generally associated with one of the already parsed non-terminals. This patch corrects this, adding a location parameter to print_error() and supplying it with the appropriate bison @N symbols. This probably breaks yacc compatiblity, but too bad - accurate error messages are more important. Signed-off-by: David Gibson --- dtc-parser.y | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index bed857e..7ee436f 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -17,17 +17,14 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ - %{ #include #include "dtc.h" #include "srcpos.h" -YYLTYPE yylloc; - extern int yylex(void); -extern void print_error(char const *fmt, ...); +extern void print_error(YYLTYPE *loc, char const *fmt, ...); extern void yyerror(char const *s); extern struct boot_info *the_boot_info; @@ -148,7 +145,7 @@ devicetree: if (target) merge_nodes(target, $3); else - print_error("label or path, '%s', not found", $2); + print_error(&@2, "label or path, '%s', not found", $2); $$ = $1; } | devicetree DT_DEL_NODE DT_REF ';' @@ -156,7 +153,7 @@ devicetree: struct node *target = get_node_by_ref($1, $3); if (!target) - print_error("label or path, '%s', not found", $3); + print_error(&@3, "label or path, '%s', not found", $3); else delete_node(target); @@ -276,7 +273,7 @@ arrayprefix: if ((bits != 8) && (bits != 16) && (bits != 32) && (bits != 64)) { - print_error("Only 8, 16, 32 and 64-bit elements" + print_error(&@2, "Only 8, 16, 32 and 64-bit elements" " are currently supported"); bits = 32; } @@ -302,7 +299,7 @@ arrayprefix: * mask), all bits are one. */ if (($2 > mask) && (($2 | mask) != -1ULL)) - print_error( + print_error(&@2, "integer value out of range " "%016lx (%d bits)", $1.bits); } @@ -318,7 +315,7 @@ arrayprefix: REF_PHANDLE, $2); else - print_error("References are only allowed in " + print_error(&@2, "References are only allowed in " "arrays with 32-bit elements."); $$.data = data_append_integer($1.data, val, $1.bits); @@ -438,7 +435,7 @@ subnodes: } | subnode propdef { - print_error("syntax error: properties must precede subnodes"); + print_error(&@2, "syntax error: properties must precede subnodes"); YYERROR; } ; @@ -461,17 +458,18 @@ subnode: %% -void print_error(char const *fmt, ...) +void print_error(YYLTYPE *loc, char const *fmt, ...) { va_list va; va_start(va, fmt); - srcpos_verror(&yylloc, "Error", fmt, va); + srcpos_verror(loc, "Error", fmt, va); va_end(va); treesource_error = true; } -void yyerror(char const *s) { - print_error("%s", s); +void yyerror(char const *s) +{ + print_error(&yylloc, "%s", s); } From fa3f3f0ebd154b0ef22cb83cd8efc50b7bbe181d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 3 Jan 2014 23:57:39 +1100 Subject: [PATCH 0433/1198] Clean up parser error messages Generally edit parser error messages for brevity and clarity. Replace the print_error() function with a a new macro for brevity and clarity in the source. Signed-off-by: David Gibson --- dtc-parser.y | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 7ee436f..42c4d75 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -24,8 +24,12 @@ #include "srcpos.h" extern int yylex(void); -extern void print_error(YYLTYPE *loc, char const *fmt, ...); extern void yyerror(char const *s); +#define ERROR(loc, ...) \ + do { \ + srcpos_error((loc), "Error", __VA_ARGS__); \ + treesource_error = true; \ + } while (0) extern struct boot_info *the_boot_info; extern bool treesource_error; @@ -145,17 +149,18 @@ devicetree: if (target) merge_nodes(target, $3); else - print_error(&@2, "label or path, '%s', not found", $2); + ERROR(&@2, "Label or path %s not found", $2); $$ = $1; } | devicetree DT_DEL_NODE DT_REF ';' { struct node *target = get_node_by_ref($1, $3); - if (!target) - print_error(&@3, "label or path, '%s', not found", $3); - else + if (target) delete_node(target); + else + ERROR(&@3, "Label or path %s not found", $3); + $$ = $1; } @@ -271,10 +276,9 @@ arrayprefix: bits = $2; if ((bits != 8) && (bits != 16) && - (bits != 32) && (bits != 64)) - { - print_error(&@2, "Only 8, 16, 32 and 64-bit elements" - " are currently supported"); + (bits != 32) && (bits != 64)) { + ERROR(&@2, "Array elements must be" + " 8, 16, 32 or 64-bits"); bits = 32; } @@ -299,9 +303,8 @@ arrayprefix: * mask), all bits are one. */ if (($2 > mask) && (($2 | mask) != -1ULL)) - print_error(&@2, - "integer value out of range " - "%016lx (%d bits)", $1.bits); + ERROR(&@2, "Value out of range for" + " %d-bit array element", $1.bits); } $$.data = data_append_integer($1.data, $2, $1.bits); @@ -315,7 +318,7 @@ arrayprefix: REF_PHANDLE, $2); else - print_error(&@2, "References are only allowed in " + ERROR(&@2, "References are only allowed in " "arrays with 32-bit elements."); $$.data = data_append_integer($1.data, val, $1.bits); @@ -435,7 +438,7 @@ subnodes: } | subnode propdef { - print_error(&@2, "syntax error: properties must precede subnodes"); + ERROR(&@2, "Properties must precede subnodes"); YYERROR; } ; @@ -458,18 +461,7 @@ subnode: %% -void print_error(YYLTYPE *loc, char const *fmt, ...) -{ - va_list va; - - va_start(va, fmt); - srcpos_verror(loc, "Error", fmt, va); - va_end(va); - - treesource_error = true; -} - void yyerror(char const *s) { - print_error(&yylloc, "%s", s); + ERROR(&yylloc, "%s", s); } From 6d889343710e0ecb14f87758608708e08df7c8c1 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 24 Jan 2014 17:19:10 -0800 Subject: [PATCH 0434/1198] dtc: avoid shadowing dirname() dirname() is declared as a function, and later on try_open() another variable dirname is used, which shadows the dirname() function declaration and will produce the following warnings/errors with -Wshadow turned on: srcpos.c: In function 'try_open': srcpos.c:71:35: error: declaration of 'dirname' shadows a global declaration [-Werror=shadow] srcpos.c:37:14: error: shadowed declaration is here [-Werror=shadow] srcpos.c: In function 'srcfile_add_search_path': srcpos.c:183:42: error: declaration of 'dirname' shadows a global declaration [-Werror=shadow] srcpos.c:37:14: error: shadowed declaration is here [-Werror=shadow] cc1: all warnings being treated as errors Fix this by renaming the function dirname() to get_dirname(). Signed-off-by: Florian Fainelli --- srcpos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcpos.c b/srcpos.c index 3999675..4549773 100644 --- a/srcpos.c +++ b/srcpos.c @@ -34,7 +34,7 @@ struct search_path { static struct search_path *search_path_head, **search_path_tail; -static char *dirname(const char *path) +static char *get_dirname(const char *path) { const char *slash = strrchr(path, '/'); @@ -150,7 +150,7 @@ void srcfile_push(const char *fname) srcfile = xmalloc(sizeof(*srcfile)); srcfile->f = srcfile_relative_open(fname, &srcfile->name); - srcfile->dir = dirname(srcfile->name); + srcfile->dir = get_dirname(srcfile->name); srcfile->prev = current_srcfile; srcfile->lineno = 1; From 89c9af54816728f56b8da1f2742b4d4db29cf538 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 24 Jan 2014 17:19:11 -0800 Subject: [PATCH 0435/1198] libfdt: avoid shadowing "err" in FDT_CHECK_HEADER FDT_CHECK_HEADER declares an internal variable named "err" whose name is far too generic and will produce the following -Wshadow warnings: libfdt/fdt_ro.c: In function 'fdt_node_offset_by_compatible': libfdt/fdt_ro.c:555:2: error: declaration of 'err' shadows a previous local [-Werror=shadow] libfdt/fdt_ro.c:553:14: error: shadowed declaration is here [-Werror=shadow] cc1: all warnings being treated as errors Since this variable is only used internally in the macro, rename to __err which should be prefixed enough not to cause new shadow warnings. Signed-off-by: Florian Fainelli --- libfdt/libfdt_internal.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 381133b..02cfa6f 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -57,9 +57,9 @@ #define FDT_CHECK_HEADER(fdt) \ { \ - int err; \ - if ((err = fdt_check_header(fdt)) != 0) \ - return err; \ + int __err; \ + if ((__err = fdt_check_header(fdt)) != 0) \ + return __err; \ } int _fdt_check_node_offset(const void *fdt, int offset); From 3a584d4760cfc81d21039346b0ce1cb5233e1d72 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 24 Jan 2014 17:19:12 -0800 Subject: [PATCH 0436/1198] libfdt: avoid shadowing "err" in FDT_RW_CHECK_HEADER FDT_RW_CHECK_HEADER declares an internal variable named "err" which is far too generic and will produce the following -Wshadow warnings: libfdt/fdt_rw.c: In function 'fdt_add_mem_rsv': libfdt/fdt_rw.c:177:2: error: declaration of 'err' shadows a previous local [-Werror=shadow] libfdt/fdt_rw.c:175:6: error: shadowed declaration is here [-Werror=shadow] libfdt/fdt_rw.c: In function 'fdt_del_mem_rsv': libfdt/fdt_rw.c:194:2: error: declaration of 'err' shadows a previous local [-Werror=shadow] libfdt/fdt_rw.c:192:6: error: shadowed declaration is here [-Werror=shadow] libfdt/fdt_rw.c: In function 'fdt_set_name': ... Since this variable is only used internally in the macro, rename to __err which should be prefixed enough not to cause new shadow warnings. Signed-off-by: Florian Fainelli --- libfdt/fdt_rw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index fdba618..70adec6 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -84,9 +84,9 @@ static int _fdt_rw_check_header(void *fdt) #define FDT_RW_CHECK_HEADER(fdt) \ { \ - int err; \ - if ((err = _fdt_rw_check_header(fdt)) != 0) \ - return err; \ + int __err; \ + if ((__err = _fdt_rw_check_header(fdt)) != 0) \ + return __err; \ } static inline int _fdt_data_size(void *fdt) From c231d94e0f620bc25c76415e09f7dea939064bd8 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 24 Jan 2014 17:19:13 -0800 Subject: [PATCH 0437/1198] Makefile: enable -Wshadow by default Now that all -Wshadow build warnings/errors are fixed, turn on -Wshadow by default to make sure we would catch new potential shadow warnings. Signed-off-by: Florian Fainelli --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 70abf05..afc0ce0 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ CONFIG_LOCALVERSION = CPPFLAGS = -I libfdt -I . WARNINGS = -Werror -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \ - -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls + -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow CFLAGS = -g -Os -fPIC -Werror $(WARNINGS) BISON = bison From 24cb3d0681d9196d57176a0a94bfc6e610ef7b45 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 1 Feb 2014 16:41:59 +1100 Subject: [PATCH 0438/1198] dtc: fix some more -Wshadow warnings Building on a RHEL6 system produced the following -Wshadow warnings in fstree.c, util.c and checks.c: cc1: warnings being treated as errors checks.c: In function 'parse_checks_option': checks.c:709: error: declaration of 'optarg' shadows a global declaration /usr/include/getopt.h:59: error: shadowed declaration is here make[1]: *** [checks.o] Error 1 make[1]: *** Waiting for unfinished jobs.... make[1]: *** Waiting for unfinished jobs.... cc1: warnings being treated as errors fstree.c: In function 'read_fstree': fstree.c:40: error: declaration of 'tmpnam' shadows a global declaration /usr/include/stdio.h:208: error: shadowed declaration is here make[1]: *** [fstree.o] Error 1 cc1: warnings being treated as errors util.c: In function 'xstrdup': util.c:42: error: declaration of 'dup' shadows a global declaration /usr/include/unistd.h:528: error: shadowed declaration is here Fix all of these -Wshadow warnings by using slightly different variable names which won't collide with anything else. Signed-off-by: Florian Fainelli --- checks.c | 10 +++++----- dtc.h | 2 +- fstree.c | 16 ++++++++-------- util.c | 6 +++--- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/checks.c b/checks.c index 11a4086..47eda65 100644 --- a/checks.c +++ b/checks.c @@ -706,15 +706,15 @@ static void disable_warning_error(struct check *c, bool warn, bool error) c->error = c->error && !error; } -void parse_checks_option(bool warn, bool error, const char *optarg) +void parse_checks_option(bool warn, bool error, const char *arg) { int i; - const char *name = optarg; + const char *name = arg; bool enable = true; - if ((strncmp(optarg, "no-", 3) == 0) - || (strncmp(optarg, "no_", 3) == 0)) { - name = optarg + 3; + if ((strncmp(arg, "no-", 3) == 0) + || (strncmp(arg, "no_", 3) == 0)) { + name = arg + 3; enable = false; } diff --git a/dtc.h b/dtc.h index 20e4d56..20de073 100644 --- a/dtc.h +++ b/dtc.h @@ -247,7 +247,7 @@ void sort_tree(struct boot_info *bi); /* Checks */ -void parse_checks_option(bool warn, bool error, const char *optarg); +void parse_checks_option(bool warn, bool error, const char *arg); void process_checks(bool force, struct boot_info *bi); /* Flattened trees */ diff --git a/fstree.c b/fstree.c index f377453..4d2791c 100644 --- a/fstree.c +++ b/fstree.c @@ -37,26 +37,26 @@ static struct node *read_fstree(const char *dirname) tree = build_node(NULL, NULL); while ((de = readdir(d)) != NULL) { - char *tmpnam; + char *tmpname; if (streq(de->d_name, ".") || streq(de->d_name, "..")) continue; - tmpnam = join_path(dirname, de->d_name); + tmpname = join_path(dirname, de->d_name); - if (lstat(tmpnam, &st) < 0) - die("stat(%s): %s\n", tmpnam, strerror(errno)); + if (lstat(tmpname, &st) < 0) + die("stat(%s): %s\n", tmpname, strerror(errno)); if (S_ISREG(st.st_mode)) { struct property *prop; FILE *pfile; - pfile = fopen(tmpnam, "r"); + pfile = fopen(tmpname, "r"); if (! pfile) { fprintf(stderr, "WARNING: Cannot open %s: %s\n", - tmpnam, strerror(errno)); + tmpname, strerror(errno)); } else { prop = build_property(xstrdup(de->d_name), data_copy_file(pfile, @@ -67,12 +67,12 @@ static struct node *read_fstree(const char *dirname) } else if (S_ISDIR(st.st_mode)) { struct node *newchild; - newchild = read_fstree(tmpnam); + newchild = read_fstree(tmpname); newchild = name_node(newchild, xstrdup(de->d_name)); add_child(tree, newchild); } - free(tmpnam); + free(tmpname); } closedir(d); diff --git a/util.c b/util.c index 330b594..be67836 100644 --- a/util.c +++ b/util.c @@ -39,11 +39,11 @@ char *xstrdup(const char *s) { int len = strlen(s) + 1; - char *dup = xmalloc(len); + char *d = xmalloc(len); - memcpy(dup, s, len); + memcpy(d, s, len); - return dup; + return d; } char *join_path(const char *path, const char *name) From 4491ed9f875cbe39aaafa9c875bb3e39121e53e1 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 3 Feb 2014 12:46:28 -0800 Subject: [PATCH 0439/1198] Makefile: add a make "dist" target make dist can be used to produce tarballs directly from the git repository, which can be useful to automate the release process as well as shipping custom releases. Signed-off-by: Florian Fainelli Signed-off-by: David Gibson --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index afc0ce0..86f5ab3 100644 --- a/Makefile +++ b/Makefile @@ -196,6 +196,11 @@ fdtget: $(FDTGET_OBJS) $(LIBFDT_archive) fdtput: $(FDTPUT_OBJS) $(LIBFDT_archive) +dist: + git archive --format=tar --prefix=dtc-v$(dtc_version)/ HEAD \ + > ../dtc-v$(dtc_version).tar + cat ../dtc-v$(dtc_version).tar | \ + gzip -9 > ../dtc-v$(dtc_version).tgz # # Testsuite rules From aef4927a70728e106c5fb03395c9b908bd54abce Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 11 Feb 2014 13:56:32 +0000 Subject: [PATCH 0440/1198] Add a README file for dtc and libfdt Add a README file to document the location of the mailing list, the home page and state who the maintainers are. Signed-off-by: Grant Likely --- README | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 README diff --git a/README b/README new file mode 100644 index 0000000..979974a --- /dev/null +++ b/README @@ -0,0 +1,20 @@ +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 + +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 + +Home Page +--------- +http://devicetree.org/Device_Tree_Compiler From aba74ddba233e6c4b8e15714a3bde736cceb8b2d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sat, 15 Feb 2014 19:47:23 +1100 Subject: [PATCH 0441/1198] Remove references to unused DT_BASE token Also remove the cbase bison union member that was only used for it. Signed-off-by: David Gibson --- dtc-parser.y | 2 -- 1 file changed, 2 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 42c4d75..ea57e0a 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -38,7 +38,6 @@ extern bool treesource_error; %union { char *propnodename; char *labelref; - unsigned int cbase; uint8_t byte; struct data data; @@ -64,7 +63,6 @@ extern bool treesource_error; %token DT_PROPNODENAME %token DT_LITERAL %token DT_CHAR_LITERAL -%token DT_BASE %token DT_BYTE %token DT_STRING %token DT_LABEL From 821acd4c171b659a682a1aa05da641246a15d51e Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 1 Mar 2014 09:11:47 +0100 Subject: [PATCH 0442/1198] Remove dead code in util.c xrealloc never returns null Signed-off-by: Heinrich Schuchardt --- util.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/util.c b/util.c index be67836..1ce8b97 100644 --- a/util.c +++ b/util.c @@ -219,10 +219,6 @@ int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len) if (offset == bufsize) { bufsize *= 2; buf = xrealloc(buf, bufsize); - if (!buf) { - ret = ENOMEM; - break; - } } ret = read(fd, &buf[offset], bufsize - offset); From 8ce36476ae8d2541e9bf3a6c23c345ec03694ee3 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 2 Mar 2014 21:39:01 +0100 Subject: [PATCH 0443/1198] Consistently use xrealloc instead of realloc fdtput.c: Replace the remaining call to realloc by xrealloc. Some redundant lines in encode_value can be saved. Signed-off-by: Heinrich Schuchardt --- fdtput.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/fdtput.c b/fdtput.c index 5226a4e..2a8d674 100644 --- a/fdtput.c +++ b/fdtput.c @@ -96,12 +96,7 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count, /* enlarge our value buffer by a suitable margin if needed */ if (upto + len > value_size) { value_size = (upto + len) + 500; - value = realloc(value, value_size); - if (!value) { - fprintf(stderr, "Out of mmory: cannot alloc " - "%d bytes\n", value_size); - return -1; - } + value = xrealloc(value, value_size); } ptr = value + upto; From 9bf20d3896c15bb51456c70eab8a50ba6fd224eb Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 2 Mar 2014 21:45:57 +0100 Subject: [PATCH 0444/1198] Remove duplicate assignment Signed-off-by: Heinrich Schuchardt --- tests/testutils.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/testutils.c b/tests/testutils.c index f185133..521f4f1 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -144,7 +144,6 @@ int nodename_eq(const char *s1, const char *s2) { int len = strlen(s2); - len = strlen(s2); if (strncmp(s1, s2, len) != 0) return 0; if (s1[len] == '\0') From 55a3a8823d433f2922cce7bf424ee32e241076c4 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 3 Mar 2014 10:51:18 +1100 Subject: [PATCH 0445/1198] Update source code location for dtc in manual.txt The information about the location of the source code of the device tree compiler was inaccurate. Signed-off-by: Heinrich Schuchardt Signed-off-by: David Gibson --- Documentation/manual.txt | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/Documentation/manual.txt b/Documentation/manual.txt index 65c8540..398de32 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -30,25 +30,23 @@ I - "dtc", the device tree compiler 1) Sources -Source code for the Device Tree Compiler can be found at jdl.com. -The gitweb interface is: +Source code for the Device Tree Compiler can be found at git.kernel.org. - http://git.jdl.com/gitweb/ +The upstream repository is here: -The repository is here: + git://git.kernel.org/pub/scm/utils/dtc/dtc.git + https://git.kernel.org/pub/scm/utils/dtc/dtc.git - git://www.jdl.com/software/dtc.git - http://www.jdl.com/software/dtc.git +The gitweb interface for the upstream respository is: -Tarballs of the 1.0.0 and latest releases are here: - - http://www.jdl.com/software/dtc-v1.2.0.tgz - http://www.jdl.com/software/dtc-latest.tgz + https://git.kernel.org/cgit/utils/dtc/dtc.git/ 1.1) Submitting Patches -Patches should be sent to jdl@jdl.com, and CC'ed to -devicetree-discuss@lists.ozlabs.org. +Patches should be sent to the maintainers: + David Gibson + Jon Loeliger +and CCed to . 2) Description From f240527e54021f82d70d8a09035e575f864c1fbd Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 9 May 2014 20:48:49 +1000 Subject: [PATCH 0446/1198] Fix bug with references to root node At present, the lexer token for references to a path doesn't permit a reference to the root node &{/}. Fixing the lexer exposes another bug handling this case. This patch fixes both bugs and adds testcases. Signed-off-by: David Gibson --- dtc-lexer.l | 2 +- livetree.c | 4 +++- tests/multilabel.dts | 2 ++ tests/multilabel_merge.dts | 4 ++++ tests/path-references.c | 16 ++++++++++++++++ tests/path-references.dts | 1 + tests/references.c | 19 +++++++++++++++++++ tests/references.dts | 2 ++ 8 files changed, 48 insertions(+), 2 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 0821bde..5c9969f 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -193,7 +193,7 @@ static void lexical_error(const char *fmt, ...); return DT_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/livetree.c b/livetree.c index b61465f..e229b84 100644 --- a/livetree.c +++ b/livetree.c @@ -511,7 +511,9 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle) struct node *get_node_by_ref(struct node *tree, const char *ref) { - if (ref[0] == '/') + if (streq(ref, "/")) + return tree; + else if (ref[0] == '/') return get_node_by_path(tree, ref); else return get_node_by_label(tree, ref); diff --git a/tests/multilabel.dts b/tests/multilabel.dts index 31116ce..77da06c 100644 --- a/tests/multilabel.dts +++ b/tests/multilabel.dts @@ -5,6 +5,8 @@ m1: mq: /memreserve/ 0 0x1000; / { p0: pw: prop = "foo"; + rref = <&{/}>; + /* Explicit phandles */ n1: nx: node1 { linux,phandle = <0x2000>; diff --git a/tests/multilabel_merge.dts b/tests/multilabel_merge.dts index 1632300..3e80298 100644 --- a/tests/multilabel_merge.dts +++ b/tests/multilabel_merge.dts @@ -64,3 +64,7 @@ m1: mq: /memreserve/ 0 0x1000; }; }; + +/ { + rref = <&{/}>; +}; diff --git a/tests/path-references.c b/tests/path-references.c index 0746b3f..c8d25fb 100644 --- a/tests/path-references.c +++ b/tests/path-references.c @@ -47,6 +47,20 @@ static void check_ref(const void *fdt, int node, const char *checkpath) node, p, checkpath); } +static void check_rref(const void *fdt) +{ + const char *p; + int len; + + /* Check reference to root node */ + p = fdt_getprop(fdt, 0, "rref", &len); + if (!p) + FAIL("fdt_getprop(0, \"rref\"): %s", fdt_strerror(len)); + if (!streq(p, "/")) + FAIL("'rref' in root node has value \"%s\" instead of \"/\"", + p); +} + int main(int argc, char *argv[]) { void *fdt; @@ -78,5 +92,7 @@ int main(int argc, char *argv[]) if ((!streq(p, "/node1") || !streq(p + strlen("/node1") + 1, "/node2"))) FAIL("multiref has wrong value"); + check_rref(fdt); + PASS(); } diff --git a/tests/path-references.dts b/tests/path-references.dts index 91e7ef7..b00fd79 100644 --- a/tests/path-references.dts +++ b/tests/path-references.dts @@ -1,6 +1,7 @@ /dts-v1/; / { + rref = &{/}; /* Check multiple references case */ multiref = &n1 , &n2; n1: node1 { diff --git a/tests/references.c b/tests/references.c index c9d05a2..46662fc 100644 --- a/tests/references.c +++ b/tests/references.c @@ -56,6 +56,23 @@ static void check_ref(const void *fdt, int node, uint32_t checkref) node, ref, checkref); } +static void check_rref(const void *fdt) +{ + const uint32_t *p; + uint32_t ref; + int len; + + p = fdt_getprop(fdt, 0, "rref", &len); + if (!p) + FAIL("fdt_getprop(0, \"rref\"): %s", fdt_strerror(len)); + if (len != sizeof(*p)) + FAIL("'rref' in root node has wrong size (%d instead of %zd)", + len, sizeof(*p)); + ref = fdt32_to_cpu(*p); + if (ref != fdt_get_phandle(fdt, 0)) + FAIL("'rref' in root node has value 0x%x instead of 0x0", ref); +} + int main(int argc, char *argv[]) { void *fdt; @@ -104,5 +121,7 @@ int main(int argc, char *argv[]) check_ref(fdt, n2, h1); check_ref(fdt, n3, h4); + check_rref(fdt); + PASS(); } diff --git a/tests/references.dts b/tests/references.dts index 640c931..f783e8b 100644 --- a/tests/references.dts +++ b/tests/references.dts @@ -1,6 +1,8 @@ /dts-v1/; / { + rref = <&{/}>; + /* Explicit phandles */ n1: node1 { linux,phandle = <0x2000>; From 40f7f576c8e7df395ed25f0f3df61fac85f1adf9 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 11 May 2014 13:13:46 +1000 Subject: [PATCH 0447/1198] libfdt: Add helpers to read #address-cells and #size-cells This patch makes a small start on libfdt functions which actually help to parse the contents of device trees, rather than purely manipulating the tree's structure. We add simple helpers to read and sanity check the #address-cells and #size-cells values for a given node. Signed-off-by: David Gibson --- libfdt/Makefile.libfdt | 3 +- libfdt/fdt_addresses.c | 96 +++++++++++++++++++++++++++++++++++++++++ libfdt/libfdt.h | 62 +++++++++++++++++++++++++- tests/.gitignore | 1 + tests/Makefile.tests | 1 + tests/addr_size_cells.c | 64 +++++++++++++++++++++++++++ tests/addresses.dts | 15 +++++++ tests/run_tests.sh | 3 ++ 8 files changed, 243 insertions(+), 2 deletions(-) create mode 100644 libfdt/fdt_addresses.c create mode 100644 tests/addr_size_cells.c create mode 100644 tests/addresses.dts diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index 91126c0..09c322e 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -6,5 +6,6 @@ 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 +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 LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) diff --git a/libfdt/fdt_addresses.c b/libfdt/fdt_addresses.c new file mode 100644 index 0000000..eff4dbc --- /dev/null +++ b/libfdt/fdt_addresses.c @@ -0,0 +1,96 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2014 David Gibson + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +int fdt_address_cells(const void *fdt, int nodeoffset) +{ + const fdt32_t *ac; + int val; + int len; + + ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len); + if (!ac) + return 2; + + if (len != sizeof(*ac)) + return -FDT_ERR_BADNCELLS; + + val = fdt32_to_cpu(*ac); + if ((val <= 0) || (val > FDT_MAX_NCELLS)) + return -FDT_ERR_BADNCELLS; + + return val; +} + +int fdt_size_cells(const void *fdt, int nodeoffset) +{ + const fdt32_t *sc; + int val; + int len; + + sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len); + if (!sc) + return 2; + + if (len != sizeof(*sc)) + return -FDT_ERR_BADNCELLS; + + val = fdt32_to_cpu(*sc); + if ((val < 0) || (val > FDT_MAX_NCELLS)) + return -FDT_ERR_BADNCELLS; + + return val; +} diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index c4d5a91..32d5227 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -116,7 +116,12 @@ * Should never be returned, if it is, it indicates a bug in * libfdt itself. */ -#define FDT_ERR_MAX 13 +/* Errors in device tree content */ +#define FDT_ERR_BADNCELLS 14 + /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells + * or similar property with a bad format or value */ + +#define FDT_ERR_MAX 14 /**********************************************************************/ /* Low-level functions (you probably don't need these) */ @@ -852,6 +857,61 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, */ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); +/**********************************************************************/ +/* Read-only functions (addressing related) */ +/**********************************************************************/ + +/** + * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells + * + * This is the maximum value for #address-cells, #size-cells and + * similar properties that will be processed by libfdt. IEE1275 + * requires that OF implementations handle values up to 4. + * Implementations may support larger values, but in practice higher + * values aren't used. + */ +#define FDT_MAX_NCELLS 4 + +/** + * fdt_address_cells - retrieve address size for a bus represented in the tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address size for + * + * When the node has a valid #address-cells property, returns its value. + * + * 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 #address-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_address_cells(const void *fdt, int nodeoffset); + +/** + * fdt_size_cells - retrieve address range size for a bus represented in the + * tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address range size for + * + * When the node has a valid #size-cells property, returns its value. + * + * 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 #size-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_size_cells(const void *fdt, int nodeoffset); + + /**********************************************************************/ /* Write-in-place functions */ /**********************************************************************/ diff --git a/tests/.gitignore b/tests/.gitignore index bb5e33a..5656555 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -3,6 +3,7 @@ *.test.dts tmp.* /add_subnode_with_nops +/addr_size_cells /appendprop[12] /asm_tree_dump /boot-cpuid diff --git a/tests/Makefile.tests b/tests/Makefile.tests index dafb618..9adedec 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -8,6 +8,7 @@ LIB_TESTS_L = get_mem_rsv \ char_literal \ sized_cells \ notfound \ + addr_size_cells \ setprop_inplace nop_property nop_node \ sw_tree1 \ move_and_save mangle-layout nopulate \ diff --git a/tests/addr_size_cells.c b/tests/addr_size_cells.c new file mode 100644 index 0000000..6090d93 --- /dev/null +++ b/tests/addr_size_cells.c @@ -0,0 +1,64 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for #address-cells and #size-cells handling + * Copyright (C) 2014 David Gibson, + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +static void check_node(const void *fdt, const char *path, int ac, int sc) +{ + int offset; + int xac, xsc; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("Couldn't find path %s", path); + + xac = fdt_address_cells(fdt, offset); + xsc = fdt_size_cells(fdt, offset); + + if (xac != ac) + FAIL("Address cells for %s is %d instead of %d\n", + path, xac, ac); + if (xsc != sc) + FAIL("Size cells for %s is %d instead of %d\n", + path, xsc, sc); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + if (argc != 2) + CONFIG("Usage: %s \n", argv[0]); + + test_init(argc, argv); + fdt = load_blob(argv[1]); + + check_node(fdt, "/", 2, 2); + check_node(fdt, "/identity-bus@0", 2, 2); + check_node(fdt, "/simple-bus@1000000", 2, 1); + PASS(); +} diff --git a/tests/addresses.dts b/tests/addresses.dts new file mode 100644 index 0000000..a2faaf5 --- /dev/null +++ b/tests/addresses.dts @@ -0,0 +1,15 @@ +/dts-v1/; + +/ { + compatible = "test_addresses"; + #address-cells = <2>; + #size-cells = <2>; + + identity-bus@0 { + }; + + simple-bus@1000000 { + #address-cells = <2>; + #size-cells = <1>; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 97e016b..f205ce6 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -188,6 +188,9 @@ ALL_LAYOUTS="mts mst tms tsm smt stm" libfdt_tests () { tree1_tests test_tree1.dtb + run_dtc_test -I dts -O dtb -o addresses.test.dtb addresses.dts + run_test addr_size_cells addresses.test.dtb + # Sequential write tests run_test sw_tree1 tree1_tests sw_tree1.test.dtb From dfcfb7f169c361e395e817f33381981c7fdf9539 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 18 Jun 2014 01:00:22 -0600 Subject: [PATCH 0448/1198] Correct output from memreserve in fdtdump This currently displays a hex value without the 0x prefix. Add the prefix as dtc requires it. Signed-off-by: Simon Glass --- fdtdump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fdtdump.c b/fdtdump.c index 723770d..a29aa5e 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -88,7 +88,7 @@ static void dump_blob(void *blob, bool debug) if (addr == 0 && size == 0) break; - printf("/memreserve/ %llx %llx;\n", + printf("/memreserve/ %#llx %#llx;\n", (unsigned long long)addr, (unsigned long long)size); } From c78ca72e1e89714a7a62a85035e5c505c8ba51f0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 18 Jun 2014 01:00:23 -0600 Subject: [PATCH 0449/1198] Tweak code to display cell values Move the division out of the loop; this seems slightly cleaner. Signed-off-by: Simon Glass --- util.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util.c b/util.c index 1ce8b97..9d65226 100644 --- a/util.c +++ b/util.c @@ -371,9 +371,9 @@ void utilfdt_print_data(const char *data, int len) const uint32_t *cell = (const uint32_t *)data; printf(" = <"); - for (i = 0; i < len; i += 4) - printf("0x%08x%s", fdt32_to_cpu(cell[i / 4]), - i < (len - 4) ? " " : ""); + for (i = 0, len /= 4; i < len; i++) + printf("0x%08x%s", fdt32_to_cpu(cell[i]), + i < (len - 1) ? " " : ""); printf(">"); } else { printf(" = ["); From 76a65b14d1bb10f300f518c11aed231575521c2e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 18 Jun 2014 21:24:32 +1000 Subject: [PATCH 0450/1198] Add a basic test for fdtdump We can test fdtdump by comparing its output with the source file that was compiled by dtc. Add a simple test that should at least catch regressions in basic functionality. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- Makefile | 1 + tests/fdtdump-runtest.sh | 30 ++++++++++++++++++++++++++++++ tests/fdtdump.dts | 37 +++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 31 ++++++++++++++++++++++++++++++- tests/tests.sh | 1 + 5 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 tests/fdtdump-runtest.sh create mode 100644 tests/fdtdump.dts diff --git a/Makefile b/Makefile index 86f5ab3..03644dd 100644 --- a/Makefile +++ b/Makefile @@ -211,6 +211,7 @@ TESTS_BIN += dtc TESTS_BIN += convert-dtsv0 TESTS_BIN += fdtput TESTS_BIN += fdtget +TESTS_BIN += fdtdump include tests/Makefile.tests diff --git a/tests/fdtdump-runtest.sh b/tests/fdtdump-runtest.sh new file mode 100644 index 0000000..77593cf --- /dev/null +++ b/tests/fdtdump-runtest.sh @@ -0,0 +1,30 @@ +#! /bin/sh + +# Arguments: +# $1 - source file to compile and compare with fdtdump output of the +# compiled file. + +. ./tests.sh + +dts="$1" +dtb="${dts}.dtb" +out="${dts}.out" +LOG=tmp.log.$$ + +files="$dtb $out $LOG" + +rm -f $files +trap "rm -f $files" 0 + +verbose_run_log_check "$LOG" $VALGRIND $DTC -O dtb $dts -o $dtb +$FDTDUMP ${dtb} | grep -v "//" >${out} + +if diff -w $dts $out >/dev/null; then + PASS +else + if [ -z "$QUIET_TEST" ]; then + echo "DIFF :-:" + diff -u -w $dts $out + fi + FAIL "Results differ from expected" +fi diff --git a/tests/fdtdump.dts b/tests/fdtdump.dts new file mode 100644 index 0000000..b9d917b --- /dev/null +++ b/tests/fdtdump.dts @@ -0,0 +1,37 @@ +/dts-v1/; + +/memreserve/ 0 0xe; +/ { + model = "MyBoardName"; + compatible = "MyBoardName", "MyBoardFamilyName"; + #address-cells = <0x00000002>; + #size-cells = <0x00000002>; + cpus { + linux,phandle = <0x00000001>; + #address-cells = <0x00000001>; + #size-cells = <0x00000000>; + PowerPC,970@0 { + device_type = "cpu"; + reg = <0x00000000>; + linux,boot-cpu; + }; + PowerPC,970@1 { + device_type = "cpu"; + reg = <0x00000001>; + }; + }; + randomnode { + string = "foo", "stuff"; + bytes = [61 62 63 64 65]; + child { + }; + }; + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x00000123 0x00000456 0x87654321>; + }; + chosen { + bootargs = "root=/dev/sda2"; + linux,platform = <0x00000600>; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index f205ce6..c6adf21 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -138,6 +138,13 @@ run_fdtput_test () { base_run_test sh fdtput-runtest.sh "$expect" "$@" } +run_fdtdump_test() { + file="$1" + shorten_echo fdtdump-runtest.sh "$file" + echo -n ": " + base_run_test sh fdtdump-runtest.sh "$file" +} + tree1_tests () { TREE=$1 @@ -602,6 +609,25 @@ utilfdt_tests () { run_test utilfdt_test } +fdtdump_tests () { + run_fdtdump_test fdtdump.dts + return + + local dts=fdtdump.dts + local dtb=fdtdump.dts.dtb + local out=fdtdump.dts.out + run_dtc_test -O dtb $dts -o ${dtb} + $FDTDUMP ${dtb} | grep -v "//" >${out} + if cmp $dts $out >/dev/null; then + PASS + else + if [ -z "$QUIET_TEST" ]; then + diff -w fdtdump.dts $out + fi + FAIL "Results differ from expected" + fi +} + while getopts "vt:me" ARG ; do case $ARG in "v") @@ -620,7 +646,7 @@ while getopts "vt:me" ARG ; do done if [ -z "$TESTSETS" ]; then - TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget fdtput" + TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget fdtput fdtdump" fi # Make sure we don't have stale blobs lying around @@ -646,6 +672,9 @@ for set in $TESTSETS; do "fdtput") fdtput_tests ;; + "fdtdump") + fdtdump_tests + ;; esac done diff --git a/tests/tests.sh b/tests/tests.sh index 31530d5..818fd09 100644 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -21,6 +21,7 @@ FAIL_IF_SIGNAL () { DTC=../dtc DTGET=../fdtget DTPUT=../fdtput +FDTDUMP=../fdtdump verbose_run () { if [ -z "$QUIET_TEST" ]; then From fa928fba7e1ce94aef58798e77a9261192fdbb01 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 18 Jun 2014 22:49:43 +1000 Subject: [PATCH 0451/1198] Fix an off-by-2 error in the source output code This has been there for ages, but the assertion makes no sense in the context of the test immediately preceding it. This caused an abort() when in -I dts -O dts mode with the right sort of internal labels in a string property value. Add a testcase for this and another candidate edge case (though this one we already get right). Signed-off-by: David Gibson --- tests/run_tests.sh | 4 ++++ tests/sourceoutput.dts | 14 ++++++++++++++ treesource.c | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/sourceoutput.dts diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c6adf21..f94d361 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -271,6 +271,10 @@ libfdt_tests () { # Specific bug tests run_test add_subnode_with_nops + run_dtc_test -I dts -O dts -o sourceoutput.test.dts sourceoutput.dts + run_dtc_test -I dts -O dtb -o sourceoutput.test.dtb sourceoutput.dts + run_dtc_test -I dts -O dtb -o sourceoutput.test.dts.test.dtb sourceoutput.test.dts + run_test dtbs_equal_ordered sourceoutput.test.dtb sourceoutput.test.dts.test.dtb } dtc_tests () { diff --git a/tests/sourceoutput.dts b/tests/sourceoutput.dts new file mode 100644 index 0000000..477762f --- /dev/null +++ b/tests/sourceoutput.dts @@ -0,0 +1,14 @@ +/dts-v1/; + +/ { + /* Some versions had an off-by-2 bug which caused an abort + * when outputing labels within strings like this in source + * format */ + prop1: prop1 = start1: "foo", mid1: "bar" end1: ; + + /* Make sure that we correctly handle source output of things + * which could almost be expressed as strings, except for the + * embedded labels */ + prop2 = start2: [66 6f 6f], mid2: "bar" end2: ; +}; + diff --git a/treesource.c b/treesource.c index bf7a626..3a87b9f 100644 --- a/treesource.c +++ b/treesource.c @@ -109,7 +109,7 @@ static void write_propval_string(FILE *f, struct data val) break; case '\0': fprintf(f, "\", "); - while (m && (m->offset < i)) { + while (m && (m->offset <= (i + 1))) { if (m->type == LABEL) { assert(m->offset == (i+1)); fprintf(f, "%s: ", m->ref); From 25a9bd6267bf1a2e144344325a71432193eed4b0 Mon Sep 17 00:00:00 2001 From: Andrei Errapart Date: Thu, 19 Jun 2014 21:05:11 +1000 Subject: [PATCH 0452/1198] Correct write_propval_bytes() for platforms with signed char by default Some platforms (including the Microsoft C compiler) have char defaulting to signed. write_propval_bytes() in the -O dts code will not behave correctly in this case, due to sign extension. Signed-off-by: Andrei Errapart Signed-off-by: David Gibson --- treesource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/treesource.c b/treesource.c index 3a87b9f..a55d1d1 100644 --- a/treesource.c +++ b/treesource.c @@ -178,7 +178,7 @@ static void write_propval_bytes(FILE *f, struct data val) m = m->next; } - fprintf(f, "%02hhx", *bp++); + fprintf(f, "%02hhx", (unsigned char)(*bp++)); if ((const void *)bp >= propend) break; fprintf(f, " "); From 83e606a64d7b555bea3c3007b48bb9f790f0139c Mon Sep 17 00:00:00 2001 From: Andrei Errapart Date: Thu, 19 Jun 2014 21:12:27 +1000 Subject: [PATCH 0453/1198] Open binary files in binary mode The "b" flag to fopen() is generally a no-op on Unix-like systems, but may be important on other systems, including Windows. Signed-off-by: Andrei Errapart Signed-off-by: David Gibson --- dtc.c | 2 +- fstree.c | 2 +- srcpos.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dtc.c b/dtc.c index d36ccdc..e3665b6 100644 --- a/dtc.c +++ b/dtc.c @@ -237,7 +237,7 @@ int main(int argc, char *argv[]) if (streq(outname, "-")) { outf = stdout; } else { - outf = fopen(outname, "w"); + outf = fopen(outname, "wb"); if (! outf) die("Couldn't open output file %s: %s\n", outname, strerror(errno)); diff --git a/fstree.c b/fstree.c index 4d2791c..6d1beec 100644 --- a/fstree.c +++ b/fstree.c @@ -52,7 +52,7 @@ static struct node *read_fstree(const char *dirname) struct property *prop; FILE *pfile; - pfile = fopen(tmpname, "r"); + pfile = fopen(tmpname, "rb"); if (! pfile) { fprintf(stderr, "WARNING: Cannot open %s: %s\n", diff --git a/srcpos.c b/srcpos.c index 4549773..f534c22 100644 --- a/srcpos.c +++ b/srcpos.c @@ -77,7 +77,7 @@ static char *try_open(const char *dirname, const char *fname, FILE **fp) else fullname = join_path(dirname, fname); - *fp = fopen(fullname, "r"); + *fp = fopen(fullname, "rb"); if (!*fp) { free(fullname); fullname = NULL; From f9e91a48ba509e77aadcb5349885e1777ef17372 Mon Sep 17 00:00:00 2001 From: Andrei Errapart Date: Thu, 19 Jun 2014 21:07:48 +1000 Subject: [PATCH 0454/1198] Work around MSVC limitations 1) No variadic macros in the form "args..."; this is a GCC extension. 2) No empty struct initializers. In any case, there is very little to win: { } vs. { 0 }. Signed-off-by: Andrei Errapart Signed-off-by: David Gibson --- dtc.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dtc.h b/dtc.h index 20de073..56212c8 100644 --- a/dtc.h +++ b/dtc.h @@ -38,9 +38,9 @@ #include "util.h" #ifdef DEBUG -#define debug(fmt,args...) printf(fmt, ##args) +#define debug(...) printf(__VA_ARGS__) #else -#define debug(fmt,args...) +#define debug(...) #endif @@ -88,7 +88,7 @@ struct data { }; -#define empty_data ((struct data){ /* all .members = 0 or NULL */ }) +#define empty_data ((struct data){ 0 /* all .members = 0 or NULL */ }) #define for_each_marker(m) \ for (; (m); (m) = (m)->next) From 5d4a8b9c4c5145bd509bff20780270e00547c80a Mon Sep 17 00:00:00 2001 From: Jack Miller Date: Wed, 6 Aug 2014 15:52:03 -0500 Subject: [PATCH 0455/1198] Properly handle embedded nul delimited string lists For example: reserved-names="res1\0res2\0res3"; Where \0 is an actual embedded NUL in the source instead of a string escape. To achieve this, use the len given by the lexer instead of strlen. Without this patch dtc will mangle the output and possibly hang on realloc. --- data.c | 2 +- tests/embedded_nul.dts | Bin 0 -> 152 bytes tests/embedded_nul_equiv.dts | 6 ++++++ tests/run_tests.sh | 4 ++++ 4 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 tests/embedded_nul.dts create mode 100644 tests/embedded_nul_equiv.dts diff --git a/data.c b/data.c index 4c50b12..8cae237 100644 --- a/data.c +++ b/data.c @@ -74,7 +74,7 @@ struct data data_copy_escape_string(const char *s, int len) struct data d; char *q; - d = data_grow_for(empty_data, strlen(s)+1); + d = data_grow_for(empty_data, len + 1); q = d.val; while (i < len) { diff --git a/tests/embedded_nul.dts b/tests/embedded_nul.dts new file mode 100644 index 0000000000000000000000000000000000000000..7b4993cc5452ba57f78cedf01715deaba55d8613 GIT binary patch literal 152 zcmdN-DJj-1Gt{@{;?h^B=He_$Elw>eOHI+uOUz9zR; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index f94d361..ace6e4f 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -275,6 +275,10 @@ libfdt_tests () { run_dtc_test -I dts -O dtb -o sourceoutput.test.dtb sourceoutput.dts run_dtc_test -I dts -O dtb -o sourceoutput.test.dts.test.dtb sourceoutput.test.dts run_test dtbs_equal_ordered sourceoutput.test.dtb sourceoutput.test.dts.test.dtb + + run_dtc_test -I dts -O dtb -o embedded_nul.test.dtb embedded_nul.dts + run_dtc_test -I dts -O dtb -o embedded_nul_equiv.test.dtb embedded_nul_equiv.dts + run_test dtbs_equal_ordered embedded_nul.test.dtb embedded_nul_equiv.test.dtb } dtc_tests () { From 1e5ddb1f39753a37fd60a7b49f858e4fee8cd998 Mon Sep 17 00:00:00 2001 From: Wang Long Date: Thu, 11 Sep 2014 15:16:37 +0800 Subject: [PATCH 0456/1198] dtc: Update the usage helper message if #define DEFAULT_FDT_VERSION 17 The message Blob version to produce, defaults to %d (for dtb and asm output) should be Blob version to produce, defaults to 17 (for dtb and asm output) This patch fix it, and delete the redundant 't'. Signed-off-by: Wang Long --- dtc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dtc.c b/dtc.c index e3665b6..8c4add6 100644 --- a/dtc.c +++ b/dtc.c @@ -48,6 +48,8 @@ static void fill_fullpaths(struct node *tree, const char *prefix) } /* Usage related data. */ +#define FDT_VERSION(version) _FDT_VERSION(version) +#define _FDT_VERSION(version) #version static const char usage_synopsis[] = "dtc [options] "; static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv"; static struct option const usage_long_opts[] = { @@ -82,9 +84,9 @@ static const char * const usage_opts_help[] = { "\t\tdts - device tree source text\n" "\t\tdtb - device tree blob\n" "\t\tasm - assembler source", - "\n\tBlob version to produce, defaults to %d (for dtb and asm output)", //, DEFAULT_FDT_VERSION); + "\n\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)", "\n\tOutput dependency file", - "\n\ttMake space for reserve map entries (for dtb and asm output)", + "\n\tMake space for reserve map entries (for dtb and asm output)", "\n\tMake the blob at least long (extra space)", "\n\tAdd padding to the blob of long (extra space)", "\n\tSet the physical boot cpu", From 6a76a9d30c977c6c9cb18cf15ba3bd2c2e89db4c Mon Sep 17 00:00:00 2001 From: Wang Long Date: Thu, 25 Sep 2014 01:52:53 +0000 Subject: [PATCH 0457/1198] dtc: Delete the unused start condition INCLUDE The scanners of the latest version of dtc and convert-dtsv0 are no longer use start condition "INCLUDE". so we should delete it. Signed-off-by: Wang Long --- convert-dtsv0-lexer.l | 1 - dtc-lexer.l | 1 - 2 files changed, 2 deletions(-) diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index 548e719..259e527 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -19,7 +19,6 @@ %option noyywrap nounput noinput never-interactive -%x INCLUDE %x BYTESTRING %x PROPNODENAME diff --git a/dtc-lexer.l b/dtc-lexer.l index 5c9969f..0ee1caf 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -20,7 +20,6 @@ %option noyywrap nounput noinput never-interactive -%x INCLUDE %x BYTESTRING %x PROPNODENAME %s V1 From 242c2642709436ceb144f9949868ff54050c70a2 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 17 Oct 2014 23:22:11 +0100 Subject: [PATCH 0458/1198] Improve portability 1) Remove the double parentheses around two comparisons in checks.c. The OSX LLVM-based C compiler warns about them. 2) Put an explicit "=" in the TN() macro, in accordance with c99. Signed-off-by: Phil Elwell --- checks.c | 4 ++-- fdtdump.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/checks.c b/checks.c index 47eda65..3bf0fa4 100644 --- a/checks.c +++ b/checks.c @@ -624,11 +624,11 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt, if (!reg && !ranges) return; - if ((node->parent->addr_cells == -1)) + if (node->parent->addr_cells == -1) FAIL(c, "Relying on default #address-cells value for %s", node->fullpath); - if ((node->parent->size_cells == -1)) + if (node->parent->size_cells == -1) FAIL(c, "Relying on default #size-cells value for %s", node->fullpath); } diff --git a/fdtdump.c b/fdtdump.c index a29aa5e..95a6a20 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -22,7 +22,7 @@ static const char *tagname(uint32_t tag) { static const char * const names[] = { -#define TN(t) [t] #t +#define TN(t) [t] = #t TN(FDT_BEGIN_NODE), TN(FDT_END_NODE), TN(FDT_PROP), From 656bd3b6b95f073dc6c6816f0110bb0624792316 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Nov 2014 14:27:02 +1100 Subject: [PATCH 0459/1198] dtc: Add maintainer script for signing and upload to kernel.org This patch adds scripts/kup-dtc which builds a tarball from a specified git tag, signs it and uploads to kernel.org with kup. This is useful only for dtc maintainers. Signed-off-by: David Gibson --- Makefile | 1 + scripts/kup-dtc | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100755 scripts/kup-dtc diff --git a/Makefile b/Makefile index 03644dd..c35f2f1 100644 --- a/Makefile +++ b/Makefile @@ -226,6 +226,7 @@ clean: libfdt_clean tests_clean rm -f $(STD_CLEANFILES) rm -f $(VERSION_FILE) rm -f $(BIN) + rm -f dtc-*.tar dtc-*.tar.sign dtc-*.tar.asc # # Generic compile rules diff --git a/scripts/kup-dtc b/scripts/kup-dtc new file mode 100755 index 0000000..e18abbb --- /dev/null +++ b/scripts/kup-dtc @@ -0,0 +1,31 @@ +#! /bin/sh + +REMOTE_GIT=/pub/scm/utils/dtc/dtc.git +REMOTE_PATH=/pub/software/utils/dtc + +set -e + +kup_one () { + VERSION="$1" + + TAG="v$VERSION" + + PREFIX="dtc-$VERSION/" + TAR="dtc-$VERSION.tar" + SIG="$TAR.sign" + + git archive --format=tar --prefix="$PREFIX" -o "$TAR" "$TAG" + gpg --detach-sign --armor -o "$SIG" "$TAR" + + ls -l "$TAR"* + + # Verify the signature as a sanity check + gpg --verify "$SIG" "$TAR" + + kup put --tar --prefix="$PREFIX" "$REMOTE_GIT" "$TAG" "$SIG" "$REMOTE_PATH/$TAR.gz" +} + +for version; do + kup_one $version +done + From 302fca9f4c283e1994cf0a5a9ce1cf43ca15e6d2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 12 Nov 2014 14:29:16 +1100 Subject: [PATCH 0460/1198] dtc: Bump version to 1.4.1 Bump version number in preparation for a release. Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c35f2f1..c1d0757 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ # VERSION = 1 PATCHLEVEL = 4 -SUBLEVEL = 0 +SUBLEVEL = 1 EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = From 5ef2f7c2fa16320d01b66601f9147a10a38edcee Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 12 Jan 2015 12:46:56 +0000 Subject: [PATCH 0461/1198] dtc: Use va_end to match corresponding va_start Although on some systems va_end is a no-op, it is good practice to use va_end, especially since the manual states: "Each invocation of va_start() must be matched by a corresponding invocation of va_end() in the same function." Signed-off-by: Colin Ian King --- checks.c | 1 + util.h | 1 + 2 files changed, 2 insertions(+) diff --git a/checks.c b/checks.c index 3bf0fa4..e81a8c7 100644 --- a/checks.c +++ b/checks.c @@ -113,6 +113,7 @@ static inline void check_msg(struct check *c, const char *fmt, ...) vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); } + va_end(ap); } #define FAIL(c, ...) \ diff --git a/util.h b/util.h index ccfdf4b..f800b60 100644 --- a/util.h +++ b/util.h @@ -34,6 +34,7 @@ static inline void __attribute__((noreturn)) die(const char *str, ...) va_start(ap, str); fprintf(stderr, "FATAL ERROR: "); vfprintf(stderr, str, ap); + va_end(ap); exit(1); } From aa719618a8b7c748be659717a9fd003bfa186017 Mon Sep 17 00:00:00 2001 From: Wang Long Date: Fri, 23 Jan 2015 01:25:20 +0000 Subject: [PATCH 0462/1198] fdtput: add delete node and property function add the delete node and property function for fdtput. usage: 1) delete nodes fdtput -r
[...] 2) delete properties fdtput -d
[...] Signed-off-by: Wang Long --- fdtput.c | 85 ++++++++++++++++++++++++++++++++++++++++++++-- tests/run_tests.sh | 22 ++++++++++++ 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/fdtput.c b/fdtput.c index 2a8d674..9b15c53 100644 --- a/fdtput.c +++ b/fdtput.c @@ -32,6 +32,8 @@ enum oper_type { OPER_WRITE_PROP, /* Write a property in a node */ OPER_CREATE_NODE, /* Create a new node */ + OPER_REMOVE_NODE, /* Delete a node */ + OPER_DELETE_PROP, /* Delete a property in a node */ }; struct display_info { @@ -270,11 +272,65 @@ static int create_node(char **blob, const char *node_name) return 0; } +/** + * Delete a property of a node in the fdt. + * + * @param blob FDT blob to write into + * @param node_name Path to node containing the property to delete + * @param prop_name Name of property to delete + * @return 0 on success, or -1 on failure + */ +static int delete_prop(char *blob, const char *node_name, const char *prop_name) +{ + int node = 0; + + node = fdt_path_offset(blob, node_name); + if (node < 0) { + report_error(node_name, -1, node); + return -1; + } + + node = fdt_delprop(blob, node, prop_name); + if (node < 0) { + report_error(node_name, -1, node); + return -1; + } + + return 0; +} + +/** + * Delete a node in the fdt. + * + * @param blob FDT blob to write into + * @param node_name Name of node to delete + * @return 0 on success, or -1 on failure + */ +static int delete_node(char *blob, const char *node_name) +{ + int node = 0; + + node = fdt_path_offset(blob, node_name); + if (node < 0) { + report_error(node_name, -1, node); + return -1; + } + + node = fdt_del_node(blob, node); + if (node < 0) { + report_error(node_name, -1, node); + return -1; + } + + return 0; +} + static int do_fdtput(struct display_info *disp, const char *filename, char **arg, int arg_count) { char *value; char *blob; + char *node; int len, ret = 0; blob = utilfdt_read(filename); @@ -302,6 +358,15 @@ static int do_fdtput(struct display_info *disp, const char *filename, ret = create_node(&blob, *arg); } break; + case OPER_REMOVE_NODE: + for (; ret >= 0 && arg_count--; arg++) + ret = delete_node(blob, *arg); + break; + case OPER_DELETE_PROP: + node = *arg; + for (arg++; ret >= 0 && arg_count-- > 1; arg++) + ret = delete_prop(blob, node, *arg); + break; } if (ret >= 0) { fdt_pack(blob); @@ -317,12 +382,16 @@ static const char usage_synopsis[] = "write a property value to a device tree\n" " fdtput
[...]\n" " fdtput -c
[...]\n" + " fdtput -r
[...]\n" + " fdtput -d
[...]\n" "\n" "The command line arguments are joined together into a single value.\n" USAGE_TYPE_MSG; -static const char usage_short_opts[] = "cpt:v" USAGE_COMMON_SHORT_OPTS; +static const char usage_short_opts[] = "crdpt:v" USAGE_COMMON_SHORT_OPTS; static struct option const usage_long_opts[] = { {"create", no_argument, NULL, 'c'}, + {"remove", no_argument, NULL, 'r'}, + {"delete", no_argument, NULL, 'd'}, {"auto-path", no_argument, NULL, 'p'}, {"type", a_argument, NULL, 't'}, {"verbose", no_argument, NULL, 'v'}, @@ -330,6 +399,8 @@ static struct option const usage_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", + "Delete properties if they already exist", "Automatically create nodes as needed for the node path", "Type of data", "Display each value decoded from command line", @@ -348,8 +419,6 @@ int main(int argc, char *argv[]) while ((opt = util_getopt_long()) != EOF) { /* * TODO: add options to: - * - delete property - * - delete node (optionally recursively) * - rename node * - pack fdt before writing * - set amount of free space when writing @@ -360,6 +429,12 @@ int main(int argc, char *argv[]) case 'c': disp.oper = OPER_CREATE_NODE; break; + case 'r': + disp.oper = OPER_REMOVE_NODE; + break; + case 'd': + disp.oper = OPER_DELETE_PROP; + break; case 'p': disp.auto_path = 1; break; @@ -390,6 +465,10 @@ int main(int argc, char *argv[]) usage("missing property"); } + if (disp.oper == OPER_DELETE_PROP) + if (argc < 1) + usage("missing node"); + if (do_fdtput(&disp, filename, argv, argc)) return 1; return 0; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index ace6e4f..c5856d9 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -610,6 +610,28 @@ fdtput_tests () { run_wrap_test $DTPUT $dtb -cp /chosen run_wrap_test $DTPUT $dtb -cp /chosen/son + # Start again with a fresh dtb + run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts + + # Node delete + run_wrap_test $DTPUT $dtb -c /chosen/node1 /chosen/node2 /chosen/node3 + run_fdtget_test "node3\nnode2\nnode1" $dtb -l /chosen + run_wrap_test $DTPUT $dtb -r /chosen/node1 /chosen/node2 + run_fdtget_test "node3" $dtb -l /chosen + + # Delete the non-existent node + run_wrap_error_test $DTPUT $dtb -r /non-existent/node + + # Property delete + run_fdtput_test "eva" $dtb /chosen/ name "" -ts "eva" + run_fdtput_test "016" $dtb /chosen/ age "" -ts "016" + run_fdtget_test "age\nname\nbootargs\nlinux,platform" $dtb -p /chosen + run_wrap_test $DTPUT $dtb -d /chosen/ name age + run_fdtget_test "bootargs\nlinux,platform" $dtb -p /chosen + + # Delete the non-existent property + run_wrap_error_test $DTPUT $dtb -d /chosen non-existent-prop + # TODO: Add tests for verbose mode? } From 3346e065aacb1f05bdfb3872e3ba709b5f895846 Mon Sep 17 00:00:00 2001 From: Nikhil Devshatwar Date: Mon, 23 Feb 2015 12:29:19 +1100 Subject: [PATCH 0463/1198] dtc: parser: Add label while overriding nodes This patch changes the dtc grammar to allow following syntax i2cexp: &i2c2 { ... }; Current device tree compiler allows to define multiple labels when defining the device node the first time. Typically device nodes are defined in DTSI files. Now these nodes can be overwritten for updating some of the properties. Typically, device nodes are overridden in DTS files. When working with adapter boards, most of the time adapter board can fit to multiple base boards. But depending on which base board it is connected to, the devices on the adapter board would be children of different devices. e.g. On dra7-evm.dts, i2c2 is exported for expansion connector whereas on dra72-evm.dts, i2c5 is exported for expansion connector. This causes a problem when writing a generic device tree file for the adapter board. Because, you cannot know whether all the devices on adapter board are present on i2c or i2c5. The problem can be solved by adding a common label (e.g. i2cexp) in both of the DTS files when overriding the device nodes for i2c2 or i2c5. This way, generic adapter board file would override the i2cexp. And depending on which base board you use the adapter board, all the devices are automatically added for correct device nodes. Signed-off-by: Nikhil Devshatwar Signed-off-by: David Gibson --- dtc-parser.y | 12 +++++++ tests/run_tests.sh | 2 ++ tests/test_tree1_label_noderef.dts | 55 ++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 tests/test_tree1_label_noderef.dts diff --git a/dtc-parser.y b/dtc-parser.y index ea57e0a..5a897e3 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -140,6 +140,18 @@ devicetree: { $$ = merge_nodes($1, $3); } + + | devicetree DT_LABEL DT_REF nodedef + { + struct node *target = get_node_by_ref($1, $3); + + add_label(&target->labels, $2); + if (target) + merge_nodes(target, $4); + else + ERROR(&@3, "Label or path %s not found", $3); + $$ = $1; + } | devicetree DT_REF nodedef { struct node *target = get_node_by_ref($1, $2); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c5856d9..5331856 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -399,6 +399,8 @@ dtc_tests () { tree1_tests dtc_tree1_merge.test.dtb test_tree1.dtb run_dtc_test -I dts -O dtb -o dtc_tree1_merge_labelled.test.dtb test_tree1_merge_labelled.dts tree1_tests dtc_tree1_merge_labelled.test.dtb test_tree1.dtb + run_dtc_test -I dts -O dtb -o dtc_tree1_label_noderef.test.dtb test_tree1_label_noderef.dts + run_test dtbs_equal_unordered dtc_tree1_label_noderef.test.dtb test_tree1.dtb run_dtc_test -I dts -O dtb -o multilabel_merge.test.dtb multilabel_merge.dts run_test references multilabel.test.dtb run_test dtbs_equal_ordered multilabel.test.dtb multilabel_merge.test.dtb diff --git a/tests/test_tree1_label_noderef.dts b/tests/test_tree1_label_noderef.dts new file mode 100644 index 0000000..b2b194c --- /dev/null +++ b/tests/test_tree1_label_noderef.dts @@ -0,0 +1,55 @@ +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; + +/ { + compatible = "test_tree1"; + prop-int = <0xdeadbeef>; + prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; + prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; + + subnode@1 { + compatible = "subnode1"; + reg = <1>; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + reg = <2>; + linux,phandle = <0x2000>; + prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; + + ssn0: subsubnode@0 { + phandle = <0x2001>; + prop-int = <0xbad>; + }; + + ss2 { + }; + }; +}; + +/* Add label to a noderef */ +ssn1: &ssn0 { + reg = <0>; + prop-int = <123456789>; +}; + +/* Use the new label for merging */ +&ssn1 { + prop-int = <0726746425>; + compatible = "subsubnode2", "subsubnode"; +}; From a4b093f7366fdb429ca1781144d3985fa50d0fbb Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Tue, 17 Mar 2015 16:00:34 +0000 Subject: [PATCH 0464/1198] libfdt: Add missing functions to shared library The commit 4e76ec7 "libfdt: Add fdt_next_subnode() to permit easy subnode iteration" adds new functions (fdt_{first,next}_subnode) but forgot to mark them as 'global' in the shared library. Signed-off-by: Julien Grall --- libfdt/version.lds | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libfdt/version.lds b/libfdt/version.lds index 80b322b..941208e 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -54,6 +54,8 @@ LIBFDT_1.2 { fdt_get_property_by_offset; fdt_getprop_by_offset; fdt_next_property_offset; + fdt_first_subnode; + fdt_next_subnode; local: *; From b4150b59aef3f2353a64ae27601339a1b42541db Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 6 Mar 2015 10:12:38 -0500 Subject: [PATCH 0465/1198] libfdt: Add fdt_path_offset_namelen() Properties may contain path names which are not NUL-terminated. For example, the 'stdout-path' property allows the form 'path:options', where the ':' character terminates the path specifier. Allow these path names to be used in-place for path descending; add fdt_path_offset_namelen(), which limits the path name to 'namelen' characters. Reimplement fdt_path_offset() as a trivial wrapper. Signed-off-by: Peter Hurley --- libfdt/fdt_ro.c | 22 ++++++++++++++-------- libfdt/libfdt.h | 11 +++++++++++ libfdt/version.lds | 1 + 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 50007f6..a65e4b5 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -154,9 +154,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); } -int fdt_path_offset(const void *fdt, const char *path) +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) { - const char *end = path + strlen(path); + const char *end = path + namelen; const char *p = path; int offset = 0; @@ -164,7 +164,7 @@ int fdt_path_offset(const void *fdt, const char *path) /* see if we have an alias */ if (*path != '/') { - const char *q = strchr(path, '/'); + const char *q = memchr(path, '/', end - p); if (!q) q = end; @@ -177,14 +177,15 @@ int fdt_path_offset(const void *fdt, const char *path) p = q; } - while (*p) { + while (p < end) { const char *q; - while (*p == '/') + while (*p == '/') { p++; - if (! *p) - return offset; - q = strchr(p, '/'); + if (p == end) + return offset; + } + q = memchr(p, '/', end - p); if (! q) q = end; @@ -198,6 +199,11 @@ int fdt_path_offset(const void *fdt, const char *path) return offset; } +int fdt_path_offset(const void *fdt, const char *path) +{ + return fdt_path_offset_namelen(fdt, path, strlen(path)); +} + const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) { const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 32d5227..1054512 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -322,6 +322,17 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, */ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); +/** + * fdt_path_offset_namelen - find a tree node by its full path + * @fdt: pointer to the device tree blob + * @path: full path of the node to locate + * @namelen: number of characters of path to consider + * + * Identical to fdt_path_offset(), but only consider the first namelen + * characters of path as the path name. + */ +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); + /** * fdt_path_offset - find a tree node by its full path * @fdt: pointer to the device tree blob diff --git a/libfdt/version.lds b/libfdt/version.lds index 941208e..f19f157 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -8,6 +8,7 @@ LIBFDT_1.2 { fdt_get_mem_rsv; fdt_subnode_offset_namelen; fdt_subnode_offset; + fdt_path_offset_namelen; fdt_path_offset; fdt_get_name; fdt_get_property_namelen; From 5fa047f498170496c37a9d5842d3b7eaf3907cca Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 7 Apr 2015 14:20:33 +1000 Subject: [PATCH 0466/1198] Use a helper function to clean up path_offset testcase This introduces a check_path_offset() helper function into the path_offset testcase to simplify it. This will also make extending the test case with tests for path_offset_namelen() and some edge cases easier. Signed-off-by: David Gibson --- tests/path_offset.c | 55 +++++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/tests/path_offset.c b/tests/path_offset.c index 4e5b7a1..0ff710d 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -54,58 +54,43 @@ static int check_subnode(void *fdt, int parent, const char *name) return offset; } +static void check_path_offset(void *fdt, char *path, int offset) +{ + int rc; + + rc = fdt_path_offset(fdt, path); + if (rc < 0) + FAIL("fdt_path_offset(\"%s\") failed: %s", + path, fdt_strerror(rc)); + if (rc != offset) + FAIL("fdt_path_offset(\"%s\") returned incorrect offset" + " %d instead of %d", path, rc, offset); +} + int main(int argc, char *argv[]) { void *fdt; - int root_offset; int subnode1_offset, subnode2_offset; - int subnode1_offset_p, subnode2_offset_p; int subsubnode1_offset, subsubnode2_offset, subsubnode2_offset2; - int subsubnode1_offset_p, subsubnode2_offset_p, subsubnode2_offset2_p; test_init(argc, argv); fdt = load_blob_arg(argc, argv); - root_offset = fdt_path_offset(fdt, "/"); - if (root_offset < 0) - FAIL("fdt_path_offset(\"/\") failed: %s", - fdt_strerror(root_offset)); - else if (root_offset != 0) - FAIL("fdt_path_offset(\"/\") returns incorrect offset %d", - root_offset); + check_path_offset(fdt, "/", 0); + subnode1_offset = check_subnode(fdt, 0, "subnode@1"); subnode2_offset = check_subnode(fdt, 0, "subnode@2"); - subnode1_offset_p = fdt_path_offset(fdt, "/subnode@1"); - subnode2_offset_p = fdt_path_offset(fdt, "/subnode@2"); - - if (subnode1_offset != subnode1_offset_p) - FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)", - subnode1_offset, subnode1_offset_p); - - if (subnode2_offset != subnode2_offset_p) - FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)", - subnode2_offset, subnode2_offset_p); + check_path_offset(fdt, "/subnode@1", subnode1_offset); + check_path_offset(fdt, "/subnode@2", subnode2_offset); subsubnode1_offset = check_subnode(fdt, subnode1_offset, "subsubnode"); subsubnode2_offset = check_subnode(fdt, subnode2_offset, "subsubnode@0"); subsubnode2_offset2 = check_subnode(fdt, subnode2_offset, "subsubnode"); - subsubnode1_offset_p = fdt_path_offset(fdt, "/subnode@1/subsubnode"); - subsubnode2_offset_p = fdt_path_offset(fdt, "/subnode@2/subsubnode@0"); - subsubnode2_offset2_p = fdt_path_offset(fdt, "/subnode@2/subsubnode"); - - if (subsubnode1_offset != subsubnode1_offset_p) - FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)", - subsubnode1_offset, subsubnode1_offset_p); - - if (subsubnode2_offset != subsubnode2_offset_p) - FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)", - subsubnode2_offset, subsubnode2_offset_p); - - if (subsubnode2_offset2 != subsubnode2_offset2_p) - FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)", - subsubnode2_offset2, subsubnode2_offset2_p); + check_path_offset(fdt, "/subnode@1/subsubnode", subsubnode1_offset); + check_path_offset(fdt, "/subnode@2/subsubnode@0", subsubnode2_offset); + check_path_offset(fdt, "/subnode@2/subsubnode", subsubnode2_offset2); PASS(); } From ecd4f9d125fa58898dd7c4811e854e3d52146d1f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 7 Apr 2015 14:25:39 +1000 Subject: [PATCH 0467/1198] Extend path_offset testcase for handling of duplicated separators Paths with multiple '/' characters in a row (e.g. //somenode//somsubnode), or trailing '/' characters (e.g. '/somenode/somesubnode/') should be handled by fdt_path_offset(), and treated as equivalent to /somenode/somesubnode. Our current path_offset testcase doesn't check for these cases, so extend it so it does. Signed-off-by: David Gibson --- tests/path_offset.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/path_offset.c b/tests/path_offset.c index 0ff710d..af53daf 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -58,6 +58,8 @@ static void check_path_offset(void *fdt, char *path, int offset) { int rc; + verbose_printf("Checking offset of \"%s\" is %d...\n", path, offset); + rc = fdt_path_offset(fdt, path); if (rc < 0) FAIL("fdt_path_offset(\"%s\") failed: %s", @@ -92,5 +94,13 @@ int main(int argc, char *argv[]) check_path_offset(fdt, "/subnode@2/subsubnode@0", subsubnode2_offset); check_path_offset(fdt, "/subnode@2/subsubnode", subsubnode2_offset2); + /* Test paths with extraneous separators */ + check_path_offset(fdt, "//", 0); + check_path_offset(fdt, "///", 0); + check_path_offset(fdt, "//subnode@1", subnode1_offset); + check_path_offset(fdt, "/subnode@1/", subnode1_offset); + check_path_offset(fdt, "//subnode@1///", subnode1_offset); + check_path_offset(fdt, "/subnode@2////subsubnode", subsubnode2_offset2); + PASS(); } From 9d3649bd3be245c93c9d92024ef4e618179dbad1 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 7 Apr 2015 14:41:42 +1000 Subject: [PATCH 0468/1198] Add testcases for fdt_path_offset_namelen() This extends the path_offset testcase to exercise the fdt_path_offset_namelen() function. Signed-off-by: David Gibson --- tests/path_offset.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/path_offset.c b/tests/path_offset.c index af53daf..bfebe9f 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -69,6 +69,26 @@ 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, + int offset) +{ + int rc; + + verbose_printf("Checking offset of \"%s\" [first %d characters]" + " is %d...\n", path, namelen, offset); + + rc = fdt_path_offset_namelen(fdt, path, namelen); + if (rc == offset) + return; + + if (rc < 0) + FAIL("fdt_path_offset_namelen(\"%s\", %d) failed: %s", + path, namelen, fdt_strerror(rc)); + else + FAIL("fdt_path_offset_namelen(\"%s\", %d) returned incorrect" + " offset %d instead of %d", path, namelen, rc, offset); +} + int main(int argc, char *argv[]) { void *fdt; @@ -102,5 +122,16 @@ int main(int argc, char *argv[]) check_path_offset(fdt, "//subnode@1///", subnode1_offset); check_path_offset(fdt, "/subnode@2////subsubnode", subsubnode2_offset2); + /* Test fdt_path_offset_namelen() */ + 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); + check_path_offset_namelen(fdt, "/subnode@2TRAILINGGARBAGE", 10, subnode2_offset); + check_path_offset_namelen(fdt, "/subnode@2TRAILINGGARBAGE", 11, -FDT_ERR_NOTFOUND); + check_path_offset_namelen(fdt, "/subnode@2/subsubnode@0/more", 23, subsubnode2_offset2); + check_path_offset_namelen(fdt, "/subnode@2/subsubnode@0/more", 22, -FDT_ERR_NOTFOUND); + check_path_offset_namelen(fdt, "/subnode@2/subsubnode@0/more", 24, subsubnode2_offset2); + check_path_offset_namelen(fdt, "/subnode@2/subsubnode@0/more", 25, -FDT_ERR_NOTFOUND); + PASS(); } From 64c46b098b969502a74c8b0fd97e6f5e4aa07e21 Mon Sep 17 00:00:00 2001 From: Jack Miller Date: Wed, 29 Apr 2015 14:02:24 -0500 Subject: [PATCH 0469/1198] Fix crash with poorly defined #size-cells If you have a parent block with #size-cells improperly set to 0, and then subsequently try to include a regs property in the child, dtc will crash with SIGFPE while validating it. This patch fixes that crash, instead printing the same invalid length warning that was causing it. Test included. Signed-off-by: Jack Miller Signed-off-by: David Gibson --- checks.c | 2 +- tests/bad-size-cells.dts | 12 ++++++++++++ tests/run_tests.sh | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 tests/bad-size-cells.dts diff --git a/checks.c b/checks.c index e81a8c7..0c03ac9 100644 --- a/checks.c +++ b/checks.c @@ -560,7 +560,7 @@ static void check_reg_format(struct check *c, struct node *dt, size_cells = node_size_cells(node->parent); entrylen = (addr_cells + size_cells) * sizeof(cell_t); - if ((prop->val.len % entrylen) != 0) + if (!entrylen || (prop->val.len % entrylen) != 0) FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) " "(#address-cells == %d, #size-cells == %d)", node->fullpath, prop->val.len, addr_cells, size_cells); diff --git a/tests/bad-size-cells.dts b/tests/bad-size-cells.dts new file mode 100644 index 0000000..515c0cc --- /dev/null +++ b/tests/bad-size-cells.dts @@ -0,0 +1,12 @@ +/dts-v1/; + +/ { + mangled { + #address-cells = <0x0>; + #size-cells = <0x0>; + + valid { + reg = <0x0 0x4000000>; + }; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 5331856..c870432 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -279,6 +279,8 @@ libfdt_tests () { run_dtc_test -I dts -O dtb -o embedded_nul.test.dtb embedded_nul.dts run_dtc_test -I dts -O dtb -o embedded_nul_equiv.test.dtb embedded_nul_equiv.dts run_test dtbs_equal_ordered embedded_nul.test.dtb embedded_nul_equiv.test.dtb + + run_dtc_test -I dts -O dtb bad-size-cells.dts } dtc_tests () { From 8b927bf3b80de4b0a49e6b6e4a56293e9baec364 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 24 May 2015 21:57:32 -0400 Subject: [PATCH 0470/1198] tests: convert `echo -n` to `printf` The -n option is not standard in POSIX, so convert to printf which should work the same in every shell. Signed-off-by: Mike Frysinger --- tests/run_tests.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c870432..dc214fd 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -42,20 +42,20 @@ base_run_test() { shorten_echo () { limit=32 - echo -n "$1" + printf "$1" shift for x; do if [ ${#x} -le $limit ]; then - echo -n " $x" + printf " $x" else short=$(echo "$x" | head -c$limit) - echo -n " \"$short\"...<${#x} bytes>" + printf " \"$short\"...<${#x} bytes>" fi done } run_test () { - echo -n "$@: " + printf "$*: " if [ -n "$VALGRIND" -a -f $1.supp ]; then VGSUPP="--suppressions=$1.supp" fi @@ -63,7 +63,7 @@ run_test () { } run_sh_test () { - echo -n "$@: " + printf "$*: " base_run_test sh "$@" } @@ -106,12 +106,12 @@ wrap_error () { run_wrap_error_test () { shorten_echo "$@" - echo -n " {!= 0}: " + printf " {!= 0}: " base_run_test wrap_error "$@" } run_dtc_test () { - echo -n "dtc $@: " + printf "dtc $*: " base_run_test wrap_test $VALGRIND $DTC "$@" } @@ -126,7 +126,7 @@ asm_to_so_test () { run_fdtget_test () { expect="$1" shift - echo -n "fdtget-runtest.sh "$expect" $@: " + printf "fdtget-runtest.sh %s $*: " "$(echo $expect)" base_run_test sh fdtget-runtest.sh "$expect" "$@" } @@ -134,14 +134,14 @@ run_fdtput_test () { expect="$1" shift shorten_echo fdtput-runtest.sh "$expect" "$@" - echo -n ": " + printf ": " base_run_test sh fdtput-runtest.sh "$expect" "$@" } run_fdtdump_test() { file="$1" shorten_echo fdtdump-runtest.sh "$file" - echo -n ": " + printf ": " base_run_test sh fdtdump-runtest.sh "$file" } From 5e78dff4248da3f4efe3a399d66b091b97940ddf Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 1 Jul 2015 00:31:27 +0100 Subject: [PATCH 0471/1198] guess input file format based on file content or file name Always needing to specify the input file format can be quite annoying, especially since a dtb is easily detected by its magic. Looking at the file name extension sounds useful as a hint, too. Add heuristic file type guessing of the input file format in case none has been specified on the command line. The heuristics are as follows (in that order): - Any issues with opening the file drop back to the current default behaviour. - A directory will be treated as the /proc/device-tree type. - If the first 4 bytes are the DTB magic, assume "dtb". - If no other test succeeded so far, use a file name based guessing method: if the filename ends with .dts or .DTS, device tree source text is assumed, .dtb or .DTB hint at a device tree blob. For the majority of practical use cases this gets rid of the tedious -I specification on the command line and simplifies actual typing of dtc command lines. Any explicit specification of the input type by using -I still avoids any guessing, which resembles the current behaviour. Signed-off-by: Andre Przywara Signed-off-by: David Gibson --- dtc.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/dtc.c b/dtc.c index 8c4add6..53793bf 100644 --- a/dtc.c +++ b/dtc.c @@ -18,6 +18,8 @@ * USA */ +#include + #include "dtc.h" #include "srcpos.h" @@ -104,10 +106,55 @@ static const char * const usage_opts_help[] = { NULL, }; +static const char *guess_type_by_name(const char *fname, const char *fallback) +{ + const char *s; + + s = strrchr(fname, '.'); + if (s == NULL) + return fallback; + if (!strcasecmp(s, ".dts")) + return "dts"; + if (!strcasecmp(s, ".dtb")) + return "dtb"; + return fallback; +} + +static const char *guess_input_format(const char *fname, const char *fallback) +{ + struct stat statbuf; + uint32_t magic; + FILE *f; + + if (stat(fname, &statbuf) != 0) + return fallback; + + if (S_ISDIR(statbuf.st_mode)) + return "fs"; + + if (!S_ISREG(statbuf.st_mode)) + return fallback; + + f = fopen(fname, "r"); + if (f == NULL) + return fallback; + if (fread(&magic, 4, 1, f) != 1) { + fclose(f); + return fallback; + } + fclose(f); + + magic = fdt32_to_cpu(magic); + if (magic == FDT_MAGIC) + return "dtb"; + + return guess_type_by_name(fname, fallback); +} + int main(int argc, char *argv[]) { struct boot_info *bi; - const char *inform = "dts"; + const char *inform = NULL; const char *outform = "dts"; const char *outname = "-"; const char *depname = NULL; @@ -213,6 +260,8 @@ int main(int argc, char *argv[]) fprintf(depfile, "%s:", outname); } + if (inform == NULL) + inform = guess_input_format(arg, "dts"); if (streq(inform, "dts")) bi = dt_from_source(arg); else if (streq(inform, "fs")) From f6dbc6ca9618391e4f30c415a0a09b7af35f7647 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 1 Jul 2015 00:31:28 +0100 Subject: [PATCH 0472/1198] guess output file format If no output file type is specified via the -O parameter, guess the desired file type by looking at the file name extension. If that provides no useful hints, assume "dtb" as long as the input type is "dts". Any other input type will lead to "dts" being used as the guessed output type. Any explicit specification of the output type will skip this guessing. Signed-off-by: Andre Przywara Signed-off-by: David Gibson --- dtc.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dtc.c b/dtc.c index 53793bf..5fa23c4 100644 --- a/dtc.c +++ b/dtc.c @@ -155,7 +155,7 @@ int main(int argc, char *argv[]) { struct boot_info *bi; const char *inform = NULL; - const char *outform = "dts"; + const char *outform = NULL; const char *outname = "-"; const char *depname = NULL; bool force = false, sort = false; @@ -262,6 +262,15 @@ int main(int argc, char *argv[]) if (inform == NULL) inform = guess_input_format(arg, "dts"); + if (outform == NULL) { + outform = guess_type_by_name(outname, NULL); + if (outform == NULL) { + if (streq(inform, "dts")) + outform = "dtb"; + else + outform = "dts"; + } + } if (streq(inform, "dts")) bi = dt_from_source(arg); else if (streq(inform, "fs")) From 2d1417cd9e4d9cb6f8446a3927e612787a56b04a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 2 Jul 2015 12:36:12 +1000 Subject: [PATCH 0473/1198] Add simple .travis.yml This adds the .travis.yml file allowing for dtc building and testing in the Travis Continuous Integration system. Signed-off-by: David Gibson --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f2336d8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: c + +script: + - make + - make check From 897a429199da12eb8b071a497ffd02538ada26b5 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 9 Jul 2015 13:29:42 +1000 Subject: [PATCH 0474/1198] Move fdt_path_offset alias tests to right tests section The test script includes several specific tests for the handling of aliases in fdt_path_offset(). These are primarily tests of the fdt_path_offset() libfdt function itself, although dtc is used to generate a test file for convenience. Move these from the dtc tests section to the libfdt tests section accordingly. Signed-off-by: David Gibson --- tests/run_tests.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index dc214fd..49f6fd8 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -269,6 +269,11 @@ libfdt_tests () { # Tests for behaviour on various sorts of corrupted trees run_test truncated_property + # Check aliases support in fdt_path_offset + run_dtc_test -I dts -O dtb -o aliases.dtb aliases.dts + run_test get_alias aliases.dtb + run_test path_offset_aliases aliases.dtb + # Specific bug tests run_test add_subnode_with_nops run_dtc_test -I dts -O dts -o sourceoutput.test.dts sourceoutput.dts @@ -327,11 +332,6 @@ dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb - # Check aliases support in fdt_path_offset - run_dtc_test -I dts -O dtb -o aliases.dtb aliases.dts - run_test get_alias aliases.dtb - run_test path_offset_aliases aliases.dtb - # Check /include/ directive run_dtc_test -I dts -O dtb -o includes.test.dtb include0.dts run_test dtbs_equal_ordered includes.test.dtb test_tree1.dtb From 067829ea5fa9a6d22d4d09fa38ffbef16d21de78 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 9 Jul 2015 13:41:21 +1000 Subject: [PATCH 0475/1198] Remove redundant fdtdump test code The overall test runner script, for the fdtdump tests invokes the helper script fdtdump-runtest.sh. It then includes directly some code very similar to fdtdump-runtest.sh, which is never reached due to a "return". Remove the never-reached test code. Signed-off-by: David Gibson --- tests/run_tests.sh | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 49f6fd8..5268293 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -645,21 +645,6 @@ utilfdt_tests () { fdtdump_tests () { run_fdtdump_test fdtdump.dts - return - - local dts=fdtdump.dts - local dtb=fdtdump.dts.dtb - local out=fdtdump.dts.out - run_dtc_test -O dtb $dts -o ${dtb} - $FDTDUMP ${dtb} | grep -v "//" >${out} - if cmp $dts $out >/dev/null; then - PASS - else - if [ -z "$QUIET_TEST" ]; then - diff -w fdtdump.dts $out - fi - FAIL "Results differ from expected" - fi } while getopts "vt:me" ARG ; do From e5e6df7c37f7de13af33a3096e9c66127bb75d15 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 9 Jul 2015 13:47:19 +1000 Subject: [PATCH 0476/1198] fdtdump: Fix bug printing bytestrings with negative values On systems where 'char' is signed, fdtdump will currently print the wrong thing on properties containing bytestring values with "negative" bytes (that is with values from 0x80..0xff). The fdtdump testcase is extended to cover this case too. This corrects the problem by forcing use of unsigned char - although this is perhaps another indication that fdtdump is a buggy hack and if you want to do real work you should use dtc -O dts. Reported-by: Igor Prusov Signed-off-by: David Gibson --- tests/fdtdump.dts | 1 + util.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/fdtdump.dts b/tests/fdtdump.dts index b9d917b..b83b7df 100644 --- a/tests/fdtdump.dts +++ b/tests/fdtdump.dts @@ -23,6 +23,7 @@ randomnode { string = "foo", "stuff"; bytes = [61 62 63 64 65]; + nbytes = [80 ff]; child { }; }; diff --git a/util.c b/util.c index 9d65226..cbb945b 100644 --- a/util.c +++ b/util.c @@ -349,7 +349,6 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size) void utilfdt_print_data(const char *data, int len) { int i; - const char *p = data; const char *s; /* no data, don't print */ @@ -376,6 +375,7 @@ void utilfdt_print_data(const char *data, int len) i < (len - 1) ? " " : ""); printf(">"); } else { + const unsigned char *p = (const unsigned char *)data; printf(" = ["); for (i = 0; i < len; i++) printf("%02x%s", *p++, i < len - 1 ? " " : ""); From 554fde2c77bd73de3f5093df3b643ce1553e1f96 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 27 Aug 2015 12:12:42 +0900 Subject: [PATCH 0477/1198] libfdt: fix comment block of fdt_get_property_namelen() The statement "Identical to fdt_get_property_namelen() ..." does not make sense for the comment of fdt_get_property_namelen() itself. Signed-off-by: Masahiro Yamada Signed-off-by: David Gibson --- libfdt/libfdt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 1054512..1bd0242 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -457,8 +457,8 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, * @namelen: number of characters of name to consider * @lenp: pointer to an integer variable (will be overwritten) or NULL * - * Identical to fdt_get_property_namelen(), but only examine the first - * namelen characters of name for matching the property name. + * Identical to fdt_get_property(), but only examine the first namelen + * characters of name for matching the property name. */ const struct fdt_property *fdt_get_property_namelen(const void *fdt, int nodeoffset, From 2218387a8cb9270a688775350a07b02db6d03103 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 30 Sep 2015 13:16:12 +1000 Subject: [PATCH 0478/1198] fdt: Add a function to count strings Given a device tree node and a property name, the fdt_stringlist_count() function counts the number of strings found in the property value. This also adds a new error code, FDT_ERR_BADVALUE, that the function returns when it encounters a non-NUL-terminated string list. Signed-off-by: Thierry Reding [Changed testcase name --dwg] Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 25 ++++++++++++++ libfdt/libfdt.h | 19 +++++++++- tests/.gitignore | 1 + tests/Makefile.tests | 1 + tests/run_tests.sh | 3 ++ tests/stringlist.c | 82 ++++++++++++++++++++++++++++++++++++++++++++ tests/stringlist.dts | 12 +++++++ 7 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 tests/stringlist.c create mode 100644 tests/stringlist.dts diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index a65e4b5..4cde931 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -538,6 +538,31 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) return 0; } +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) +{ + const char *list, *end; + int length, count = 0; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return -length; + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + list += length; + count++; + } + + return count; +} + int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible) { diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 1bd0242..2863001 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -121,7 +121,12 @@ /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells * or similar property with a bad format or value */ -#define FDT_ERR_MAX 14 +#define FDT_ERR_BADVALUE 15 + /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected + * value. For example: a property expected to contain a string list + * is not NUL-terminated within the length of its value. */ + +#define FDT_ERR_MAX 15 /**********************************************************************/ /* Low-level functions (you probably don't need these) */ @@ -868,6 +873,18 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, */ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); +/** + * fdt_stringlist_count - count the number of strings in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @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 + */ +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); + /**********************************************************************/ /* Read-only functions (addressing related) */ /**********************************************************************/ diff --git a/tests/.gitignore b/tests/.gitignore index 5656555..e4532da 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -49,6 +49,7 @@ tmp.* /setprop_inplace /sized_cells /string_escapes +/stringlist /subnode_iterate /subnode_offset /supernode_atdepth_offset diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 9adedec..f7c3a4b 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -9,6 +9,7 @@ LIB_TESTS_L = get_mem_rsv \ sized_cells \ notfound \ addr_size_cells \ + stringlist \ setprop_inplace nop_property nop_node \ sw_tree1 \ move_and_save mangle-layout nopulate \ diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 5268293..1063d1e 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -198,6 +198,9 @@ libfdt_tests () { run_dtc_test -I dts -O dtb -o addresses.test.dtb addresses.dts run_test addr_size_cells addresses.test.dtb + run_dtc_test -I dts -O dtb -o stringlist.test.dtb stringlist.dts + run_test stringlist stringlist.test.dtb + # Sequential write tests run_test sw_tree1 tree1_tests sw_tree1.test.dtb diff --git a/tests/stringlist.c b/tests/stringlist.c new file mode 100644 index 0000000..923e2ed --- /dev/null +++ b/tests/stringlist.c @@ -0,0 +1,82 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for string handling + * Copyright (C) 2015 NVIDIA Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +static void check_expected_failure(const void *fdt, const char *path, + const char *property) +{ + int offset, err; + + offset = fdt_path_offset(fdt, "/"); + if (offset < 0) + FAIL("Couldn't find path %s", path); + + err = fdt_stringlist_count(fdt, offset, "#address-cells"); + if (err != -FDT_ERR_BADVALUE) + FAIL("unexpectedly succeeded in parsing #address-cells\n"); +} + +static void check_string_count(const void *fdt, const char *path, + const char *property, int count) +{ + int offset, err; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("Couldn't find path %s", path); + + err = fdt_stringlist_count(fdt, offset, property); + if (err < 0) + FAIL("Couldn't count strings in property %s of node %s: %d\n", + property, path, err); + + if (err != count) + FAIL("String count for property %s of node %s is %d instead of %d\n", + path, property, err, count); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + if (argc != 2) + CONFIG("Usage: %s \n", argv[0]); + + test_init(argc, argv); + fdt = load_blob(argv[1]); + + check_expected_failure(fdt, "/", "#address-cells"); + check_expected_failure(fdt, "/", "#size-cells"); + + check_string_count(fdt, "/", "compatible", 1); + check_string_count(fdt, "/device", "compatible", 2); + check_string_count(fdt, "/device", "big-endian", 0); + + PASS(); +} diff --git a/tests/stringlist.dts b/tests/stringlist.dts new file mode 100644 index 0000000..1e4d314 --- /dev/null +++ b/tests/stringlist.dts @@ -0,0 +1,12 @@ +/dts-v1/; + +/ { + compatible = "test-strings"; + #address-cells = <2>; + #size-cells = <2>; + + device { + compatible = "foo", "bar"; + big-endian; + }; +}; From 8702bd1d3b430c16aaa37056cb24b6d984da48f7 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 29 Sep 2015 11:09:07 +0200 Subject: [PATCH 0479/1198] fdt: Add a function to get the index of a string The new fdt_stringlist_search() function will look up a given string in the list contained in the value of a named property of a given device tree node and return its index. Signed-off-by: Thierry Reding [Fix some -Wshadow warnings --dwg] Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 30 ++++++++++++++++++++++++++++++ libfdt/libfdt.h | 22 ++++++++++++++++++++++ tests/stringlist.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 4cde931..2d74c37 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -563,6 +563,36 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) return count; } +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string) +{ + int length, len, idx = 0; + const char *list, *end; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return -length; + + len = strlen(string) + 1; + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + if (length == len && memcmp(list, string, length) == 0) + return idx; + + list += length; + idx++; + } + + return -FDT_ERR_NOTFOUND; +} + int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible) { diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 2863001..aa376b8 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -885,6 +885,28 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); */ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); +/** + * fdt_stringlist_search - find a string in a string list and return its index + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @string: string to look up in the string list + * + * Note that it is possible for this function to succeed on property values + * that are not NUL-terminated. That's because the function will stop after + * finding the first occurrence of @string. This can for example happen with + * small-valued cell properties, such as #address-cells, when searching for + * the empty string. + * + * @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 + * the given string + */ +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string); + /**********************************************************************/ /* Read-only functions (addressing related) */ /**********************************************************************/ diff --git a/tests/stringlist.c b/tests/stringlist.c index 923e2ed..b8835b7 100644 --- a/tests/stringlist.c +++ b/tests/stringlist.c @@ -40,6 +40,24 @@ static void check_expected_failure(const void *fdt, const char *path, err = fdt_stringlist_count(fdt, offset, "#address-cells"); if (err != -FDT_ERR_BADVALUE) FAIL("unexpectedly succeeded in parsing #address-cells\n"); + + err = fdt_stringlist_search(fdt, offset, "#address-cells", "foo"); + if (err != -FDT_ERR_BADVALUE) + FAIL("found string in #address-cells: %d\n", err); + + /* + * Note that the #address-cells property contains a small 32-bit + * unsigned integer, hence some bytes will be zero, and searching for + * the empty string will succeed. + * + * The reason for this oddity is that the function will exit when the + * first occurrence of the string is found, but in order to determine + * that the property does not contain a valid string list it would + * need to process the whole value. + */ + err = fdt_stringlist_search(fdt, offset, "#address-cells", ""); + if (err != 0) + FAIL("empty string not found in #address-cells: %d\n", err); } static void check_string_count(const void *fdt, const char *path, @@ -61,6 +79,23 @@ static void check_string_count(const void *fdt, const char *path, path, property, err, count); } +static void check_string_index(const void *fdt, const char *path, + const char *property, const char *string, + int idx) +{ + int offset, err; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("Couldn't find path %s", path); + + err = fdt_stringlist_search(fdt, offset, property, string); + + if (err != idx) + FAIL("Index of %s in property %s of node %s is %d, expected %d\n", + string, property, path, err, idx); +} + int main(int argc, char *argv[]) { void *fdt; @@ -78,5 +113,10 @@ int main(int argc, char *argv[]) check_string_count(fdt, "/device", "compatible", 2); check_string_count(fdt, "/device", "big-endian", 0); + check_string_index(fdt, "/", "compatible", "test-strings", 0); + check_string_index(fdt, "/device", "compatible", "foo", 0); + check_string_index(fdt, "/device", "compatible", "bar", 1); + check_string_index(fdt, "/device", "big-endian", "baz", -1); + PASS(); } From 604e61e081e3c6c8fa1a8189c71cb3908a5bbc1e Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 29 Sep 2015 11:09:08 +0200 Subject: [PATCH 0480/1198] fdt: Add functions to retrieve strings Given a device tree node, a property name and an index, the new function fdt_stringlist_get() will return a pointer to the index'th string in the property's value and return its length (or an error code on failure) in an output argument. Signed-off-by: Thierry Reding [Fix some -Wshadow warnings --dwg] Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ libfdt/libfdt.h | 28 ++++++++++++++++++++++++++++ tests/stringlist.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 2d74c37..e5b3136 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -593,6 +593,51 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, return -FDT_ERR_NOTFOUND; } +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int idx, + int *lenp) +{ + const char *list, *end; + int length; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) { + if (lenp) + *lenp = length; + + return NULL; + } + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) { + if (lenp) + *lenp = -FDT_ERR_BADVALUE; + + return NULL; + } + + if (idx == 0) { + if (lenp) + *lenp = length - 1; + + return list; + } + + list += length; + idx--; + } + + if (lenp) + *lenp = -FDT_ERR_NOTFOUND; + + return NULL; +} + int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible) { diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index aa376b8..78adb12 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -907,6 +907,34 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, const char *string); +/** + * fdt_stringlist_get() - obtain the string at a given index in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @index: index of the string to return + * @lenp: return location for the string length or an error code on failure + * + * Note that this will successfully extract strings from properties with + * non-NUL-terminated values. For example on small-valued cell properties + * this function will return the empty string. + * + * 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: + * 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 + * the following negative error codes will be returned in the lenp parameter + * (if non-NULL): + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist + */ +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int index, + int *lenp); + /**********************************************************************/ /* Read-only functions (addressing related) */ /**********************************************************************/ diff --git a/tests/stringlist.c b/tests/stringlist.c index b8835b7..a9d3e73 100644 --- a/tests/stringlist.c +++ b/tests/stringlist.c @@ -58,6 +58,13 @@ static void check_expected_failure(const void *fdt, const char *path, err = fdt_stringlist_search(fdt, offset, "#address-cells", ""); if (err != 0) FAIL("empty string not found in #address-cells: %d\n", err); + + /* + * fdt_get_string() can successfully extract strings from non-string + * properties. This is because it doesn't necessarily parse the whole + * property value, which would be necessary for it to determine if a + * valid string or string list is present. + */ } static void check_string_count(const void *fdt, const char *path, @@ -96,6 +103,27 @@ static void check_string_index(const void *fdt, const char *path, string, property, path, err, idx); } +static void check_string(const void *fdt, const char *path, + const char *property, int idx, + const char *string) +{ + const char *result; + int offset, len; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("Couldn't find path %s", path); + + result = fdt_stringlist_get(fdt, offset, property, idx, &len); + if (!result) + FAIL("Couldn't extract string %d from property %s of node %s: %d\n", + idx, property, path, len); + + if (strcmp(string, result) != 0) + FAIL("String %d in property %s of node %s is %s, expected %s\n", + idx, property, path, result, string); +} + int main(int argc, char *argv[]) { void *fdt; @@ -118,5 +146,9 @@ int main(int argc, char *argv[]) check_string_index(fdt, "/device", "compatible", "bar", 1); check_string_index(fdt, "/device", "big-endian", "baz", -1); + check_string(fdt, "/", "compatible", 0, "test-strings"); + check_string(fdt, "/device", "compatible", 0, "foo"); + check_string(fdt, "/device", "compatible", 1, "bar"); + PASS(); } From af9f26d1e5f05f524675bb3e9cbb7e36142b6615 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 16 Nov 2015 23:45:36 +1100 Subject: [PATCH 0481/1198] Remove duplicated -Werror in dtc Makefile The "-Werror" compiler flag is currently declared twice in the Makefile, one time in WARNINGS, and one time in CFLAGS. Let's remove one of them. Signed-off-by: Thomas Huth [Moved remaining -Werror from WARNINGS to CFLAGS --dwg] Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c1d0757..078ecf6 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ LOCAL_VERSION = CONFIG_LOCALVERSION = CPPFLAGS = -I libfdt -I . -WARNINGS = -Werror -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \ +WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \ -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow CFLAGS = -g -Os -fPIC -Werror $(WARNINGS) From f58799be130e27cc729cb2d45566daa0bb3b8605 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 1 Dec 2015 12:55:21 +1100 Subject: [PATCH 0482/1198] libfdt: Add some missing symbols to version.lds Several functions in the header file were missing from the version.lds script, meaning that they couldn't be used from a libfdt shared library. Reported by Ken Aaker, via github issue tracker. Signed-off-by: David Gibson --- libfdt/version.lds | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libfdt/version.lds b/libfdt/version.lds index f19f157..1f4e1ea 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -57,6 +57,10 @@ LIBFDT_1.2 { fdt_next_property_offset; fdt_first_subnode; fdt_next_subnode; + fdt_address_cells; + fdt_size_cells; + fdt_stringlist_contains; + fdt_resize; local: *; From d4c7c25c9ed138df8bafbe61097c27c9d2629ee3 Mon Sep 17 00:00:00 2001 From: Courtney Cavin Date: Tue, 1 Dec 2015 16:43:10 -0800 Subject: [PATCH 0483/1198] libfdt: check for potential overrun in _fdt_splice() This patch catches the conditions where: - 'splicepoint' is set to a point outside of [ fdt, fdt_totalsize(fdt) ) - 'newlen' is negative, or 'splicepoint' plus 'newlen' results in overflow Either of these cases can be caused by math which overflows in calling functions, or by sizes specified through dynamic means. Signed-off-by: Courtney Cavin Signed-off-by: Bjorn Andersson --- libfdt/fdt_rw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 70adec6..8be02b1 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -101,6 +101,8 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) if (((p + oldlen) < p) || ((p + oldlen) > end)) return -FDT_ERR_BADOFFSET; + if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) + return -FDT_ERR_BADOFFSET; if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) return -FDT_ERR_NOSPACE; memmove(p + newlen, p + oldlen, end - p - oldlen); From d0b3ab0a0f46ac929b4713da46f7fdcd893dd3bd Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 17 Dec 2015 17:19:11 +1100 Subject: [PATCH 0484/1198] libfdt: Fix undefined behaviour in fdt_offset_ptr() Using pointer arithmetic to generate a pointer outside a known object is, technically, undefined behaviour in C. Unfortunately, we were using that in fdt_offset_ptr() to detect overflows. To fix this we need to do our bounds / overflow checking on the offsets before constructing pointers from them. Reported-by: David Binderman Signed-off-by: David Gibson --- libfdt/fdt.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 2ce6a44..22286a1 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt) const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { - const char *p; + unsigned absoffset = offset + fdt_off_dt_struct(fdt); + + if ((absoffset < offset) + || ((absoffset + len) < absoffset) + || (absoffset + len) > fdt_totalsize(fdt)) + return NULL; if (fdt_version(fdt) >= 0x11) if (((offset + len) < offset) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; - p = _fdt_offset_ptr(fdt, offset); - - if (p + len < p) - return NULL; - return p; + return _fdt_offset_ptr(fdt, offset); } uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) From 19370955884ff0c49328956227c302225f4a014b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 3 Jan 2016 22:27:32 +1100 Subject: [PATCH 0485/1198] Prevent crash on division by zero Currently, attempting to divide by zero in an integer expression in a dts file will cause dtc to crash with a division by zero (SIGFPE). This patch corrects this to properly detect this case and raise an error. Reported-by: Anton Blanchard Signed-off-by: David Gibson --- dtc-parser.y | 10 +++++++++- tests/division-by-zero.dts | 5 +++++ tests/run_tests.sh | 2 ++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/division-by-zero.dts diff --git a/dtc-parser.y b/dtc-parser.y index 5a897e3..00d4dbb 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -410,7 +410,15 @@ integer_add: integer_mul: integer_mul '*' integer_unary { $$ = $1 * $3; } - | integer_mul '/' integer_unary { $$ = $1 / $3; } + | integer_mul '/' integer_unary + { + if ($3 != 0) { + $$ = $1 / $3; + } else { + ERROR(&@$, "Division by zero"); + $$ = 0; + } + } | integer_mul '%' integer_unary { $$ = $1 % $3; } | integer_unary ; diff --git a/tests/division-by-zero.dts b/tests/division-by-zero.dts new file mode 100644 index 0000000..d26fc27 --- /dev/null +++ b/tests/division-by-zero.dts @@ -0,0 +1,5 @@ +/dts-v1/; + +/ { + prop = < (1/0) >; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 1063d1e..3d6a230 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -289,6 +289,8 @@ libfdt_tests () { run_test dtbs_equal_ordered embedded_nul.test.dtb embedded_nul_equiv.test.dtb run_dtc_test -I dts -O dtb bad-size-cells.dts + + run_wrap_error_test $DTC division-by-zero.dts } dtc_tests () { From 1ab2205a6f0f9e826a623e639da02787d372de37 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 3 Jan 2016 22:54:37 +1100 Subject: [PATCH 0486/1198] Gracefully handle bad octal literals The code handling integer literals in dtc-lexer.l assumes that the flex regexp means that strtoull() can't fail to interpret the string as a valid integer (either decimal, octal, or hexadecimal). This is not true for octals. For example '09' is accepted as a literal by the regexp, strtoull() attempts to handle it as octal, but it has a bad digit. This changes the code to give a more useful error in this case. Reported-by: Anton Blanchard Signed-off-by: David Gibson --- dtc-lexer.l | 5 ++++- tests/bad-octal-literal.dts | 5 +++++ tests/run_tests.sh | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tests/bad-octal-literal.dts diff --git a/dtc-lexer.l b/dtc-lexer.l index 0ee1caf..22dda7d 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -153,7 +153,10 @@ static void lexical_error(const char *fmt, ...); errno = 0; yylval.integer = strtoull(yytext, &e, 0); - assert(!(*e) || !e[strspn(e, "UL")]); + if (*e && e[strspn(e, "UL")]) { + lexical_error("Bad integer literal '%s'", + yytext); + } if (errno == ERANGE) lexical_error("Integer literal '%s' out of range", diff --git a/tests/bad-octal-literal.dts b/tests/bad-octal-literal.dts new file mode 100644 index 0000000..26558a2 --- /dev/null +++ b/tests/bad-octal-literal.dts @@ -0,0 +1,5 @@ +/dts-v1/; + +/ { + x = <09>; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 3d6a230..7bdf8e0 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -291,6 +291,7 @@ libfdt_tests () { run_dtc_test -I dts -O dtb bad-size-cells.dts run_wrap_error_test $DTC division-by-zero.dts + run_wrap_error_test $DTC bad-octal-literal.dts } dtc_tests () { From d728ad59f53e72be21fe9bc419953c94aea798cc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 3 Jan 2016 23:01:24 +1100 Subject: [PATCH 0487/1198] Fix crash on nul character in string escape sequence If a dts file contains a string with \ followed by a nul byte - an actual nul in the input file, not the \\0 escape - then the assert() in get_escape_char() will trip, crashing dtc. As far as I can tell, there isn't any valid need for this assert(), so just remove it. Reported-by: Anton Blanchard Signed-off-by: David Gibson --- tests/nul-in-escape.dts | Bin 0 -> 36 bytes tests/run_tests.sh | 1 + util.c | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 tests/nul-in-escape.dts diff --git a/tests/nul-in-escape.dts b/tests/nul-in-escape.dts new file mode 100644 index 0000000000000000000000000000000000000000..9bed351cf021b252cd5e72fe6ade6c14b697c0e7 GIT binary patch literal 36 lcmdN-DJj-1Gt{@{;?h^B=2C!y3I$sQr5FY!Ypz;rE&!6l2R#4) literal 0 HcmV?d00001 diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 7bdf8e0..b40ba9c 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -292,6 +292,7 @@ libfdt_tests () { run_wrap_error_test $DTC division-by-zero.dts run_wrap_error_test $DTC bad-octal-literal.dts + run_dtc_test -I dts -O dtb nul-in-escape.dts } dtc_tests () { diff --git a/util.c b/util.c index cbb945b..fb124ee 100644 --- a/util.c +++ b/util.c @@ -152,7 +152,6 @@ char get_escape_char(const char *s, int *i) int j = *i + 1; char val; - assert(c); switch (c) { case 'a': val = '\a'; From b43345039b03ac5691961e1ce37dfb8c4c03a863 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 4 Jan 2016 22:56:39 +1100 Subject: [PATCH 0488/1198] Fix some bugs in processing of line directives In order to work with preprocessed dts files more easily, dts will parse line number information in the form emitted by cpp. Anton Blanchard (using a fuzzer) reported that including a line number directive with a nul character (a literal nul in the input file, not a \0 sequence) would cause dtc to SEGV. I spotted several more problems on examining the code: * It modified yytext in place which seems to work, but is ugly and I'm not sure if it's safe on all lex/flex versions * The regexp used in the lexer to recognize line number information accepts strings with escape characters, but it won't process these escapes. - GNU cpp at least, will generate \ escapes in line number information, at least with files containing " or \ in the name This patch reworks the handling of line number information to address these problems. \ escapes should now be handled directly. nuls in file names (either with a literal nul in the input file, or with a \0 escape sequence) are still not permitted, but will now result in a lexical error rather than a SEGV. Reported-by: Anton Blanchard Signed-off-by: David Gibson --- dtc-lexer.l | 34 +++++++++++++++++++++------------- tests/line_directives.dts | 5 +++++ tests/nul-in-line-info1.dts | Bin 0 -> 8 bytes tests/nul-in-line-info2.dts | 1 + tests/run_tests.sh | 2 ++ 5 files changed, 29 insertions(+), 13 deletions(-) create mode 100644 tests/nul-in-line-info1.dts create mode 100644 tests/nul-in-line-info2.dts diff --git a/dtc-lexer.l b/dtc-lexer.l index 22dda7d..790fbf6 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -73,24 +73,32 @@ static void lexical_error(const char *fmt, ...); } <*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? { - char *line, *tmp, *fn; + char *line, *fnstart, *fnend; + struct data fn; /* skip text before line # */ line = yytext; while (!isdigit((unsigned char)*line)) line++; - /* skip digits in line # */ - tmp = line; - while (!isspace((unsigned char)*tmp)) - tmp++; - /* "NULL"-terminate line # */ - *tmp = '\0'; - /* start of filename */ - fn = strchr(tmp + 1, '"') + 1; - /* strip trailing " from filename */ - tmp = strchr(fn, '"'); - *tmp = 0; + + /* regexp ensures that first and list " + * in the whole yytext are those at + * beginning and end of the filename string */ + fnstart = memchr(yytext, '"', yyleng); + for (fnend = yytext + yyleng - 1; + *fnend != '"'; fnend--) + ; + assert(fnstart && fnend && (fnend > fnstart)); + + fn = data_copy_escape_string(fnstart + 1, + fnend - fnstart - 1); + + /* Don't allow nuls in filenames */ + if (memchr(fn.val, '\0', fn.len - 1)) + lexical_error("nul in line number directive"); + /* -1 since #line is the number of the next line */ - srcpos_set_line(xstrdup(fn), atoi(line) - 1); + srcpos_set_line(xstrdup(fn.val), atoi(line) - 1); + data_free(fn); } <*><> { diff --git a/tests/line_directives.dts b/tests/line_directives.dts index 046ef37..67b5e08 100644 --- a/tests/line_directives.dts +++ b/tests/line_directives.dts @@ -18,4 +18,9 @@ # 10 "qux.dts" 0x12345678 >; +/* + * Check processing of escapes in filenames + */ +# 100 "\".dts" +# 200 "\\.dts" }; diff --git a/tests/nul-in-line-info1.dts b/tests/nul-in-line-info1.dts new file mode 100644 index 0000000000000000000000000000000000000000..ceb7261b7ef61529b9809e5a934770dd4ef2be19 GIT binary patch literal 8 PcmY#ZFi=opP~rjr1eO5e literal 0 HcmV?d00001 diff --git a/tests/nul-in-line-info2.dts b/tests/nul-in-line-info2.dts new file mode 100644 index 0000000..1157d23 --- /dev/null +++ b/tests/nul-in-line-info2.dts @@ -0,0 +1 @@ +# 0 "\0" diff --git a/tests/run_tests.sh b/tests/run_tests.sh index b40ba9c..8863c9a 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -293,6 +293,8 @@ libfdt_tests () { run_wrap_error_test $DTC division-by-zero.dts run_wrap_error_test $DTC bad-octal-literal.dts run_dtc_test -I dts -O dtb nul-in-escape.dts + run_wrap_error_test $DTC nul-in-line-info1.dts + run_wrap_error_test $DTC nul-in-line-info2.dts } dtc_tests () { From b06e55c88b9b922ff7e25cd62a4709b65524f0fc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 12 Jan 2016 19:27:25 +1100 Subject: [PATCH 0489/1198] Prevent crash on modulo by zero 1937095 "Prevent crash on division by zero" fixed a crash when attempting a division by zero using the / operator in a dts. However, it missed the precisely equivalent crash with the % (modulus) operator. This patch fixes the oversight. Reported-by: Anton Blanchard Signed-off-by: David Gibson --- dtc-parser.y | 10 +++++++++- tests/division-by-zero.dts | 3 ++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 00d4dbb..000873f 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -419,7 +419,15 @@ integer_mul: $$ = 0; } } - | integer_mul '%' integer_unary { $$ = $1 % $3; } + | integer_mul '%' integer_unary + { + if ($3 != 0) { + $$ = $1 % $3; + } else { + ERROR(&@$, "Division by zero"); + $$ = 0; + } + } | integer_unary ; diff --git a/tests/division-by-zero.dts b/tests/division-by-zero.dts index d26fc27..2984b29 100644 --- a/tests/division-by-zero.dts +++ b/tests/division-by-zero.dts @@ -1,5 +1,6 @@ /dts-v1/; / { - prop = < (1/0) >; + prop-div = < (1/0) >; + prop-mod = < (1%0) >; }; From 2e53f9d2f0a8faab6cec0d78958d52c155f6c6eb Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sun, 3 Jan 2016 08:43:35 +1100 Subject: [PATCH 0490/1198] Catch unsigned 32bit overflow when parsing flattened device tree offsets We have a couple of checks of the form: if (offset+size > totalsize) die(); We need to check that offset+size doesn't overflow, otherwise the check will pass, and we may access past totalsize. Found with AFL. Signed-off-by: Anton Blanchard [Added a testcase] Signed-off-by: David Gibson --- flattree.c | 4 ++-- tests/dumptrees.c | 1 + tests/run_tests.sh | 2 ++ tests/testdata.h | 1 + tests/trees.S | 31 +++++++++++++++++++++++++++++++ 5 files changed, 37 insertions(+), 2 deletions(-) diff --git a/flattree.c b/flattree.c index bd99fa2..ec14954 100644 --- a/flattree.c +++ b/flattree.c @@ -889,7 +889,7 @@ struct boot_info *dt_from_blob(const char *fname) if (version >= 3) { uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings); - if (off_str+size_str > totalsize) + if ((off_str+size_str < off_str) || (off_str+size_str > totalsize)) die("String table extends past total size\n"); inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str); } else { @@ -898,7 +898,7 @@ struct boot_info *dt_from_blob(const char *fname) if (version >= 17) { size_dt = fdt32_to_cpu(fdt->size_dt_struct); - if (off_dt+size_dt > totalsize) + if ((off_dt+size_dt < off_dt) || (off_dt+size_dt > totalsize)) die("Structure block extends past total size\n"); } diff --git a/tests/dumptrees.c b/tests/dumptrees.c index bebf553..a49dbfa 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -36,6 +36,7 @@ struct { #define TREE(name) { &_##name, #name ".dtb" } TREE(test_tree1), TREE(bad_node_char), TREE(bad_node_format), TREE(bad_prop_char), + TREE(ovf_size_strings), }; #define NUM_TREES (sizeof(trees) / sizeof(trees[0])) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 8863c9a..710f2ac 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -295,6 +295,8 @@ libfdt_tests () { run_dtc_test -I dts -O dtb 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 -I dtb -O dts -o /dev/null ovf_size_strings.dtb } dtc_tests () { diff --git a/tests/testdata.h b/tests/testdata.h index ce715e4..576974d 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -33,4 +33,5 @@ extern struct fdt_header _truncated_property; extern struct fdt_header _bad_node_char; extern struct fdt_header _bad_node_format; extern struct fdt_header _bad_prop_char; +extern struct fdt_header _ovf_size_strings; #endif /* ! __ASSEMBLY */ diff --git a/tests/trees.S b/tests/trees.S index 2389cd3..3d24aa2 100644 --- a/tests/trees.S +++ b/tests/trees.S @@ -209,3 +209,34 @@ bad_prop_char_strings: STRING(bad_prop_char, prop, "prop$erty") bad_prop_char_strings_end: bad_prop_char_end: + + + /* overflow_size_strings */ + .balign 8 + .globl _ovf_size_strings +_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) + +ovf_size_strings_struct: + BEGIN_NODE("") + PROP_INT(ovf_size_strings, bad_string, 0) + END_NODE + FDTLONG(FDT_END) +ovf_size_strings_struct_end: + +ovf_size_strings_strings: + 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: From c9d9121683b35281239305e15adddfff2b462cf9 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 19 Feb 2016 15:59:29 +1100 Subject: [PATCH 0491/1198] Warn on node name unit-address presence/absence mismatch ePAPR 1.1 section 2.2.1.1 "Node Name Requirements" specifies that any node that has a reg property must include a unit address in its name with value matching the first entry in its reg property. Conversely, if a node does not have a reg property, the node name must not include a unit address. Also allow ranges property as it is deemed valid, but ePAPR is not clear about it. Implement a check for this. The code doesn't validate the format of the unit address; ePAPR implies this may vary from (containing bus) binding to binding, so doing so would be much more complex. Signed-off-by: Stephen Warren [robh: also allow non-empty ranges] Signed-off-by: Rob Herring [moved new test in check_table] Signed-off-by: David Gibson --- checks.c | 26 ++++++++++++++++++++++++++ tests/reg-without-unit-addr.dts | 10 ++++++++++ tests/run_tests.sh | 2 ++ tests/unit-addr-without-reg.dts | 9 +++++++++ 4 files changed, 47 insertions(+) create mode 100644 tests/reg-without-unit-addr.dts create mode 100644 tests/unit-addr-without-reg.dts diff --git a/checks.c b/checks.c index 0c03ac9..386f956 100644 --- a/checks.c +++ b/checks.c @@ -294,6 +294,30 @@ static void check_node_name_format(struct check *c, struct node *dt, } NODE_ERROR(node_name_format, NULL, &node_name_chars); +static void check_unit_address_vs_reg(struct check *c, struct node *dt, + struct node *node) +{ + const char *unitname = get_unitname(node); + struct property *prop = get_property(node, "reg"); + + if (!prop) { + prop = get_property(node, "ranges"); + if (prop && !prop->val.len) + prop = NULL; + } + + if (prop) { + if (!unitname[0]) + FAIL(c, "Node %s has a reg or ranges property, but no unit name", + node->fullpath); + } else { + if (unitname[0]) + FAIL(c, "Node %s has a unit name, but no reg property", + node->fullpath); + } +} +NODE_WARNING(unit_address_vs_reg, NULL); + static void check_property_name_chars(struct check *c, struct node *dt, struct node *node, struct property *prop) { @@ -667,6 +691,8 @@ static struct check *check_table[] = { &addr_size_cells, ®_format, &ranges_format, + &unit_address_vs_reg, + &avoid_default_addr_size, &obsolete_chosen_interrupt_controller, diff --git a/tests/reg-without-unit-addr.dts b/tests/reg-without-unit-addr.dts new file mode 100644 index 0000000..aaf8af7 --- /dev/null +++ b/tests/reg-without-unit-addr.dts @@ -0,0 +1,10 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + node { + reg = <0 1>; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 710f2ac..7eb9b3d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -445,6 +445,8 @@ dtc_tests () { check_tests reg-ranges-root.dts reg_format ranges_format check_tests default-addr-size.dts avoid_default_addr_size check_tests obsolete-chosen-interrupt-controller.dts obsolete_chosen_interrupt_controller + check_tests reg-without-unit-addr.dts unit_address_vs_reg + check_tests unit-addr-without-reg.dts unit_address_vs_reg run_sh_test dtc-checkfails.sh node_name_chars -- -I dtb -O dtb bad_node_char.dtb run_sh_test dtc-checkfails.sh node_name_format -- -I dtb -O dtb bad_node_format.dtb run_sh_test dtc-checkfails.sh prop_name_chars -- -I dtb -O dtb bad_prop_char.dtb diff --git a/tests/unit-addr-without-reg.dts b/tests/unit-addr-without-reg.dts new file mode 100644 index 0000000..ac786eb --- /dev/null +++ b/tests/unit-addr-without-reg.dts @@ -0,0 +1,9 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + node@1 { + }; +}; From 53bf130b1cdd7f6262eedd5e1b224c18bf7f1498 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 12 Feb 2016 14:45:12 +0900 Subject: [PATCH 0492/1198] libfdt: simplify fdt_node_check_compatible() Because fdt_stringlist_contains() returns 1 or 0, fdt_node_check_compatible() can just return the inverted value. Signed-off-by: Masahiro Yamada Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index e5b3136..50cce86 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -647,10 +647,8 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); if (!prop) return len; - if (fdt_stringlist_contains(prop, len, compatible)) - return 0; - else - return 1; + + return !fdt_stringlist_contains(prop, len, compatible); } int fdt_node_offset_by_compatible(const void *fdt, int startoffset, From b0dbceafd49a421c493e2a6ed596a12ad840fc56 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 6 Mar 2016 20:12:46 -0700 Subject: [PATCH 0493/1198] Correct space-after-tab in libfdt.h There are a few places with a space before a tab in this file. Fix them. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- libfdt/libfdt.h | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 78adb12..25311cb 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -174,15 +174,15 @@ int fdt_next_subnode(const void *fdt, int offset); #define fdt_get_header(fdt, field) \ (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) -#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) +#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) #define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) #define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) #define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) #define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) #define fdt_version(fdt) (fdt_get_header(fdt, version)) -#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) -#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) -#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) +#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) +#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) +#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) #define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) #define __fdt_set_hdr(name) \ @@ -647,7 +647,7 @@ const char *fdt_get_alias(const void *fdt, const char *name); * 0, on success * buf contains the absolute path of the node at * nodeoffset, as a NUL-terminated string. - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) * characters and will not fit in the given buffer. * -FDT_ERR_BADMAGIC, @@ -677,11 +677,10 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); * structure from the start to nodeoffset. * * returns: - * structure block offset of the node at node offset's ancestor * of depth supernodedepth (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag -* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, @@ -703,7 +702,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, * * returns: * depth of the node at nodeoffset (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, @@ -726,7 +725,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset); * returns: * structure block offset of the parent of the node at nodeoffset * (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, @@ -766,7 +765,7 @@ int fdt_parent_offset(const void *fdt, int nodeoffset); * on success * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the * tree after startoffset - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, @@ -813,7 +812,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); * 1, if the node has a 'compatible' property, but it does not list * the given string * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property - * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, @@ -850,7 +849,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, * on success * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the * tree after startoffset - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, From 68d43cec125334f45bda39f819375072d4b4aea4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 6 Mar 2016 20:12:47 -0700 Subject: [PATCH 0494/1198] Correct line lengths in libfdt.h There are a few lines that are over 80 columns. Fix these. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- libfdt/libfdt.h | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 25311cb..2c7b4e8 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -318,8 +318,9 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, * returns: * structure block offset of the requested 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 - * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, @@ -351,7 +352,8 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); * address). * * returns: - * structure block offset of the node with the requested path (>=0), on success + * 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_NOTFOUND, if the requested node does not exist * -FDT_ERR_BADMAGIC, @@ -375,10 +377,12 @@ int fdt_path_offset(const void *fdt, const char *path); * * returns: * pointer to the node's name, on success - * If lenp is non-NULL, *lenp contains the length of that name (>=0) + * If lenp is non-NULL, *lenp contains the length of that name + * (>=0) * NULL, on error * if lenp is non-NULL *lenp contains an error code (<0): - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, standard meanings @@ -490,7 +494,8 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt, * NULL, on error * if lenp is non-NULL, *lenp contains an error code (<0): * -FDT_ERR_NOTFOUND, node does not have named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, @@ -575,7 +580,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, * NULL, on error * if lenp is non-NULL, *lenp contains an error code (<0): * -FDT_ERR_NOTFOUND, node does not have named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, @@ -680,7 +686,8 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); * structure block offset of the node at node offset's ancestor * of depth supernodedepth (>=0), on success * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset + * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of + * nodeoffset * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, @@ -959,7 +966,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 #address-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #address-cells property * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, @@ -979,7 +987,8 @@ int fdt_address_cells(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 #size-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #size-cells property * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, @@ -1603,9 +1612,11 @@ 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 nodeequested 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 + * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE + * tag * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of * the given name * -FDT_ERR_NOSPACE, if there is insufficient free space in the From beef80b8b55f32e5d3338ac13429382336e38ead Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 6 Mar 2016 20:12:48 -0700 Subject: [PATCH 0495/1198] Correct a missing space in a fdt_header cast The code style here is slightly incorrect. Fix it. Signed-off-by: Simon Glass 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 2c7b4e8..36222fd 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -188,7 +188,7 @@ int fdt_next_subnode(const void *fdt, int offset); #define __fdt_set_hdr(name) \ static inline void fdt_set_##name(void *fdt, uint32_t val) \ { \ - struct fdt_header *fdth = (struct fdt_header*)fdt; \ + struct fdt_header *fdth = (struct fdt_header *)fdt; \ fdth->name = cpu_to_fdt32(val); \ } __fdt_set_hdr(magic); From 9dc404958e9c91f33f75450f69b690a5e676af04 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Tue, 24 May 2016 20:50:35 +0300 Subject: [PATCH 0496/1198] util: Add xasprintf portable asprintf variant Include a portable asprintf variant that works on any C99 conforming platform. Signed-off-by: Pantelis Antoniou Signed-off-by: David Gibson --- util.c | 30 ++++++++++++++++++++++++++++++ util.h | 1 + 2 files changed, 31 insertions(+) diff --git a/util.c b/util.c index fb124ee..3550f86 100644 --- a/util.c +++ b/util.c @@ -46,6 +46,36 @@ char *xstrdup(const char *s) return d; } +/* based in part from (3) vsnprintf */ +int xasprintf(char **strp, const char *fmt, ...) +{ + int n, size = 128; /* start with 128 bytes */ + char *p; + va_list ap; + + /* initial pointer is NULL making the fist realloc to be malloc */ + p = NULL; + while (1) { + p = xrealloc(p, size); + + /* Try to print in the allocated space. */ + va_start(ap, fmt); + n = vsnprintf(p, size, fmt, ap); + va_end(ap); + + /* If that worked, return the string. */ + if (n > -1 && n < size) + break; + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + size = n + 1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + } + *strp = p; + return strlen(p); +} + char *join_path(const char *path, const char *name) { int lenp = strlen(path); diff --git a/util.h b/util.h index f800b60..f5c4f1b 100644 --- a/util.h +++ b/util.h @@ -59,6 +59,7 @@ static inline void *xrealloc(void *p, size_t len) } extern char *xstrdup(const char *s); +extern int xasprintf(char **strp, const char *fmt, ...); extern char *join_path(const char *path, const char *name); /** From d71d25d76012896521f937bf0c69f27b1a37cdc2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 25 May 2016 15:15:36 +1000 Subject: [PATCH 0497/1198] Use xasprintf() in srcpos Now that we have an xasprintf() helper function, use it to simplify the srcpos_string() implementation. Signed-off-by: David Gibson --- srcpos.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/srcpos.c b/srcpos.c index f534c22..af7fb3c 100644 --- a/srcpos.c +++ b/srcpos.c @@ -266,26 +266,22 @@ srcpos_string(struct srcpos *pos) { const char *fname = ""; char *pos_str; - int rc; if (pos) fname = pos->file->name; if (pos->first_line != pos->last_line) - rc = asprintf(&pos_str, "%s:%d.%d-%d.%d", fname, - pos->first_line, pos->first_column, - pos->last_line, pos->last_column); + xasprintf(&pos_str, "%s:%d.%d-%d.%d", fname, + pos->first_line, pos->first_column, + pos->last_line, pos->last_column); else if (pos->first_column != pos->last_column) - rc = asprintf(&pos_str, "%s:%d.%d-%d", fname, - pos->first_line, pos->first_column, - pos->last_column); + xasprintf(&pos_str, "%s:%d.%d-%d", fname, + pos->first_line, pos->first_column, + pos->last_column); else - rc = asprintf(&pos_str, "%s:%d.%d", fname, - pos->first_line, pos->first_column); - - if (rc == -1) - die("Couldn't allocate in srcpos string"); + xasprintf(&pos_str, "%s:%d.%d", fname, + pos->first_line, pos->first_column); return pos_str; } From c4cb12e193e314226991deb468c1b397296dea53 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 2 Jun 2014 15:23:40 +1000 Subject: [PATCH 0498/1198] Alter grammar to allow multiple /dts-v1/ tags This patch allows dtc to accept multiple /dts-v1/ tags (provided they're all at the beginning of the input), rather than giving a syntax error. This makes it more convenient to include one .dts file from another without having to be careful that the /dts-v1/ tag is in exactly one of them. We a couple of existing testcases to take advantage of this, which simplifies them slightly. Signed-off-by: David Gibson --- dtc-parser.y | 11 +++++++--- tests/test_tree1.dts | 44 ++++++++++++++++++++++++++++++++++++- tests/test_tree1_body.dtsi | 43 ------------------------------------ tests/test_tree1_delete.dts | 2 +- 4 files changed, 52 insertions(+), 48 deletions(-) delete mode 100644 tests/test_tree1_body.dtsi diff --git a/dtc-parser.y b/dtc-parser.y index 000873f..14aaf2e 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -101,13 +101,18 @@ extern bool treesource_error; %% sourcefile: - DT_V1 ';' memreserves devicetree + v1tag memreserves devicetree { - the_boot_info = build_boot_info($3, $4, - guess_boot_cpuid($4)); + the_boot_info = build_boot_info($2, $3, + guess_boot_cpuid($3)); } ; +v1tag: + DT_V1 ';' + | DT_V1 ';' v1tag + ; + memreserves: /* empty */ { diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts index c7b170c..67ecfd0 100644 --- a/tests/test_tree1.dts +++ b/tests/test_tree1.dts @@ -1,3 +1,45 @@ /dts-v1/; -/include/ "test_tree1_body.dtsi" +/memreserve/ 0xdeadbeef00000000 0x100000; +/memreserve/ 123456789 010000; + +/ { + compatible = "test_tree1"; + prop-int = <0xdeadbeef>; + prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; + prop-str = "hello world"; + #address-cells = <1>; + #size-cells = <0>; + + subnode@1 { + compatible = "subnode1"; + reg = <1>; + prop-int = [deadbeef]; + + subsubnode { + compatible = "subsubnode1", "subsubnode"; + prop-int = <0xdeadbeef>; + }; + + ss1 { + }; + }; + + subnode@2 { + reg = <2>; + linux,phandle = <0x2000>; + prop-int = <123456789>; + #address-cells = <1>; + #size-cells = <0>; + + ssn0: subsubnode@0 { + reg = <0>; + phandle = <0x2001>; + compatible = "subsubnode2", "subsubnode"; + prop-int = <0726746425>; + }; + + ss2 { + }; + }; +}; diff --git a/tests/test_tree1_body.dtsi b/tests/test_tree1_body.dtsi deleted file mode 100644 index 24a5e1e..0000000 --- a/tests/test_tree1_body.dtsi +++ /dev/null @@ -1,43 +0,0 @@ -/memreserve/ 0xdeadbeef00000000 0x100000; -/memreserve/ 123456789 010000; - -/ { - compatible = "test_tree1"; - prop-int = <0xdeadbeef>; - prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; - prop-str = "hello world"; - #address-cells = <1>; - #size-cells = <0>; - - subnode@1 { - compatible = "subnode1"; - reg = <1>; - prop-int = [deadbeef]; - - subsubnode { - compatible = "subsubnode1", "subsubnode"; - prop-int = <0xdeadbeef>; - }; - - ss1 { - }; - }; - - subnode@2 { - reg = <2>; - linux,phandle = <0x2000>; - prop-int = <123456789>; - #address-cells = <1>; - #size-cells = <0>; - - ssn0: subsubnode@0 { - reg = <0>; - phandle = <0x2001>; - compatible = "subsubnode2", "subsubnode"; - prop-int = <0726746425>; - }; - - ss2 { - }; - }; -}; diff --git a/tests/test_tree1_delete.dts b/tests/test_tree1_delete.dts index a2f1bfd..b95ef1e 100644 --- a/tests/test_tree1_delete.dts +++ b/tests/test_tree1_delete.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ "test_tree1_body.dtsi" +/include/ "test_tree1.dts" / { nonexistant-property = <0xdeadbeef>; From 2e709d158e11f0adf897d2eb8cd1fd7a145a4c1f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 27 Oct 2013 19:18:06 +1100 Subject: [PATCH 0499/1198] Remove tree check functions The tree check functions from the checking infrastructure aren't very useful. There were only two examples using them, and they're basically equivalent to a node check which is applied only to the root node, so those are easily replaced. Signed-off-by: David Gibson --- checks.c | 67 ++++++++++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/checks.c b/checks.c index 386f956..6026884 100644 --- a/checks.c +++ b/checks.c @@ -40,14 +40,12 @@ enum checkstatus { struct check; -typedef void (*tree_check_fn)(struct check *c, struct node *dt); typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node); typedef void (*prop_check_fn)(struct check *c, struct node *dt, struct node *node, struct property *prop); struct check { const char *name; - tree_check_fn tree_fn; node_check_fn node_fn; prop_check_fn prop_fn; void *data; @@ -58,11 +56,10 @@ struct check { struct check **prereq; }; -#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...) \ +#define CHECK_ENTRY(nm, nfn, pfn, d, w, e, ...) \ static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \ static struct check nm = { \ .name = #nm, \ - .tree_fn = (tfn), \ .node_fn = (nfn), \ .prop_fn = (pfn), \ .data = (d), \ @@ -72,31 +69,25 @@ struct check { .num_prereqs = ARRAY_SIZE(nm##_prereqs), \ .prereq = nm##_prereqs, \ }; -#define WARNING(nm, tfn, nfn, pfn, d, ...) \ - CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__) -#define ERROR(nm, tfn, nfn, pfn, d, ...) \ - CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__) -#define CHECK(nm, tfn, nfn, pfn, d, ...) \ - CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__) +#define WARNING(nm, nfn, pfn, d, ...) \ + CHECK_ENTRY(nm, nfn, pfn, d, true, false, __VA_ARGS__) +#define ERROR(nm, nfn, pfn, d, ...) \ + CHECK_ENTRY(nm, nfn, pfn, d, false, true, __VA_ARGS__) +#define CHECK(nm, nfn, pfn, d, ...) \ + CHECK_ENTRY(nm, nfn, pfn, d, false, false, __VA_ARGS__) -#define TREE_WARNING(nm, d, ...) \ - WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) -#define TREE_ERROR(nm, d, ...) \ - ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) -#define TREE_CHECK(nm, d, ...) \ - CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) #define NODE_WARNING(nm, d, ...) \ - WARNING(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) + WARNING(nm, check_##nm, NULL, d, __VA_ARGS__) #define NODE_ERROR(nm, d, ...) \ - ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) + ERROR(nm, check_##nm, NULL, d, __VA_ARGS__) #define NODE_CHECK(nm, d, ...) \ - CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) + CHECK(nm, check_##nm, NULL, d, __VA_ARGS__) #define PROP_WARNING(nm, d, ...) \ - WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) + WARNING(nm, NULL, check_##nm, d, __VA_ARGS__) #define PROP_ERROR(nm, d, ...) \ - ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) + ERROR(nm, NULL, check_##nm, d, __VA_ARGS__) #define PROP_CHECK(nm, d, ...) \ - CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) + CHECK(nm, NULL, check_##nm, d, __VA_ARGS__) #ifdef __GNUC__ static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); @@ -170,8 +161,6 @@ static bool run_check(struct check *c, struct node *dt) if (c->node_fn || c->prop_fn) check_nodes_props(c, dt, dt); - if (c->tree_fn) - c->tree_fn(c, dt); if (c->status == UNCHECKED) c->status = PASSED; @@ -189,11 +178,12 @@ out: */ /* A check which always fails, for testing purposes only */ -static inline void check_always_fail(struct check *c, struct node *dt) +static inline void check_always_fail(struct check *c, struct node *dt, + struct node *node) { FAIL(c, "always_fail check"); } -TREE_CHECK(always_fail, NULL); +NODE_CHECK(always_fail, NULL); static void check_is_string(struct check *c, struct node *root, struct node *node) @@ -210,9 +200,9 @@ static void check_is_string(struct check *c, struct node *root, propname, node->fullpath); } #define WARNING_IF_NOT_STRING(nm, propname) \ - WARNING(nm, NULL, check_is_string, NULL, (propname)) + WARNING(nm, check_is_string, NULL, (propname)) #define ERROR_IF_NOT_STRING(nm, propname) \ - ERROR(nm, NULL, check_is_string, NULL, (propname)) + ERROR(nm, check_is_string, NULL, (propname)) static void check_is_cell(struct check *c, struct node *root, struct node *node) @@ -229,9 +219,9 @@ static void check_is_cell(struct check *c, struct node *root, propname, node->fullpath); } #define WARNING_IF_NOT_CELL(nm, propname) \ - WARNING(nm, NULL, check_is_cell, NULL, (propname)) + WARNING(nm, check_is_cell, NULL, (propname)) #define ERROR_IF_NOT_CELL(nm, propname) \ - ERROR(nm, NULL, check_is_cell, NULL, (propname)) + ERROR(nm, check_is_cell, NULL, (propname)) /* * Structural check functions @@ -382,7 +372,7 @@ static void check_duplicate_label_prop(struct check *c, struct node *dt, for_each_marker_of_type(m, LABEL) check_duplicate_label(c, dt, m->ref, node, prop, m); } -ERROR(duplicate_label, NULL, check_duplicate_label_node, +ERROR(duplicate_label, check_duplicate_label_node, check_duplicate_label_prop, NULL); static void check_explicit_phandles(struct check *c, struct node *root, @@ -499,7 +489,7 @@ static void fixup_phandle_references(struct check *c, struct node *dt, *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); } } -ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL, +ERROR(phandle_references, NULL, fixup_phandle_references, NULL, &duplicate_node_names, &explicit_phandles); static void fixup_path_references(struct check *c, struct node *dt, @@ -524,7 +514,7 @@ static void fixup_path_references(struct check *c, struct node *dt, strlen(path) + 1); } } -ERROR(path_references, NULL, NULL, fixup_path_references, NULL, +ERROR(path_references, NULL, fixup_path_references, NULL, &duplicate_node_names); /* @@ -554,7 +544,7 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt, if (prop) node->size_cells = propval_cell(prop); } -WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, +WARNING(addr_size_cells, fixup_addr_size_cells, NULL, NULL, &address_cells_is_cell, &size_cells_is_cell); #define node_addr_cells(n) \ @@ -660,11 +650,16 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt, NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells); static void check_obsolete_chosen_interrupt_controller(struct check *c, - struct node *dt) + struct node *dt, + struct node *node) { struct node *chosen; struct property *prop; + if (node != dt) + return; + + chosen = get_node_by_path(dt, "/chosen"); if (!chosen) return; @@ -674,7 +669,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c, FAIL(c, "/chosen has obsolete \"interrupt-controller\" " "property"); } -TREE_WARNING(obsolete_chosen_interrupt_controller, NULL); +NODE_WARNING(obsolete_chosen_interrupt_controller, NULL); static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, From 9d97527a8621bb6f4a8c18a523ebb05a2a9b3a7e Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 27 Oct 2013 22:23:45 +1100 Subject: [PATCH 0500/1198] Remove property check functions Property checking functions aren't particularly useful. They're used only in a handful of cases, and most of those really only check a small handful of specific properties. This patches converts the few cases to node check functions and removes property check functions entirely. Signed-off-by: David Gibson --- checks.c | 216 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 115 insertions(+), 101 deletions(-) diff --git a/checks.c b/checks.c index 6026884..40110a1 100644 --- a/checks.c +++ b/checks.c @@ -41,13 +41,10 @@ enum checkstatus { struct check; typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node); -typedef void (*prop_check_fn)(struct check *c, struct node *dt, - struct node *node, struct property *prop); struct check { const char *name; node_check_fn node_fn; - prop_check_fn prop_fn; void *data; bool warn, error; enum checkstatus status; @@ -56,12 +53,11 @@ struct check { struct check **prereq; }; -#define CHECK_ENTRY(nm, nfn, pfn, d, w, e, ...) \ +#define CHECK_ENTRY(nm, nfn, d, w, e, ...) \ static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \ static struct check nm = { \ .name = #nm, \ .node_fn = (nfn), \ - .prop_fn = (pfn), \ .data = (d), \ .warn = (w), \ .error = (e), \ @@ -69,25 +65,19 @@ struct check { .num_prereqs = ARRAY_SIZE(nm##_prereqs), \ .prereq = nm##_prereqs, \ }; -#define WARNING(nm, nfn, pfn, d, ...) \ - CHECK_ENTRY(nm, nfn, pfn, d, true, false, __VA_ARGS__) -#define ERROR(nm, nfn, pfn, d, ...) \ - CHECK_ENTRY(nm, nfn, pfn, d, false, true, __VA_ARGS__) -#define CHECK(nm, nfn, pfn, d, ...) \ - CHECK_ENTRY(nm, nfn, pfn, d, false, false, __VA_ARGS__) +#define WARNING(nm, nfn, d, ...) \ + CHECK_ENTRY(nm, nfn, d, true, false, __VA_ARGS__) +#define ERROR(nm, nfn, d, ...) \ + CHECK_ENTRY(nm, nfn, d, false, true, __VA_ARGS__) +#define CHECK(nm, nfn, d, ...) \ + CHECK_ENTRY(nm, nfn, d, false, false, __VA_ARGS__) #define NODE_WARNING(nm, d, ...) \ - WARNING(nm, check_##nm, NULL, d, __VA_ARGS__) + WARNING(nm, check_##nm, d, __VA_ARGS__) #define NODE_ERROR(nm, d, ...) \ - ERROR(nm, check_##nm, NULL, d, __VA_ARGS__) + ERROR(nm, check_##nm, d, __VA_ARGS__) #define NODE_CHECK(nm, d, ...) \ - CHECK(nm, check_##nm, NULL, d, __VA_ARGS__) -#define PROP_WARNING(nm, d, ...) \ - WARNING(nm, NULL, check_##nm, d, __VA_ARGS__) -#define PROP_ERROR(nm, d, ...) \ - ERROR(nm, NULL, check_##nm, d, __VA_ARGS__) -#define PROP_CHECK(nm, d, ...) \ - CHECK(nm, NULL, check_##nm, d, __VA_ARGS__) + CHECK(nm, check_##nm, d, __VA_ARGS__) #ifdef __GNUC__ static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); @@ -117,18 +107,11 @@ static inline void check_msg(struct check *c, const char *fmt, ...) static void check_nodes_props(struct check *c, struct node *dt, struct node *node) { struct node *child; - struct property *prop; TRACE(c, "%s", node->fullpath); if (c->node_fn) c->node_fn(c, dt, node); - if (c->prop_fn) - for_each_property(node, prop) { - TRACE(c, "%s\t'%s'", node->fullpath, prop->name); - c->prop_fn(c, dt, node, prop); - } - for_each_child(node, child) check_nodes_props(c, dt, child); } @@ -158,7 +141,7 @@ static bool run_check(struct check *c, struct node *dt) if (c->status != UNCHECKED) goto out; - if (c->node_fn || c->prop_fn) + if (c->node_fn) check_nodes_props(c, dt, dt); if (c->status == UNCHECKED) @@ -200,9 +183,9 @@ static void check_is_string(struct check *c, struct node *root, propname, node->fullpath); } #define WARNING_IF_NOT_STRING(nm, propname) \ - WARNING(nm, check_is_string, NULL, (propname)) + WARNING(nm, check_is_string, (propname)) #define ERROR_IF_NOT_STRING(nm, propname) \ - ERROR(nm, check_is_string, NULL, (propname)) + ERROR(nm, check_is_string, (propname)) static void check_is_cell(struct check *c, struct node *root, struct node *node) @@ -219,9 +202,9 @@ static void check_is_cell(struct check *c, struct node *root, propname, node->fullpath); } #define WARNING_IF_NOT_CELL(nm, propname) \ - WARNING(nm, check_is_cell, NULL, (propname)) + WARNING(nm, check_is_cell, (propname)) #define ERROR_IF_NOT_CELL(nm, propname) \ - ERROR(nm, check_is_cell, NULL, (propname)) + ERROR(nm, check_is_cell, (propname)) /* * Structural check functions @@ -309,15 +292,19 @@ static void check_unit_address_vs_reg(struct check *c, struct node *dt, NODE_WARNING(unit_address_vs_reg, NULL); static void check_property_name_chars(struct check *c, struct node *dt, - struct node *node, struct property *prop) + struct node *node) { - int n = strspn(prop->name, c->data); + struct property *prop; - if (n < strlen(prop->name)) - FAIL(c, "Bad character '%c' in property name \"%s\", node %s", - prop->name[n], prop->name, node->fullpath); + for_each_property(node, prop) { + int n = strspn(prop->name, c->data); + + if (n < strlen(prop->name)) + FAIL(c, "Bad character '%c' in property name \"%s\", node %s", + prop->name[n], prop->name, node->fullpath); + } } -PROP_ERROR(property_name_chars, PROPNODECHARS); +NODE_ERROR(property_name_chars, PROPNODECHARS); #define DESCLABEL_FMT "%s%s%s%s%s" #define DESCLABEL_ARGS(node,prop,mark) \ @@ -356,40 +343,38 @@ static void check_duplicate_label_node(struct check *c, struct node *dt, struct node *node) { struct label *l; + struct property *prop; for_each_label(node->labels, l) check_duplicate_label(c, dt, l->label, node, NULL, NULL); + + for_each_property(node, prop) { + struct marker *m = prop->val.markers; + + for_each_label(prop->labels, l) + check_duplicate_label(c, dt, l->label, node, prop, NULL); + + for_each_marker_of_type(m, LABEL) + check_duplicate_label(c, dt, m->ref, node, prop, m); + } } -static void check_duplicate_label_prop(struct check *c, struct node *dt, - struct node *node, struct property *prop) -{ - struct marker *m = prop->val.markers; - struct label *l; - - for_each_label(prop->labels, l) - check_duplicate_label(c, dt, l->label, node, prop, NULL); - - for_each_marker_of_type(m, LABEL) - check_duplicate_label(c, dt, m->ref, node, prop, m); -} -ERROR(duplicate_label, check_duplicate_label_node, - check_duplicate_label_prop, NULL); - -static void check_explicit_phandles(struct check *c, struct node *root, - struct node *node, struct property *prop) +ERROR(duplicate_label, check_duplicate_label_node, NULL); + +static cell_t check_phandle_prop(struct check *c, struct node *root, + struct node *node, const char *propname) { + struct property *prop; struct marker *m; - struct node *other; cell_t phandle; - if (!streq(prop->name, "phandle") - && !streq(prop->name, "linux,phandle")) - return; + prop = get_property(node, propname); + if (!prop) + return 0; if (prop->val.len != sizeof(cell_t)) { FAIL(c, "%s has bad length (%d) %s property", node->fullpath, prop->val.len, prop->name); - return; + return 0; } m = prop->val.markers; @@ -401,14 +386,13 @@ static void check_explicit_phandles(struct check *c, struct node *root, * by construction. */ { FAIL(c, "%s in %s is a reference to another node", prop->name, node->fullpath); - return; } /* But setting this node's phandle equal to its own * phandle is allowed - that means allocate a unique * phandle for this node, even if it's not otherwise * referenced. The value will be filled in later, so - * no further checking for now. */ - return; + * we treat it as having no phandle data for now. */ + return 0; } phandle = propval_cell(prop); @@ -416,12 +400,35 @@ static void check_explicit_phandles(struct check *c, struct node *root, if ((phandle == 0) || (phandle == -1)) { FAIL(c, "%s has bad value (0x%x) in %s property", node->fullpath, phandle, prop->name); - return; + return 0; } - if (node->phandle && (node->phandle != phandle)) - FAIL(c, "%s has %s property which replaces existing phandle information", - node->fullpath, prop->name); + return phandle; +} + +static void check_explicit_phandles(struct check *c, struct node *root, + struct node *node) +{ + struct node *other; + cell_t phandle, linux_phandle; + + /* Nothing should have assigned phandles yet */ + assert(!node->phandle); + + phandle = check_phandle_prop(c, root, node, "phandle"); + + linux_phandle = check_phandle_prop(c, root, node, "linux,phandle"); + + if (!phandle && !linux_phandle) + /* No valid phandles; nothing further to check */ + return; + + if (linux_phandle && phandle && (phandle != linux_phandle)) + FAIL(c, "%s has mismatching 'phandle' and 'linux,phandle'" + " properties", node->fullpath); + + if (linux_phandle && !phandle) + phandle = linux_phandle; other = get_node_by_phandle(root, phandle); if (other && (other != node)) { @@ -432,7 +439,7 @@ static void check_explicit_phandles(struct check *c, struct node *root, node->phandle = phandle; } -PROP_ERROR(explicit_phandles, NULL); +NODE_ERROR(explicit_phandles, NULL); static void check_name_properties(struct check *c, struct node *root, struct node *node) @@ -469,53 +476,60 @@ NODE_ERROR(name_properties, NULL, &name_is_string); */ static void fixup_phandle_references(struct check *c, struct node *dt, - struct node *node, struct property *prop) + struct node *node) { - struct marker *m = prop->val.markers; - struct node *refnode; - cell_t phandle; + struct property *prop; - for_each_marker_of_type(m, REF_PHANDLE) { - assert(m->offset + sizeof(cell_t) <= prop->val.len); + for_each_property(node, prop) { + struct marker *m = prop->val.markers; + struct node *refnode; + cell_t phandle; - refnode = get_node_by_ref(dt, m->ref); - if (! refnode) { - FAIL(c, "Reference to non-existent node or label \"%s\"\n", - m->ref); - continue; + for_each_marker_of_type(m, REF_PHANDLE) { + assert(m->offset + sizeof(cell_t) <= prop->val.len); + + refnode = get_node_by_ref(dt, m->ref); + if (! refnode) { + FAIL(c, "Reference to non-existent node or label \"%s\"\n", + m->ref); + continue; + } + + phandle = get_node_phandle(dt, refnode); + *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); } - - phandle = get_node_phandle(dt, refnode); - *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); } } -ERROR(phandle_references, NULL, fixup_phandle_references, NULL, +ERROR(phandle_references, fixup_phandle_references, NULL, &duplicate_node_names, &explicit_phandles); static void fixup_path_references(struct check *c, struct node *dt, - struct node *node, struct property *prop) + struct node *node) { - struct marker *m = prop->val.markers; - struct node *refnode; - char *path; + struct property *prop; - for_each_marker_of_type(m, REF_PATH) { - assert(m->offset <= prop->val.len); + for_each_property(node, prop) { + struct marker *m = prop->val.markers; + struct node *refnode; + char *path; - refnode = get_node_by_ref(dt, m->ref); - if (!refnode) { - FAIL(c, "Reference to non-existent node or label \"%s\"\n", - m->ref); - continue; + for_each_marker_of_type(m, REF_PATH) { + assert(m->offset <= prop->val.len); + + refnode = get_node_by_ref(dt, m->ref); + if (!refnode) { + FAIL(c, "Reference to non-existent node or label \"%s\"\n", + m->ref); + continue; + } + + path = refnode->fullpath; + prop->val = data_insert_at_marker(prop->val, m, path, + strlen(path) + 1); } - - path = refnode->fullpath; - prop->val = data_insert_at_marker(prop->val, m, path, - strlen(path) + 1); } } -ERROR(path_references, NULL, fixup_path_references, NULL, - &duplicate_node_names); +ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names); /* * Semantic checks @@ -544,7 +558,7 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt, if (prop) node->size_cells = propval_cell(prop); } -WARNING(addr_size_cells, fixup_addr_size_cells, NULL, NULL, +WARNING(addr_size_cells, fixup_addr_size_cells, NULL, &address_cells_is_cell, &size_cells_is_cell); #define node_addr_cells(n) \ From 1ee0ae24ea0985589364a755d33b0159a8b0eee1 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 1 Nov 2013 23:57:17 +1100 Subject: [PATCH 0501/1198] Simplify check field and macro names Now that "node" checks are the only type of checks, simplify some names accordingly. Signed-off-by: David Gibson --- checks.c | 78 ++++++++++++++++++++++++++------------------------------ 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/checks.c b/checks.c index 40110a1..0381c98 100644 --- a/checks.c +++ b/checks.c @@ -40,11 +40,11 @@ enum checkstatus { struct check; -typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node); +typedef void (*check_fn)(struct check *c, struct node *dt, struct node *node); struct check { const char *name; - node_check_fn node_fn; + check_fn fn; void *data; bool warn, error; enum checkstatus status; @@ -53,31 +53,24 @@ struct check { struct check **prereq; }; -#define CHECK_ENTRY(nm, nfn, d, w, e, ...) \ - static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \ - static struct check nm = { \ - .name = #nm, \ - .node_fn = (nfn), \ - .data = (d), \ - .warn = (w), \ - .error = (e), \ +#define CHECK_ENTRY(_nm, _fn, _d, _w, _e, ...) \ + static struct check *_nm##_prereqs[] = { __VA_ARGS__ }; \ + static struct check _nm = { \ + .name = #_nm, \ + .fn = (_fn), \ + .data = (_d), \ + .warn = (_w), \ + .error = (_e), \ .status = UNCHECKED, \ - .num_prereqs = ARRAY_SIZE(nm##_prereqs), \ - .prereq = nm##_prereqs, \ + .num_prereqs = ARRAY_SIZE(_nm##_prereqs), \ + .prereq = _nm##_prereqs, \ }; -#define WARNING(nm, nfn, d, ...) \ - CHECK_ENTRY(nm, nfn, d, true, false, __VA_ARGS__) -#define ERROR(nm, nfn, d, ...) \ - CHECK_ENTRY(nm, nfn, d, false, true, __VA_ARGS__) -#define CHECK(nm, nfn, d, ...) \ - CHECK_ENTRY(nm, nfn, d, false, false, __VA_ARGS__) - -#define NODE_WARNING(nm, d, ...) \ - WARNING(nm, check_##nm, d, __VA_ARGS__) -#define NODE_ERROR(nm, d, ...) \ - ERROR(nm, check_##nm, d, __VA_ARGS__) -#define NODE_CHECK(nm, d, ...) \ - CHECK(nm, check_##nm, d, __VA_ARGS__) +#define WARNING(_nm, _fn, _d, ...) \ + CHECK_ENTRY(_nm, _fn, _d, true, false, __VA_ARGS__) +#define ERROR(_nm, _fn, _d, ...) \ + CHECK_ENTRY(_nm, _fn, _d, false, true, __VA_ARGS__) +#define CHECK(_nm, _fn, _d, ...) \ + CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__) #ifdef __GNUC__ static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); @@ -109,8 +102,8 @@ static void check_nodes_props(struct check *c, struct node *dt, struct node *nod struct node *child; TRACE(c, "%s", node->fullpath); - if (c->node_fn) - c->node_fn(c, dt, node); + if (c->fn) + c->fn(c, dt, node); for_each_child(node, child) check_nodes_props(c, dt, child); @@ -141,8 +134,7 @@ static bool run_check(struct check *c, struct node *dt) if (c->status != UNCHECKED) goto out; - if (c->node_fn) - check_nodes_props(c, dt, dt); + check_nodes_props(c, dt, dt); if (c->status == UNCHECKED) c->status = PASSED; @@ -166,7 +158,7 @@ static inline void check_always_fail(struct check *c, struct node *dt, { FAIL(c, "always_fail check"); } -NODE_CHECK(always_fail, NULL); +CHECK(always_fail, check_always_fail, NULL); static void check_is_string(struct check *c, struct node *root, struct node *node) @@ -223,7 +215,7 @@ static void check_duplicate_node_names(struct check *c, struct node *dt, FAIL(c, "Duplicate node name %s", child->fullpath); } -NODE_ERROR(duplicate_node_names, NULL); +ERROR(duplicate_node_names, check_duplicate_node_names, NULL); static void check_duplicate_property_names(struct check *c, struct node *dt, struct node *node) @@ -240,7 +232,7 @@ static void check_duplicate_property_names(struct check *c, struct node *dt, } } } -NODE_ERROR(duplicate_property_names, NULL); +ERROR(duplicate_property_names, check_duplicate_property_names, NULL); #define LOWERCASE "abcdefghijklmnopqrstuvwxyz" #define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -256,7 +248,7 @@ static void check_node_name_chars(struct check *c, struct node *dt, FAIL(c, "Bad character '%c' in node %s", node->name[n], node->fullpath); } -NODE_ERROR(node_name_chars, PROPNODECHARS "@"); +ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@"); static void check_node_name_format(struct check *c, struct node *dt, struct node *node) @@ -265,7 +257,7 @@ static void check_node_name_format(struct check *c, struct node *dt, FAIL(c, "Node %s has multiple '@' characters in name", node->fullpath); } -NODE_ERROR(node_name_format, NULL, &node_name_chars); +ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars); static void check_unit_address_vs_reg(struct check *c, struct node *dt, struct node *node) @@ -289,7 +281,7 @@ static void check_unit_address_vs_reg(struct check *c, struct node *dt, node->fullpath); } } -NODE_WARNING(unit_address_vs_reg, NULL); +WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL); static void check_property_name_chars(struct check *c, struct node *dt, struct node *node) @@ -304,7 +296,7 @@ static void check_property_name_chars(struct check *c, struct node *dt, prop->name[n], prop->name, node->fullpath); } } -NODE_ERROR(property_name_chars, PROPNODECHARS); +ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS); #define DESCLABEL_FMT "%s%s%s%s%s" #define DESCLABEL_ARGS(node,prop,mark) \ @@ -439,7 +431,7 @@ static void check_explicit_phandles(struct check *c, struct node *root, node->phandle = phandle; } -NODE_ERROR(explicit_phandles, NULL); +ERROR(explicit_phandles, check_explicit_phandles, NULL); static void check_name_properties(struct check *c, struct node *root, struct node *node) @@ -469,7 +461,7 @@ static void check_name_properties(struct check *c, struct node *root, } } ERROR_IF_NOT_STRING(name_is_string, "name"); -NODE_ERROR(name_properties, NULL, &name_is_string); +ERROR(name_properties, check_name_properties, NULL, &name_is_string); /* * Reference fixup functions @@ -593,7 +585,7 @@ static void check_reg_format(struct check *c, struct node *dt, "(#address-cells == %d, #size-cells == %d)", node->fullpath, prop->val.len, addr_cells, size_cells); } -NODE_WARNING(reg_format, NULL, &addr_size_cells); +WARNING(reg_format, check_reg_format, NULL, &addr_size_cells); static void check_ranges_format(struct check *c, struct node *dt, struct node *node) @@ -634,7 +626,7 @@ static void check_ranges_format(struct check *c, struct node *dt, p_addr_cells, c_addr_cells, c_size_cells); } } -NODE_WARNING(ranges_format, NULL, &addr_size_cells); +WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells); /* * Style checks @@ -661,7 +653,8 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt, FAIL(c, "Relying on default #size-cells value for %s", node->fullpath); } -NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells); +WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL, + &addr_size_cells); static void check_obsolete_chosen_interrupt_controller(struct check *c, struct node *dt, @@ -683,7 +676,8 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c, FAIL(c, "/chosen has obsolete \"interrupt-controller\" " "property"); } -NODE_WARNING(obsolete_chosen_interrupt_controller, NULL); +WARNING(obsolete_chosen_interrupt_controller, + check_obsolete_chosen_interrupt_controller, NULL); static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, From cb9241ae345378b7193b3d7c9621e8abe657faa6 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Dubois Date: Mon, 11 Jul 2016 00:16:52 +0200 Subject: [PATCH 0502/1198] DTC: Fix memory leak on flatname. If flatname was not referenced by the "node" structure, the reference to the allocated string is lost at function exit. We need to free it if is not used by "node". Signed-off-by: Jean-Christophe Dubois Signed-off-by: David Gibson --- flattree.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flattree.c b/flattree.c index ec14954..089b976 100644 --- a/flattree.c +++ b/flattree.c @@ -797,6 +797,10 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, } } while (val != FDT_END_NODE); + if (node->name != flatname) { + free(flatname); + } + return node; } From 44a59713cf0518382cb8fe705f59fd974a1ac030 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 13 Jul 2016 00:44:53 +1000 Subject: [PATCH 0503/1198] Remove unused srcpos_dump() function srcpos_dump() has no current users, and I have no plans to use it. So remove it. Signed-off-by: David Gibson --- srcpos.c | 15 --------------- srcpos.h | 1 - 2 files changed, 16 deletions(-) diff --git a/srcpos.c b/srcpos.c index af7fb3c..aa3aad0 100644 --- a/srcpos.c +++ b/srcpos.c @@ -246,21 +246,6 @@ srcpos_copy(struct srcpos *pos) return pos_new; } - - -void -srcpos_dump(struct srcpos *pos) -{ - printf("file : \"%s\"\n", - pos->file ? (char *) pos->file : ""); - printf("first_line : %d\n", pos->first_line); - printf("first_column: %d\n", pos->first_column); - printf("last_line : %d\n", pos->last_line); - printf("last_column : %d\n", pos->last_column); - printf("file : %s\n", pos->file->name); -} - - char * srcpos_string(struct srcpos *pos) { diff --git a/srcpos.h b/srcpos.h index f81827b..2cdfcd8 100644 --- a/srcpos.h +++ b/srcpos.h @@ -105,7 +105,6 @@ extern struct srcpos srcpos_empty; extern void srcpos_update(struct srcpos *pos, const char *text, int len); extern struct srcpos *srcpos_copy(struct srcpos *pos); extern char *srcpos_string(struct srcpos *pos); -extern void srcpos_dump(struct srcpos *pos); extern void srcpos_verror(struct srcpos *pos, const char *prefix, const char *fmt, va_list va) From e24d39a024e608476ffc896c5d02afa117a54cd7 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Dubois Date: Wed, 13 Jul 2016 02:31:13 +0200 Subject: [PATCH 0504/1198] fdtdump.c: make sure size_t argument to memchr is always unsigned. CID 132817 (#1 of 1): Integer overflowed argument (INTEGER_OVERFLOW) 15. overflow_sink: Overflowed or truncated value (or a value computed from an overflowed or truncated value) endp - p - 4L used as critical argument to function. Signed-off-by: Jean-Christophe Dubois Signed-off-by: David Gibson --- fdtdump.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fdtdump.c b/fdtdump.c index 95a6a20..a9a2484 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -15,6 +15,8 @@ #include "util.h" +#define FDT_MAGIC_SIZE 4 + #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) #define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) #define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) @@ -188,15 +190,15 @@ int main(int argc, char *argv[]) /* try and locate an embedded fdt in a bigger blob */ if (scan) { - unsigned char smagic[4]; + unsigned char smagic[FDT_MAGIC_SIZE]; char *p = buf; char *endp = buf + len; fdt_set_magic(smagic, FDT_MAGIC); /* poor man's memmem */ - while (true) { - p = memchr(p, smagic[0], endp - p - 4); + while ((endp - p) >= FDT_MAGIC_SIZE) { + p = memchr(p, smagic[0], endp - p - FDT_MAGIC_SIZE); if (!p) break; if (fdt_magic(p) == FDT_MAGIC) { @@ -215,7 +217,7 @@ int main(int argc, char *argv[]) } ++p; } - if (!p) + if (!p || ((endp - p) < FDT_MAGIC_SIZE)) die("%s: could not locate fdt magic\n", file); printf("%s: found fdt at offset %#zx\n", file, p - buf); buf = p; From 1074ee54b63f85603e0fc91614eebda9d7409035 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 24 Jul 2016 00:50:30 +1000 Subject: [PATCH 0505/1198] convert-dtsv0-lexer.l: fix memory leak CID 132822 (#1 of 1): Resource leak (RESOURCE_LEAK) 9. leaked_storage: Variable newname going out of scope leaks the storage it points to Signed-off-by: Jean-Christophe Dubois [dwg: Removed unnecessary hunk] Signed-off-by: David Gibson --- convert-dtsv0-lexer.l | 2 ++ 1 file changed, 2 insertions(+) diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index 259e527..aa32dc8 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -223,6 +223,8 @@ static void convert_file(const char *fname) while(yylex()) ; + + free(newname); } int main(int argc, char *argv[]) From f79ddb83e18505b522700476e546591bae6a9d4f Mon Sep 17 00:00:00 2001 From: Jean-Christophe Dubois Date: Wed, 13 Jul 2016 00:36:08 +0200 Subject: [PATCH 0506/1198] fdtget.c: Fix memory leak CID 132823 (#1 of 1): Resource leak (RESOURCE_LEAK) 5. leaked_storage: Variable blob going out of scope leaks the storage it points to. Signed-off-by: Jean-Christophe Dubois Signed-off-by: David Gibson --- fdtget.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fdtget.c b/fdtget.c index 4377419..fb9d0e1 100644 --- a/fdtget.c +++ b/fdtget.c @@ -266,14 +266,20 @@ static int do_fdtget(struct display_info *disp, const char *filename, continue; } else { report_error(arg[i], node); + free(blob); return -1; } } prop = args_per_step == 1 ? NULL : arg[i + 1]; - if (show_data_for_item(blob, disp, node, prop)) + if (show_data_for_item(blob, disp, node, prop)) { + free(blob); return -1; + } } + + free(blob); + return 0; } From c539075ba8ba61fffbf7e005ce2e834868a9e0ab Mon Sep 17 00:00:00 2001 From: Jean-Christophe Dubois Date: Wed, 13 Jul 2016 00:36:21 +0200 Subject: [PATCH 0507/1198] fdtput.c: Fix memory leak. CID 132821 (#1 of 1): Resource leak (RESOURCE_LEAK) 12. leaked_storage: Variable value going out of scope leaks the storage it points to. Signed-off-by: Jean-Christophe Dubois Signed-off-by: David Gibson --- fdtput.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fdtput.c b/fdtput.c index 9b15c53..db65e96 100644 --- a/fdtput.c +++ b/fdtput.c @@ -328,7 +328,7 @@ static int delete_node(char *blob, const char *node_name) static int do_fdtput(struct display_info *disp, const char *filename, char **arg, int arg_count) { - char *value; + char *value = NULL; char *blob; char *node; int len, ret = 0; @@ -374,6 +374,11 @@ static int do_fdtput(struct display_info *disp, const char *filename, } free(blob); + + if (value) { + free(value); + } + return ret; } From 902d0f0953d0074b329a2780a4b637fae0d776da Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 27 Jul 2016 14:55:53 +0200 Subject: [PATCH 0508/1198] libfdt: Add a subnodes iterator macro The fdt_for_each_subnode() iterator macro provided by this patch can be used to iterate over a device tree node's subnodes. At each iteration a loop variable will be set to the next subnode. Signed-off-by: Thierry Reding Signed-off-by: Maxime Ripard Signed-off-by: David Gibson --- libfdt/libfdt.h | 28 ++++++++++++++++++++++++++++ tests/subnode_iterate.c | 8 ++------ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 36222fd..911e548 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -168,6 +168,34 @@ int fdt_first_subnode(const void *fdt, int offset); */ int fdt_next_subnode(const void *fdt, int offset); +/** + * fdt_for_each_subnode - iterate over all subnodes of a parent + * + * @node: child node (int, lvalue) + * @fdt: FDT blob (const void *) + * @parent: parent node (int) + * + * This is actually a wrapper around a for loop and would be used like so: + * + * fdt_for_each_subnode(node, fdt, parent) { + * Use node + * ... + * } + * + * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) { + * Error handling + * } + * + * 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); \ + node >= 0; \ + node = fdt_next_subnode(fdt, node)) + /**********************************************************************/ /* General functions */ /**********************************************************************/ diff --git a/tests/subnode_iterate.c b/tests/subnode_iterate.c index b9f379d..0fb5c90 100644 --- a/tests/subnode_iterate.c +++ b/tests/subnode_iterate.c @@ -48,9 +48,7 @@ static void test_node(void *fdt, int parent_offset) subnodes = cpu_to_fdt32(*prop); count = 0; - for (offset = fdt_first_subnode(fdt, parent_offset); - offset >= 0; - offset = fdt_next_subnode(fdt, offset)) + fdt_for_each_subnode(offset, fdt, parent_offset) count++; if (count != subnodes) { @@ -65,9 +63,7 @@ static void check_fdt_next_subnode(void *fdt) int offset; int count = 0; - for (offset = fdt_first_subnode(fdt, 0); - offset >= 0; - offset = fdt_next_subnode(fdt, offset)) { + fdt_for_each_subnode(offset, fdt, 0) { test_node(fdt, offset); count++; } From d29126c90acb0d705d695b2be07162f38ee48d69 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 27 Jul 2016 14:55:54 +0200 Subject: [PATCH 0509/1198] libfdt: Add iterator over properties Implement a macro based on fdt_first_property_offset and fdt_next_property_offset that provides a convenience to iterate over all the properties of a given node. Signed-off-by: Maxime Ripard Acked-by: Simon Glass [dwg: Removed a stray trailing blank line] Signed-off-by: David Gibson --- libfdt/libfdt.h | 27 +++++++++++ tests/.gitignore | 1 + tests/Makefile.tests | 1 + tests/property_iterate.c | 97 ++++++++++++++++++++++++++++++++++++++ tests/property_iterate.dts | 23 +++++++++ tests/run_tests.sh | 3 ++ 6 files changed, 152 insertions(+) create mode 100644 tests/property_iterate.c create mode 100644 tests/property_iterate.dts diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 911e548..be109a8 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -458,6 +458,33 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset); */ 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) + * + * This is actually a wrapper around a for loop and would be used like so: + * + * fdt_for_each_property_offset(property, fdt, node) { + * Use property + * ... + * } + * + * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) { + * Error handling + * } + * + * Note that this is implemented as a macro and property is used as + * iterator in the loop. The node variable can be constant or even a + * literal. + */ +#define fdt_for_each_property_offset(property, fdt, node) \ + for (property = fdt_first_property_offset(fdt, node); \ + property >= 0; \ + property = fdt_next_property_offset(fdt, property)) + /** * fdt_get_property_by_offset - retrieve the property at a given offset * @fdt: pointer to the device tree blob diff --git a/tests/.gitignore b/tests/.gitignore index e4532da..fa4616b 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -40,6 +40,7 @@ tmp.* /path_offset /path_offset_aliases /phandle_format +/property_iterate /propname_escapes /references /root_node diff --git a/tests/Makefile.tests b/tests/Makefile.tests index f7c3a4b..196518c 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -23,6 +23,7 @@ LIB_TESTS_L = get_mem_rsv \ add_subnode_with_nops path_offset_aliases \ utilfdt_test \ integer-expressions \ + property_iterate \ subnode_iterate LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) diff --git a/tests/property_iterate.c b/tests/property_iterate.c new file mode 100644 index 0000000..0f3959c --- /dev/null +++ b/tests/property_iterate.c @@ -0,0 +1,97 @@ +/* + * libfdt - Flat Device Tree manipulation + * Tests that fdt_next_subnode() works as expected + * + * Copyright (C) 2013 Google, Inc + * + * Copyright (C) 2007 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +static void test_node(void *fdt, int parent_offset) +{ + fdt32_t properties; + const fdt32_t *prop; + int offset, property; + int count; + int len; + + /* + * This property indicates the number of properties in our + * test node to expect + */ + prop = fdt_getprop(fdt, parent_offset, "test-properties", &len); + if (!prop || len != sizeof(fdt32_t)) { + FAIL("Missing/invalid test-properties property at '%s'", + fdt_get_name(fdt, parent_offset, NULL)); + } + properties = cpu_to_fdt32(*prop); + + count = 0; + offset = fdt_first_subnode(fdt, parent_offset); + if (offset < 0) + FAIL("Missing test node\n"); + + fdt_for_each_property_offset(property, fdt, offset) + count++; + + if (count != properties) { + FAIL("Node '%s': Expected %d properties, got %d\n", + fdt_get_name(fdt, parent_offset, NULL), properties, + count); + } +} + +static void check_fdt_next_subnode(void *fdt) +{ + int offset; + int count = 0; + + fdt_for_each_subnode(offset, fdt, 0) { + test_node(fdt, offset); + count++; + } + + if (count != 2) + FAIL("Expected %d tests, got %d\n", 2, count); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + if (argc != 2) + CONFIG("Usage: %s ", argv[0]); + + fdt = load_blob(argv[1]); + if (!fdt) + FAIL("No device tree available"); + + check_fdt_next_subnode(fdt); + + PASS(); +} diff --git a/tests/property_iterate.dts b/tests/property_iterate.dts new file mode 100644 index 0000000..e8f5f8f --- /dev/null +++ b/tests/property_iterate.dts @@ -0,0 +1,23 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <0>; + + test1 { + test-properties = <3>; + + test { + linux,phandle = <0x1>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + test2 { + test-properties = <0>; + + test { + }; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 7eb9b3d..6a2662b 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -269,6 +269,9 @@ libfdt_tests () { run_dtc_test -I dts -O dtb -o subnode_iterate.dtb subnode_iterate.dts run_test subnode_iterate subnode_iterate.dtb + run_dtc_test -I dts -O dtb -o property_iterate.dtb property_iterate.dts + run_test property_iterate property_iterate.dtb + # Tests for behaviour on various sorts of corrupted trees run_test truncated_property From 84e0e1346c68ed85050177c0aef6bc365b77541d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 27 Jul 2016 14:55:55 +0200 Subject: [PATCH 0510/1198] libfdt: Add max phandle retrieval function Add a function to retrieve the highest phandle in a given device tree. Acked-by: Simon Glass Reviewed-by: Stefan Agner Reviewed-by: David Gibson Signed-off-by: Maxime Ripard Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 26 ++++++++++++++++++++++++++ libfdt/libfdt.h | 15 +++++++++++++++ tests/get_phandle.c | 6 ++++++ 3 files changed, 47 insertions(+) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 50cce86..0459098 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -88,6 +88,32 @@ static int _fdt_string_eq(const void *fdt, int stroffset, return (strlen(p) == len) && (memcmp(p, s, len) == 0); } +uint32_t fdt_get_max_phandle(const void *fdt) +{ + uint32_t max_phandle = 0; + int offset; + + for (offset = fdt_next_node(fdt, -1, NULL);; + offset = fdt_next_node(fdt, offset, NULL)) { + uint32_t phandle; + + if (offset == -FDT_ERR_NOTFOUND) + return max_phandle; + + if (offset < 0) + return (uint32_t)-1; + + phandle = fdt_get_phandle(fdt, offset); + if (phandle == (uint32_t)-1) + continue; + + if (phandle > max_phandle) + max_phandle = phandle; + } + + return 0; +} + int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) { FDT_CHECK_HEADER(fdt); diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index be109a8..06b84cc 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -286,6 +286,21 @@ int fdt_move(const void *fdt, void *buf, int bufsize); */ const char *fdt_string(const void *fdt, int stroffset); +/** + * fdt_get_max_phandle - retrieves the highest phandle in a tree + * @fdt: pointer to the device tree blob + * + * fdt_get_max_phandle retrieves the highest phandle in the given + * device tree. This will ignore badly formatted phandles, or phandles + * with a value of 0 or -1. + * + * returns: + * the highest phandle on success + * 0, if no phandle was found in the device tree + * -1, if an error occurred + */ +uint32_t fdt_get_max_phandle(const void *fdt); + /** * fdt_num_mem_rsv - retrieve the number of memory reserve map entries * @fdt: pointer to the device tree blob diff --git a/tests/get_phandle.c b/tests/get_phandle.c index 2079591..22bd7b8 100644 --- a/tests/get_phandle.c +++ b/tests/get_phandle.c @@ -44,6 +44,7 @@ static void check_phandle(void *fdt, const char *path, uint32_t checkhandle) int main(int argc, char *argv[]) { + uint32_t max; void *fdt; test_init(argc, argv); @@ -53,5 +54,10 @@ int main(int argc, char *argv[]) check_phandle(fdt, "/subnode@2", PHANDLE_1); check_phandle(fdt, "/subnode@2/subsubnode@0", PHANDLE_2); + max = fdt_get_max_phandle(fdt); + if (max != PHANDLE_2) + FAIL("fdt_get_max_phandle returned 0x%x instead of 0x%x\n", + max, PHANDLE_2); + PASS(); } From 3e9037aaad44de3008ad77e4549962473ed71c6d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 27 Jul 2016 14:55:56 +0200 Subject: [PATCH 0511/1198] libfdt: Add fdt_getprop_namelen_w Add a function to retrieve a writeable property only by the first characters of its name. Reviewed-by: David Gibson Signed-off-by: Maxime Ripard 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 06b84cc..0189350 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -629,6 +629,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, */ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, const char *name, int namelen, int *lenp); +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, + const char *name, int namelen, + int *lenp) +{ + return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, + namelen, lenp); +} /** * fdt_getprop - retrieve the value of a given property From d877364e4a0f405ef24df7f4d50065c586207f5b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 29 Jul 2016 11:55:48 +0200 Subject: [PATCH 0512/1198] libfdt: Add fdt_setprop_inplace_namelen_partial Add a function to modify inplace only a portion of a property.. This is especially useful when the property is an array of values, and you want to update one of them without changing the DT size. Acked-by: Simon Glass Reviewed-by: David Gibson Signed-off-by: Maxime Ripard [dwg: Remove unnecessary unsigned qualifier, correct a comment] Signed-off-by: David Gibson --- libfdt/fdt_wip.c | 31 ++++++++++++++++++++++++++----- libfdt/libfdt.h | 21 +++++++++++++++++++++ tests/setprop_inplace.c | 10 ++++++++++ tests/testdata.h | 3 +++ 4 files changed, 60 insertions(+), 5 deletions(-) diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c index c5bbb68..6aaab39 100644 --- a/libfdt/fdt_wip.c +++ b/libfdt/fdt_wip.c @@ -55,21 +55,42 @@ #include "libfdt_internal.h" -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, - const void *val, int len) +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, + const char *name, int namelen, + uint32_t idx, const void *val, + int len) { void *propval; int proplen; - propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen); + propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, + &proplen); + if (!propval) + return proplen; + + if (proplen < (len + idx)) + return -FDT_ERR_NOSPACE; + + memcpy((char *)propval + idx, val, len); + return 0; +} + +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + const void *propval; + int proplen; + + propval = fdt_getprop(fdt, nodeoffset, name, &proplen); if (! propval) return proplen; if (proplen != len) return -FDT_ERR_NOSPACE; - memcpy(propval, val, len); - return 0; + return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, + strlen(name), 0, + val, len); } static void _fdt_nop_region(void *start, int len) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 0189350..376e628 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1079,6 +1079,27 @@ int fdt_size_cells(const void *fdt, int nodeoffset); /* Write-in-place functions */ /**********************************************************************/ +/** + * fdt_setprop_inplace_namelen_partial - change a property's value, + * but not its size + * @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 + * @idx: index of the property to change in the array + * @val: pointer to data to replace the property value with + * @len: length of the property value + * + * Identical to fdt_setprop_inplace(), but modifies the given property + * 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. + */ +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, + const char *name, int namelen, + uint32_t idx, const void *val, + int len); + /** * fdt_setprop_inplace - change a property's value, but not its size * @fdt: pointer to the device tree blob diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c index daef182..80447a0 100644 --- a/tests/setprop_inplace.c +++ b/tests/setprop_inplace.c @@ -83,5 +83,15 @@ int main(int argc, char *argv[]) strp = check_getprop(fdt, 0, "prop-str", xlen+1, xstr); verbose_printf("New string value is \"%s\"\n", strp); + err = fdt_setprop_inplace_namelen_partial(fdt, 0, "compatible", + strlen("compatible"), 4, + TEST_STRING_4_PARTIAL, + strlen(TEST_STRING_4_PARTIAL)); + if (err) + FAIL("Failed to set \"compatible\": %s\n", fdt_strerror(err)); + + check_getprop(fdt, 0, "compatible", strlen(TEST_STRING_4_RESULT) + 1, + TEST_STRING_4_RESULT); + PASS(); } diff --git a/tests/testdata.h b/tests/testdata.h index 576974d..3588778 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -21,6 +21,9 @@ #define TEST_STRING_2 "nastystring: \a\b\t\n\v\f\r\\\"" #define TEST_STRING_3 "\xde\xad\xbe\xef" +#define TEST_STRING_4_PARTIAL "foobar" +#define TEST_STRING_4_RESULT "testfoobar" + #define TEST_CHAR1 '\r' #define TEST_CHAR2 'b' #define TEST_CHAR3 '\0' From 36fd7331fb11276c09a6affc0d8cd4977f2fe100 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 22 Aug 2016 18:55:49 +0900 Subject: [PATCH 0513/1198] libfdt: simplify fdt_del_mem_rsv() The variable "err" is unneeded. Signed-off-by: Masahiro Yamada Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 8be02b1..2eed4f5 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -191,17 +191,13 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) int fdt_del_mem_rsv(void *fdt, int n) { struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); - int err; FDT_RW_CHECK_HEADER(fdt); if (n >= fdt_num_mem_rsv(fdt)) return -FDT_ERR_NOTFOUND; - err = _fdt_splice_mem_rsv(fdt, re, 1, 0); - if (err) - return err; - return 0; + return _fdt_splice_mem_rsv(fdt, re, 1, 0); } static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, From 1ed45d40a137299671b8d0c924e87f9c080899d7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sat, 3 Sep 2016 16:28:07 +1000 Subject: [PATCH 0514/1198] dtc: Bump version to 1.4.2 Bump version in preparation for a new release. Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 078ecf6..ee8e3b2 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ # VERSION = 1 PATCHLEVEL = 4 -SUBLEVEL = 1 +SUBLEVEL = 2 EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = From ec02b34c05be04f249ffaaca4b666f5246877dea Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sat, 3 Sep 2016 21:02:30 +1000 Subject: [PATCH 0515/1198] dtc: Makefile improvements for release uploading This has some fixes to the make dist target, and a new make kup target for maintainer convenience uploading new releases. Signed-off-by: David Gibson --- Makefile | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index ee8e3b2..32dcfcf 100644 --- a/Makefile +++ b/Makefile @@ -197,10 +197,26 @@ fdtget: $(FDTGET_OBJS) $(LIBFDT_archive) fdtput: $(FDTPUT_OBJS) $(LIBFDT_archive) dist: - git archive --format=tar --prefix=dtc-v$(dtc_version)/ HEAD \ - > ../dtc-v$(dtc_version).tar - cat ../dtc-v$(dtc_version).tar | \ - gzip -9 > ../dtc-v$(dtc_version).tgz + git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \ + > ../dtc-$(dtc_version).tar + cat ../dtc-$(dtc_version).tar | \ + gzip -9 > ../dtc-$(dtc_version).tar.gz + +# +# Release signing and uploading +# This is for maintainer convenience, don't try this at home. +# +ifeq ($(MAINTAINER),y) +GPG = gpg2 +KUP = kup +KUPDIR = /pub/software/utils/dtc + +kup: dist + $(GPG) --detach-sign --armor -o ../dtc-$(dtc_version).tar.sign \ + ../dtc-$(dtc_version).tar + $(KUP) put ../dtc-$(dtc_version).tar.gz ../dtc-$(dtc_version).tar.sign \ + $(KUPDIR)/dtc-$(dtc_version).tar.gz +endif # # Testsuite rules From 874f40588d3eb7e406521117c6e24d5a3376a77e Mon Sep 17 00:00:00 2001 From: Tim Wang Date: Mon, 18 Jul 2016 15:56:53 +0800 Subject: [PATCH 0516/1198] Implement the -a option to pad dtb aligned There is one condition that need cat the dtb files into one dtb.img which can support several boards use same SoC platform. And the original dtb file size is not aligned to any base. This may cause "Synchronous Abort" when load from a unligned address on some SoC machine, such as ARM. So this patch implement the -a option to pad zero at the end of dtb files and make the dtb size aligned to . Then, the aligned dtbs can cat together and load without "Synchronous Abort". Signed-off-by: Tim Wang Signed-off-by: David Gibson --- dtc.c | 17 ++++++++++++++++- dtc.h | 1 + flattree.c | 17 +++++++++++++---- tests/run_tests.sh | 28 ++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 5 deletions(-) diff --git a/dtc.c b/dtc.c index 5fa23c4..9dcf640 100644 --- a/dtc.c +++ b/dtc.c @@ -30,8 +30,14 @@ int quiet; /* Level of quietness */ 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 phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */ +static int is_power_of_2(int x) +{ + return (x > 0) && ((x & (x - 1)) == 0); +} + static void fill_fullpaths(struct node *tree, const char *prefix) { struct node *child; @@ -53,7 +59,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix) #define FDT_VERSION(version) _FDT_VERSION(version) #define _FDT_VERSION(version) #version static const char usage_synopsis[] = "dtc [options] "; -static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv"; +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:hv"; static struct option const usage_long_opts[] = { {"quiet", no_argument, NULL, 'q'}, {"in-format", a_argument, NULL, 'I'}, @@ -64,6 +70,7 @@ static struct option const usage_long_opts[] = { {"reserve", a_argument, NULL, 'R'}, {"space", a_argument, NULL, 'S'}, {"pad", a_argument, NULL, 'p'}, + {"align", a_argument, NULL, 'a'}, {"boot-cpu", a_argument, NULL, 'b'}, {"force", no_argument, NULL, 'f'}, {"include", a_argument, NULL, 'i'}, @@ -91,6 +98,7 @@ static const char * const usage_opts_help[] = { "\n\tMake space for reserve map entries (for dtb and asm output)", "\n\tMake the blob at least long (extra space)", "\n\tAdd padding to the blob of long (extra space)", + "\n\tMake the blob align to the (extra space)", "\n\tSet the physical boot cpu", "\n\tTry to produce output even if the input tree has errors", "\n\tAdd a path to search for include files", @@ -169,6 +177,7 @@ int main(int argc, char *argv[]) reservenum = 0; minsize = 0; padsize = 0; + alignsize = 0; while ((opt = util_getopt_long()) != EOF) { switch (opt) { @@ -196,6 +205,12 @@ int main(int argc, char *argv[]) case 'p': padsize = strtol(optarg, NULL, 0); break; + case 'a': + alignsize = strtol(optarg, NULL, 0); + if (!is_power_of_2(alignsize)) + die("Invalid argument \"%d\" to -a option\n", + optarg); + break; case 'f': force = true; break; diff --git a/dtc.h b/dtc.h index 56212c8..32009bc 100644 --- a/dtc.h +++ b/dtc.h @@ -53,6 +53,7 @@ extern int quiet; /* Level of quietness */ extern 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 phandle_format; /* Use linux,phandle or phandle properties */ #define PHANDLE_LEGACY 0x1 diff --git a/flattree.c b/flattree.c index 089b976..a9d9520 100644 --- a/flattree.c +++ b/flattree.c @@ -398,15 +398,22 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version) */ if (minsize > 0) { padlen = minsize - fdt32_to_cpu(fdt.totalsize); - if ((padlen < 0) && (quiet < 1)) - fprintf(stderr, - "Warning: blob size %d >= minimum size %d\n", - fdt32_to_cpu(fdt.totalsize), minsize); + if (padlen < 0) { + padlen = 0; + if (quiet < 1) + fprintf(stderr, + "Warning: blob size %d >= minimum size %d\n", + fdt32_to_cpu(fdt.totalsize), minsize); + } } if (padsize > 0) padlen = padsize; + if (alignsize > 0) + padlen = ALIGN(fdt32_to_cpu(fdt.totalsize) + padlen, alignsize) + - fdt32_to_cpu(fdt.totalsize); + if (padlen > 0) { int tsize = fdt32_to_cpu(fdt.totalsize); tsize += padlen; @@ -572,6 +579,8 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version) if (padsize > 0) { fprintf(f, "\t.space\t%d, 0\n", padsize); } + if (alignsize > 0) + asm_emit_align(f, alignsize); emit_label(f, symprefix, "blob_abs_end"); data_free(strbuf); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 6a2662b..a71909c 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -62,6 +62,11 @@ run_test () { base_run_test $VALGRIND $VGSUPP "./$@" } +run_local_test () { + printf "$*: " + base_run_test "$@" +} + run_sh_test () { printf "$*: " base_run_test sh "$@" @@ -110,6 +115,20 @@ run_wrap_error_test () { base_run_test wrap_error "$@" } +# $1: dtb file +# $2: align base +align_test () { + local size=`stat -c %s $1` + local mod=$(($size%$2)) + ( + if [ $mod -eq 0 ] ;then + PASS + else + FAIL + fi + ) +} + run_dtc_test () { printf "dtc $*: " base_run_test wrap_test $VALGRIND $DTC "$@" @@ -503,6 +522,15 @@ dtc_tests () { -o search_paths_b.dtb search_paths_b.dts run_dtc_test -I dts -O dtb -o search_paths_subdir.dtb \ search_dir_b/search_paths_subdir.dts + + # Check -a option + local alignbase=64 + # -p -a + run_dtc_test -O dtb -p 1000 -a $alignbase -o align0.dtb subnode_iterate.dts + run_local_test align_test align0.dtb alignbase + # -S -a + run_dtc_test -O dtb -S 1999 -a $alignbase -o align1.dtb subnode_iterate.dts + run_local_test align_test align1.dtb alignbase } cmp_tests () { From a34bb721caca10964cb7d22b9d9322b0424c9042 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 22 Sep 2016 14:42:42 +1000 Subject: [PATCH 0517/1198] dtc: Fix assorted problems in the testcases for the -a option We just added the -a option to allow padding of the output dtb's size to a specified alignment. Unfortunately the test cases for this had several bugs: * Didn't actually test anything since "alignbase" instead of $alignbase was passed to the checker function * Introduced an unnecessary run_local_test wrapper * Didn't provide very helpful output on failure * Only attempted to check one alignment value This patch fixes up these problems. Signed-off-by: David Gibson --- tests/run_tests.sh | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index a71909c..f4b32e4 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -62,11 +62,6 @@ run_test () { base_run_test $VALGRIND $VGSUPP "./$@" } -run_local_test () { - printf "$*: " - base_run_test "$@" -} - run_sh_test () { printf "$*: " base_run_test sh "$@" @@ -117,14 +112,15 @@ run_wrap_error_test () { # $1: dtb file # $2: align base -align_test () { - local size=`stat -c %s $1` - local mod=$(($size%$2)) +check_align () { + shorten_echo "check_align $@: " + local size=$(stat -c %s "$1") + local align="$2" ( - if [ $mod -eq 0 ] ;then + if [ $(($size % $align)) -eq 0 ] ;then PASS else - FAIL + FAIL "Output size $size is not $align-byte aligned" fi ) } @@ -524,13 +520,14 @@ dtc_tests () { search_dir_b/search_paths_subdir.dts # Check -a option - local alignbase=64 - # -p -a - run_dtc_test -O dtb -p 1000 -a $alignbase -o align0.dtb subnode_iterate.dts - run_local_test align_test align0.dtb alignbase - # -S -a - run_dtc_test -O dtb -S 1999 -a $alignbase -o align1.dtb subnode_iterate.dts - run_local_test align_test align1.dtb alignbase + for align in 2 4 8 16 32 64; do + # -p -a + run_dtc_test -O dtb -p 1000 -a $align -o align0.dtb subnode_iterate.dts + check_align align0.dtb $align + # -S -a + run_dtc_test -O dtb -S 1999 -a $align -o align1.dtb subnode_iterate.dts + check_align align1.dtb $align + done } cmp_tests () { From 45fd440a956112c78dc3b602e3a618f22f495db2 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 26 Sep 2016 18:12:26 +0200 Subject: [PATCH 0518/1198] Fix some typing errors in libfdt.h and livetree.c Correct some typos discovered with the codespell utility. Signed-off-by: Thomas Huth Signed-off-by: David Gibson --- libfdt/libfdt.h | 4 ++-- livetree.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 376e628..ecb11fc 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -61,7 +61,7 @@ #define FDT_ERR_NOTFOUND 1 /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ #define FDT_ERR_EXISTS 2 - /* FDT_ERR_EXISTS: Attemped to create a node or property which + /* FDT_ERR_EXISTS: Attempted to create a node or property which * already exists */ #define FDT_ERR_NOSPACE 3 /* FDT_ERR_NOSPACE: Operation needed to expand the device @@ -700,7 +700,7 @@ const char *fdt_get_alias_namelen(const void *fdt, const char *name, int namelen); /** - * fdt_get_alias - retreive the path referenced by a given alias + * 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 * diff --git a/livetree.c b/livetree.c index e229b84..3dc7559 100644 --- a/livetree.c +++ b/livetree.c @@ -204,7 +204,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) } } - /* if no collision occured, add child to the old node. */ + /* if no collision occurred, add child to the old node. */ if (new_child) add_child(old_node, new_child); } From 6d1832c9e64bc464d08c62bbd082ba06986476cb Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 28 Sep 2016 11:29:07 +1000 Subject: [PATCH 0519/1198] dtc: Remove "home page" link The supposed home page hasn't existed for some time. We don't really have anything else, so remove the link from the README. Signed-off-by: David Gibson --- README | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README b/README index 979974a..f92008f 100644 --- a/README +++ b/README @@ -14,7 +14,3 @@ mailto:devicetree-compiler@vger.kernel.org Core device tree bindings are discussed on the devicetree-spec list: mailto:devicetree-spec@vger.kernel.org - -Home Page ---------- -http://devicetree.org/Device_Tree_Compiler From 4aa3a6f5e6d92179099d466422c450ebc12e5b1a Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 30 Sep 2016 15:57:14 +0200 Subject: [PATCH 0520/1198] libfdt: Add new errors for the overlay code Add a few new error codes to report the failure conditions we might encounter in the overlay application code: - FDT_ERR_BADOVERLAY, when an overlay cannot be parsed, even though its structure is correct - FDT_ERR_NOPHANDLES, when we ran out of available phandles and we cannot use a new phandle without either using an invalid one (-1 or 0), or one already used. Signed-off-by: Maxime Ripard Signed-off-by: David Gibson --- libfdt/fdt_strerror.c | 3 +++ libfdt/libfdt.h | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c index e6c3cee..3cb357f 100644 --- a/libfdt/fdt_strerror.c +++ b/libfdt/fdt_strerror.c @@ -76,6 +76,9 @@ static struct fdt_errtabent fdt_errtable[] = { FDT_ERRTABENT(FDT_ERR_BADVERSION), FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), FDT_ERRTABENT(FDT_ERR_BADLAYOUT), + FDT_ERRTABENT(FDT_ERR_BADOVERLAY), + FDT_ERRTABENT(FDT_ERR_BADOVERLAY), + FDT_ERRTABENT(FDT_ERR_NOPHANDLES), }; #define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index ecb11fc..361cc6c 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -126,7 +126,16 @@ * value. For example: a property expected to contain a string list * is not NUL-terminated within the length of its value. */ -#define FDT_ERR_MAX 15 +#define FDT_ERR_BADOVERLAY 16 + /* FDT_ERR_BADOVERLAY: The device tree overlay, while + * correctly structured, cannot be applied due to some + * unexpected or missing value, property or node. */ + +#define FDT_ERR_NOPHANDLES 17 + /* FDT_ERR_NOPHANDLES: The device tree doesn't have any + * phandle available anymore without causing an overflow */ + +#define FDT_ERR_MAX 17 /**********************************************************************/ /* Low-level functions (you probably don't need these) */ From 39240cc865cfbd4aecf86e33a72156f7fc043df3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 30 Sep 2016 15:57:15 +0200 Subject: [PATCH 0521/1198] libfdt: Extend the reach of FDT_ERR_BADPHANDLE So far, the BADPHANDLE error was only used for incorrect phandle values. Extend that meaning to an improperly formatted phandle property. Signed-off-by: Maxime Ripard Signed-off-by: David Gibson --- libfdt/libfdt.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 361cc6c..d2e5e03 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -79,8 +79,10 @@ * (e.g. missing a leading / for a function which requires an * absolute path) */ #define FDT_ERR_BADPHANDLE 6 - /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle - * value. phandle values of 0 and -1 are not permitted. */ + /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle. + * This can be caused either by an invalid phandle property + * length, or the phandle value was either 0 or -1, which are + * not permitted. */ #define FDT_ERR_BADSTATE 7 /* FDT_ERR_BADSTATE: Function was passed an incomplete device * tree created by the sequential-write functions, which is From 0cdd06c5135bd9f46853c2f58ad2ac91b0fa87f3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 30 Sep 2016 15:57:16 +0200 Subject: [PATCH 0522/1198] libfdt: Add overlay application function The device tree overlays are a good way to deal with user-modifyable boards or boards with some kind of an expansion mechanism where we can easily plug new board in (like the BBB, the Raspberry Pi or the CHIP). Add a new function to merge overlays with a base device tree. Signed-off-by: Maxime Ripard Signed-off-by: David Gibson --- libfdt/Makefile.libfdt | 2 +- libfdt/fdt_overlay.c | 670 +++++++++++++++++++++++++++++++++++++++++ libfdt/libfdt.h | 31 ++ libfdt/libfdt_env.h | 1 + 4 files changed, 703 insertions(+), 1 deletion(-) create mode 100644 libfdt/fdt_overlay.c diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index 09c322e..098b3f3 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -7,5 +7,5 @@ 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_addresses.c fdt_overlay.c LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c new file mode 100644 index 0000000..c7e5508 --- /dev/null +++ b/libfdt/fdt_overlay.c @@ -0,0 +1,670 @@ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +/** + * overlay_get_target_phandle - retrieves the target phandle of a fragment + * @fdto: pointer to the device tree overlay blob + * @fragment: node offset of the fragment in the overlay + * + * overlay_get_target_phandle() retrieves the target phandle of an + * overlay fragment when that fragment uses a phandle (target + * property) instead of a path (target-path property). + * + * returns: + * the phandle pointed by the target property + * 0, if the phandle was not found + * -1, if the phandle was malformed + */ +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) +{ + const uint32_t *val; + int len; + + val = fdt_getprop(fdto, fragment, "target", &len); + if (!val) + return 0; + + if ((len != sizeof(*val)) || (*val == (uint32_t)-1)) + return (uint32_t)-1; + + 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 + * + * overlay_get_target() retrieves the target offset in the base + * device tree of a fragment, no matter how the actual targetting is + * done (through a phandle or a path) + * + * returns: + * the targetted 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) +{ + uint32_t phandle; + const char *path; + int path_len; + + /* Try first to do a phandle based lookup */ + phandle = overlay_get_target_phandle(fdto, fragment); + if (phandle == (uint32_t)-1) + return -FDT_ERR_BADPHANDLE; + + if (phandle) + return fdt_node_offset_by_phandle(fdt, phandle); + + /* And then a path based lookup */ + path = fdt_getprop(fdto, fragment, "target-path", &path_len); + if (!path) { + /* + * If we haven't found either a target or a + * target-path property in a node that contains a + * __overlay__ subnode (we wouldn't be called + * otherwise), consider it a improperly written + * overlay + */ + if (path_len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + + return path_len; + } + + return fdt_path_offset(fdt, path); +} + +/** + * overlay_phandle_add_offset - Increases a phandle by an offset + * @fdt: Base device tree blob + * @node: Device tree overlay blob + * @name: Name of the property to modify (phandle or linux,phandle) + * @delta: offset to apply + * + * overlay_phandle_add_offset() increments a node phandle by a given + * offset. + * + * returns: + * 0 on success. + * Negative error code on error + */ +static int overlay_phandle_add_offset(void *fdt, int node, + const char *name, uint32_t delta) +{ + const uint32_t *val; + uint32_t adj_val; + int len; + + val = fdt_getprop(fdt, node, name, &len); + if (!val) + return len; + + if (len != sizeof(*val)) + return -FDT_ERR_BADPHANDLE; + + adj_val = fdt32_to_cpu(*val); + if ((adj_val + delta) < adj_val) + 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); +} + +/** + * overlay_adjust_node_phandles - Offsets the phandles of a node + * @fdto: Device tree overlay blob + * @node: Offset of the node we want to adjust + * @delta: Offset to shift the phandles of + * + * overlay_adjust_node_phandles() adds a constant to all the phandles + * of a given node. This is mainly use as part of the overlay + * application process, when we want to update all the overlay + * phandles to not conflict with the overlays of the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_adjust_node_phandles(void *fdto, int node, + uint32_t delta) +{ + int child; + int ret; + + ret = overlay_phandle_add_offset(fdto, node, "phandle", delta); + if (ret && ret != -FDT_ERR_NOTFOUND) + return ret; + + ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta); + if (ret && ret != -FDT_ERR_NOTFOUND) + return ret; + + fdt_for_each_subnode(child, fdto, node) { + ret = overlay_adjust_node_phandles(fdto, child, delta); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay + * @fdto: Device tree overlay blob + * @delta: Offset to shift the phandles of + * + * overlay_adjust_local_phandles() adds a constant to all the + * phandles of an overlay. This is mainly use as part of the overlay + * application process, when we want to update all the overlay + * phandles to not conflict with the overlays of the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta) +{ + /* + * Start adjusting the phandles from the overlay root + */ + return overlay_adjust_node_phandles(fdto, 0, delta); +} + +/** + * overlay_update_local_node_references - Adjust the overlay references + * @fdto: Device tree overlay blob + * @tree_node: Node offset of the node to operate on + * @fixup_node: Node offset of the matching local fixups node + * @delta: Offset to shift the phandles of + * + * overlay_update_local_nodes_references() update the phandles + * pointing to a node within the device tree overlay by adding a + * constant delta. + * + * This is mainly used as part of a device tree application process, + * where you want the device tree overlays phandles to not conflict + * with the ones from the base device tree before merging them. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_update_local_node_references(void *fdto, + int tree_node, + int fixup_node, + uint32_t delta) +{ + int fixup_prop; + int fixup_child; + int ret; + + fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { + const uint32_t *fixup_val; + const char *tree_val; + const char *name; + 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; + + tree_val = fdt_getprop(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 / sizeof(uint32_t)); i++) { + uint32_t adj_val, index; + + index = fdt32_to_cpu(fixup_val[i]); + + /* + * phandles to fixup can be unaligned. + * + * Use a memcpy for the architectures that do + * not support unaligned accesses. + */ + memcpy(&adj_val, tree_val + index, sizeof(adj_val)); + + adj_val = fdt32_to_cpu(adj_val); + adj_val += delta; + adj_val = cpu_to_fdt32(adj_val); + + ret = fdt_setprop_inplace_namelen_partial(fdto, + tree_node, + name, + strlen(name), + index, + &adj_val, + sizeof(adj_val)); + if (ret == -FDT_ERR_NOSPACE) + return -FDT_ERR_BADOVERLAY; + + if (ret) + return ret; + } + } + + 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 < 0) + return tree_child; + + ret = overlay_update_local_node_references(fdto, + tree_child, + fixup_child, + delta); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_update_local_references - Adjust the overlay references + * @fdto: Device tree overlay blob + * @delta: Offset to shift the phandles of + * + * overlay_update_local_references() update all the phandles pointing + * to a node within the device tree overlay by adding a constant + * delta to not conflict with the base overlay. + * + * This is mainly used as part of a device tree application process, + * where you want the device tree overlays phandles to not conflict + * with the ones from the base device tree before merging them. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_update_local_references(void *fdto, uint32_t delta) +{ + int fixups; + + fixups = fdt_path_offset(fdto, "/__local_fixups__"); + if (fixups < 0) { + /* There's no local phandles to adjust, bail out */ + if (fixups == -FDT_ERR_NOTFOUND) + return 0; + + return fixups; + } + + /* + * Update our local references from the root of the tree + */ + return overlay_update_local_node_references(fdto, 0, fixups, + 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 + * @path_len: number of path characters to consider + * @name: Name of the property holding the phandle reference in the overlay + * @name_len: number of name characters to consider + * @index: Index in the overlay property where the phandle is stored + * @label: Label of the node referenced by the phandle + * + * overlay_fixup_one_phandle() resolves an overlay phandle pointing to + * a node in the base device tree. + * + * This is part of the device tree overlay application process, when + * you want all the phandles in the overlay to point to the actual + * base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +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 index, const char *label) +{ + const char *symbol_path; + uint32_t phandle; + int symbol_off, fixup_off; + int prop_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; + + fixup_off = fdt_path_offset_namelen(fdto, path, path_len); + if (fixup_off == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + if (fixup_off < 0) + return fixup_off; + + phandle = cpu_to_fdt32(phandle); + return fdt_setprop_inplace_namelen_partial(fdto, fixup_off, + name, name_len, index, + &phandle, sizeof(phandle)); +}; + +/** + * overlay_fixup_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 + * @property: Property offset in the overlay holding the list of fixups + * + * overlay_fixup_phandle() resolves all the overlay phandles pointed + * to in a __fixups__ property, and updates them to match the phandles + * in use in the base device tree. + * + * This is part of the device tree overlay application process, when + * you want all the phandles in the overlay to point to the actual + * base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, + int property) +{ + const char *value; + const char *label; + int len; + + value = fdt_getprop_by_offset(fdto, property, + &label, &len); + if (!value) { + if (len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + + return len; + } + + do { + const char *path, *name, *fixup_end; + const char *fixup_str = value; + uint32_t path_len, name_len; + uint32_t fixup_len; + char *sep, *endptr; + int index, ret; + + fixup_end = memchr(value, '\0', len); + if (!fixup_end) + return -FDT_ERR_BADOVERLAY; + fixup_len = fixup_end - fixup_str; + + len -= fixup_len + 1; + value += fixup_len + 1; + + path = fixup_str; + sep = memchr(fixup_str, ':', fixup_len); + if (!sep || *sep != ':') + return -FDT_ERR_BADOVERLAY; + + path_len = sep - path; + if (path_len == (fixup_len - 1)) + return -FDT_ERR_BADOVERLAY; + + fixup_len -= path_len + 1; + name = sep + 1; + sep = memchr(name, ':', fixup_len); + if (!sep || *sep != ':') + return -FDT_ERR_BADOVERLAY; + + name_len = sep - name; + if (!name_len) + return -FDT_ERR_BADOVERLAY; + + index = strtoul(sep + 1, &endptr, 10); + if ((*endptr != '\0') || (endptr <= (sep + 1))) + return -FDT_ERR_BADOVERLAY; + + ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off, + path, path_len, name, name_len, + index, label); + if (ret) + return ret; + } while (len > 0); + + return 0; +} + +/** + * overlay_fixup_phandles - Resolve the overlay phandles to the base + * device tree + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_fixup_phandles() resolves all the overlay phandles pointing + * to nodes in the base device tree. + * + * This is one of the steps of the device tree overlay application + * process, when you want all the phandles in the overlay to point to + * the actual base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_phandles(void *fdt, void *fdto) +{ + int fixups_off, symbols_off; + int property; + + /* We can have overlays without any fixups */ + fixups_off = fdt_path_offset(fdto, "/__fixups__"); + if (fixups_off == -FDT_ERR_NOTFOUND) + return 0; + if (fixups_off < 0) + return fixups_off; + + symbols_off = fdt_path_offset(fdt, "/__symbols__"); + if (symbols_off < 0) + return symbols_off; + + fdt_for_each_property_offset(property, fdto, fixups_off) { + int ret; + + ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_apply_node - Merges a node into the base device tree + * @fdt: Base Device Tree blob + * @target: Node offset in the base device tree to apply the fragment to + * @fdto: Device tree overlay blob + * @node: Node offset in the overlay holding the changes to merge + * + * overlay_apply_node() merges a node into a target base device tree + * node pointed. + * + * This is part of the final step in the device tree overlay + * application process, when all the phandles have been adjusted and + * resolved and you just have to merge overlay into the base device + * tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_apply_node(void *fdt, int target, + void *fdto, int node) +{ + int property; + int subnode; + + fdt_for_each_property_offset(property, fdto, node) { + const char *name; + const void *prop; + int prop_len; + int ret; + + prop = fdt_getprop_by_offset(fdto, property, &name, + &prop_len); + if (prop_len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + if (prop_len < 0) + return prop_len; + + ret = fdt_setprop(fdt, target, name, prop, prop_len); + if (ret) + return ret; + } + + fdt_for_each_subnode(subnode, fdto, node) { + const char *name = fdt_get_name(fdto, subnode, NULL); + int nnode; + int ret; + + nnode = fdt_add_subnode(fdt, target, name); + if (nnode == -FDT_ERR_EXISTS) { + nnode = fdt_subnode_offset(fdt, target, name); + if (nnode == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + } + + if (nnode < 0) + return nnode; + + ret = overlay_apply_node(fdt, nnode, fdto, subnode); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_merge - Merge an overlay into its base device tree + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_merge() merges an overlay into its base device tree. + * + * This is the final step in the device tree overlay application + * process, when all the phandles have been adjusted and resolved and + * you just have to merge overlay into the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_merge(void *fdt, void *fdto) +{ + int fragment; + + fdt_for_each_subnode(fragment, fdto, 0) { + int overlay; + int target; + int ret; + + /* + * Each fragments will have an __overlay__ node. If + * they don't, it's not supposed to be merged + */ + overlay = fdt_subnode_offset(fdto, fragment, "__overlay__"); + if (overlay == -FDT_ERR_NOTFOUND) + continue; + + if (overlay < 0) + return overlay; + + target = overlay_get_target(fdt, fdto, fragment); + if (target < 0) + return target; + + ret = overlay_apply_node(fdt, target, fdto, overlay); + if (ret) + return ret; + } + + return 0; +} + +int fdt_overlay_apply(void *fdt, void *fdto) +{ + uint32_t delta = fdt_get_max_phandle(fdt); + int ret; + + FDT_CHECK_HEADER(fdt); + FDT_CHECK_HEADER(fdto); + + ret = overlay_adjust_local_phandles(fdto, delta); + if (ret) + goto err; + + ret = overlay_update_local_references(fdto, delta); + if (ret) + goto err; + + ret = overlay_fixup_phandles(fdt, fdto); + if (ret) + goto err; + + ret = overlay_merge(fdt, fdto); + if (ret) + goto err; + + /* + * The overlay has been damaged, erase its magic. + */ + fdt_set_magic(fdto, ~0); + + return 0; + +err: + /* + * The overlay might have been damaged, erase its magic. + */ + fdt_set_magic(fdto, ~0); + + /* + * The base device tree might have been damaged, erase its + * magic. + */ + fdt_set_magic(fdt, ~0); + + return ret; +} diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index d2e5e03..c69e918 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1763,6 +1763,37 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name); */ int fdt_del_node(void *fdt, int nodeoffset); +/** + * fdt_overlay_apply - Applies a DT overlay on a base DT + * @fdt: pointer to the base device tree blob + * @fdto: pointer to the device tree overlay blob + * + * fdt_overlay_apply() will apply the given device tree overlay on the + * given base device tree. + * + * Expect the base device tree to be modified, even if the function + * returns an error. + * + * 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 + * properties in the base DT + * -FDT_ERR_BADPHANDLE, + * -FDT_ERR_BADOVERLAY, + * -FDT_ERR_NOPHANDLES, + * -FDT_ERR_INTERNAL, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADOFFSET, + * -FDT_ERR_BADPATH, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_overlay_apply(void *fdt, void *fdto); + /**********************************************************************/ /* Debugging / informational functions */ /**********************************************************************/ diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h index 9dea97d..99f936d 100644 --- a/libfdt/libfdt_env.h +++ b/libfdt/libfdt_env.h @@ -54,6 +54,7 @@ #include #include +#include #include #ifdef __CHECKER__ From aea8860d831ed05a147a1896c15e1312a9a66917 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 30 Sep 2016 15:57:17 +0200 Subject: [PATCH 0523/1198] tests: Add tests cases for the overlay code Add some test infrastructure to test that the overlay can be merged, but also that poorly formatted fixups would fail as expected. Signed-off-by: Maxime Ripard [dwg: Don't execute bad overlay tests without overlay aware dtc] Signed-off-by: David Gibson --- tests/.gitignore | 2 + tests/Makefile.tests | 3 +- tests/overlay.c | 232 ++++++++++++++++++++ tests/overlay_bad_fixup.c | 70 ++++++ tests/overlay_bad_fixup_bad_index.dts | 14 ++ tests/overlay_bad_fixup_base.dtsi | 18 ++ tests/overlay_bad_fixup_empty.dts | 14 ++ tests/overlay_bad_fixup_empty_index.dts | 14 ++ tests/overlay_bad_fixup_index_trailing.dts | 14 ++ tests/overlay_bad_fixup_path_empty_prop.dts | 14 ++ tests/overlay_bad_fixup_path_only.dts | 14 ++ tests/overlay_bad_fixup_path_only_sep.dts | 14 ++ tests/overlay_bad_fixup_path_prop.dts | 14 ++ tests/overlay_base.dts | 21 ++ tests/overlay_overlay_dtc.dts | 85 +++++++ tests/overlay_overlay_nodtc.dts | 82 +++++++ tests/run_tests.sh | 32 +++ 17 files changed, 656 insertions(+), 1 deletion(-) create mode 100644 tests/overlay.c create mode 100644 tests/overlay_bad_fixup.c create mode 100644 tests/overlay_bad_fixup_bad_index.dts create mode 100644 tests/overlay_bad_fixup_base.dtsi create mode 100644 tests/overlay_bad_fixup_empty.dts create mode 100644 tests/overlay_bad_fixup_empty_index.dts create mode 100644 tests/overlay_bad_fixup_index_trailing.dts create mode 100644 tests/overlay_bad_fixup_path_empty_prop.dts create mode 100644 tests/overlay_bad_fixup_path_only.dts create mode 100644 tests/overlay_bad_fixup_path_only_sep.dts create mode 100644 tests/overlay_bad_fixup_path_prop.dts create mode 100644 tests/overlay_base.dts create mode 100644 tests/overlay_overlay_dtc.dts create mode 100644 tests/overlay_overlay_nodtc.dts diff --git a/tests/.gitignore b/tests/.gitignore index fa4616b..354b565 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -35,6 +35,8 @@ tmp.* /nopulate /notfound /open_pack +/overlay +/overlay_bad_fixup /parent_offset /path-references /path_offset diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 196518c..eb039c5 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -24,7 +24,8 @@ LIB_TESTS_L = get_mem_rsv \ utilfdt_test \ integer-expressions \ property_iterate \ - subnode_iterate + subnode_iterate \ + overlay overlay_bad_fixup LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property diff --git a/tests/overlay.c b/tests/overlay.c new file mode 100644 index 0000000..e467b03 --- /dev/null +++ b/tests/overlay.c @@ -0,0 +1,232 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for DT overlays() + * Copyright (C) 2016 Free Electrons + * Copyright (C) 2016 NextThing Co. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include + +#include "tests.h" + +#define CHECK(code) \ + { \ + if (code) \ + FAIL(#code ": %s", fdt_strerror(code)); \ + } + +/* 4k ought to be enough for anybody */ +#define FDT_COPY_SIZE (4 * 1024) + +static int fdt_getprop_u32_by_index(void *fdt, const char *path, + const char *name, int index, + unsigned long *out) +{ + const fdt32_t *val; + int node_off; + int len; + + node_off = fdt_path_offset(fdt, path); + if (node_off < 0) + return node_off; + + val = fdt_getprop(fdt, node_off, name, &len); + if (!val || (len < (sizeof(uint32_t) * (index + 1)))) + return -FDT_ERR_NOTFOUND; + + *out = fdt32_to_cpu(*(val + index)); + + return 0; +} + +static int check_getprop_string_by_name(void *fdt, const char *path, + const char *name, const char *val) +{ + int node_off; + + node_off = fdt_path_offset(fdt, path); + if (node_off < 0) + return node_off; + + check_getprop_string(fdt, node_off, name, val); + + return 0; +} + +static int check_getprop_u32_by_name(void *fdt, const char *path, + const char *name, uint32_t val) +{ + int node_off; + + node_off = fdt_path_offset(fdt, path); + CHECK(node_off < 0); + + check_getprop_cell(fdt, node_off, name, val); + + return 0; +} + +static int check_getprop_null_by_name(void *fdt, const char *path, + const char *name) +{ + int node_off; + + node_off = fdt_path_offset(fdt, path); + CHECK(node_off < 0); + + check_property(fdt, node_off, name, 0, NULL); + + return 0; +} + +static int fdt_overlay_change_int_property(void *fdt) +{ + return check_getprop_u32_by_name(fdt, "/test-node", "test-int-property", + 43); +} + +static int fdt_overlay_change_str_property(void *fdt) +{ + return check_getprop_string_by_name(fdt, "/test-node", + "test-str-property", "foobar"); +} + +static int fdt_overlay_add_str_property(void *fdt) +{ + return check_getprop_string_by_name(fdt, "/test-node", + "test-str-property-2", "foobar2"); +} + +static int fdt_overlay_add_node(void *fdt) +{ + return check_getprop_null_by_name(fdt, "/test-node/new-node", + "new-property"); +} + +static int fdt_overlay_add_subnode_property(void *fdt) +{ + check_getprop_null_by_name(fdt, "/test-node/sub-test-node", + "sub-test-property"); + check_getprop_null_by_name(fdt, "/test-node/sub-test-node", + "new-sub-test-property"); + + return 0; +} + +static int fdt_overlay_local_phandle(void *fdt) +{ + uint32_t local_phandle; + unsigned long val = 0; + int off; + + off = fdt_path_offset(fdt, "/test-node/new-local-node"); + CHECK(off < 0); + + local_phandle = fdt_get_phandle(fdt, off); + CHECK(!local_phandle); + + CHECK(fdt_getprop_u32_by_index(fdt, "/test-node", + "test-several-phandle", + 0, &val)); + CHECK(val != local_phandle); + + CHECK(fdt_getprop_u32_by_index(fdt, "/test-node", + "test-several-phandle", + 1, &val)); + CHECK(val != local_phandle); + + return 0; +} + +static int fdt_overlay_local_phandles(void *fdt) +{ + uint32_t local_phandle, test_phandle; + unsigned long val = 0; + int off; + + off = fdt_path_offset(fdt, "/test-node/new-local-node"); + CHECK(off < 0); + + local_phandle = fdt_get_phandle(fdt, off); + CHECK(!local_phandle); + + off = fdt_path_offset(fdt, "/test-node"); + CHECK(off < 0); + + test_phandle = fdt_get_phandle(fdt, off); + CHECK(!test_phandle); + + CHECK(fdt_getprop_u32_by_index(fdt, "/test-node", + "test-phandle", 0, &val)); + CHECK(test_phandle != val); + + CHECK(fdt_getprop_u32_by_index(fdt, "/test-node", + "test-phandle", 1, &val)); + CHECK(local_phandle != val); + + return 0; +} + +static void *open_dt(char *path) +{ + void *dt, *copy; + + dt = load_blob(path); + copy = xmalloc(FDT_COPY_SIZE); + + /* + * Resize our DTs to 4k so that we have room to operate on + */ + CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE)); + + return copy; +} + +int main(int argc, char *argv[]) +{ + void *fdt_base, *fdt_overlay; + + test_init(argc, argv); + if (argc != 3) + CONFIG("Usage: %s ", argv[0]); + + fdt_base = open_dt(argv[1]); + fdt_overlay = open_dt(argv[2]); + + /* Apply the overlay */ + CHECK(fdt_overlay_apply(fdt_base, fdt_overlay)); + + fdt_overlay_change_int_property(fdt_base); + fdt_overlay_change_str_property(fdt_base); + fdt_overlay_add_str_property(fdt_base); + fdt_overlay_add_node(fdt_base); + fdt_overlay_add_subnode_property(fdt_base); + + /* + * If the base tree has a __symbols__ node, do the tests that + * are only successful with a proper phandle support, and thus + * dtc -@ + */ + if (fdt_path_offset(fdt_base, "/__symbols__") >= 0) { + fdt_overlay_local_phandle(fdt_base); + fdt_overlay_local_phandles(fdt_base); + } + + PASS(); +} diff --git a/tests/overlay_bad_fixup.c b/tests/overlay_bad_fixup.c new file mode 100644 index 0000000..5014f5e --- /dev/null +++ b/tests/overlay_bad_fixup.c @@ -0,0 +1,70 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for DT overlays() + * Copyright (C) 2016 Free Electrons + * Copyright (C) 2016 NextThing Co. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include + +#include "tests.h" + +#define CHECK(code, expected) \ + { \ + err = (code); \ + if (err != expected) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } + +/* 4k ought to be enough for anybody */ +#define FDT_COPY_SIZE (4 * 1024) + +static void *open_dt(char *path) +{ + void *dt, *copy; + int err; + + dt = load_blob(path); + copy = xmalloc(FDT_COPY_SIZE); + + /* + * Resize our DTs to 4k so that we have room to operate on + */ + CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE), 0); + + return copy; +} + +int main(int argc, char *argv[]) +{ + void *fdt_base, *fdt_overlay; + int err; + + test_init(argc, argv); + if (argc != 3) + CONFIG("Usage: %s ", argv[0]); + + fdt_base = open_dt(argv[1]); + fdt_overlay = open_dt(argv[2]); + + /* Apply the overlay */ + CHECK(fdt_overlay_apply(fdt_base, fdt_overlay), -FDT_ERR_BADOVERLAY); + + PASS(); +} diff --git a/tests/overlay_bad_fixup_bad_index.dts b/tests/overlay_bad_fixup_bad_index.dts new file mode 100644 index 0000000..b5cf131 --- /dev/null +++ b/tests/overlay_bad_fixup_bad_index.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/include/ "overlay_bad_fixup_base.dtsi" + +/ { + __fixups__ { + test = "/fragment@0:target:ab"; + }; +}; diff --git a/tests/overlay_bad_fixup_base.dtsi b/tests/overlay_bad_fixup_base.dtsi new file mode 100644 index 0000000..216bcab --- /dev/null +++ b/tests/overlay_bad_fixup_base.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +/ { + fragment@0 { + target = <0xffffffff>; + + __overlay__ { + test-property; + }; + }; +}; diff --git a/tests/overlay_bad_fixup_empty.dts b/tests/overlay_bad_fixup_empty.dts new file mode 100644 index 0000000..e111db4 --- /dev/null +++ b/tests/overlay_bad_fixup_empty.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/include/ "overlay_bad_fixup_base.dtsi" + +/ { + __fixups__ { + test = ""; + }; +}; diff --git a/tests/overlay_bad_fixup_empty_index.dts b/tests/overlay_bad_fixup_empty_index.dts new file mode 100644 index 0000000..9e12e21 --- /dev/null +++ b/tests/overlay_bad_fixup_empty_index.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/include/ "overlay_bad_fixup_base.dtsi" + +/ { + __fixups__ { + test = "/fragment@0:target:"; + }; +}; diff --git a/tests/overlay_bad_fixup_index_trailing.dts b/tests/overlay_bad_fixup_index_trailing.dts new file mode 100644 index 0000000..f586bef --- /dev/null +++ b/tests/overlay_bad_fixup_index_trailing.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/include/ "overlay_bad_fixup_base.dtsi" + +/ { + __fixups__ { + test = "/fragment@0:target:0a"; + }; +}; diff --git a/tests/overlay_bad_fixup_path_empty_prop.dts b/tests/overlay_bad_fixup_path_empty_prop.dts new file mode 100644 index 0000000..608b5f9 --- /dev/null +++ b/tests/overlay_bad_fixup_path_empty_prop.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/include/ "overlay_bad_fixup_base.dtsi" + +/ { + __fixups__ { + test = "/fragment@0::"; + }; +}; diff --git a/tests/overlay_bad_fixup_path_only.dts b/tests/overlay_bad_fixup_path_only.dts new file mode 100644 index 0000000..2485dd9 --- /dev/null +++ b/tests/overlay_bad_fixup_path_only.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/include/ "overlay_bad_fixup_base.dtsi" + +/ { + __fixups__ { + test = "/fragment@0"; + }; +}; diff --git a/tests/overlay_bad_fixup_path_only_sep.dts b/tests/overlay_bad_fixup_path_only_sep.dts new file mode 100644 index 0000000..3cbf6c4 --- /dev/null +++ b/tests/overlay_bad_fixup_path_only_sep.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/include/ "overlay_bad_fixup_base.dtsi" + +/ { + __fixups__ { + test = "/fragment@0:"; + }; +}; diff --git a/tests/overlay_bad_fixup_path_prop.dts b/tests/overlay_bad_fixup_path_prop.dts new file mode 100644 index 0000000..ca79b52 --- /dev/null +++ b/tests/overlay_bad_fixup_path_prop.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/include/ "overlay_bad_fixup_base.dtsi" + +/ { + __fixups__ { + test = "/fragment@0:target"; + }; +}; diff --git a/tests/overlay_base.dts b/tests/overlay_base.dts new file mode 100644 index 0000000..2603adb --- /dev/null +++ b/tests/overlay_base.dts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +/ { + test: test-node { + test-int-property = <42>; + test-str-property = "foo"; + + subtest: sub-test-node { + sub-test-property; + }; + }; +}; + + diff --git a/tests/overlay_overlay_dtc.dts b/tests/overlay_overlay_dtc.dts new file mode 100644 index 0000000..30d2362 --- /dev/null +++ b/tests/overlay_overlay_dtc.dts @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +/plugin/; + +/ { + /* Test that we can change an int by another */ + fragment@0 { + target = <&test>; + + __overlay__ { + test-int-property = <43>; + }; + }; + + /* Test that we can replace a string by a longer one */ + fragment@1 { + target = <&test>; + + __overlay__ { + test-str-property = "foobar"; + }; + }; + + /* Test that we add a new property */ + fragment@2 { + target = <&test>; + + __overlay__ { + test-str-property-2 = "foobar2"; + }; + }; + + /* Test that we add a new node (by phandle) */ + fragment@3 { + target = <&test>; + + __overlay__ { + new-node { + new-property; + }; + }; + }; + + fragment@5 { + target = <&test>; + + __overlay__ { + local: new-local-node { + new-property; + }; + }; + }; + + fragment@6 { + target = <&test>; + + __overlay__ { + test-phandle = <&test>, <&local>; + }; + }; + + fragment@7 { + target = <&test>; + + __overlay__ { + test-several-phandle = <&local>, <&local>; + }; + }; + + fragment@8 { + target = <&test>; + + __overlay__ { + sub-test-node { + new-sub-test-property; + }; + }; + }; +}; diff --git a/tests/overlay_overlay_nodtc.dts b/tests/overlay_overlay_nodtc.dts new file mode 100644 index 0000000..e8d0f96 --- /dev/null +++ b/tests/overlay_overlay_nodtc.dts @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +/ { + fragment@0 { + target-path = "/test-node"; + + __overlay__ { + test-int-property = <43>; + }; + }; + + /* Test that we can replace a string by a longer one */ + fragment@1 { + target-path = "/test-node"; + + __overlay__ { + test-str-property = "foobar"; + }; + }; + + /* Test that we add a new property */ + fragment@2 { + target-path = "/test-node"; + + __overlay__ { + test-str-property-2 = "foobar2"; + }; + }; + + fragment@3 { + target-path = "/test-node"; + + __overlay__ { + new-node { + new-property; + }; + }; + }; + + fragment@4 { + target-path = "/"; + + __overlay__ { + local: new-local-node { + new-property; + }; + }; + }; + + fragment@5 { + target-path = "/"; + + __overlay__ { + test-several-phandle = <&local>, <&local>; + }; + }; + + fragment@6 { + target-path = "/test-node"; + + __overlay__ { + sub-test-node { + new-sub-test-property; + }; + }; + }; + + __local_fixups__ { + fragment@5 { + __overlay__ { + test-several-phandle = <0 4>; + }; + }; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index f4b32e4..10b41bc 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -160,6 +160,37 @@ run_fdtdump_test() { base_run_test sh fdtdump-runtest.sh "$file" } +BAD_FIXUP_TREES="bad_index \ + empty \ + empty_index \ + index_trailing \ + path_empty_prop \ + path_only \ + path_only_sep \ + path_prop" + +overlay_tests () { + # Overlay tests that don't require overlay support in dtc + run_dtc_test -I dts -O dtb -o overlay_base.dtb overlay_base.dts + run_dtc_test -I dts -O dtb -o overlay_overlay.dtb overlay_overlay_nodtc.dts + run_test overlay overlay_base.dtb overlay_overlay.dtb + + # Overlay tests that requires overlay support in dtc + echo "/dts-v1/; / {};" | $DTC -@ > /dev/null 2>&1 + if [ $? -eq 0 ]; then + run_dtc_test -@ -I dts -O dtb -o overlay_base.dtb overlay_base.dts + run_dtc_test -@ -I dts -O dtb -o overlay_overlay.dtb overlay_overlay_dtc.dts + run_test overlay overlay_base.dtb overlay_overlay.dtb + + # Bad fixup tests + for test in $BAD_FIXUP_TREES; do + tree="overlay_bad_fixup_$test" + run_dtc_test -I dts -O dtb -o $tree.dtb $tree.dts + run_test overlay_bad_fixup overlay_base.dtb $tree.dtb + done + fi +} + tree1_tests () { TREE=$1 @@ -273,6 +304,7 @@ libfdt_tests () { run_test appendprop2 appendprop1.test.dtb run_dtc_test -I dts -O dtb -o appendprop.test.dtb appendprop.dts run_test dtbs_equal_ordered appendprop2.test.dtb appendprop.test.dtb + overlay_tests for basetree in test_tree1.dtb sw_tree1.test.dtb rw_tree1.test.dtb; do run_test nopulate $basetree From 7b7a6be9ba159125a8e11b7ccc86233d17109187 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 6 Oct 2016 20:45:14 +1100 Subject: [PATCH 0524/1198] libfdt: Don't use 'index' as a local variable name Using 'index' as a local variable name shadows the standard library index() function. This causes warnings on at least some compiler versions. The recently added overlay code has a number of instances of this. This patch replaces 'index' with 'poffset', since 'index' is being used to mean "offset within a property value" in these cases. Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 20 ++++++++++---------- tests/overlay.c | 30 +++++++++++++++--------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index c7e5508..322e7ad 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -234,9 +234,9 @@ static int overlay_update_local_node_references(void *fdto, } for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) { - uint32_t adj_val, index; + uint32_t adj_val, poffset; - index = fdt32_to_cpu(fixup_val[i]); + poffset = fdt32_to_cpu(fixup_val[i]); /* * phandles to fixup can be unaligned. @@ -244,7 +244,7 @@ static int overlay_update_local_node_references(void *fdto, * Use a memcpy for the architectures that do * not support unaligned accesses. */ - memcpy(&adj_val, tree_val + index, sizeof(adj_val)); + memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); adj_val = fdt32_to_cpu(adj_val); adj_val += delta; @@ -254,7 +254,7 @@ static int overlay_update_local_node_references(void *fdto, tree_node, name, strlen(name), - index, + poffset, &adj_val, sizeof(adj_val)); if (ret == -FDT_ERR_NOSPACE) @@ -332,7 +332,7 @@ static int overlay_update_local_references(void *fdto, uint32_t delta) * @path_len: number of path characters to consider * @name: Name of the property holding the phandle reference in the overlay * @name_len: number of name characters to consider - * @index: Index in the overlay property where the phandle is stored + * @poffset: Offset within the overlay property where the phandle is stored * @label: Label of the node referenced by the phandle * * overlay_fixup_one_phandle() resolves an overlay phandle pointing to @@ -350,7 +350,7 @@ 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 index, const char *label) + int poffset, const char *label) { const char *symbol_path; uint32_t phandle; @@ -378,7 +378,7 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto, phandle = cpu_to_fdt32(phandle); return fdt_setprop_inplace_namelen_partial(fdto, fixup_off, - name, name_len, index, + name, name_len, poffset, &phandle, sizeof(phandle)); }; @@ -423,7 +423,7 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, uint32_t path_len, name_len; uint32_t fixup_len; char *sep, *endptr; - int index, ret; + int poffset, ret; fixup_end = memchr(value, '\0', len); if (!fixup_end) @@ -452,13 +452,13 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, if (!name_len) return -FDT_ERR_BADOVERLAY; - index = strtoul(sep + 1, &endptr, 10); + poffset = strtoul(sep + 1, &endptr, 10); if ((*endptr != '\0') || (endptr <= (sep + 1))) return -FDT_ERR_BADOVERLAY; ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off, path, path_len, name, name_len, - index, label); + poffset, label); if (ret) return ret; } while (len > 0); diff --git a/tests/overlay.c b/tests/overlay.c index e467b03..961ed60 100644 --- a/tests/overlay.c +++ b/tests/overlay.c @@ -34,9 +34,9 @@ /* 4k ought to be enough for anybody */ #define FDT_COPY_SIZE (4 * 1024) -static int fdt_getprop_u32_by_index(void *fdt, const char *path, - const char *name, int index, - unsigned long *out) +static int fdt_getprop_u32_by_poffset(void *fdt, const char *path, + const char *name, int poffset, + unsigned long *out) { const fdt32_t *val; int node_off; @@ -47,10 +47,10 @@ static int fdt_getprop_u32_by_index(void *fdt, const char *path, return node_off; val = fdt_getprop(fdt, node_off, name, &len); - if (!val || (len < (sizeof(uint32_t) * (index + 1)))) + if (!val || (len < (sizeof(uint32_t) * (poffset + 1)))) return -FDT_ERR_NOTFOUND; - *out = fdt32_to_cpu(*(val + index)); + *out = fdt32_to_cpu(*(val + poffset)); return 0; } @@ -141,14 +141,14 @@ static int fdt_overlay_local_phandle(void *fdt) local_phandle = fdt_get_phandle(fdt, off); CHECK(!local_phandle); - CHECK(fdt_getprop_u32_by_index(fdt, "/test-node", - "test-several-phandle", - 0, &val)); + CHECK(fdt_getprop_u32_by_poffset(fdt, "/test-node", + "test-several-phandle", + 0, &val)); CHECK(val != local_phandle); - CHECK(fdt_getprop_u32_by_index(fdt, "/test-node", - "test-several-phandle", - 1, &val)); + CHECK(fdt_getprop_u32_by_poffset(fdt, "/test-node", + "test-several-phandle", + 1, &val)); CHECK(val != local_phandle); return 0; @@ -172,12 +172,12 @@ static int fdt_overlay_local_phandles(void *fdt) test_phandle = fdt_get_phandle(fdt, off); CHECK(!test_phandle); - CHECK(fdt_getprop_u32_by_index(fdt, "/test-node", - "test-phandle", 0, &val)); + CHECK(fdt_getprop_u32_by_poffset(fdt, "/test-node", + "test-phandle", 0, &val)); CHECK(test_phandle != val); - CHECK(fdt_getprop_u32_by_index(fdt, "/test-node", - "test-phandle", 1, &val)); + CHECK(fdt_getprop_u32_by_poffset(fdt, "/test-node", + "test-phandle", 1, &val)); CHECK(local_phandle != val); return 0; From deb0a5c1aeaa34130305d765251bbb76e888f4e7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 6 Oct 2016 13:39:56 +0200 Subject: [PATCH 0525/1198] libfdt: Add BADPHANDLE error string The BADPHANDLE error was missing a string, leading to an string being returned if you were to call fdt_strerror. Signed-off-by: Maxime Ripard 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 3cb357f..e00fcb1 100644 --- a/libfdt/fdt_strerror.c +++ b/libfdt/fdt_strerror.c @@ -69,6 +69,7 @@ static struct fdt_errtabent fdt_errtable[] = { FDT_ERRTABENT(FDT_ERR_BADOFFSET), FDT_ERRTABENT(FDT_ERR_BADPATH), + FDT_ERRTABENT(FDT_ERR_BADPHANDLE), FDT_ERRTABENT(FDT_ERR_BADSTATE), FDT_ERRTABENT(FDT_ERR_TRUNCATED), From cabbaa972cddb193dbe170f3797825a5d4ca66fa Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 6 Oct 2016 13:39:57 +0200 Subject: [PATCH 0526/1198] libfdt: overlay: Report a bad overlay for mismatching local fixups The __local_fixups__ node as a structure that mimics the structure of the main overlay part. This means that if we have a child node somewhere in the local fixups sub-tree and if that node is not present in the main tree, the overlay is poorly formatted, and we should report it as such. Signed-off-by: Maxime Ripard Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index 322e7ad..2f306e4 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -272,6 +272,8 @@ static int overlay_update_local_node_references(void *fdto, tree_child = fdt_subnode_offset(fdto, tree_node, fixup_child_name); + if (ret == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; if (tree_child < 0) return tree_child; From 7a72d89d3f8112c1f4065d43e636aa572278f42e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 6 Oct 2016 13:39:58 +0200 Subject: [PATCH 0527/1198] libfdt: overlay: Fix symbols and fixups nodes condition Some base device tree might not have any __symbols__ nodes, since they might not have any phandle at all. Similarly, if an overlay doesn't use any base device tree phandles, its __fixups__ node will be empty. In such cases, we don't want to stop the phandle parsing, but rather just ignore the error reported about the missing node. If it's actually an issue for the overlay we're trying to apply on a given base device tree, it will be caught later on, but we cannot make the assumption that early in the application process. Signed-off-by: Maxime Ripard Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index 2f306e4..bb41404 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -492,13 +492,12 @@ static int overlay_fixup_phandles(void *fdt, void *fdto) /* We can have overlays without any fixups */ fixups_off = fdt_path_offset(fdto, "/__fixups__"); - if (fixups_off == -FDT_ERR_NOTFOUND) - return 0; - if (fixups_off < 0) + if ((fixups_off < 0 && (fixups_off != -FDT_ERR_NOTFOUND))) return fixups_off; + /* And base DTs without symbols */ symbols_off = fdt_path_offset(fdt, "/__symbols__"); - if (symbols_off < 0) + if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND))) return symbols_off; fdt_for_each_property_offset(property, fdto, fixups_off) { From e8c3a1a493fa96153badd4b8a831edfb96d5bdc7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 6 Oct 2016 13:39:59 +0200 Subject: [PATCH 0528/1198] tests: overlay: Move back the bad fixup tests The bad fixups tests were meant to be usable even for a non-overlay-enabled dtc. Move them out of that check. Signed-off-by: Maxime Ripard 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 10b41bc..dc19f80 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -181,14 +181,14 @@ overlay_tests () { run_dtc_test -@ -I dts -O dtb -o overlay_base.dtb overlay_base.dts run_dtc_test -@ -I dts -O dtb -o overlay_overlay.dtb overlay_overlay_dtc.dts run_test overlay overlay_base.dtb overlay_overlay.dtb - - # Bad fixup tests - for test in $BAD_FIXUP_TREES; do - tree="overlay_bad_fixup_$test" - run_dtc_test -I dts -O dtb -o $tree.dtb $tree.dts - run_test overlay_bad_fixup overlay_base.dtb $tree.dtb - done fi + + # Bad fixup tests + for test in $BAD_FIXUP_TREES; do + tree="overlay_bad_fixup_$test" + run_dtc_test -I dts -O dtb -o $tree.dtb $tree.dts + run_test overlay_bad_fixup overlay_base.dtb $tree.dtb + done } tree1_tests () { From 804a9db90ad284d2c2e24978d68ca40ec638a15f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 11 Oct 2016 10:10:31 +0200 Subject: [PATCH 0529/1198] fdt: strerr: Remove spurious BADOVERLAY There's one FDT_ERR_BADOVERLAY too many in the fdt error table. Signed-off-by: Maxime Ripard Signed-off-by: David Gibson --- libfdt/fdt_strerror.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c index e00fcb1..4ab3eb7 100644 --- a/libfdt/fdt_strerror.c +++ b/libfdt/fdt_strerror.c @@ -78,7 +78,6 @@ static struct fdt_errtabent fdt_errtable[] = { FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), FDT_ERRTABENT(FDT_ERR_BADLAYOUT), FDT_ERRTABENT(FDT_ERR_BADOVERLAY), - FDT_ERRTABENT(FDT_ERR_BADOVERLAY), FDT_ERRTABENT(FDT_ERR_NOPHANDLES), }; #define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) From 5ce8634733b70c2051a2a88fd7255f1a5b1a0903 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 11 Oct 2016 10:10:32 +0200 Subject: [PATCH 0530/1198] libfdt: Add fdt_overlay_apply to the exported symbols fdt_overlay_apply was not usable in the shared library. Export it to allow its use. Signed-off-by: Maxime Ripard Signed-off-by: David Gibson --- libfdt/version.lds | 1 + 1 file changed, 1 insertion(+) diff --git a/libfdt/version.lds b/libfdt/version.lds index 1f4e1ea..cff0358 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -61,6 +61,7 @@ LIBFDT_1.2 { fdt_size_cells; fdt_stringlist_contains; fdt_resize; + fdt_overlay_apply; local: *; From 96162d2bd9cbea74c57a523b3145b8abbfd32c8d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 11 Oct 2016 10:10:33 +0200 Subject: [PATCH 0531/1198] tests: overlay: Add test suffix to the compiled blobs The compiled blobs in the overlay tests do not have the test suffix which is usually used to clean up and ignore the test artifacts. Let's add that suffix. Signed-off-by: Maxime Ripard Signed-off-by: David Gibson --- tests/run_tests.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index dc19f80..b49fa62 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -171,23 +171,23 @@ BAD_FIXUP_TREES="bad_index \ overlay_tests () { # Overlay tests that don't require overlay support in dtc - run_dtc_test -I dts -O dtb -o overlay_base.dtb overlay_base.dts - run_dtc_test -I dts -O dtb -o overlay_overlay.dtb overlay_overlay_nodtc.dts - run_test overlay overlay_base.dtb overlay_overlay.dtb + run_dtc_test -I dts -O dtb -o overlay_base.test.dtb overlay_base.dts + run_dtc_test -I dts -O dtb -o overlay_overlay.test.dtb overlay_overlay_nodtc.dts + run_test overlay overlay_base.test.dtb overlay_overlay.test.dtb # Overlay tests that requires overlay support in dtc echo "/dts-v1/; / {};" | $DTC -@ > /dev/null 2>&1 if [ $? -eq 0 ]; then - run_dtc_test -@ -I dts -O dtb -o overlay_base.dtb overlay_base.dts - run_dtc_test -@ -I dts -O dtb -o overlay_overlay.dtb overlay_overlay_dtc.dts - run_test overlay overlay_base.dtb overlay_overlay.dtb + run_dtc_test -@ -I dts -O dtb -o overlay_base.test.dtb overlay_base.dts + run_dtc_test -@ -I dts -O dtb -o overlay_overlay.test.dtb overlay_overlay_dtc.dts + run_test overlay overlay_base.test.dtb overlay_overlay.test.dtb fi # Bad fixup tests for test in $BAD_FIXUP_TREES; do tree="overlay_bad_fixup_$test" - run_dtc_test -I dts -O dtb -o $tree.dtb $tree.dts - run_test overlay_bad_fixup overlay_base.dtb $tree.dtb + run_dtc_test -I dts -O dtb -o $tree.test.dtb $tree.dts + run_test overlay_bad_fixup overlay_base.test.dtb $tree.test.dtb done } From ae97c7722840148b636ac8fde2de3d0a24c04cfc Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 11 Oct 2016 16:44:07 +0200 Subject: [PATCH 0532/1198] tests: overlay: Rename the device tree blobs to be more explicit Rename the blobs to have a more explicit output that will give us a clearer idea about whether a DT (and the test) has been compiled using a dtc with our without overlays support. Signed-off-by: Maxime Ripard 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 b49fa62..e4139dd 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -171,23 +171,23 @@ BAD_FIXUP_TREES="bad_index \ overlay_tests () { # Overlay tests that don't require overlay support in dtc - run_dtc_test -I dts -O dtb -o overlay_base.test.dtb overlay_base.dts - run_dtc_test -I dts -O dtb -o overlay_overlay.test.dtb overlay_overlay_nodtc.dts - run_test overlay overlay_base.test.dtb overlay_overlay.test.dtb + run_dtc_test -I dts -O dtb -o overlay_base_no_symbols.test.dtb overlay_base.dts + run_dtc_test -I dts -O dtb -o overlay_overlay_no_symbols.test.dtb overlay_overlay_nodtc.dts + run_test overlay overlay_base_no_symbols.test.dtb overlay_overlay_no_symbols.test.dtb # Overlay tests that requires overlay support in dtc echo "/dts-v1/; / {};" | $DTC -@ > /dev/null 2>&1 if [ $? -eq 0 ]; then - run_dtc_test -@ -I dts -O dtb -o overlay_base.test.dtb overlay_base.dts - run_dtc_test -@ -I dts -O dtb -o overlay_overlay.test.dtb overlay_overlay_dtc.dts - run_test overlay overlay_base.test.dtb overlay_overlay.test.dtb + run_dtc_test -@ -I dts -O dtb -o overlay_base_with_symbols.test.dtb overlay_base.dts + run_dtc_test -@ -I dts -O dtb -o overlay_overlay_with_symbols.test.dtb overlay_overlay_dtc.dts + run_test overlay overlay_base_with_symbols.test.dtb overlay_overlay_with_symbols.test.dtb fi # Bad fixup tests for test in $BAD_FIXUP_TREES; do tree="overlay_bad_fixup_$test" run_dtc_test -I dts -O dtb -o $tree.test.dtb $tree.dts - run_test overlay_bad_fixup overlay_base.test.dtb $tree.test.dtb + run_test overlay_bad_fixup overlay_base_no_symbols.test.dtb $tree.test.dtb done } From e28eff5b787adb3f461d1653598818b2f1f25a73 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 17 Oct 2016 15:08:23 +0900 Subject: [PATCH 0533/1198] libfdt: fix fdt_stringlist_count() If fdt_getprop() fails, negative error code should be returned. Signed-off-by: Masahiro Yamada 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 0459098..db8d10f 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -571,7 +571,7 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) list = fdt_getprop(fdt, nodeoffset, property, &length); if (!list) - return -length; + return length; end = list + length; From daa75e8fa5942caa8e97931aed3a1ee0b7edd74b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 17 Oct 2016 15:08:24 +0900 Subject: [PATCH 0534/1198] libfdt: fix fdt_stringlist_search() If fdt_getprop() fails, negative error code should be returned. Signed-off-by: Masahiro Yamada 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 db8d10f..3d00d2e 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -597,7 +597,7 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, list = fdt_getprop(fdt, nodeoffset, property, &length); if (!list) - return -length; + return length; len = strlen(string) + 1; end = list + length; From ea10f953878feea45ccdae846dbd3382e79e7f7e Mon Sep 17 00:00:00 2001 From: Benjamin Fair Date: Thu, 3 Nov 2016 10:47:42 -0500 Subject: [PATCH 0535/1198] libfdt: add missing errors to fdt_strerror() Some error values were missing from the table which meant that they could not be translated by fdt_strerror(). Signed-off-by: Benjamin Fair Signed-off-by: David Gibson --- libfdt/fdt_strerror.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c index 4ab3eb7..9677a18 100644 --- a/libfdt/fdt_strerror.c +++ b/libfdt/fdt_strerror.c @@ -77,6 +77,9 @@ static struct fdt_errtabent fdt_errtable[] = { FDT_ERRTABENT(FDT_ERR_BADVERSION), FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), FDT_ERRTABENT(FDT_ERR_BADLAYOUT), + FDT_ERRTABENT(FDT_ERR_INTERNAL), + FDT_ERRTABENT(FDT_ERR_BADNCELLS), + FDT_ERRTABENT(FDT_ERR_BADVALUE), FDT_ERRTABENT(FDT_ERR_BADOVERLAY), FDT_ERRTABENT(FDT_ERR_NOPHANDLES), }; From 8f70ac39801d9bb388e2aaebbc9fe9d2a438a151 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Fri, 25 Nov 2016 14:32:08 +0200 Subject: [PATCH 0536/1198] checks: Pass boot_info instead of root node As preparation for overlay support we need to pass the boot info parameter instead of the root node to each check method. The root node can be retrieved by accessing boot info's dt member. No other functional changes are made. Signed-off-by: Pantelis Antoniou Signed-off-by: David Gibson --- checks.c | 78 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/checks.c b/checks.c index 0381c98..2bd27a4 100644 --- a/checks.c +++ b/checks.c @@ -40,7 +40,7 @@ enum checkstatus { struct check; -typedef void (*check_fn)(struct check *c, struct node *dt, struct node *node); +typedef void (*check_fn)(struct check *c, struct boot_info *bi, struct node *node); struct check { const char *name; @@ -97,20 +97,21 @@ static inline void check_msg(struct check *c, const char *fmt, ...) check_msg((c), __VA_ARGS__); \ } while (0) -static void check_nodes_props(struct check *c, struct node *dt, struct node *node) +static void check_nodes_props(struct check *c, struct boot_info *bi, struct node *node) { struct node *child; TRACE(c, "%s", node->fullpath); if (c->fn) - c->fn(c, dt, node); + c->fn(c, bi, node); for_each_child(node, child) - check_nodes_props(c, dt, child); + check_nodes_props(c, bi, child); } -static bool run_check(struct check *c, struct node *dt) +static bool run_check(struct check *c, struct boot_info *bi) { + struct node *dt = bi->dt; bool error = false; int i; @@ -123,7 +124,7 @@ static bool run_check(struct check *c, struct node *dt) for (i = 0; i < c->num_prereqs; i++) { struct check *prq = c->prereq[i]; - error = error || run_check(prq, dt); + error = error || run_check(prq, bi); if (prq->status != PASSED) { c->status = PREREQ; check_msg(c, "Failed prerequisite '%s'", @@ -134,7 +135,7 @@ static bool run_check(struct check *c, struct node *dt) if (c->status != UNCHECKED) goto out; - check_nodes_props(c, dt, dt); + check_nodes_props(c, bi, dt); if (c->status == UNCHECKED) c->status = PASSED; @@ -153,14 +154,14 @@ out: */ /* A check which always fails, for testing purposes only */ -static inline void check_always_fail(struct check *c, struct node *dt, +static inline void check_always_fail(struct check *c, struct boot_info *bi, struct node *node) { FAIL(c, "always_fail check"); } CHECK(always_fail, check_always_fail, NULL); -static void check_is_string(struct check *c, struct node *root, +static void check_is_string(struct check *c, struct boot_info *bi, struct node *node) { struct property *prop; @@ -179,7 +180,7 @@ static void check_is_string(struct check *c, struct node *root, #define ERROR_IF_NOT_STRING(nm, propname) \ ERROR(nm, check_is_string, (propname)) -static void check_is_cell(struct check *c, struct node *root, +static void check_is_cell(struct check *c, struct boot_info *bi, struct node *node) { struct property *prop; @@ -202,7 +203,7 @@ static void check_is_cell(struct check *c, struct node *root, * Structural check functions */ -static void check_duplicate_node_names(struct check *c, struct node *dt, +static void check_duplicate_node_names(struct check *c, struct boot_info *bi, struct node *node) { struct node *child, *child2; @@ -217,7 +218,7 @@ static void check_duplicate_node_names(struct check *c, struct node *dt, } ERROR(duplicate_node_names, check_duplicate_node_names, NULL); -static void check_duplicate_property_names(struct check *c, struct node *dt, +static void check_duplicate_property_names(struct check *c, struct boot_info *bi, struct node *node) { struct property *prop, *prop2; @@ -239,7 +240,7 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL); #define DIGITS "0123456789" #define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-" -static void check_node_name_chars(struct check *c, struct node *dt, +static void check_node_name_chars(struct check *c, struct boot_info *bi, struct node *node) { int n = strspn(node->name, c->data); @@ -250,7 +251,7 @@ static void check_node_name_chars(struct check *c, struct node *dt, } ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@"); -static void check_node_name_format(struct check *c, struct node *dt, +static void check_node_name_format(struct check *c, struct boot_info *bi, struct node *node) { if (strchr(get_unitname(node), '@')) @@ -259,8 +260,8 @@ static void check_node_name_format(struct check *c, struct node *dt, } ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars); -static void check_unit_address_vs_reg(struct check *c, struct node *dt, - struct node *node) +static void check_unit_address_vs_reg(struct check *c, struct boot_info *bi, + struct node *node) { const char *unitname = get_unitname(node); struct property *prop = get_property(node, "reg"); @@ -283,7 +284,7 @@ static void check_unit_address_vs_reg(struct check *c, struct node *dt, } WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL); -static void check_property_name_chars(struct check *c, struct node *dt, +static void check_property_name_chars(struct check *c, struct boot_info *bi, struct node *node) { struct property *prop; @@ -305,10 +306,11 @@ ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS); ((prop) ? (prop)->name : ""), \ ((prop) ? "' in " : ""), (node)->fullpath -static void check_duplicate_label(struct check *c, struct node *dt, +static void check_duplicate_label(struct check *c, struct boot_info *bi, const char *label, struct node *node, struct property *prop, struct marker *mark) { + struct node *dt = bi->dt; struct node *othernode = NULL; struct property *otherprop = NULL; struct marker *othermark = NULL; @@ -331,30 +333,31 @@ static void check_duplicate_label(struct check *c, struct node *dt, DESCLABEL_ARGS(othernode, otherprop, othermark)); } -static void check_duplicate_label_node(struct check *c, struct node *dt, +static void check_duplicate_label_node(struct check *c, struct boot_info *bi, struct node *node) { struct label *l; struct property *prop; for_each_label(node->labels, l) - check_duplicate_label(c, dt, l->label, node, NULL, NULL); + check_duplicate_label(c, bi, l->label, node, NULL, NULL); for_each_property(node, prop) { struct marker *m = prop->val.markers; for_each_label(prop->labels, l) - check_duplicate_label(c, dt, l->label, node, prop, NULL); + check_duplicate_label(c, bi, l->label, node, prop, NULL); for_each_marker_of_type(m, LABEL) - check_duplicate_label(c, dt, m->ref, node, prop, m); + check_duplicate_label(c, bi, m->ref, node, prop, m); } } ERROR(duplicate_label, check_duplicate_label_node, NULL); -static cell_t check_phandle_prop(struct check *c, struct node *root, +static cell_t check_phandle_prop(struct check *c, struct boot_info *bi, struct node *node, const char *propname) { + struct node *root = bi->dt; struct property *prop; struct marker *m; cell_t phandle; @@ -398,18 +401,19 @@ static cell_t check_phandle_prop(struct check *c, struct node *root, return phandle; } -static void check_explicit_phandles(struct check *c, struct node *root, +static void check_explicit_phandles(struct check *c, struct boot_info *bi, struct node *node) { + struct node *root = bi->dt; struct node *other; cell_t phandle, linux_phandle; /* Nothing should have assigned phandles yet */ assert(!node->phandle); - phandle = check_phandle_prop(c, root, node, "phandle"); + phandle = check_phandle_prop(c, bi, node, "phandle"); - linux_phandle = check_phandle_prop(c, root, node, "linux,phandle"); + linux_phandle = check_phandle_prop(c, bi, node, "linux,phandle"); if (!phandle && !linux_phandle) /* No valid phandles; nothing further to check */ @@ -433,7 +437,7 @@ static void check_explicit_phandles(struct check *c, struct node *root, } ERROR(explicit_phandles, check_explicit_phandles, NULL); -static void check_name_properties(struct check *c, struct node *root, +static void check_name_properties(struct check *c, struct boot_info *bi, struct node *node) { struct property **pp, *prop = NULL; @@ -467,9 +471,10 @@ ERROR(name_properties, check_name_properties, NULL, &name_is_string); * Reference fixup functions */ -static void fixup_phandle_references(struct check *c, struct node *dt, +static void fixup_phandle_references(struct check *c, struct boot_info *bi, struct node *node) { + struct node *dt = bi->dt; struct property *prop; for_each_property(node, prop) { @@ -495,9 +500,10 @@ static void fixup_phandle_references(struct check *c, struct node *dt, ERROR(phandle_references, fixup_phandle_references, NULL, &duplicate_node_names, &explicit_phandles); -static void fixup_path_references(struct check *c, struct node *dt, +static void fixup_path_references(struct check *c, struct boot_info *bi, struct node *node) { + struct node *dt = bi->dt; struct property *prop; for_each_property(node, prop) { @@ -534,7 +540,7 @@ WARNING_IF_NOT_STRING(device_type_is_string, "device_type"); WARNING_IF_NOT_STRING(model_is_string, "model"); WARNING_IF_NOT_STRING(status_is_string, "status"); -static void fixup_addr_size_cells(struct check *c, struct node *dt, +static void fixup_addr_size_cells(struct check *c, struct boot_info *bi, struct node *node) { struct property *prop; @@ -558,7 +564,7 @@ WARNING(addr_size_cells, fixup_addr_size_cells, NULL, #define node_size_cells(n) \ (((n)->size_cells == -1) ? 1 : (n)->size_cells) -static void check_reg_format(struct check *c, struct node *dt, +static void check_reg_format(struct check *c, struct boot_info *bi, struct node *node) { struct property *prop; @@ -587,7 +593,7 @@ static void check_reg_format(struct check *c, struct node *dt, } WARNING(reg_format, check_reg_format, NULL, &addr_size_cells); -static void check_ranges_format(struct check *c, struct node *dt, +static void check_ranges_format(struct check *c, struct boot_info *bi, struct node *node) { struct property *prop; @@ -631,7 +637,7 @@ WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells); /* * Style checks */ -static void check_avoid_default_addr_size(struct check *c, struct node *dt, +static void check_avoid_default_addr_size(struct check *c, struct boot_info *bi, struct node *node) { struct property *reg, *ranges; @@ -657,9 +663,10 @@ WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL, &addr_size_cells); static void check_obsolete_chosen_interrupt_controller(struct check *c, - struct node *dt, + struct boot_info *bi, struct node *node) { + struct node *dt = bi->dt; struct node *chosen; struct property *prop; @@ -765,7 +772,6 @@ void parse_checks_option(bool warn, bool error, const char *arg) void process_checks(bool force, struct boot_info *bi) { - struct node *dt = bi->dt; int i; int error = 0; @@ -773,7 +779,7 @@ void process_checks(bool force, struct boot_info *bi) struct check *c = check_table[i]; if (c->warn || c->error) - error = error || run_check(c, dt); + error = error || run_check(c, bi); } if (error) { From a2c92cac53f806e6c1936c1c522a6c24a5ec7199 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Wed, 7 Dec 2016 14:48:17 +0200 Subject: [PATCH 0537/1198] dtc: Document the dynamic plugin internals Provides the document explaining the internal mechanics of plugins and options. Signed-off-by: Pantelis Antoniou Signed-off-by: David Gibson --- Documentation/dt-object-internal.txt | 310 +++++++++++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100644 Documentation/dt-object-internal.txt diff --git a/Documentation/dt-object-internal.txt b/Documentation/dt-object-internal.txt new file mode 100644 index 0000000..51d68ab --- /dev/null +++ b/Documentation/dt-object-internal.txt @@ -0,0 +1,310 @@ +Device Tree Dynamic Object format internals +------------------------------------------- + +The Device Tree for most platforms is a static representation of +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 +modifications made to the Device Tree compiler, which make it possible. + +1. Simplified Problem Definition +-------------------------------- + +Assume we have a platform which boots using following simplified Device Tree. + +---- foo.dts ----------------------------------------------------------------- + /* FOO platform */ + / { + compatible = "corp,foo"; + + /* shared resources */ + res: res { + }; + + /* On chip peripherals */ + ocp: ocp { + /* peripherals that are always instantiated */ + peripheral1 { ... }; + }; + }; +---- foo.dts ----------------------------------------------------------------- + +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. + +So for the bar peripheral we would have this: + +---- foo+bar.dts ------------------------------------------------------------- + /* FOO platform + bar peripheral */ + / { + compatible = "corp,foo"; + + /* shared resources */ + res: res { + }; + + /* On chip peripherals */ + ocp: ocp { + /* peripherals that are always instantiated */ + peripheral1 { ... }; + + /* bar peripheral */ + bar { + compatible = "corp,bar"; + ... /* various properties and child nodes */ + }; + }; + }; +---- foo+bar.dts ------------------------------------------------------------- + +While for the baz peripheral we would have this: + +---- foo+baz.dts ------------------------------------------------------------- + /* FOO platform + baz peripheral */ + / { + compatible = "corp,foo"; + + /* shared resources */ + res: res { + /* baz resources */ + baz_res: res_baz { ... }; + }; + + /* On chip peripherals */ + ocp: ocp { + /* peripherals that are always instantiated */ + peripheral1 { ... }; + + /* baz peripheral */ + baz { + compatible = "corp,baz"; + /* reference to another point in the tree */ + ref-to-res = <&baz_res>; + ... /* various properties and child nodes */ + }; + }; + }; +---- foo+baz.dts ------------------------------------------------------------- + +We note that the baz case is more complicated, since the baz peripheral needs to +reference another node in the DT tree. + +2. Device Tree Object Format Requirements +----------------------------------------- + +Since the Device Tree is used for booting a number of very different hardware +platforms it is imperative that we tread very carefully. + +2.a) No changes to the Device Tree binary format for the base tree. We cannot +modify the tree format at all and all the information we require should be +encoded using Device Tree itself. We can add nodes that can be safely ignored +by both bootloaders and the kernel. The plugin dtbs are optionally tagged +with a different magic number in the header but otherwise they're simple +blobs. + +2.b) Changes to the DTS source format should be absolutely minimal, and should +only be needed for the DT fragment definitions, and not the base boot DT. + +2.c) An explicit option should be used to instruct DTC to generate the required +information needed for object resolution. Platforms that don't use the +dynamic object format can safely ignore it. + +2.d) Finally, DT syntax changes should be kept to a minimum. It should be +possible to express everything using the existing DT syntax. + +3. Implementation +----------------- + +The basic unit of addressing in Device Tree is the phandle. Turns out it's +relatively simple to extend the way phandles are generated and referenced +so that it's possible to dynamically convert symbolic references (labels) +to phandle values. This is a valid assumption as long as the author uses +reference syntax and does not assign phandle values manually (which might +be a problem with decompiled source files). + +We can roughly divide the operation into two steps. + +3.a) Compilation of the base board DTS file using the '-@' option +generates a valid DT blob with an added __symbols__ node at the root node, +containing a list of all nodes that are marked with a label. + +Using the foo.dts file above the following node will be generated; + +$ dtc -@ -O dtb -o foo.dtb -b 0 foo.dts +$ fdtdump foo.dtb +... +/ { + ... + res { + ... + phandle = <0x00000001>; + ... + }; + ocp { + ... + phandle = <0x00000002>; + ... + }; + __symbols__ { + res="/res"; + ocp="/ocp"; + }; +}; + +Notice that all the nodes that had a label have been recorded, and that +phandles have been generated for them. + +This blob can be used to boot the board normally, the __symbols__ node will +be safely ignored both by the bootloader and the kernel (the only loss will +be a few bytes of memory and disk space). + +We generate a __symbols__ node to record nodes that had labels in the base +tree (or subsequent loaded overlays) so that they can be matched up with +references made to them in Device Tree objects. + +3.b) The Device Tree fragments must be compiled with the same option but they +must also have a tag (/plugin/) that allows undefined references to nodes +that are not present at compilation time to be recorded so that the runtime +loader can fix them. + +So the bar peripheral's DTS format would be of the form: + +/dts-v1/; +/plugin/; /* allow undefined references and record them */ +/ { + .... /* various properties for loader use; i.e. part id etc. */ + fragment@0 { + target = <&ocp>; + __overlay__ { + /* bar peripheral */ + bar { + compatible = "corp,bar"; + ... /* various properties and child nodes */ + } + }; + }; +}; + +Note that there's a target property that specifies the location where the +contents of the overlay node will be placed, and it references the node +in the foo.dts file. + +$ dtc -@ -O dtb -o bar.dtbo -b 0 bar.dts +$ fdtdump bar.dtbo +... +/ { + ... /* properties */ + fragment@0 { + target = <0xffffffff>; + __overlay__ { + bar { + compatible = "corp,bar"; + ... /* various properties and child nodes */ + } + }; + }; + __fixups__ { + ocp = "/fragment@0:target:0"; + }; +}; + +No __symbols__ node has been generated (no label in bar.dts). +Note that the target's ocp label is undefined, so the phandle +value is filled with the illegal value '0xffffffff', while a __fixups__ +node has been generated, which marks the location in the tree where +the label lookup should store the runtime phandle value of the ocp node. + +The format of the __fixups__ node entry is + +
[ ]... + fdtget -p
[ ]... + +where options are: + + s=string, i=int, u=unsigned, x=hex + Optional modifier prefix: + hh or b=byte, h=2 byte, l=4 byte (default) + + Options: -[t:pld:hV] + -t, --type Type of data + -p, --properties List properties for each node + -l, --list List subnodes for each node + -d, --default Default value to display when the property is missing + -h, --help Print this help and exit + -V, --version Print version and exit + +If -t is not provided, fdtget will try to figure out the type, trying to detect +strings, string lists and the size of each value in the property. This is +similar to how fdtdump works, and uses the same heuristics. From 4d09a83420df9b971415133b1904bcd9cc4f6fdd Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 6 Jun 2018 12:33:32 -0600 Subject: [PATCH 0704/1198] fdtput: Add documentation This is missing at present and the fdtput tool could use a litle more information than just its help text. This might be useful for distributions which want to provide a man page. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- Documentation/manual.txt | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Documentation/manual.txt b/Documentation/manual.txt index af8d315..6898caa 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -724,3 +724,36 @@ where options are: If -t is not provided, fdtget will try to figure out the type, trying to detect strings, string lists and the size of each value in the property. This is similar to how fdtdump works, and uses the same heuristics. + + +5 ) fdtput - Write properties to a device tree + +The syntax of the fdtput command is: + + fdtput
[...] + fdtput -c
[...] + fdtput -r
[...] + fdtput -d
[...] + +Options are: + + s=string, i=int, u=unsigned, x=hex + Optional modifier prefix: + hh or b=byte, h=2 byte, l=4 byte (default) + + -c, --create Create nodes if they don't already exist + -r, --remove Delete nodes (and any subnodes) if they already exist + -d, --delete Delete properties if they already exist + -p, --auto-path Automatically create nodes as needed for the node path + -t, --type Type of data + -v, --verbose Display each value decoded from command line + -h, --help Print this help and exit + -V, --version Print version and exit + +The option determines which usage is selected and therefore the operation that +is performed. The first usage adds or updates properties; the rest are used to +create/delete nodes and delete properties. + +For the first usage, the command line arguments are joined together into a +single value which is written to the property. The -t option is required so +that fdtput knows how to decode its arguments. From 64a69d123935511f35da1a6101e32d4276f57cd3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 6 Jun 2018 13:58:12 -0600 Subject: [PATCH 0705/1198] pylibfdt: Return string instead of bytearray from getprop() The return value is not actually mutable, so it seems more correct to return bytes rather than a bytearray. Suggested-by: David Gibson Signed-off-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 2c104ac..170005f 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -365,7 +365,7 @@ class Fdt: quiet: Errors to ignore (empty to raise on all errors) Returns: - Value of property as a bytearray, or -ve error number + Value of property as a string of bytes, or -ve error number Raises: FdtError if any error occurs (e.g. the property is not found) @@ -374,7 +374,8 @@ class Fdt: quiet) if isinstance(pdata, (int)): return pdata - return bytearray(pdata[0]) + # Use bytes() rather than string(). This works on both Python 2 and 3 + return bytes(pdata[0]) def get_phandle(self, nodeoffset): """Get the phandle of a node From f0f8c9169819e5505e63e247e40e9593625e01a4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 6 Jun 2018 15:37:00 -0600 Subject: [PATCH 0706/1198] pylibfdt: Reorder functions to match libfdt.h The ordering of the Python functions loosely matches the corresponding function in the C header file, but not exactly. As we add more functions it is easier to track what is missing if they are in the same order. Move some functions around to achieve this. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 144 +++++++++++++++++++++++----------------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 170005f..2ad9d33 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -185,6 +185,52 @@ class Fdt: """ return bytearray(self._fdt) + def first_subnode(self, nodeoffset, quiet=()): + """Find the first subnode of a parent node + + Args: + nodeoffset: Node offset of parent node + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + The offset of the first subnode, if any + + Raises: + FdtException if no subnodes found or other error occurs + """ + return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet) + + def next_subnode(self, nodeoffset, quiet=()): + """Find the next subnode + + Args: + nodeoffset: Node offset of previous subnode + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + The offset of the next subnode, if any + + Raises: + FdtException if no more subnodes found or other error occurs + """ + return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet) + + def totalsize(self): + """Return the total size of the device tree + + Returns: + Total tree size in bytes + """ + return check_err(fdt_totalsize(self._fdt)) + + def off_dt_struct(self): + """Return the start of the device tree struct area + + Returns: + Start offset of struct area + """ + return check_err(fdt_off_dt_struct(self._fdt)) + def subnode_offset(self, parentoffset, name, quiet=()): """Get the offset of a named subnode @@ -217,6 +263,20 @@ class Fdt: """ return check_err(fdt_path_offset(self._fdt, path), quiet) + def get_name(self, nodeoffset): + """Get the name of a node + + Args: + nodeoffset: Offset of node to check + + Returns: + Node name + + Raises: + FdtException on error (e.g. nodeoffset is invalid) + """ + return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0] + def first_property_offset(self, nodeoffset, quiet=()): """Get the offset of the first property in a node offset @@ -251,20 +311,6 @@ class Fdt: return check_err(fdt_next_property_offset(self._fdt, prop_offset), quiet) - def get_name(self, nodeoffset): - """Get the name of a node - - Args: - nodeoffset: Offset of node to check - - Returns: - Node name - - Raises: - FdtException on error (e.g. nodeoffset is invalid) - """ - return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0] - def get_property_by_offset(self, prop_offset, quiet=()): """Obtains a property that can be examined @@ -285,52 +331,6 @@ class Fdt: return pdata return Property(pdata[0], pdata[1]) - def first_subnode(self, nodeoffset, quiet=()): - """Find the first subnode of a parent node - - Args: - nodeoffset: Node offset of parent node - quiet: Errors to ignore (empty to raise on all errors) - - Returns: - The offset of the first subnode, if any - - Raises: - FdtException if no subnode found or other error occurs - """ - return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet) - - def next_subnode(self, nodeoffset, quiet=()): - """Find the next subnode - - Args: - nodeoffset: Node offset of previous subnode - quiet: Errors to ignore (empty to raise on all errors) - - Returns: - The offset of the next subnode, if any - - Raises: - FdtException if no more subnode found or other error occurs - """ - return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet) - - def totalsize(self): - """Return the total size of the device tree - - Returns: - Total tree size in bytes - """ - return check_err(fdt_totalsize(self._fdt)) - - def off_dt_struct(self): - """Return the start of the device tree struct area - - Returns: - Start offset of struct area - """ - return check_err(fdt_off_dt_struct(self._fdt)) - def pack(self, quiet=()): """Pack the device tree to remove unused space @@ -344,18 +344,6 @@ class Fdt: """ return check_err(fdt_pack(self._fdt), quiet) - def delprop(self, nodeoffset, prop_name): - """Delete a property from a node - - Args: - nodeoffset: Node offset containing property to delete - prop_name: Name of property to delete - - Raises: - FdtError if the property does not exist, or another error occurs - """ - return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) - def getprop(self, nodeoffset, prop_name, quiet=()): """Get a property from a node @@ -404,6 +392,18 @@ class Fdt: """ return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet) + def delprop(self, nodeoffset, prop_name): + """Delete a property from a node + + Args: + nodeoffset: Node offset containing property to delete + prop_name: Name of property to delete + + Raises: + FdtError if the property does not exist, or another error occurs + """ + return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) + def node_offset_by_phandle(self, phandle, quiet=()): """Get the offset of a node with the given phandle From 582a7159a5d0e1f4c96d5bdaab63defc69762c95 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 6 Jun 2018 15:37:01 -0600 Subject: [PATCH 0707/1198] pylibfdt: Add support for fdt_next_node() This function requires a bit of typemap effort to get the depth parameter to work correctly. Add support for it, along with a test. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 33 +++++++++++++++++++++++++++++++++ tests/pylibfdt_tests.py | 18 ++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 2ad9d33..e8282a4 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -185,6 +185,25 @@ class Fdt: """ return bytearray(self._fdt) + def next_node(self, nodeoffset, depth, quiet=()): + """Find the next subnode + + Args: + nodeoffset: Node offset of previous node + depth: The depth of the node at nodeoffset. This is used to + calculate the depth of the returned node + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + Typle: + Offset of the next node, if any, else a -ve error + Depth of the returned node, if any, else undefined + + Raises: + FdtException if no more nodes found or other error occurs + """ + return check_err(fdt_next_node(self._fdt, nodeoffset, depth), quiet) + def first_subnode(self, nodeoffset, quiet=()): """Find the first subnode of a parent node @@ -466,6 +485,7 @@ typedef int fdt32_t; fdt = fdt; /* avoid unused variable warning */ } +/* typemap used for fdt_get_property_by_offset() */ %typemap(out) (struct fdt_property *) { PyObject *buff; @@ -488,6 +508,19 @@ typedef int fdt32_t; $result = Py_BuildValue("s#", $1, *arg4); } +/* typemaps used for fdt_next_node() */ +%typemap(in, numinputs=1) int *depth (int depth) { + depth = (int) PyInt_AsLong($input); + $1 = &depth; +} + +%typemap(argout) int *depth { + PyObject *val = Py_BuildValue("i", *arg$argnum); + resultobj = SWIG_Python_AppendOutput(resultobj, val); +} + +%apply int *depth { int *depth }; + /* 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 343a1e4..900644d 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -220,6 +220,24 @@ class PyLibfdtTests(unittest.TestCase): self.assertEquals(libfdt.strerror(-libfdt.NOTFOUND), 'FDT_ERR_NOTFOUND') + def testNextNodeOffset(self): + """Check that we can walk through nodes""" + node_list = [] + node = 0 + depth = 0 + while depth >= 0: + node_list.append([depth, self.fdt.get_name(node)]) + node, depth = self.fdt.next_node(node, depth, (libfdt.BADOFFSET,)) + self.assertEquals(node_list, [ + [0, ''], + [1, 'subnode@1'], + [2, 'subsubnode'], + [2, 'ss1'], + [1, 'subnode@2'], + [2, 'subsubnode@0'], + [2, 'ss2'], + ]) + def testFirstNextSubnodeOffset(self): """Check that we can walk through subnodes""" node_list = [] From 29bb05aa4200285ae3de07a45efd4e5bf1999980 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 6 Jun 2018 15:37:02 -0600 Subject: [PATCH 0708/1198] pylibfdt: Add support for the rest of the header functions Export all of these through Python. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 71 +++++++++++++++++++++++++++++++++++++++-- tests/pylibfdt_tests.py | 8 +++++ 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index e8282a4..ce34b60 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -234,21 +234,86 @@ class Fdt: """ return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet) + def magic(self): + """Return the magic word from the header + + Returns: + Magic word + """ + # Use a mask to ensure that this does not return a -ve number + return fdt_magic(self._fdt) & 0xffffffff + def totalsize(self): """Return the total size of the device tree Returns: Total tree size in bytes """ - return check_err(fdt_totalsize(self._fdt)) + return fdt_totalsize(self._fdt) def off_dt_struct(self): - """Return the start of the device tree struct area + """Return the start of the device-tree struct area Returns: Start offset of struct area """ - return check_err(fdt_off_dt_struct(self._fdt)) + return fdt_off_dt_struct(self._fdt) + + def off_dt_strings(self): + """Return the start of the device-tree string area + + Returns: + Start offset of string area + """ + return fdt_off_dt_strings(self._fdt) + + def off_mem_rsvmap(self): + """Return the start of the memory reserve map + + Returns: + Start offset of memory reserve map + """ + return fdt_off_mem_rsvmap(self._fdt) + + def version(self): + """Return the version of the device tree + + Returns: + Version number of the device tree + """ + return fdt_version(self._fdt) + + def last_comp_version(self): + """Return the last compatible version of the device tree + + Returns: + Last compatible version number of the device tree + """ + return fdt_last_comp_version(self._fdt) + + def boot_cpuid_phys(self): + """Return the physical boot CPU ID + + Returns: + Physical boot CPU ID + """ + return fdt_boot_cpuid_phys(self._fdt) + + def size_dt_strings(self): + """Return the start of the device-tree string area + + Returns: + Start offset of string area + """ + return fdt_size_dt_strings(self._fdt) + + def size_dt_struct(self): + """Return the start of the device-tree struct area + + Returns: + Start offset of struct area + """ + return fdt_size_dt_struct(self._fdt) def subnode_offset(self, parentoffset, name, quiet=()): """Get the offset of a named subnode diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 900644d..75d9bbc 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -275,8 +275,16 @@ class PyLibfdtTests(unittest.TestCase): def testHeader(self): """Test that we can access the header values""" + self.assertEquals(self.fdt.magic(), 0xd00dfeed) self.assertEquals(self.fdt.totalsize(), len(self.fdt._fdt)) self.assertEquals(self.fdt.off_dt_struct(), 88) + self.assertEquals(self.fdt.off_dt_strings(), 652) + self.assertEquals(self.fdt.off_mem_rsvmap(), 40) + self.assertEquals(self.fdt.version(), 17) + self.assertEquals(self.fdt.last_comp_version(), 16) + self.assertEquals(self.fdt.boot_cpuid_phys(), 0) + self.assertEquals(self.fdt.size_dt_strings(), 105) + self.assertEquals(self.fdt.size_dt_struct(), 564) def testPack(self): """Test that we can pack the tree after deleting something""" From 483e170625e1b6905fc4c40db92ee48d47ee3283 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 6 Jun 2018 15:37:03 -0600 Subject: [PATCH 0709/1198] pylibfdt: Add support for reading the memory reserve map Add a way to access this information from Python. Signed-off-by: Simon Glass Reviewed-by: David Gibson Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 34 ++++++++++++++++++++++++++++++++++ tests/pylibfdt_tests.py | 8 ++++++++ 2 files changed, 42 insertions(+) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index ce34b60..2074e9b 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -315,6 +315,25 @@ class Fdt: """ return fdt_size_dt_struct(self._fdt) + def num_mem_rsv(self, quiet=()): + """Return the number of memory reserve-map records + + Returns: + Number of memory reserve-map records + """ + return check_err(fdt_num_mem_rsv(self._fdt), quiet) + + def get_mem_rsv(self, index, quiet=()): + """Return the indexed memory reserve-map record + + Args: + index: Record to return (0=first) + + Returns: + Number of memory reserve-map records + """ + return check_err(fdt_get_mem_rsv(self._fdt, index), quiet) + def subnode_offset(self, parentoffset, name, quiet=()): """Get the offset of a named subnode @@ -586,6 +605,21 @@ typedef int fdt32_t; %apply int *depth { int *depth }; +/* typemaps for fdt_get_mem_rsv */ +%typemap(in, numinputs=0) uint64_t * (uint64_t temp) { + $1 = &temp; +} + +%typemap(argout) uint64_t * { + PyObject *val = PyLong_FromUnsignedLong(*arg$argnum); + if (!result) { + if (PyTuple_GET_SIZE(resultobj) == 0) + resultobj = val; + else + resultobj = SWIG_Python_AppendOutput(resultobj, val); + } +} + /* 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 75d9bbc..b624f7b 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -357,5 +357,13 @@ class PyLibfdtTests(unittest.TestCase): self.assertEquals(node2, self.fdt.node_offset_by_phandle(0x2001)) + def testReserveMap(self): + """Test that we can access the memory reserve map""" + self.assertEquals(2, self.fdt.num_mem_rsv()) + self.assertEquals([ 0xdeadbeef00000000, 0x100000], + self.fdt.get_mem_rsv(0)) + self.assertEquals([123456789, 010000], self.fdt.get_mem_rsv(1)) + + if __name__ == "__main__": unittest.main() From 5a598671fdbf20355ecbaf59d9f502e689df683f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 6 Jun 2018 15:37:04 -0600 Subject: [PATCH 0710/1198] pylibfdt: Support device-tree creation/expansion Add support for fdt_open_into() and fdt_create_empty_tree() from the Python library. The former is named resize() since it better fits with what the Python binding actually does. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 33 +++++++++++++++++++++++++++++++++ tests/pylibfdt_tests.py | 18 +++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 2074e9b..da32148 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -434,6 +434,39 @@ class Fdt: return pdata return Property(pdata[0], pdata[1]) + @staticmethod + def create_empty_tree(size, quiet=()): + """Create an empty device tree ready for use + + Args: + size: Size of device tree in bytes + + Returns: + Fdt object containing the device tree + """ + data = bytearray(size) + err = check_err(fdt_create_empty_tree(data, size), quiet) + if err: + return err + return Fdt(data) + + def resize(self, size, quiet=()): + """Move the device tree into a larger or smaller space + + This creates a new device tree of size @size and moves the existing + device tree contents over to that. It can be used to create more space + in a device tree. Note that the Fdt object remains the same, but it + now has a new bytearray holding the contents. + + Args: + size: Required new size of device tree in bytes + """ + fdt = bytearray(size) + err = check_err(fdt_open_into(self._fdt, fdt, size), quiet) + if err: + return err + self._fdt = fdt + def pack(self, quiet=()): """Pack the device tree to remove unused space diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index b624f7b..ea38b78 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -55,7 +55,7 @@ import unittest sys.path.insert(0, '../pylibfdt') import libfdt -from libfdt import FdtException, QUIET_NOTFOUND, QUIET_ALL +from libfdt import Fdt, FdtException, QUIET_NOTFOUND, QUIET_ALL def get_err(err_code): """Convert an error code into an error message @@ -364,6 +364,22 @@ class PyLibfdtTests(unittest.TestCase): self.fdt.get_mem_rsv(0)) self.assertEquals([123456789, 010000], self.fdt.get_mem_rsv(1)) + def testEmpty(self): + """Test that we can create an empty tree""" + self.assertEquals(-libfdt.NOSPACE, + Fdt.create_empty_tree(1, (libfdt.NOSPACE,))) + fdt = Fdt.create_empty_tree(128) + self.assertEquals(128, fdt.totalsize()) + + def testOpenInto(self): + """Test that we can resize a tree""" + fdt = Fdt.create_empty_tree(128) + self.assertEquals(128, fdt.totalsize()) + fdt.resize(256) + self.assertEquals(256, fdt.totalsize()) + fdt.pack() + self.assertTrue(fdt.totalsize() < 128) + if __name__ == "__main__": unittest.main() From 9aafa33d99ed8a6fd9af827480b58a3f463917fb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 6 Jun 2018 15:37:05 -0600 Subject: [PATCH 0711/1198] pylibfdt: Add functions to update properties Allow updating and creating properties, including special methods for integers. Signed-off-by: Simon Glass Reviewed-by: David Gibson Signed-off-by: David Gibson --- libfdt/libfdt.h | 3 +++ pylibfdt/libfdt.i | 59 +++++++++++++++++++++++++++++++++++++++++ tests/pylibfdt_tests.py | 48 +++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 79e4d82..c99d28f 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1345,10 +1345,13 @@ static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) fdt64_t tmp = cpu_to_fdt64(val); return fdt_property(fdt, name, &tmp, sizeof(tmp)); } + +#ifndef SWIG /* Not available in Python */ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) { return fdt_property_u32(fdt, name, val); } +#endif /** * fdt_property_placeholder - add a new property and return a ptr to its value diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index da32148..3abcf32 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -528,6 +528,60 @@ class Fdt: """ return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet) + def setprop(self, nodeoffset, prop_name, val, quiet=()): + """Set the value of a property + + Args: + nodeoffset: Node offset containing the property to create/update + prop_name: Name of property + val: Value to write (string or bytearray) + 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 + """ + return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val, + len(val)), quiet) + + def setprop_u32(self, nodeoffset, prop_name, val, quiet=()): + """Set the value of a property + + Args: + nodeoffset: Node offset containing the property to create/update + prop_name: Name of property + val: Value to write (integer) + 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 + """ + return check_err(fdt_setprop_u32(self._fdt, nodeoffset, prop_name, val), + quiet) + + def setprop_u64(self, nodeoffset, prop_name, val, quiet=()): + """Set the value of a property + + Args: + nodeoffset: Node offset containing the property to create/update + prop_name: Name of property + val: Value to write (integer) + 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 + """ + return check_err(fdt_setprop_u64(self._fdt, nodeoffset, prop_name, val), + quiet) + def delprop(self, nodeoffset, prop_name): """Delete a property from a node @@ -625,6 +679,11 @@ typedef int fdt32_t; $result = Py_BuildValue("s#", $1, *arg4); } +/* typemap used for fdt_setprop() */ +%typemap(in) (const void *val) { + $1 = PyString_AsString($input); /* char *str */ +} + /* typemaps used for fdt_next_node() */ %typemap(in, numinputs=1) int *depth (int depth) { depth = (int) PyInt_AsLong($input); diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index ea38b78..08c4f57 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -49,6 +49,7 @@ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # +import struct import sys import types import unittest @@ -57,6 +58,18 @@ sys.path.insert(0, '../pylibfdt') import libfdt from libfdt import Fdt, FdtException, QUIET_NOTFOUND, QUIET_ALL +small_size = 160 +full_size = 1024 + +TEST_VALUE_1 = 0xdeadbeef + +TEST_VALUE64_1H = 0xdeadbeef +TEST_VALUE64_1L = 0x01abcdef +TEST_VALUE64_1 = (TEST_VALUE64_1H << 32) | TEST_VALUE64_1L + +TEST_STRING_1 = 'hello world' + + def get_err(err_code): """Convert an error code into an error message @@ -380,6 +393,41 @@ class PyLibfdtTests(unittest.TestCase): fdt.pack() self.assertTrue(fdt.totalsize() < 128) + def testSetProp(self): + """Test that we can update and create properties""" + node = self.fdt.path_offset('/subnode@1') + self.fdt.setprop(node, 'compatible', TEST_STRING_1) + self.assertEquals(TEST_STRING_1, self.fdt.getprop(node, 'compatible')) + + # Check that this property is missing, and that we don't have space to + # add it + self.assertEquals(-libfdt.NOTFOUND, + self.fdt.getprop(node, 'missing', QUIET_NOTFOUND)) + self.assertEquals(-libfdt.NOSPACE, + self.fdt.setprop(node, 'missing', TEST_STRING_1, + quiet=(libfdt.NOSPACE,))) + + # Expand the device tree so we now have room + self.fdt.resize(self.fdt.totalsize() + 50) + self.fdt.setprop(node, 'missing', TEST_STRING_1) + self.assertEquals(TEST_STRING_1, self.fdt.getprop(node, 'missing')) + + def testSetPropU32(self): + """Test that we can update and create integer properties""" + node = 0 + prop = 'prop-int' + self.fdt.setprop_u32(node, prop, TEST_VALUE_1) + self.assertEquals(struct.pack('>I', TEST_VALUE_1), + self.fdt.getprop(node, prop)) + + def testSetPropU64(self): + """Test that we can update and create integer properties""" + node = 0 + prop = 'prop-int64' + self.fdt.setprop_u64(node, prop, TEST_VALUE64_1) + self.assertEquals(struct.pack('>Q', TEST_VALUE64_1), + self.fdt.getprop(node, prop)) + if __name__ == "__main__": unittest.main() From 481246a0c13a364081579c97fc4efbba5213cac1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 6 Jun 2018 15:37:07 -0600 Subject: [PATCH 0712/1198] pylibfdt: Avoid accessing the internal _fdt member in tests We can use the accessor now, so do so. Signed-off-by: Simon Glass Reviewed-by: David Gibson Signed-off-by: David Gibson --- tests/pylibfdt_tests.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 08c4f57..f195a34 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -336,10 +336,9 @@ class PyLibfdtTests(unittest.TestCase): def testIntegers(self): """Check that integers can be passed and returned""" - self.assertEquals(0, libfdt.fdt_get_phandle(self.fdt.as_bytearray(), 0)) + self.assertEquals(0, libfdt.fdt_get_phandle(self.fdt._fdt, 0)) node2 = self.fdt.path_offset('/subnode@2') - self.assertEquals( - 0x2000, libfdt.fdt_get_phandle(self.fdt.as_bytearray(), node2)) + self.assertEquals(0x2000, libfdt.fdt_get_phandle(self.fdt._fdt, node2)) def testGetPhandle(self): """Test for the get_phandle() method""" From 49d32ce40bb44a35536326236c4f82ca6848b0f0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 12 Jun 2018 23:24:11 -0600 Subject: [PATCH 0713/1198] pylibfdt: Use an unsigned type for fdt32_t The members of struct fdt_header are declared as fdt32_t which is a 32-bit, big-endian, unsigned integer. These fields are accessed by macros in libfdt.h so no return type is declared. But the correct return type is uint32_t, not fdt32_t, since the endianness conversion is done within the macro before returning the value. The macros are re-declared as normal functions in pylibfdt since swig does not support macros. The return type is currently int. Change it to uint32_t, which allows us to drop the work-around mask in Fdt.magic(). Also change the typedef for fdt32_t to uint32_t. The currently has no obvious effect, since use of big-endian values should always be internal to pylibfdt, but it is more correct. Signed-off-by: Simon Glass Suggested-by: David Gibson Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 3abcf32..520911e 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -240,8 +240,7 @@ class Fdt: Returns: Magic word """ - # Use a mask to ensure that this does not return a -ve number - return fdt_magic(self._fdt) & 0xffffffff + return fdt_magic(self._fdt) def totalsize(self): """Return the total size of the device tree @@ -628,7 +627,11 @@ class Property(bytearray): %rename(fdt_property) fdt_property_func; -typedef int fdt32_t; +/* + * fdt32_t is a big-endian 32-bit value defined to uint32_t in libfdt_env.h + * so use the same type here. + */ +typedef uint32_t fdt32_t; %include "libfdt/fdt.h" @@ -716,15 +719,15 @@ typedef int fdt32_t; %warnfilter(302) fdt_property; /* These are macros in the header so have to be redefined here */ -int fdt_magic(const void *fdt); -int fdt_totalsize(const void *fdt); -int fdt_off_dt_struct(const void *fdt); -int fdt_off_dt_strings(const void *fdt); -int fdt_off_mem_rsvmap(const void *fdt); -int fdt_version(const void *fdt); -int fdt_last_comp_version(const void *fdt); -int fdt_boot_cpuid_phys(const void *fdt); -int fdt_size_dt_strings(const void *fdt); -int fdt_size_dt_struct(const void *fdt); +uint32_t fdt_magic(const void *fdt); +uint32_t fdt_totalsize(const void *fdt); +uint32_t fdt_off_dt_struct(const void *fdt); +uint32_t fdt_off_dt_strings(const void *fdt); +uint32_t fdt_off_mem_rsvmap(const void *fdt); +uint32_t fdt_version(const void *fdt); +uint32_t fdt_last_comp_version(const void *fdt); +uint32_t fdt_boot_cpuid_phys(const void *fdt); +uint32_t fdt_size_dt_strings(const void *fdt); +uint32_t fdt_size_dt_struct(const void *fdt); %include <../libfdt/libfdt.h> From 3c374d46accee1911f5679ccb131d1404abbdbbf Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 12 Jun 2018 23:37:31 -0600 Subject: [PATCH 0714/1198] pylibfdt: Allow reading integer values from properties Extend the Properties class with some functions to read a single integer property. Add a new getprop_obj() function to return a Property object instead of the raw data. This suggested approach can be extended to handle other types, as well as arrays. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 22 +++++++++++++++++++--- tests/pylibfdt_tests.py | 12 ++++++++++++ tests/run_tests.sh | 1 + tests/test_props.dts | 11 +++++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 tests/test_props.dts diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 520911e..adb4ee8 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -488,7 +488,9 @@ class Fdt: quiet: Errors to ignore (empty to raise on all errors) Returns: - Value of property as a string of bytes, or -ve error number + Value of property as a Property object (which can be used as a + bytearray/string), or -ve error number. On failure, returns an + integer error Raises: FdtError if any error occurs (e.g. the property is not found) @@ -497,8 +499,7 @@ class Fdt: quiet) if isinstance(pdata, (int)): return pdata - # Use bytes() rather than string(). This works on both Python 2 and 3 - return bytes(pdata[0]) + return Property(prop_name, bytearray(pdata[0])) def get_phandle(self, nodeoffset): """Get the phandle of a node @@ -623,6 +624,21 @@ class Property(bytearray): def __init__(self, name, value): bytearray.__init__(self, value) self.name = name + + def as_cell(self, fmt): + return struct.unpack('>' + fmt, self)[0] + + def as_uint32(self): + return self.as_cell('L') + + def as_int32(self): + return self.as_cell('l') + + def as_uint64(self): + return self.as_cell('Q') + + def as_int64(self): + return self.as_cell('q') %} %rename(fdt_property) fdt_property_func; diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index f195a34..0467375 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -102,6 +102,7 @@ class PyLibfdtTests(unittest.TestCase): def setUp(self): """Read in the device tree we use for testing""" self.fdt = _ReadFdt('test_tree1.dtb') + self.fdt2 = _ReadFdt('test_props.dtb') def GetPropList(self, node_path): """Read a list of properties from a node @@ -368,6 +369,17 @@ class PyLibfdtTests(unittest.TestCase): node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') self.assertEquals(node2, self.fdt.node_offset_by_phandle(0x2001)) + def get_prop(self, name): + return self.fdt2.getprop(0, name) + + def testGetIntProperties(self): + """Test that we can access properties as integers""" + self.assertEquals(0xdeadbeef, self.get_prop("prop-hex32").as_uint32()) + self.assertEquals(123, self.get_prop("prop-uint32").as_uint32()) + self.assertEquals(-2, self.get_prop("prop-int32").as_int32()) + self.assertEquals(9223372036854775807, + self.get_prop("prop-uint64").as_uint64()) + self.assertEquals(-2, self.get_prop("prop-int64").as_int64()) def testReserveMap(self): """Test that we can access the memory reserve map""" diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 28e528f..21b633e 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -888,6 +888,7 @@ fdtoverlay_tests() { } pylibfdt_tests () { + run_dtc_test -I dts -O dtb -o test_props.dtb test_props.dts TMP=/tmp/tests.stderr.$$ python pylibfdt_tests.py -v 2> $TMP diff --git a/tests/test_props.dts b/tests/test_props.dts new file mode 100644 index 0000000..7e59bd1 --- /dev/null +++ b/tests/test_props.dts @@ -0,0 +1,11 @@ +/dts-v1/; + +/ { + compatible = "test_props"; + prop-hex32 = <0xdeadbeef>; + prop-uint32 = <123>; + prop-int32 = <0xfffffffe>; + prop-hex64 = /bits/ 64 <0xdeadbeef01abcdef>; + prop-uint64 = /bits/ 64 <9223372036854775807>; + prop-int64 = /bits/ 64 <0xfffffffffffffffe>; +}; From 354d3dc55939499954b5e1f4948517da24591cd2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jun 2018 05:38:23 -0600 Subject: [PATCH 0715/1198] pylibfdt: Update the bytearray size with pack() At present pack() calls fdt_pack() which may well reduce the size of the device-tree data. However this does not currently update the size of the bytearray to take account of any reduction. This means that there may be unused data at the end of the bytearray and any users of as_bytearray() will see this extra data. Fix this by resizing the bytearray after packing. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 9 ++++++++- tests/pylibfdt_tests.py | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index adb4ee8..c0a2191 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -474,10 +474,17 @@ class Fdt: Args: quiet: Errors to ignore (empty to raise on all errors) + Returns: + Error code, or 0 if OK + Raises: FdtException if any error occurs """ - return check_err(fdt_pack(self._fdt), quiet) + err = check_err(fdt_pack(self._fdt), quiet) + if err: + return err + del self._fdt[self.totalsize():] + return err def getprop(self, nodeoffset, prop_name, quiet=()): """Get a property from a node diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 0467375..c9653a5 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -308,6 +308,7 @@ class PyLibfdtTests(unittest.TestCase): self.assertEquals(orig_size, self.fdt.totalsize()) self.assertEquals(self.fdt.pack(), 0) self.assertTrue(self.fdt.totalsize() < orig_size) + self.assertEquals(self.fdt.totalsize(), len(self.fdt.as_bytearray())) def testBadPropertyOffset(self): """Test that bad property offsets are detected""" From 2f0d07e678e05f260b575342867a26d466bdec85 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jun 2018 21:44:43 -0600 Subject: [PATCH 0716/1198] pylibfdt: Add functions to set and get properties as strings It is common to want to set a property to a nul-terminated string in a device tree. Add python methods to handle this. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 30 ++++++++++++++++++++++++++++++ tests/pylibfdt_tests.py | 25 +++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index c0a2191..2896513 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -589,6 +589,28 @@ class Fdt: return check_err(fdt_setprop_u64(self._fdt, nodeoffset, prop_name, val), quiet) + def setprop_str(self, nodeoffset, prop_name, val, quiet=()): + """Set the string value of a property + + The property is set to the string, with a nul terminator added + + Args: + nodeoffset: Node offset containing the property to create/update + prop_name: Name of property + val: Value to write (string without nul terminator). Unicode is + supposed by encoding to UTF-8 + 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 + """ + val = val.encode('utf-8') + '\0' + return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, + val, len(val)), quiet) + def delprop(self, nodeoffset, prop_name): """Delete a property from a node @@ -646,6 +668,14 @@ class Property(bytearray): def as_int64(self): return self.as_cell('q') + + def as_str(self): + """Unicode is supported by decoding from UTF-8""" + if self[-1] != 0: + raise ValueError('Property lacks nul termination') + if 0 in self[:-1]: + raise ValueError('Property contains embedded nul characters') + return self[:-1].decode('utf-8') %} %rename(fdt_property) fdt_property_func; diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index c9653a5..f3be0ac 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -68,6 +68,8 @@ TEST_VALUE64_1L = 0x01abcdef TEST_VALUE64_1 = (TEST_VALUE64_1H << 32) | TEST_VALUE64_1L TEST_STRING_1 = 'hello world' +TEST_STRING_2 = 'hi world' +TEST_STRING_3 = u'unicode ' + unichr(467) def get_err(err_code): @@ -440,6 +442,29 @@ class PyLibfdtTests(unittest.TestCase): self.assertEquals(struct.pack('>Q', TEST_VALUE64_1), self.fdt.getprop(node, prop)) + def testSetPropStr(self): + """Test that we can set a property to a particular string""" + node = 0 + prop = 'prop-str' + self.assertEquals(TEST_STRING_1, self.fdt.getprop(node, prop).as_str()) + self.fdt.setprop_str(node, prop, TEST_STRING_2) + self.assertEquals(TEST_STRING_2, self.fdt.getprop(node, prop).as_str()) + with self.assertRaises(ValueError) as e: + self.fdt.getprop(node, 'prop-int').as_str() + self.assertIn('lacks nul termination', str(e.exception)) + + node2 = self.fdt.path_offset('/subnode@1/subsubnode') + with self.assertRaises(ValueError) as e: + self.fdt.getprop(node2, 'compatible').as_str() + self.assertIn('embedded nul', str(e.exception)) + + # Expand the device tree so we now have room + self.fdt.resize(self.fdt.totalsize() + 50) + prop = 'prop-unicode' + self.fdt.setprop_str(node, prop, TEST_STRING_3) + self.assertEquals(TEST_STRING_3, + self.fdt.getprop(node, prop).as_str()) + if __name__ == "__main__": unittest.main() From b770f3d1c13f63a22c7015bd2438dbc1164b5362 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jun 2018 21:44:44 -0600 Subject: [PATCH 0717/1198] pylibfdt: Support setting the name of a node Add a method to call fdt_set_name(). Signed-off-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 17 +++++++++++++++++ tests/pylibfdt_tests.py | 15 +++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 2896513..aed5390 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -535,6 +535,23 @@ class Fdt: """ return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet) + def set_name(self, nodeoffset, name, quiet=()): + """Set the name of a node + + Args: + nodeoffset: Node offset of node to update + name: New node name (string without \0) + + Returns: + Error code, or 0 if OK + + Raises: + FdtException if no parent found or other error occurs + """ + if chr(0) in name: + raise ValueError('Property contains embedded nul characters') + return check_err(fdt_set_name(self._fdt, nodeoffset, name), quiet) + def setprop(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 f3be0ac..9f3e55a 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -465,6 +465,21 @@ class PyLibfdtTests(unittest.TestCase): self.assertEquals(TEST_STRING_3, self.fdt.getprop(node, prop).as_str()) + def testSetName(self): + """Test that we can update a node name""" + node = self.fdt.path_offset('/subnode@1') + old_val = self.fdt.get_name(node) + self.fdt.set_name(node, 'test') + self.assertEquals('test', self.fdt.get_name(node)) + + with self.assertRaises(ValueError) as e: + self.fdt.set_name(node, 'some\0name') + self.assertIn('embedded nul', str(e.exception)) + + with self.assertRaises(ValueError) as e: + self.fdt.set_name(node, 'name\0') + self.assertIn('embedded nul', str(e.exception)) + if __name__ == "__main__": unittest.main() From 9d78c33bf8a122eb3a97934e71b8c651cc1b1e4b Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 15 Jun 2018 15:37:14 -0600 Subject: [PATCH 0718/1198] tests: fix grep for checks error messages I noticed the error type passed in didn't matter for check tests to pass. There's a couple of problems with the grep regex. The error/warning messages begin with the output filename now, so "ERROR" or "Warning" is not at the beginning of the line. Secondly, the parentheses seem to be wrong. It's not clear to me what was intended. Signed-off-by: Rob Herring Signed-off-by: David Gibson --- tests/dtc-checkfails.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh index 76ded15..7319597 100755 --- a/tests/dtc-checkfails.sh +++ b/tests/dtc-checkfails.sh @@ -30,13 +30,13 @@ ret="$?" FAIL_IF_SIGNAL $ret for c in $YESCHECKS; do - if ! grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then + if ! grep -E "(ERROR|Warning) \($c\):" $LOG > /dev/null; then FAIL "Failed to trigger check \"$c\"" fi done for c in $NOCHECKS; do - if grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then + if grep -E "(ERROR|Warning) \($c\):" $LOG > /dev/null; then FAIL "Incorrectly triggered check \"$c\"" fi done From 42607f21d43e44aafc7ac7d9ca4f0ea1e3bda904 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 15 Jun 2018 15:37:15 -0600 Subject: [PATCH 0719/1198] tests: Fix incorrect check name 'prop_name_chars' 'prop_name_chars' is not a valid check name, but the test was passing due to a bug in dtc-checkfails.sh. Fix it to be the correct name, 'property_name_chars'. Signed-off-by: Rob Herring 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 21b633e..87a64ae 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -627,7 +627,7 @@ dtc_tests () { check_tests bad-interrupt-cells.dts interrupts_property run_sh_test dtc-checkfails.sh node_name_chars -- -I dtb -O dtb bad_node_char.dtb run_sh_test dtc-checkfails.sh node_name_format -- -I dtb -O dtb bad_node_format.dtb - run_sh_test dtc-checkfails.sh prop_name_chars -- -I dtb -O dtb bad_prop_char.dtb + run_sh_test dtc-checkfails.sh property_name_chars -- -I dtb -O dtb bad_prop_char.dtb run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label1.dts run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label2.dts From 6dcb8ba408ec18009083acaa9f85429afa39e453 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 21 Jun 2018 15:32:40 +1000 Subject: [PATCH 0720/1198] libfdt: Add helpers for accessing unaligned words This adds some helpers to load (32 or 64 bit) words from an fdt blob, even if they're unaligned and we're on a platform that doesn't like plain unaligned loads and stores. We then use the helpers in a number of places. There are two purposes for this: 1) This makes libfdt more robust against a blob loaded at an unaligned address. It's usually good practice to load a blob at a 64-bit alignment, but it's nice to work even then. 2) Users can use these helpers to load integer values from within property values. These can often be unaligned, even if the blob as a whole is aligned, since some property encodings have integers and strings mixed together without any alignment gaps. Signed-off-by: David Gibson --- fdtget.c | 2 +- libfdt/fdt_ro.c | 18 +++++++++--------- libfdt/libfdt.h | 25 ++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/fdtget.c b/fdtget.c index ee7139f..a79c3b2 100644 --- a/fdtget.c +++ b/fdtget.c @@ -76,7 +76,7 @@ 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_to_cpu(*(const fdt32_t *)p) : + value = size == 4 ? fdt32_ld((const fdt32_t *)p) : size == 2 ? (*p << 8) | p[1] : *p; printf(fmt, value); } diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 4ba7c93..eafc142 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -191,8 +191,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) if (!re) return -FDT_ERR_BADOFFSET; - *address = fdt64_to_cpu(re->address); - *size = fdt64_to_cpu(re->size); + *address = fdt64_ld(&re->address); + *size = fdt64_ld(&re->size); return 0; } @@ -202,7 +202,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_to_cpu(re->size) == 0) + if (fdt64_ld(&re->size) == 0) return i; } return -FDT_ERR_TRUNCATED; @@ -379,7 +379,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, prop = fdt_offset_ptr_(fdt, offset); if (lenp) - *lenp = fdt32_to_cpu(prop->len); + *lenp = fdt32_ld(&prop->len); return prop; } @@ -416,7 +416,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, offset = -FDT_ERR_INTERNAL; break; } - if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff), + if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff), name, namelen)) { if (poffset) *poffset = offset; @@ -469,7 +469,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, /* Handle realignment */ if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 && - fdt32_to_cpu(prop->len) >= 8) + fdt32_ld(&prop->len) >= 8) return prop->data + 4; return prop->data; } @@ -485,7 +485,7 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, if (namep) { const char *name; int namelen; - name = fdt_get_string(fdt, fdt32_to_cpu(prop->nameoff), + name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), &namelen); if (!name) { if (lenp) @@ -497,7 +497,7 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, /* Handle realignment */ if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 && - fdt32_to_cpu(prop->len) >= 8) + fdt32_ld(&prop->len) >= 8) return prop->data + 4; return prop->data; } @@ -522,7 +522,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) return 0; } - return fdt32_to_cpu(*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 c99d28f..38ec313 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -154,6 +154,29 @@ 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 + */ + +static inline uint32_t fdt32_ld(const fdt32_t *p) +{ + fdt32_t v; + + memcpy(&v, p, sizeof(v)); + return fdt32_to_cpu(v); +} + +static inline uint64_t fdt64_ld(const fdt64_t *p) +{ + fdt64_t v; + + memcpy(&v, p, sizeof(v)); + return fdt64_to_cpu(v); +} + /**********************************************************************/ /* Traversal functions */ /**********************************************************************/ @@ -214,7 +237,7 @@ int fdt_next_subnode(const void *fdt, int offset); /* General functions */ /**********************************************************************/ #define fdt_get_header(fdt, field) \ - (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) + (fdt32_ld(&((const struct fdt_header *)(fdt))->field)) #define fdt_magic(fdt) (fdt_get_header(fdt, magic)) #define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) #define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) From 32b9c61307629ac76c6ac0bead6f926d579b3d2c Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 28 Jun 2018 15:37:01 -0600 Subject: [PATCH 0721/1198] Preserve datatype markers when emitting dts format If datatype markers are present in the property value, use them to output the data in the correct format instead of trying to guess the datatype. This also will preserve data grouping, such as in an interrupts list. This is a step forward for preserving and using datatype information when processing DTS/DTB files. Schema validation tools can use the datatype information to make sure a DT is correctly formed and intepreted. Signed-off-by: Grant Likely [robh: rework marker handling and fix label output] Signed-off-by: Rob Herring Signed-off-by: David Gibson --- dtc.h | 1 + tests/run_tests.sh | 7 ++ tests/type-preservation.dts | 28 +++++ treesource.c | 226 +++++++++++++++++++++--------------- 4 files changed, 169 insertions(+), 93 deletions(-) create mode 100644 tests/type-preservation.dts diff --git a/dtc.h b/dtc.h index e648cdf..303c2a6 100644 --- a/dtc.h +++ b/dtc.h @@ -74,6 +74,7 @@ typedef uint32_t cell_t; /* Data blobs */ enum markertype { + TYPE_NONE, REF_PHANDLE, REF_PATH, LABEL, diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 87a64ae..759625d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -551,6 +551,13 @@ dtc_tests () { run_test dtbs_equal_ordered $tree odts_$tree.test.dtb done + # Check -Odts preserving type information + for tree in type-preservation.dts; do + run_dtc_test -I dts -O dts -o $tree.test.dts $tree + run_dtc_test -I dts -O dts $tree.test.dts + run_wrap_test cmp $tree $tree.test.dts + done + # Check version conversions for tree in test_tree1.dtb ; do for aver in 1 2 3 16 17; do diff --git a/tests/type-preservation.dts b/tests/type-preservation.dts new file mode 100644 index 0000000..62c0c23 --- /dev/null +++ b/tests/type-preservation.dts @@ -0,0 +1,28 @@ +/dts-v1/; + +/ { + #address-cells = < 0x01 >; + #size-cells = < 0x00 >; + + sub1: subnode@1 { + prop_label: compatible = value_label: "subnode1"; + reg = < 0x01 >; + int-array = < 0x00 0x01 >, int_value_label: < 0x02 0x03 >; + int8 = [ 56 ]; + int8-array = [ 00 12 34 56 label: ]; + int16 = /bits/ 16 < 0x3210 >; + int16-array = /bits/ 16 < 0x1234 0x5678 0x90ab 0xcdef >; + int16-matrix = /bits/ 16 < 0x1234 0x5678 >, < 0x90ab 0xcdef >; + int64 = /bits/ 64 < 0x200000000 >; + int64-array = /bits/ 64 < 0x100000000 0x00 int64_array_label_end: >; + a-string-with-nulls = "foo\0bar", "baz"; + + subsub1: subsubnode { + compatible = "subsubnode1", "subsubnode"; + + subsubsub1: subsubsubnode { + compatible = "subsubsubnode1", < 0x1234 >, valuea: valueb: "subsubsubnode"; + }; + }; + }; +}; diff --git a/treesource.c b/treesource.c index 2461a3d..f99544d 100644 --- a/treesource.c +++ b/treesource.c @@ -61,24 +61,14 @@ static bool isstring(char c) || strchr("\a\b\t\n\v\f\r", c)); } -static void write_propval_string(FILE *f, struct data val) +static void write_propval_string(FILE *f, const char *s, size_t len) { - const char *str = val.val; - int i; - struct marker *m = val.markers; + const char *end = s + len - 1; + assert(*end == '\0'); - assert(str[val.len-1] == '\0'); - - while (m && (m->offset == 0)) { - if (m->type == LABEL) - fprintf(f, "%s: ", m->ref); - m = m->next; - } fprintf(f, "\""); - - for (i = 0; i < (val.len-1); i++) { - char c = str[i]; - + while (s < end) { + char c = *s++; switch (c) { case '\a': fprintf(f, "\\a"); @@ -108,91 +98,73 @@ static void write_propval_string(FILE *f, struct data val) fprintf(f, "\\\""); break; case '\0': - fprintf(f, "\", "); - while (m && (m->offset <= (i + 1))) { - if (m->type == LABEL) { - assert(m->offset == (i+1)); - fprintf(f, "%s: ", m->ref); - } - m = m->next; - } - fprintf(f, "\""); + fprintf(f, "\\0"); break; default: if (isprint((unsigned char)c)) fprintf(f, "%c", c); else - fprintf(f, "\\x%02hhx", c); + fprintf(f, "\\x%02"PRIx8, c); } } fprintf(f, "\""); - - /* Wrap up any labels at the end of the value */ - for_each_marker_of_type(m, LABEL) { - assert (m->offset == val.len); - fprintf(f, " %s:", m->ref); - } } -static void write_propval_cells(FILE *f, struct data val) +static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) { - void *propend = val.val + val.len; - fdt32_t *cp = (fdt32_t *)val.val; - struct marker *m = val.markers; + const char *end = p + len; + assert(len % width == 0); - fprintf(f, "<"); - for (;;) { - while (m && (m->offset <= ((char *)cp - val.val))) { - if (m->type == LABEL) { - assert(m->offset == ((char *)cp - val.val)); - fprintf(f, "%s: ", m->ref); - } - m = m->next; - } - - fprintf(f, "0x%x", fdt32_to_cpu(*cp++)); - if ((void *)cp >= propend) + for (; p < end; p += width) { + switch (width) { + case 1: + fprintf(f, " %02"PRIx8, *(const uint8_t*)p); break; - fprintf(f, " "); + case 2: + fprintf(f, " 0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); + break; + case 4: + fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); + break; + case 8: + fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); + break; + } } - - /* Wrap up any labels at the end of the value */ - for_each_marker_of_type(m, LABEL) { - assert (m->offset == val.len); - fprintf(f, " %s:", m->ref); - } - fprintf(f, ">"); } -static void write_propval_bytes(FILE *f, struct data val) +static struct marker *next_type_marker(struct marker *m) { - void *propend = val.val + val.len; - const char *bp = val.val; - struct marker *m = val.markers; - - fprintf(f, "["); - for (;;) { - while (m && (m->offset == (bp-val.val))) { - if (m->type == LABEL) - fprintf(f, "%s: ", m->ref); - m = m->next; - } - - fprintf(f, "%02hhx", (unsigned char)(*bp++)); - if ((const void *)bp >= propend) - break; - fprintf(f, " "); - } - - /* Wrap up any labels at the end of the value */ - for_each_marker_of_type(m, LABEL) { - assert (m->offset == val.len); - fprintf(f, " %s:", m->ref); - } - fprintf(f, "]"); + while (m && (m->type == LABEL || m->type == REF_PHANDLE || m->type == REF_PATH)) + m = m->next; + return m; } -static void write_propval(FILE *f, struct property *prop) +static 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 <", + [TYPE_UINT32] = "<", + [TYPE_UINT64] = "/bits/ 64 <", + [TYPE_STRING] = "", +}; +static const char *delim_end[] = { + [TYPE_UINT8] = " ]", + [TYPE_UINT16] = " >", + [TYPE_UINT32] = " >", + [TYPE_UINT64] = " >", + [TYPE_STRING] = "", +}; + +static enum markertype guess_value_type(struct property *prop) { int len = prop->val.len; const char *p = prop->val.val; @@ -201,11 +173,6 @@ static void write_propval(FILE *f, struct property *prop) int nnotstringlbl = 0, nnotcelllbl = 0; int i; - if (len == 0) { - fprintf(f, ";\n"); - return; - } - for (i = 0; i < len; i++) { if (! isstring(p[i])) nnotstring++; @@ -220,17 +187,91 @@ static void write_propval(FILE *f, struct property *prop) nnotcelllbl++; } - fprintf(f, " = "); if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) && (nnotstringlbl == 0)) { - write_propval_string(f, prop->val); + return TYPE_STRING; } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { - write_propval_cells(f, prop->val); - } else { - write_propval_bytes(f, prop->val); + return TYPE_UINT32; } - fprintf(f, ";\n"); + return TYPE_UINT8; +} + +static void write_propval(FILE *f, struct property *prop) +{ + size_t len = prop->val.len; + struct marker *m = prop->val.markers; + struct marker dummy_marker; + enum markertype emit_type = TYPE_NONE; + + if (len == 0) { + fprintf(f, ";\n"); + return; + } + + fprintf(f, " = "); + + if (!next_type_marker(m)) { + /* data type information missing, need to guess */ + dummy_marker.type = guess_value_type(prop); + dummy_marker.next = prop->val.markers; + dummy_marker.offset = 0; + dummy_marker.ref = NULL; + m = &dummy_marker; + } + + struct marker *m_label = prop->val.markers; + for_each_marker(m) { + size_t chunk_len; + const char *p = &prop->val.val[m->offset]; + + if (m->type < TYPE_UINT8) + continue; + + chunk_len = type_marker_length(m); + if (!chunk_len) + chunk_len = len - m->offset; + + if (emit_type != TYPE_NONE) + fprintf(f, "%s, ", delim_end[emit_type]); + emit_type = m->type; + + for_each_marker_of_type(m_label, LABEL) { + if (m_label->offset > m->offset) + break; + fprintf(f, "%s: ", m_label->ref); + } + + fprintf(f, "%s", delim_start[emit_type]); + + if (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); + break; + case TYPE_UINT64: + write_propval_int(f, p, chunk_len, 8); + break; + case TYPE_STRING: + write_propval_string(f, p, chunk_len); + break; + default: + write_propval_int(f, p, chunk_len, 1); + } + } + + /* Wrap up any labels at the end of the value */ + for_each_marker_of_type(m_label, LABEL) { + assert (m_label->offset == len); + fprintf(f, " %s:", m_label->ref); + } + + fprintf(f, "%s;\n", delim_end[emit_type] ? : ""); } static void write_tree_source_node(FILE *f, struct node *tree, int level) @@ -281,4 +322,3 @@ void dt_to_source(FILE *f, struct dt_info *dti) write_tree_source_node(f, dti->dt, 0); } - From c72fa777e61383850436f9f9cac3b0ddae41317b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 7 Jul 2018 13:57:19 -0600 Subject: [PATCH 0722/1198] libfdt: Copy the struct region in fdt_resize() At present this function appears to copy only the data before the struct region and the data in the string region. It does not seem to copy the struct region itself. From the arguments of this function it seems that it should support fdt and buf being different. This patch attempts to fix this problem. Signed-off-by: Simon Glass 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 178b365..024f4d8 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -170,7 +170,7 @@ int fdt_resize(void *fdt, void *buf, int bufsize) FDT_SW_PROBE(fdt); - headsize = fdt_off_dt_struct(fdt); + headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); tailsize = fdt_size_dt_strings(fdt); if ((headsize + tailsize) > bufsize) From 1087504bb3e8b00988e7bb99784eb02d4d9d9fd1 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 9 Jul 2018 14:50:38 +1000 Subject: [PATCH 0723/1198] libfdt: Add necessary header padding in fdt_create() At present fdt_create() will succeed if there is exactly enough space to put in the fdt header. However, it sets the off_mem_rsvmap field, a few bytes past that in order to align the memory reservation block. Having block pointers pointing past the end of the fdt is pretty ugly, even if it is just a transient state. Worse, if fdt_resize() is called at exactly the wrong time, it can end up accessing data past the blob's allocated space because of this. So, correct fdt_create() to ensure that there is sufficient space for the alignment padding as well as the plain header. For paranoia, also add a check in fdt_resize() to make sure we don't copy data from outside the blob's bounds. Signed-off-by: David Gibson --- libfdt/fdt_sw.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 024f4d8..9fa4a94 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -143,9 +143,11 @@ static void *fdt_grab_space_(void *fdt, size_t len) int fdt_create(void *buf, int bufsize) { + const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry)); void *fdt = buf; - if (bufsize < sizeof(struct fdt_header)) + if (bufsize < hdrsize) return -FDT_ERR_NOSPACE; memset(buf, 0, bufsize); @@ -155,8 +157,7 @@ int fdt_create(void *buf, int bufsize) fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); fdt_set_totalsize(fdt, bufsize); - fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), - sizeof(struct fdt_reserve_entry))); + fdt_set_off_mem_rsvmap(fdt, hdrsize); fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); fdt_set_off_dt_strings(fdt, 0); @@ -173,6 +174,9 @@ int fdt_resize(void *fdt, void *buf, int bufsize) headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); tailsize = fdt_size_dt_strings(fdt); + if ((headsize + tailsize) > fdt_totalsize(fdt)) + return -FDT_ERR_INTERNAL; + if ((headsize + tailsize) > bufsize) return -FDT_ERR_NOSPACE; From 9b0e4fe26093cf3846868543b24b874990ec76e1 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 9 Jul 2018 11:00:21 +1000 Subject: [PATCH 0724/1198] tests: Improve fdt_resize() tests We primarily test fdt_resize() in the sw_tree1 testcase, but it has some deficiencies: - It didn't check for errors actually originating in fdt_resize(), just for errors before and after - It only tested cases where the resized buffer was at the same address as the original one, whereas fdt_resize() is also supposed to work if the new buffer is entirely separate, or partly overlapping Signed-off-by: David Gibson --- tests/run_tests.sh | 2 +- tests/sw_tree1.c | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 759625d..cf87066 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -348,7 +348,7 @@ libfdt_tests () { run_test sw_states # Resizing tests - for mode in resize realloc; do + for mode in resize realloc newalloc; do run_test sw_tree1 $mode tree1_tests sw_tree1.test.dtb tree1_tests unfinished_tree1.test.dtb diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 386b05f..2a67c12 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -35,10 +35,13 @@ static enum { FIXED = 0, RESIZE, REALLOC, + NEWALLOC, } alloc_mode; static void realloc_fdt(void **fdt, size_t *size, bool created) { + int err; + switch (alloc_mode) { case FIXED: if (!(*fdt)) @@ -52,7 +55,10 @@ static void realloc_fdt(void **fdt, size_t *size, bool created) *fdt = xmalloc(SPACE); } else if (*size < SPACE) { *size += 1; - fdt_resize(*fdt, *fdt, *size); + err = fdt_resize(*fdt, *fdt, *size); + if (err < 0) + FAIL("fdt_resize() failed: %s", + fdt_strerror(err)); } else { FAIL("Ran out of space"); } @@ -61,10 +67,30 @@ static void realloc_fdt(void **fdt, size_t *size, bool created) case REALLOC: *size += 1; *fdt = xrealloc(*fdt, *size); - if (created) - fdt_resize(*fdt, *fdt, *size); + if (created) { + err = fdt_resize(*fdt, *fdt, *size); + if (err < 0) + FAIL("fdt_resize() failed: %s", + fdt_strerror(err)); + } return; + case NEWALLOC: { + void *buf; + + *size += 1; + buf = xmalloc(*size); + if (created) { + err = fdt_resize(*fdt, buf, *size); + if (err < 0) + FAIL("fdt_resize() failed: %s", + fdt_strerror(err)); + } + free(*fdt); + *fdt = buf; + return; + } + default: CONFIG("Bad allocation mode"); } @@ -101,6 +127,9 @@ int main(int argc, char *argv[]) } else if (streq(argv[1], "realloc")) { alloc_mode = REALLOC; size = 0; + } else if (streq(argv[1], "newalloc")) { + alloc_mode = NEWALLOC; + size = 0; } else { char *endp; From 853649accebaaa780142916a9c676a3a1fe0f2e5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 10 Jul 2018 14:49:07 -0600 Subject: [PATCH 0725/1198] pylibfdt: Support the sequential-write interface It is useful to be able to create a device tree from scratch using software. This is supported in libfdt but not currently available in the Python bindings. Add a new FdtSw class to handle this, with various methods corresponding to the libfdt functions. When the tree is complete, calling AsFdt() will return the completed device-tree object. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 460 +++++++++++++++++++++++++++++++++------- tests/pylibfdt_tests.py | 119 ++++++++++- 2 files changed, 497 insertions(+), 82 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index aed5390..fc53a8c 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -57,6 +57,18 @@ %{ #define SWIG_FILE_WITH_INIT #include "libfdt.h" + +/* + * We rename this function here to avoid problems with swig, since we also have + * a struct called fdt_property. That struct causes swig to create a class in + * libfdt.py called fdt_property(), which confuses things. + */ +static int fdt_property_stub(void *fdt, const char *name, const char *val, + int len) +{ + return fdt_property(fdt, name, val, len); +} + %} %pythoncode %{ @@ -88,6 +100,7 @@ import struct # Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors, # instead of raising an exception. QUIET_NOTFOUND = (NOTFOUND,) +QUIET_NOSPACE = (NOSPACE,) class FdtException(Exception): @@ -153,22 +166,18 @@ def check_err_null(val, quiet=()): raise FdtException(val) return val -class Fdt: - """Device tree class, supporting all operations +class FdtRo(object): + """Class for a read-only device-tree - The Fdt object is created is created from a device tree binary file, - e.g. with something like: + This is a base class used by FdtRw (read-write access) and FdtSw + (sequential-write access). It implements read-only access to the + device tree. - fdt = Fdt(open("filename.dtb").read()) + Here are the three classes and when you should use them: - Operations can then be performed using the methods in this class. Each - method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...). - - All methods raise an FdtException if an error occurs. To avoid this - behaviour a 'quiet' parameter is provided for some functions. This - defaults to empty, but you can pass a list of errors that you expect. - If one of these errors occurs, the function will return an error number - (e.g. -NOTFOUND). + FdtRo - read-only access to an existing FDT + FdtRw - read-write access to an existing FDT (most common case) + FdtSw - for creating a new FDT, as well as allowing read-only access """ def __init__(self, data): self._fdt = bytearray(data) @@ -433,6 +442,91 @@ class Fdt: return pdata return Property(pdata[0], pdata[1]) + def getprop(self, nodeoffset, prop_name, quiet=()): + """Get a property from a node + + Args: + nodeoffset: Node offset containing property to get + prop_name: Name of property to get + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + Value of property as a Property object (which can be used as a + bytearray/string), or -ve error number. On failure, returns an + integer error + + Raises: + FdtError if any error occurs (e.g. the property is not found) + """ + pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), + quiet) + if isinstance(pdata, (int)): + return pdata + return Property(prop_name, bytearray(pdata[0])) + + def get_phandle(self, nodeoffset): + """Get the phandle of a node + + Args: + nodeoffset: Node offset to check + + Returns: + phandle of node, or 0 if the node has no phandle or another error + occurs + """ + return fdt_get_phandle(self._fdt, nodeoffset) + + def parent_offset(self, nodeoffset, quiet=()): + """Get the offset of a node's parent + + Args: + nodeoffset: Node offset to check + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + The offset of the parent node, if any + + Raises: + FdtException if no parent found or other error occurs + """ + return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet) + + def node_offset_by_phandle(self, phandle, quiet=()): + """Get the offset of a node with the given phandle + + Args: + phandle: Phandle to search for + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + The offset of node with that phandle, if any + + Raises: + FdtException if no node found or other error occurs + """ + return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet) + + +class Fdt(FdtRo): + """Device tree class, supporting all operations + + The Fdt object is created is created from a device tree binary file, + e.g. with something like: + + fdt = Fdt(open("filename.dtb").read()) + + Operations can then be performed using the methods in this class. Each + method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...). + + All methods raise an FdtException if an error occurs. To avoid this + behaviour a 'quiet' parameter is provided for some functions. This + defaults to empty, but you can pass a list of errors that you expect. + If one of these errors occurs, the function will return an error number + (e.g. -NOTFOUND). + """ + def __init__(self, data): + FdtRo.__init__(self, data) + @staticmethod def create_empty_tree(size, quiet=()): """Create an empty device tree ready for use @@ -486,55 +580,6 @@ class Fdt: del self._fdt[self.totalsize():] return err - def getprop(self, nodeoffset, prop_name, quiet=()): - """Get a property from a node - - Args: - nodeoffset: Node offset containing property to get - prop_name: Name of property to get - quiet: Errors to ignore (empty to raise on all errors) - - Returns: - Value of property as a Property object (which can be used as a - bytearray/string), or -ve error number. On failure, returns an - integer error - - Raises: - FdtError if any error occurs (e.g. the property is not found) - """ - pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), - quiet) - if isinstance(pdata, (int)): - return pdata - return Property(prop_name, bytearray(pdata[0])) - - def get_phandle(self, nodeoffset): - """Get the phandle of a node - - Args: - nodeoffset: Node offset to check - - Returns: - phandle of node, or 0 if the node has no phandle or another error - occurs - """ - return fdt_get_phandle(self._fdt, nodeoffset) - - def parent_offset(self, nodeoffset, quiet=()): - """Get the offset of a node's parent - - Args: - nodeoffset: Node offset to check - quiet: Errors to ignore (empty to raise on all errors) - - Returns: - The offset of the parent node, if any - - Raises: - FdtException if no parent found or other error occurs - """ - return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet) - def set_name(self, nodeoffset, name, quiet=()): """Set the name of a node @@ -640,21 +685,6 @@ class Fdt: """ return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) - def node_offset_by_phandle(self, phandle, quiet=()): - """Get the offset of a node with the given phandle - - Args: - phandle: Phandle to search for - quiet: Errors to ignore (empty to raise on all errors) - - Returns: - The offset of node with that phandle, if any - - Raises: - FdtException if no node found or other error occurs - """ - return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet) - class Property(bytearray): """Holds a device tree property name and value. @@ -693,6 +723,268 @@ class Property(bytearray): if 0 in self[:-1]: raise ValueError('Property contains embedded nul characters') return self[:-1].decode('utf-8') + + +class FdtSw(FdtRo): + """Software interface to create a device tree from scratch + + The methods in this class work by adding to an existing 'partial' device + tree buffer of a fixed size created by instantiating this class. When the + tree is complete, call as_fdt() to obtain a device tree ready to be used. + + Similarly with nodes, a new node is started with begin_node() and finished + with end_node(). + + The context manager functions can be used to make this a bit easier: + + # First create the device tree with a node and property: + sw = FdtSw() + with sw.add_node('node'): + sw.property_u32('reg', 2) + fdt = sw.as_fdt() + + # Now we can use it as a real device tree + fdt.setprop_u32(0, 'reg', 3) + + The size hint provides a starting size for the space to be used by the + device tree. This will be increased automatically as needed as new items + are added to the tree. + """ + INC_SIZE = 1024 # Expand size by this much when out of space + + def __init__(self, size_hint=None): + """Create a new FdtSw object + + Args: + size_hint: A hint as to the initial size to use + + Raises: + ValueError if size_hint is negative + + Returns: + FdtSw object on success, else integer error code (if not raising) + """ + if not size_hint: + size_hint = self.INC_SIZE + fdtsw = bytearray(size_hint) + err = check_err(fdt_create(fdtsw, size_hint)) + if err: + return err + self._fdt = fdtsw + + def as_fdt(self): + """Convert a FdtSw into an Fdt so it can be accessed as normal + + Creates a new Fdt object from the work-in-progress device tree. This + does not call fdt_finish() on the current object, so it is possible to + add more nodes/properties and call as_fdt() again to get an updated + tree. + + Returns: + Fdt object allowing access to the newly created device tree + """ + fdtsw = bytearray(self._fdt) + check_err(fdt_finish(fdtsw)) + return Fdt(fdtsw) + + def check_space(self, val): + """Check if we need to add more space to the FDT + + This should be called with the error code from an operation. If this is + -NOSPACE then the FDT will be expanded to have more space, and True will + be returned, indicating that the operation needs to be tried again. + + Args: + val: Return value from the operation that was attempted + + Returns: + True if the operation must be retried, else False + """ + if check_err(val, QUIET_NOSPACE) < 0: + self.resize(len(self._fdt) + self.INC_SIZE) + return True + return False + + def resize(self, size): + """Resize the buffer to accommodate a larger tree + + Args: + size: New size of tree + + Raises: + FdtException on any error + """ + fdt = bytearray(size) + err = check_err(fdt_resize(self._fdt, fdt, size)) + self._fdt = fdt + + def add_reservemap_entry(self, addr, size): + """Add a new memory reserve map entry + + Once finished adding, you must call finish_reservemap(). + + Args: + addr: 64-bit start address + size: 64-bit size + + Raises: + FdtException on any error + """ + while self.check_space(fdt_add_reservemap_entry(self._fdt, addr, + size)): + pass + + def finish_reservemap(self): + """Indicate that there are no more reserve map entries to add + + Raises: + FdtException on any error + """ + while self.check_space(fdt_finish_reservemap(self._fdt)): + pass + + def begin_node(self, name): + """Begin a new node + + Use this before adding properties to the node. Then call end_node() to + finish it. You can also use the context manager as shown in the FdtSw + class comment. + + Args: + name: Name of node to begin + + Raises: + FdtException on any error + """ + while self.check_space(fdt_begin_node(self._fdt, name)): + pass + + def property_string(self, name, string): + """Add a property with a string value + + The string will be nul-terminated when written to the device tree + + Args: + name: Name of property to add + string: String value of property + + Raises: + FdtException on any error + """ + while self.check_space(fdt_property_string(self._fdt, name, string)): + pass + + def property_u32(self, name, val): + """Add a property with a 32-bit value + + Write a single-cell value to the device tree + + Args: + name: Name of property to add + val: Value of property + + Raises: + FdtException on any error + """ + while self.check_space(fdt_property_u32(self._fdt, name, val)): + pass + + def property_u64(self, name, val): + """Add a property with a 64-bit value + + Write a double-cell value to the device tree in big-endian format + + Args: + name: Name of property to add + val: Value of property + + Raises: + FdtException on any error + """ + while self.check_space(fdt_property_u64(self._fdt, name, val)): + pass + + def property_cell(self, name, val): + """Add a property with a single-cell value + + Write a single-cell value to the device tree + + Args: + name: Name of property to add + val: Value of property + quiet: Errors to ignore (empty to raise on all errors) + + Raises: + FdtException on any error + """ + while self.check_space(fdt_property_cell(self._fdt, name, val)): + pass + + def property(self, name, val): + """Add a property + + Write a new property with the given value to the device tree. The value + is taken as is and is not nul-terminated + + Args: + name: Name of property to add + val: Value of property + quiet: Errors to ignore (empty to raise on all errors) + + Raises: + FdtException on any error + """ + while self.check_space(fdt_property_stub(self._fdt, name, val, + len(val))): + pass + + def end_node(self): + """End a node + + Use this after adding properties to a node to close it off. You can also + use the context manager as shown in the FdtSw class comment. + + Args: + quiet: Errors to ignore (empty to raise on all errors) + + Raises: + FdtException on any error + """ + while self.check_space(fdt_end_node(self._fdt)): + pass + + def add_node(self, name): + """Create a new context for adding a node + + When used in a 'with' clause this starts a new node and finishes it + afterward. + + Args: + name: Name of node to add + """ + return NodeAdder(self, name) + + +class NodeAdder(): + """Class to provide a node context + + This allows you to add nodes in a more natural way: + + with fdtsw.add_node('name'): + fdtsw.property_string('test', 'value') + + The node is automatically completed with a call to end_node() when the + context exits. + """ + def __init__(self, fdtsw, name): + self._fdt = fdtsw + self._name = name + + def __enter__(self): + self._fdt.begin_node(self._name) + + def __exit__(self, type, value, traceback): + self._fdt.end_node() %} %rename(fdt_property) fdt_property_func; @@ -757,6 +1049,11 @@ typedef uint32_t fdt32_t; $1 = PyString_AsString($input); /* char *str */ } +/* typemap used for fdt_add_reservemap_entry() */ +%typemap(in) uint64_t { + $1 = PyLong_AsUnsignedLong($input); +} + /* typemaps used for fdt_next_node() */ %typemap(in, numinputs=1) int *depth (int depth) { depth = (int) PyInt_AsLong($input); @@ -800,4 +1097,13 @@ uint32_t fdt_boot_cpuid_phys(const void *fdt); uint32_t fdt_size_dt_strings(const void *fdt); uint32_t fdt_size_dt_struct(const void *fdt); +int fdt_property_string(void *fdt, const char *name, const char *val); +int fdt_property_cell(void *fdt, const char *name, uint32_t val); + +/* + * This function has a stub since the name fdt_property is used for both a + * function and a struct, which confuses SWIG. + */ +int fdt_property_stub(void *fdt, const char *name, const char *val, int len); + %include <../libfdt/libfdt.h> diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 9f3e55a..e61fda9 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -56,17 +56,32 @@ import unittest sys.path.insert(0, '../pylibfdt') import libfdt -from libfdt import Fdt, FdtException, QUIET_NOTFOUND, QUIET_ALL +from libfdt import Fdt, FdtSw, FdtException, QUIET_NOTFOUND, QUIET_ALL -small_size = 160 -full_size = 1024 +TEST_ADDR_1H = 0xdeadbeef +TEST_ADDR_1L = 0x00000000 +TEST_ADDR_1 = (TEST_ADDR_1H << 32) | TEST_ADDR_1L +TEST_ADDR_1 = 0x8000000000000000 +TEST_SIZE_1H = 0x00000000 +TEST_SIZE_1L = 0x00100000 +TEST_SIZE_1 = (TEST_SIZE_1H << 32) | TEST_SIZE_1L +TEST_ADDR_2H = 0 +TEST_ADDR_2L = 123456789 +TEST_ADDR_2 = (TEST_ADDR_2H << 32) | TEST_ADDR_2L +TEST_SIZE_2H = 0 +TEST_SIZE_2L = 010000 +TEST_SIZE_2 = (TEST_SIZE_2H << 32) | TEST_SIZE_2L TEST_VALUE_1 = 0xdeadbeef +TEST_VALUE_2 = 123456789 TEST_VALUE64_1H = 0xdeadbeef TEST_VALUE64_1L = 0x01abcdef TEST_VALUE64_1 = (TEST_VALUE64_1H << 32) | TEST_VALUE64_1L +PHANDLE_1 = 0x2000 +PHANDLE_2 = 0x2001 + TEST_STRING_1 = 'hello world' TEST_STRING_2 = 'hi world' TEST_STRING_3 = u'unicode ' + unichr(467) @@ -94,8 +109,8 @@ def _ReadFdt(fname): """ return libfdt.Fdt(open(fname).read()) -class PyLibfdtTests(unittest.TestCase): - """Test class for pylibfdt +class PyLibfdtBasicTests(unittest.TestCase): + """Test class for basic pylibfdt access functions Properties: fdt: Device tree file used for testing @@ -481,5 +496,99 @@ class PyLibfdtTests(unittest.TestCase): self.assertIn('embedded nul', str(e.exception)) +class PyLibfdtSwTests(unittest.TestCase): + """Test class for pylibfdt sequential-write DT creation + """ + def assertOk(self, err_code): + self.assertEquals(0, err_code) + + def testCreate(self): + # First check the minimum size and also the FdtSw() constructor + with self.assertRaisesRegexp(FdtException, get_err(libfdt.NOSPACE)): + self.assertEquals(-libfdt.NOSPACE, FdtSw(3)) + + sw = FdtSw() + sw.add_reservemap_entry(TEST_ADDR_1, TEST_SIZE_1) + sw.add_reservemap_entry(TEST_ADDR_2, TEST_SIZE_2) + sw.finish_reservemap() + + sw.begin_node('') + sw.property_string('compatible', 'test_tree1') + sw.property_u32('prop-int', TEST_VALUE_1) + + sw.property_u32('prop-int', TEST_VALUE_1) + sw.property_u64('prop-int64', TEST_VALUE64_1) + sw.property_string('prop-str', TEST_STRING_1) + sw.property_u32('#address-cells', 1) + sw.property_u32('#size-cells', 0) + + sw.begin_node('subnode@1') + sw.property_string('compatible', 'subnode1') + sw.property_u32('reg', 1) + sw.property_cell('prop-int', TEST_VALUE_1) + sw.begin_node('subsubnode') + sw.property('compatible', 'subsubnode1\0subsubnode') + sw.property_cell('prop-int', TEST_VALUE_1) + sw.end_node() + sw.begin_node('ss1') + sw.end_node() + sw.end_node() + + for i in range(2, 11): + with sw.add_node('subnode@%d' % i): + sw.property_u32('reg', 2) + sw.property_cell('linux,phandle', PHANDLE_1) + sw.property_cell('prop-int', TEST_VALUE_2) + sw.property_u32('#address-cells', 1) + sw.property_u32('#size-cells', 0) + with sw.add_node('subsubnode@0'): + sw.property_u32('reg', 0) + sw.property_cell('phandle', PHANDLE_2) + sw.property('compatible', 'subsubnode2\0subsubnode') + sw.property_cell('prop-int', TEST_VALUE_2) + with sw.add_node('ss2'): + pass + sw.end_node() + + fdt = sw.as_fdt() + self.assertEqual(2, fdt.num_mem_rsv()) + self.assertEqual([TEST_ADDR_1, TEST_SIZE_1], fdt.get_mem_rsv(0)) + + # Make sure we can add a few more things + with sw.add_node('another'): + sw.property_u32('reg', 3) + + # Make sure we can read from the tree too + node = sw.path_offset('/subnode@1') + self.assertEqual('subnode1' + chr(0), sw.getprop(node, 'compatible')) + + # Make sure we did at least two resizes + self.assertTrue(len(fdt.as_bytearray()) > FdtSw.INC_SIZE * 2) + + +class PyLibfdtRoTests(unittest.TestCase): + """Test class for read-only pylibfdt access functions + + This just tests a few simple cases. Most of the tests are in + PyLibfdtBasicTests. + + Properties: + fdt: Device tree file used for testing + """ + + def setUp(self): + """Read in the device tree we use for testing""" + self.fdt = libfdt.FdtRo(open('test_tree1.dtb').read()) + + def testAccess(self): + """Basic sanity check for the FdtRo class""" + node = self.fdt.path_offset('/subnode@1') + self.assertEqual('subnode1' + chr(0), + self.fdt.getprop(node, 'compatible')) + node = self.fdt.first_subnode(node) + self.assertEqual('this is a placeholder string\0string2\0', + self.fdt.getprop(node, 'placeholder')) + + if __name__ == "__main__": unittest.main() From 3fe0eeda0b7f275cd01f29773d2ad6b8888d6701 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 12 Jul 2018 18:20:05 -0600 Subject: [PATCH 0726/1198] livetree: Set phandle properties type to uint32 Generated phandle property values are a single cell, so set the type marker to uint32. Otherwise, we default to uint8. Signed-off-by: Rob Herring Signed-off-by: David Gibson --- livetree.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/livetree.c b/livetree.c index 6e4c367..4ff0679 100644 --- a/livetree.c +++ b/livetree.c @@ -594,6 +594,7 @@ struct node *get_node_by_ref(struct node *tree, const char *ref) 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)) return node->phandle; @@ -603,17 +604,16 @@ 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", - data_append_cell(empty_data, phandle))); + add_property(node, build_property("linux,phandle", d)); if (!get_property(node, "phandle") && (phandle_format & PHANDLE_EPAPR)) - add_property(node, - build_property("phandle", - data_append_cell(empty_data, phandle))); + add_property(node, build_property("phandle", d)); /* If the node *does* have a phandle property, we must * be dealing with a self-referencing phandle, which will be From c12b2b0c20eb8fbe1a22065f1d5f0f155ab56b0a Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 19 Jul 2018 08:19:43 +0200 Subject: [PATCH 0727/1198] libfdt: fdt_address_cells() and fdt_size_cells() Add internal fdt_cells() to avoid copy and paste. Test error cases and default values. Fix typo in fdt_size_cells() documentation comment. Signed-off-by: Sebastian Huber Signed-off-by: David Gibson --- libfdt/fdt_addresses.c | 35 +++++++++-------------- libfdt/libfdt.h | 2 +- tests/.gitignore | 1 + tests/Makefile.tests | 1 + tests/addr_size_cells.c | 3 ++ tests/addr_size_cells2.c | 62 ++++++++++++++++++++++++++++++++++++++++ tests/addresses.dts | 15 ++++++++++ tests/run_tests.sh | 2 ++ 8 files changed, 98 insertions(+), 23 deletions(-) create mode 100644 tests/addr_size_cells2.c diff --git a/libfdt/fdt_addresses.c b/libfdt/fdt_addresses.c index eff4dbc..49537b5 100644 --- a/libfdt/fdt_addresses.c +++ b/libfdt/fdt_addresses.c @@ -1,6 +1,7 @@ /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2014 David Gibson + * Copyright (C) 2018 embedded brains GmbH * * libfdt is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. @@ -55,42 +56,32 @@ #include "libfdt_internal.h" -int fdt_address_cells(const void *fdt, int nodeoffset) +static int fdt_cells(const void *fdt, int nodeoffset, const char *name) { - const fdt32_t *ac; + const fdt32_t *c; int val; int len; - ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len); - if (!ac) + c = fdt_getprop(fdt, nodeoffset, name, &len); + if (!c) return 2; - if (len != sizeof(*ac)) + if (len != sizeof(*c)) return -FDT_ERR_BADNCELLS; - val = fdt32_to_cpu(*ac); + val = fdt32_to_cpu(*c); if ((val <= 0) || (val > FDT_MAX_NCELLS)) return -FDT_ERR_BADNCELLS; return val; } +int fdt_address_cells(const void *fdt, int nodeoffset) +{ + return fdt_cells(fdt, nodeoffset, "#address-cells"); +} + int fdt_size_cells(const void *fdt, int nodeoffset) { - const fdt32_t *sc; - int val; - int len; - - sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len); - if (!sc) - return 2; - - if (len != sizeof(*sc)) - return -FDT_ERR_BADNCELLS; - - val = fdt32_to_cpu(*sc); - if ((val < 0) || (val > FDT_MAX_NCELLS)) - return -FDT_ERR_BADNCELLS; - - return val; + return fdt_cells(fdt, nodeoffset, "#size-cells"); } diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 38ec313..830b77e 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1145,7 +1145,7 @@ int fdt_address_cells(const void *fdt, int nodeoffset); * * returns: * 0 <= n < FDT_MAX_NCELLS, on success - * 2, if the node has no #address-cells property + * 2, 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, diff --git a/tests/.gitignore b/tests/.gitignore index d423570..7a99f5a 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -4,6 +4,7 @@ tmp.* /add_subnode_with_nops /addr_size_cells +/addr_size_cells2 /appendprop[12] /asm_tree_dump /boot-cpuid diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 2c2c4fd..e7cf6bc 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -9,6 +9,7 @@ LIB_TESTS_L = get_mem_rsv \ sized_cells \ notfound \ addr_size_cells \ + addr_size_cells2 \ stringlist \ setprop_inplace nop_property nop_node \ sw_tree1 sw_states \ diff --git a/tests/addr_size_cells.c b/tests/addr_size_cells.c index 6090d93..fcd9ff0 100644 --- a/tests/addr_size_cells.c +++ b/tests/addr_size_cells.c @@ -60,5 +60,8 @@ int main(int argc, char *argv[]) check_node(fdt, "/", 2, 2); check_node(fdt, "/identity-bus@0", 2, 2); check_node(fdt, "/simple-bus@1000000", 2, 1); + check_node(fdt, "/c0", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS); + check_node(fdt, "/c1", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS); + check_node(fdt, "/c2", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS); PASS(); } diff --git a/tests/addr_size_cells2.c b/tests/addr_size_cells2.c new file mode 100644 index 0000000..38b2c04 --- /dev/null +++ b/tests/addr_size_cells2.c @@ -0,0 +1,62 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for #address-cells and #size-cells handling + * Copyright (C) 2014 David Gibson, + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +static void check_node(const void *fdt, const char *path, int ac, int sc) +{ + int offset; + int xac, xsc; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("Couldn't find path %s", path); + + xac = fdt_address_cells(fdt, offset); + xsc = fdt_size_cells(fdt, offset); + + if (xac != ac) + FAIL("Address cells for %s is %d instead of %d\n", + path, xac, ac); + if (xsc != sc) + FAIL("Size cells for %s is %d instead of %d\n", + path, xsc, sc); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + if (argc != 2) + CONFIG("Usage: %s \n", argv[0]); + + test_init(argc, argv); + fdt = load_blob(argv[1]); + + check_node(fdt, "/", 2, 2); + PASS(); +} diff --git a/tests/addresses.dts b/tests/addresses.dts index a2faaf5..fab6b19 100644 --- a/tests/addresses.dts +++ b/tests/addresses.dts @@ -12,4 +12,19 @@ #address-cells = <2>; #size-cells = <1>; }; + + c0@0 { + #address-cells = <1 1>; + #size-cells = <1 1>; + }; + + c1@0 { + #address-cells = <0x80000000>; + #size-cells = <0x80000000>; + }; + + c2@0 { + #address-cells = <5>; + #size-cells = <5>; + }; }; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index cf87066..7348c9c 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -336,6 +336,8 @@ libfdt_tests () { run_dtc_test -I dts -O dtb -o addresses.test.dtb addresses.dts run_test addr_size_cells addresses.test.dtb + run_dtc_test -I dts -O dtb -o addresses2.test.dtb empty.dts + run_test addr_size_cells2 addresses2.test.dtb run_dtc_test -I dts -O dtb -o stringlist.test.dtb stringlist.dts run_test stringlist stringlist.test.dtb From 57f7f9e7bc7cbcf1eb4dc00692d0229c73057d69 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 20 Jul 2018 14:35:12 +1000 Subject: [PATCH 0728/1198] tests: Don't call memcmp() with NULL arguments You're not supposed to pass NULL to memcmp(), and some sanitizers complain about it, even when the length is zero. Signed-off-by: David Gibson --- tests/testutils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/testutils.c b/tests/testutils.c index 3c83b96..378869a 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -127,7 +127,7 @@ void check_property(void *fdt, int nodeoffset, const char *name, if (proplen != len) FAIL("Size mismatch on property \"%s\": %d insead of %d", name, proplen, len); - if (memcmp(val, prop->data, len) != 0) + if (len && memcmp(val, prop->data, len) != 0) FAIL("Data mismatch on property \"%s\"", name); } @@ -144,7 +144,7 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name, if (proplen != len) FAIL("Size mismatch on property \"%s\": %d insead of %d", name, proplen, len); - if (memcmp(val, propval, len) != 0) + if (len && memcmp(val, propval, len) != 0) FAIL("Data mismatch on property \"%s\"", name); return propval; From 85bce8b2f06d17a909d9e20358630a2034f381ff Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 23 Jul 2018 12:16:09 +1000 Subject: [PATCH 0729/1198] tests: Correction to vg_prepare_blob() vg_prepare_blob() assumes a valid return from fdt_num_mem_rsv() in order to make sensible initialization of the valgrind mem checker. Usually that's fine, but it breaks down on the (deliberately corrupted) truncated_memrsv testcase. That led to marking a negative-size (== enormously sized once cast to size_t) as defined with VALGRIND_MAKE_MEM_DEFINED, which casued valgrind to freeze up and consume ludicrous amounts of memory until OOMing. This correction makes us robust in that case. Signed-off-by: David Gibson --- tests/testutils.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/testutils.c b/tests/testutils.c index 378869a..75e3e20 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -168,18 +168,22 @@ void vg_prepare_blob(void *fdt, size_t bufsize) { char *blob = fdt; int off_memrsv, off_strings, off_struct; + int num_memrsv; size_t size_memrsv, size_strings, size_struct; - size_memrsv = (fdt_num_mem_rsv(fdt) + 1) - * sizeof(struct fdt_reserve_entry); + off_memrsv = fdt_off_mem_rsvmap(fdt); + num_memrsv = fdt_num_mem_rsv(fdt); + if (num_memrsv < 0) + size_memrsv = fdt_totalsize(fdt) - off_memrsv; + else + size_memrsv = (num_memrsv + 1) + * sizeof(struct fdt_reserve_entry); VALGRIND_MAKE_MEM_UNDEFINED(blob, bufsize); VALGRIND_MAKE_MEM_DEFINED(blob, FDT_V1_SIZE); VALGRIND_MAKE_MEM_DEFINED(blob, fdt_header_size(fdt)); if (fdt_magic(fdt) == FDT_MAGIC) { - off_memrsv = fdt_off_mem_rsvmap(fdt); - off_strings = fdt_off_dt_strings(fdt); if (fdt_version(fdt) >= 3) size_strings = fdt_size_dt_strings(fdt); @@ -192,8 +196,6 @@ void vg_prepare_blob(void *fdt, size_t bufsize) else size_struct = fdt_totalsize(fdt) - off_struct; } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { - off_memrsv = fdt_off_mem_rsvmap(fdt); - size_strings = fdt_size_dt_strings(fdt); off_strings = fdt_off_dt_strings(fdt) - size_strings; From 88f18909db731a627456f26d779445f84e449536 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 23 Jul 2018 13:00:50 +1000 Subject: [PATCH 0730/1198] dtc: Bump version to v1.4.7 We've accumulated a bunch of bugfixes, including considerable improvements to libfdt's memory safety, so get ready for another release. Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6d55e13..d8ebc4f 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ # VERSION = 1 PATCHLEVEL = 4 -SUBLEVEL = 6 +SUBLEVEL = 7 EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = From 53a1bd5469055af7049a0ddaf00524a56d21bca2 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 26 Jul 2018 21:19:31 -0600 Subject: [PATCH 0731/1198] checks: add I2C bus checks Add I2C bus type detection and checks. The node name is used to find I2C buses as there is no common compatible or property which can be used to identify I2C controllers/buses. There are some common I2C properties, but they are not used frequently enough to match on. Signed-off-by: Rob Herring Signed-off-by: David Gibson --- checks.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/checks.c b/checks.c index a2cc103..f0b9f87 100644 --- a/checks.c +++ b/checks.c @@ -962,6 +962,73 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no } WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge); +static const struct bus_type i2c_bus = { + .name = "i2c-bus", +}; + +static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) +{ + if (strprefixeq(node->name, node->basenamelen, "i2c-bus") || + strprefixeq(node->name, node->basenamelen, "i2c-arb")) { + node->bus = &i2c_bus; + } else if (strprefixeq(node->name, node->basenamelen, "i2c")) { + struct node *child; + for_each_child(node, child) { + if (strprefixeq(child->name, node->basenamelen, "i2c-bus")) + return; + } + node->bus = &i2c_bus; + } else + return; + + if (!node->children) + return; + + if (node_addr_cells(node) != 1) + FAIL(c, dti, node, "incorrect #address-cells for I2C bus"); + if (node_size_cells(node) != 0) + FAIL(c, dti, node, "incorrect #size-cells for I2C bus"); + +} +WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells); + +static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + const char *unitname = get_unitname(node); + char unit_addr[17]; + uint32_t reg = 0; + int len; + cell_t *cells = NULL; + + if (!node->parent || (node->parent->bus != &i2c_bus)) + return; + + prop = get_property(node, "reg"); + if (prop) + cells = (cell_t *)prop->val.val; + + if (!cells) { + FAIL(c, dti, node, "missing or empty reg property"); + return; + } + + reg = fdt32_to_cpu(*cells); + 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\"", + unit_addr); + + for (len = prop->val.len; len > 0; len -= 4) { + reg = fdt32_to_cpu(*(cells++)); + if (reg > 0x3ff) + FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"", + reg); + + } +} +WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, ®_format, &i2c_bus_bridge); + static void check_unit_address_format(struct check *c, struct dt_info *dti, struct node *node) { @@ -1582,6 +1649,9 @@ static struct check *check_table[] = { &simple_bus_bridge, &simple_bus_reg, + &i2c_bus_bridge, + &i2c_bus_reg, + &avoid_default_addr_size, &avoid_unnecessary_addr_size, &unique_unit_address, From 90a190eb04d926655b643328ae995336568b705b Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 26 Jul 2018 21:19:32 -0600 Subject: [PATCH 0732/1198] checks: add SPI bus checks Add SPI bus type detection and checks. The node name is the preferred way to find SPI buses as there is no common compatible or property which can be used. There are a few common properties used in child nodes, so they can be used as a fallback detection method. This lets us warn if the SPI controller is not properly named 'spi@...'. Signed-off-by: Rob Herring Signed-off-by: David Gibson --- checks.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/checks.c b/checks.c index f0b9f87..9c9b0c3 100644 --- a/checks.c +++ b/checks.c @@ -1029,6 +1029,76 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node } WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, ®_format, &i2c_bus_bridge); +static const struct bus_type spi_bus = { + .name = "spi-bus", +}; + +static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) +{ + + if (strprefixeq(node->name, node->basenamelen, "spi")) { + node->bus = &spi_bus; + } else { + /* Try to detect SPI buses which don't have proper node name */ + struct node *child; + + if (node_addr_cells(node) != 1 || node_size_cells(node) != 0) + return; + + for_each_child(node, child) { + struct property *prop; + for_each_property(child, prop) { + if (strprefixeq(prop->name, 4, "spi-")) { + node->bus = &spi_bus; + break; + } + } + if (node->bus == &spi_bus) + break; + } + + if (node->bus == &spi_bus && get_property(node, "reg")) + FAIL(c, dti, node, "node name for SPI buses should be 'spi'"); + } + if (node->bus != &spi_bus || !node->children) + return; + + if (node_addr_cells(node) != 1) + FAIL(c, dti, node, "incorrect #address-cells for SPI bus"); + if (node_size_cells(node) != 0) + FAIL(c, dti, node, "incorrect #size-cells for SPI bus"); + +} +WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells); + +static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + const char *unitname = get_unitname(node); + char unit_addr[9]; + uint32_t reg = 0; + cell_t *cells = NULL; + + if (!node->parent || (node->parent->bus != &spi_bus)) + return; + + prop = get_property(node, "reg"); + if (prop) + cells = (cell_t *)prop->val.val; + + if (!cells) { + FAIL(c, dti, node, "missing or empty reg property"); + return; + } + + reg = fdt32_to_cpu(*cells); + snprintf(unit_addr, sizeof(unit_addr), "%x", reg); + if (!streq(unitname, unit_addr)) + FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"", + unit_addr); +} +WARNING(spi_bus_reg, check_spi_bus_reg, NULL, ®_format, &spi_bus_bridge); + static void check_unit_address_format(struct check *c, struct dt_info *dti, struct node *node) { @@ -1652,6 +1722,9 @@ static struct check *check_table[] = { &i2c_bus_bridge, &i2c_bus_reg, + &spi_bus_bridge, + &spi_bus_reg, + &avoid_default_addr_size, &avoid_unnecessary_addr_size, &unique_unit_address, From ac68ff92ae20f7447f7af6c154a95f528df46851 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 30 Jul 2018 21:57:35 -0600 Subject: [PATCH 0733/1198] parser: add TYPE_STRING marker to path references Path references are also a string, so add TYPE_STRING marker in addition to REF_PATH. Signed-off-by: Rob Herring Signed-off-by: David Gibson --- dtc-parser.y | 1 + 1 file changed, 1 insertion(+) diff --git a/dtc-parser.y b/dtc-parser.y index 815481a..dd70ebf 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -287,6 +287,7 @@ propdata: } | propdataprefix DT_REF { + $1 = data_add_marker($1, TYPE_STRING, $2); $$ = data_add_marker($1, REF_PATH, $2); } | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' From 9619c8619c37b9aea98100bcc15c51a5642e877e Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Thu, 30 Aug 2018 12:01:59 +0200 Subject: [PATCH 0734/1198] Kill bogus TYPE_BLOB marker type Since commit 32b9c6130762 "Preserve datatype markers when emitting dts format", we no longer try to guess the value type. Instead, we reuse the type of the datatype markers when they are present, if the type is either TYPE_UINT* or TYPE_STRING. This causes 'dtc -I fs' to crash: Starting program: /root/dtc -q -f -O dts -I fs /proc/device-tree /dts-v1/; / { Program received signal SIGSEGV, Segmentation fault. __strlen_power8 () at ../sysdeps/powerpc/powerpc64/power8/strlen.S:47 47 ld r12,0(r4) /* Load doubleword from memory. */ (gdb) bt #0 __strlen_power8 () at ../sysdeps/powerpc/powerpc64/power8/strlen.S:47 #1 0x00007ffff7de3d10 in __GI__IO_fputs (str=, fp=) at iofputs.c:33 #2 0x000000001000c7a0 in write_propval (prop=0x100525e0, f=0x7ffff7f718a0 <_IO_2_1_stdout_>) at treesource.c:245 The offending line is: fprintf(f, "%s", delim_start[emit_type]); where emit_type is TYPE_BLOB and: static const char *delim_start[] = { [TYPE_UINT8] = "[", [TYPE_UINT16] = "/bits/ 16 <", [TYPE_UINT32] = "<", [TYPE_UINT64] = "/bits/ 64 <", [TYPE_STRING] = "", }; /* Data blobs */ enum markertype { TYPE_NONE, REF_PHANDLE, REF_PATH, LABEL, TYPE_UINT8, TYPE_UINT16, TYPE_UINT32, TYPE_UINT64, TYPE_BLOB, TYPE_STRING, }; Because TYPE_BLOB < TYPE_STRING and delim_start[] is a static array, delim_start[emit_type] is 0x0. The glibc usually prints out "(null)" when one passes 0x0 to %s, but it seems to call fputs() internally if the format is exactly "%s", hence the crash. TYPE_BLOB basically means the data comes from a file and we don't know its type. We don't care for the former, and the latter is TYPE_NONE. So let's drop TYPE_BLOB completely and use TYPE_NONE instead when reading the file. Then, try to guess the data type at emission time, like the code already does for refs and labels. Instead of adding yet another check for TYPE_NONE, an helper is introduced to check if the data marker has type information, ie, >= TYPE_UINT8. Fixes: 32b9c61307629ac76c6ac0bead6f926d579b3d2c Suggested-by: David Gibson Signed-off-by: Greg Kurz Signed-off-by: David Gibson --- data.c | 2 +- dtc.h | 1 - treesource.c | 9 +++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/data.c b/data.c index accdfae..4a20414 100644 --- a/data.c +++ b/data.c @@ -95,7 +95,7 @@ struct data data_copy_file(FILE *f, size_t maxlen) { struct data d = empty_data; - d = data_add_marker(d, TYPE_BLOB, NULL); + d = data_add_marker(d, TYPE_NONE, NULL); while (!feof(f) && (d.len < maxlen)) { size_t chunksize, ret; diff --git a/dtc.h b/dtc.h index 303c2a6..51c03ef 100644 --- a/dtc.h +++ b/dtc.h @@ -82,7 +82,6 @@ enum markertype { TYPE_UINT16, TYPE_UINT32, TYPE_UINT64, - TYPE_BLOB, TYPE_STRING, }; extern const char *markername(enum markertype markertype); diff --git a/treesource.c b/treesource.c index f99544d..53e6203 100644 --- a/treesource.c +++ b/treesource.c @@ -133,9 +133,14 @@ 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 && (m->type == LABEL || m->type == REF_PHANDLE || m->type == REF_PATH)) + while (m && !has_data_type_information(m)) m = m->next; return m; } @@ -225,7 +230,7 @@ static void write_propval(FILE *f, struct property *prop) size_t chunk_len; const char *p = &prop->val.val[m->offset]; - if (m->type < TYPE_UINT8) + if (!has_data_type_information(m)) continue; chunk_len = type_marker_length(m); From 04853cad18f423647d283062d1cb98f63c401720 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 27 Aug 2018 11:36:28 +1000 Subject: [PATCH 0735/1198] pylibfdt: Don't incorrectly / unnecessarily override uint64_t typemap In libfdt.i we set the handling of uint64_t parameters to use PyLong_AsUnsignedLong. But for 32-bit platforms, where an unsigned long is 32-bits, this will truncate the value we need. It turns out swig's default typemapping for uint64_t correctly handles conversions both to python ints and python longs, so we don't need this typemap at all. Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index fc53a8c..1bbc5e3 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -1049,11 +1049,6 @@ typedef uint32_t fdt32_t; $1 = PyString_AsString($input); /* char *str */ } -/* typemap used for fdt_add_reservemap_entry() */ -%typemap(in) uint64_t { - $1 = PyLong_AsUnsignedLong($input); -} - /* typemaps used for fdt_next_node() */ %typemap(in, numinputs=1) int *depth (int depth) { depth = (int) PyInt_AsLong($input); From 0fd1c8c783f3ee31af934ce7aacf8211961e23f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Hor=C3=A1k?= Date: Sat, 1 Sep 2018 14:15:41 +0200 Subject: [PATCH 0736/1198] pylibfdt: fdt_get_mem_rsv returns 2 uint64_t values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix typemap for fdt_get_mem_rsv so it returns 64-bit values. Fixes https://github.com/dgibson/dtc/issues/15. Signed-off-by: Dan Horák [dwg: Adjusted commit message for typo and context] Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 1bbc5e3..5e8e05d 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -1068,7 +1068,7 @@ typedef uint32_t fdt32_t; } %typemap(argout) uint64_t * { - PyObject *val = PyLong_FromUnsignedLong(*arg$argnum); + PyObject *val = PyLong_FromUnsignedLongLong(*arg$argnum); if (!result) { if (PyTuple_GET_SIZE(resultobj) == 0) resultobj = val; From 0ac9fdee37c7afe42285bbf197e6e3152b6c6c45 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Mon, 3 Sep 2018 10:50:36 +0200 Subject: [PATCH 0737/1198] dtc: trivial '-I fs -O dts' test Some recent changes caused '-I fs -O dts' to crash instantly when emitting the first property holding actual data, ie, coming from a non-empty file. This got fixed already by another patch. This simply adds a test for the original problem. Signed-off-by: Greg Kurz Signed-off-by: David Gibson --- tests/run_tests.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 7348c9c..e240356 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -448,6 +448,11 @@ libfdt_tests () { run_test check_header test_tree1.dtb + rm -rf fstree + mkdir fstree + echo -n "foo" > fstree/non_empty_prop + run_dtc_test -I fs -O dts fstree + # check full tests for good in test_tree1.dtb; do run_test check_full $good From c3f50c9a86d91758d9ca3885adcad0622eac66aa Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 10 Sep 2018 12:41:20 +1000 Subject: [PATCH 0738/1198] tests: Allow dtbs_equal_unordered to ignore mem reserves For some upcoming tests we want to be able to test if two trees are equal, but we don't care about the memory reservation map. So, this adds an option to the dtbs_equal_unordered test helper which tells it to ignore the reserve map. Signed-off-by: David Gibson --- tests/dtbs_equal_unordered.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/tests/dtbs_equal_unordered.c b/tests/dtbs_equal_unordered.c index baf2ae7..47baa84 100644 --- a/tests/dtbs_equal_unordered.c +++ b/tests/dtbs_equal_unordered.c @@ -30,6 +30,7 @@ #include "testdata.h" static int notequal; /* = 0 */ +static int ignore_memrsv; /* = 0 */ #define MISMATCH(fmt, ...) \ do { \ @@ -195,22 +196,41 @@ static void compare_node(const void *fdt1, int offset1, compare_subnodes(fdt2, offset2, fdt1, offset1, 0); } +static void badargs(char **argv) +{ + CONFIG("Usage: %s [-n] [-m] ", argv[0]); +} + int main(int argc, char *argv[]) { void *fdt1, *fdt2; uint32_t cpuid1, cpuid2; + char **args; + int argsleft; test_init(argc, argv); - if ((argc != 3) - && ((argc != 4) || !streq(argv[1], "-n"))) - CONFIG("Usage: %s [-n] ", argv[0]); - if (argc == 4) - notequal = 1; - fdt1 = load_blob(argv[argc-2]); - fdt2 = load_blob(argv[argc-1]); + args = &argv[1]; + argsleft = argc - 1; - compare_mem_rsv(fdt1, fdt2); + while (argsleft > 2) { + if (streq(args[0], "-n")) + notequal = 1; + else if (streq(args[0], "-m")) + ignore_memrsv = 1; + else + badargs(argv); + args++; + argsleft--; + } + if (argsleft != 2) + badargs(argv); + + fdt1 = load_blob(args[0]); + fdt2 = load_blob(args[1]); + + if (!ignore_memrsv) + compare_mem_rsv(fdt1, fdt2); compare_node(fdt1, 0, fdt2, 0); cpuid1 = fdt_boot_cpuid_phys(fdt1); From fd06c54d4711f20d16bb1e18cba4d7bed09e5ad2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 10 Sep 2018 12:59:53 +1000 Subject: [PATCH 0739/1198] tests: Better testing of dtc -I fs mode Greg Kurz added a trivial test of the -I fs mode recently, which was previously basically untested. This is an oversight, since we recently had a bug which completely broke it. This replaces Greg's test with a more thorough test of -I fs mode. We use a test helper to create the familiar test_tree1 in "fs" form, then use dtc -I fs to process it, and check that the results match what they should. We only check the content in -I fs -O dtb mode, since that's simplest, but we do run -I fs -O dts mode as well to make sure it doesn't blow up (the aforementioned bug caused just such a blow up, specific to -O dts mode, for example). Signed-off-by: David Gibson --- tests/.gitignore | 2 + tests/Makefile.tests | 6 +- tests/fs_tree1.c | 168 +++++++++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 11 +-- 4 files changed, 182 insertions(+), 5 deletions(-) create mode 100644 tests/fs_tree1.c diff --git a/tests/.gitignore b/tests/.gitignore index 7a99f5a..70a8c95 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -2,6 +2,7 @@ *.dts.test.s *.test.dts tmp.* +/fs/ /add_subnode_with_nops /addr_size_cells /addr_size_cells2 @@ -28,6 +29,7 @@ tmp.* /getprop /incbin /integer-expressions +/fs_tree1 /mangle-layout /move_and_save /node_check_compatible diff --git a/tests/Makefile.tests b/tests/Makefile.tests index e7cf6bc..6903333 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -27,7 +27,8 @@ LIB_TESTS_L = get_mem_rsv \ property_iterate \ subnode_iterate \ overlay overlay_bad_fixup \ - check_path check_header check_full + check_path check_header check_full \ + fs_tree1 LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv @@ -49,6 +50,8 @@ TESTS_DEPFILES = $(TESTS:%=%.d) \ TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts *.dtsv1 tmp.* TESTS_CLEANFILES_L += dumptrees TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) +TESTS_CLEANDIRS_L = fs +TESTS_CLEANDIRS = $(TESTS_CLEANDIRS_L:%=$(TESTS_PREFIX)%) .PHONY: tests tests: $(TESTS) $(TESTS_TREES) @@ -75,6 +78,7 @@ tests_clean: @$(VECHO) CLEAN "(tests)" rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%) rm -f $(TESTS_CLEANFILES) + rm -rf $(TESTS_CLEANDIRS) check: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) cd $(TESTS_PREFIX); ./run_tests.sh diff --git a/tests/fs_tree1.c b/tests/fs_tree1.c new file mode 100644 index 0000000..5762465 --- /dev/null +++ b/tests/fs_tree1.c @@ -0,0 +1,168 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase/tool constructing an fs tree for further test + * Copyright (C) 2018 David Gibson, Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +static void start_dir(const char *name) +{ + int rc; + + rc = mkdir(name, 0777); + if (rc != 0) + FAIL("mkdir(\"%s\"): %s", name, strerror(errno)); + + rc = chdir(name); + if (rc != 0) + FAIL("chdir(\"%s\"): %s", name, strerror(errno)); +} + +static void end_dir(void) +{ + int rc; + + rc = chdir(".."); + if (rc != 0) + FAIL("chdir(..): %s", strerror(errno)); +} + +static void mkfile(const char *name, void *data, size_t len) +{ + int fd; + int rc; + + fd = open(name, O_WRONLY|O_CREAT, 0666); + if (fd < 0) + FAIL("open(\"%s\"): %s", name, strerror(errno)); + + rc = write(fd, data, len); + if (rc < 0) + FAIL("write(\"%s\"): %s", name, strerror(errno)); + if (rc != len) + FAIL("write(\"%s\"): short write", name); + + rc = close(fd); + if (rc != 0) + FAIL("close(\"%s\"): %s", name, strerror(errno)); +} + +#define mkfile_str(name, s) \ + do { \ + char str[] = s; \ + mkfile((name), str, sizeof(str)); \ + } while (0) + +static void mkfile_u32(const char *name, uint32_t val) +{ + val = cpu_to_fdt32(val); + mkfile(name, &val, sizeof(val)); +} + +static void mkfile_u64(const char *name, uint64_t val) +{ + val = cpu_to_fdt64(val); + mkfile(name, &val, sizeof(val)); +} + +int main(int argc, char *argv[]) +{ + const char *base; + + test_init(argc, argv); + if (argc != 2) + CONFIG("Usage: %s ", argv[0]); + + base = argv[1]; + + start_dir(base); + mkfile_str("compatible", "test_tree1"); + mkfile_u32("prop-int", TEST_VALUE_1); + mkfile_u64("prop-int64", 0xdeadbeef01abcdefULL); + mkfile_str("prop-str", "hello world"); + mkfile_u32("#address-cells", 1); + mkfile_u32("#size-cells", 0); + + { + start_dir("subnode@1"); + + mkfile_str("compatible", "subnode1"); + mkfile_u32("reg", 1); + mkfile_u32("prop-int", TEST_VALUE_1); + + { + start_dir("subsubnode"); + + mkfile_str("compatible", "subsubnode1\0subsubnode"); + mkfile_str("placeholder", "this is a placeholder string\0string2"); + mkfile_u32("prop-int", TEST_VALUE_1); + + end_dir(); + } + + { + start_dir("ss1"); + end_dir(); + } + + end_dir(); + } + + { + start_dir("subnode@2"); + + mkfile_u32("reg", 2); + mkfile_u32("linux,phandle", 0x2000); + mkfile_u32("prop-int", TEST_VALUE_2); + mkfile_u32("#address-cells", 1); + mkfile_u32("#size-cells", 0); + + { + start_dir("subsubnode@0"); + + mkfile_u32("reg", 0); + mkfile_u32("phandle", 0x2001); + mkfile_str("compatible", "subsubnode2\0subsubnode"); + mkfile_u32("prop-int", TEST_VALUE_2); + + end_dir(); + } + + { + start_dir("ss2"); + end_dir(); + } + + end_dir(); + } + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index e240356..bbdc5c8 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -448,10 +448,13 @@ libfdt_tests () { run_test check_header test_tree1.dtb - rm -rf fstree - mkdir fstree - echo -n "foo" > fstree/non_empty_prop - run_dtc_test -I fs -O dts fstree + FSBASE=fs + rm -rf $FSBASE + mkdir -p $FSBASE + run_test fs_tree1 $FSBASE/test_tree1 + 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 # check full tests for good in test_tree1.dtb; do From b94c056b137e59deefc62fbfe0cd3a23edfcc07c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 10 Sep 2018 16:46:59 +1000 Subject: [PATCH 0740/1198] Make valgrind optional Some platforms don't have valgrind support, and sometimes you simply might not want to use valgrind. But at present, dtc, or more specifically its testsuite, won't compile without valgrind because we use the valgrind client interface in some places to improve our testing and suppress false positives. This adds some Makefile detection to correctly handle the case where valgrind is not available. Signed-off-by: David Gibson --- .travis.yml | 9 +++------ Makefile | 7 +++++++ tests/Makefile.tests | 5 +++++ tests/testutils.c | 10 ++++++++++ 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 87adfa0..ecdef0d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,11 +25,8 @@ matrix: - make - make check && make checkm - # Check it builds properly without the python bits - - addons: - apt: - packages: - - valgrind - script: + # Check it builds properly without optional packages: + # python, valgrind + - script: - make - make check diff --git a/Makefile b/Makefile index d8ebc4f..c4bfae6 100644 --- a/Makefile +++ b/Makefile @@ -39,6 +39,13 @@ INCLUDEDIR = $(PREFIX)/include HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ sed -e 's/\(cygwin\|msys\).*/\1/') +NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?) +ifeq ($(NO_VALGRIND),1) + CFLAGS += -DNO_VALGRIND +else + CFLAGS += $(shell $(PKG_CONFIG) --cflags valgrind) +endif + ifeq ($(HOSTOS),darwin) SHAREDLIB_EXT = dylib SHAREDLIB_CFLAGS = -fPIC diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 6903333..bd1c8ef 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -83,8 +83,13 @@ tests_clean: check: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) cd $(TESTS_PREFIX); ./run_tests.sh +ifeq ($(NO_VALGRIND),1) +checkm: + @echo "make checkm requires valgrind, but NO_VALGRIND=1" +else checkm: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$ +endif checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) cd $(TESTS_PREFIX); ./run_tests.sh -v diff --git a/tests/testutils.c b/tests/testutils.c index 75e3e20..0217b02 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -30,7 +30,17 @@ #include #include +#if NO_VALGRIND +static inline void VALGRIND_MAKE_MEM_UNDEFINED(void *p, size_t len) +{ +} + +static inline void VALGRIND_MAKE_MEM_DEFINED(void *p, size_t len) +{ +} +#else #include +#endif #include From 9005f4108e7c440764153d3ea0c85e927a75ae55 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 11 Sep 2018 03:28:38 -0600 Subject: [PATCH 0741/1198] pylibfdt: Allow delprop() to return errors At present this method always raised an exception when an error occurs. Add a 'quiet' argument so it matches the other methods. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 5e8e05d..12d2812 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -673,17 +673,21 @@ class Fdt(FdtRo): return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val, len(val)), quiet) - def delprop(self, nodeoffset, prop_name): + def delprop(self, nodeoffset, prop_name, quiet=()): """Delete a property from a node Args: nodeoffset: Node offset containing property to delete prop_name: Name of property to delete + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + Error code, or 0 if OK Raises: FdtError if the property does not exist, or another error occurs """ - return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) + return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name), quiet) class Property(bytearray): From bfbfab047e45445dd59bcdba98b61843e086d0d2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 11 Sep 2018 03:28:39 -0600 Subject: [PATCH 0742/1198] pylibfdt: Add a means to add and delete notes These methods are needed to permit larger changes to the device tree blob. Add two new methods and an associate test. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 29 +++++++++++++++++++++++++++++ tests/pylibfdt_tests.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 12d2812..842e7b6 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -689,6 +689,35 @@ class Fdt(FdtRo): """ return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name), quiet) + def add_subnode(self, parentoffset, name, quiet=()): + """Add a new subnode to a node + + Args: + parentoffset: Parent offset to add the subnode to + name: Name of node to add + + Returns: + offset of the node created, or negative error code on failure + + Raises: + FdtError if there is not enough space, or another error occurs + """ + return check_err(fdt_add_subnode(self._fdt, parentoffset, name), quiet) + + def del_node(self, nodeoffset, quiet=()): + """Delete a node + + Args: + nodeoffset: Offset of node to delete + + Returns: + Error code, or 0 if OK + + Raises: + FdtError if an error occurs + """ + return check_err(fdt_del_node(self._fdt, nodeoffset), quiet) + class Property(bytearray): """Holds a device tree property name and value. diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index e61fda9..fbb1ce2 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -139,6 +139,24 @@ class PyLibfdtBasicTests(unittest.TestCase): poffset = self.fdt.next_property_offset(poffset, QUIET_NOTFOUND) return prop_list + def GetSubnodes(self, node_path): + """Read a list of subnodes from a node + + Args: + node_path: Full path to node, e.g. '/subnode@1/subsubnode' + + Returns: + List of subnode names for that node, e.g. ['subsubnode', 'ss1'] + """ + subnode_list = [] + node = self.fdt.path_offset(node_path) + offset = self.fdt.first_subnode(node, QUIET_NOTFOUND) + while offset > 0: + name = self.fdt.get_name(offset) + subnode_list.append(name) + offset = self.fdt.next_subnode(offset, QUIET_NOTFOUND) + return subnode_list + def testImport(self): """Check that we can import the library correctly""" self.assertEquals(type(libfdt), types.ModuleType) @@ -495,6 +513,19 @@ class PyLibfdtBasicTests(unittest.TestCase): self.fdt.set_name(node, 'name\0') self.assertIn('embedded nul', str(e.exception)) + def testAddDeleteNodes(self): + """Test that we can add and delete nodes""" + node_name = '/subnode@1' + self.assertEquals(self.GetSubnodes(node_name), ['subsubnode', 'ss1']) + node = self.fdt.path_offset('%s/subsubnode' % node_name) + self.assertEquals(self.fdt.del_node(node, 'subsubnode'), 0) + self.assertEquals(self.GetSubnodes(node_name), ['ss1']) + + node = self.fdt.path_offset(node_name) + offset = self.fdt.add_subnode(node, 'more') + self.assertTrue(offset > 0) + self.assertEquals(self.GetSubnodes(node_name), ['more', 'ss1']) + class PyLibfdtSwTests(unittest.TestCase): """Test class for pylibfdt sequential-write DT creation From 361b5e7d80673e7d3613cfdf989449013bf109a0 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 11 Sep 2018 15:41:30 -0500 Subject: [PATCH 0743/1198] Make type_marker_length helper public Make type_marker_length available to other users of TYPE_* markers. Signed-off-by: Rob Herring Signed-off-by: David Gibson --- dtc.h | 2 ++ treesource.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dtc.h b/dtc.h index 51c03ef..bb769d2 100644 --- a/dtc.h +++ b/dtc.h @@ -108,6 +108,8 @@ struct data { for_each_marker(m) \ if ((m)->type == (t)) +size_t type_marker_length(struct marker *m); + void data_free(struct data d); struct data data_grow_for(struct data d, int xlen); diff --git a/treesource.c b/treesource.c index 53e6203..f2874f1 100644 --- a/treesource.c +++ b/treesource.c @@ -145,7 +145,7 @@ static struct marker *next_type_marker(struct marker *m) return m; } -static size_t type_marker_length(struct marker *m) +size_t type_marker_length(struct marker *m) { struct marker *next = next_type_marker(m->next); From c86da84d30e4b72cfb4fee22b62bea4257bc14bf Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 11 Sep 2018 15:41:31 -0500 Subject: [PATCH 0744/1198] Add support for YAML encoded output YAML encoded DT is useful for validation of DTs using binding schemas. The YAML encoding is an intermediate format used for validation and is therefore subject to change as needed. The YAML output is dependent on DTS input with type information preserved. Signed-off-by: Grant Likely [robh: make YAML support optional, build fixes, Travis CI test, preserve type information in paths and phandles] Signed-off-by: Rob Herring Signed-off-by: David Gibson --- .travis.yml | 3 +- Documentation/manual.txt | 3 + Makefile | 9 +- Makefile.dtc | 4 + dtc.c | 11 ++ dtc.h | 4 + tests/run_tests.sh | 8 ++ tests/type-preservation.dt.yaml | 20 +++ yamltree.c | 247 ++++++++++++++++++++++++++++++++ 9 files changed, 307 insertions(+), 2 deletions(-) create mode 100644 tests/type-preservation.dt.yaml create mode 100644 yamltree.c diff --git a/.travis.yml b/.travis.yml index ecdef0d..114932a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ matrix: - swig - python-dev - valgrind + - libyaml-0-2 coverity_scan: project: name: dtc @@ -26,7 +27,7 @@ matrix: - make check && make checkm # Check it builds properly without optional packages: - # python, valgrind + # python, valgrind, libyaml - script: - make - make check diff --git a/Documentation/manual.txt b/Documentation/manual.txt index 6898caa..db32dd7 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -78,6 +78,9 @@ The currently supported Output Formats are: then simply be added to your Makefile. Additionally, the assembly file exports some symbols that can be used. + - "yaml": DT encoded in YAML format. This representation is an + intermediate format used for validation tools. + 3) Command Line diff --git a/Makefile b/Makefile index c4bfae6..7a472b7 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,13 @@ else CFLAGS += $(shell $(PKG_CONFIG) --cflags valgrind) endif +NO_YAML := $(shell $(PKG_CONFIG) --exists yaml-0.1; echo $$?) +ifeq ($(NO_YAML),1) + CFLAGS += -DNO_YAML +else + LDLIBS += $(shell $(PKG_CONFIG) --libs yaml-0.1) +endif + ifeq ($(HOSTOS),darwin) SHAREDLIB_EXT = dylib SHAREDLIB_CFLAGS = -fPIC @@ -329,7 +336,7 @@ clean: libfdt_clean pylibfdt_clean tests_clean # %: %.o @$(VECHO) LD $@ - $(LINK.c) -o $@ $^ + $(LINK.c) -o $@ $^ $(LDLIBS) %.o: %.c @$(VECHO) CC $@ diff --git a/Makefile.dtc b/Makefile.dtc index bece49b..d437563 100644 --- a/Makefile.dtc +++ b/Makefile.dtc @@ -14,5 +14,9 @@ DTC_SRCS = \ treesource.c \ util.c +ifneq ($(NO_YAML),1) +DTC_SRCS += yamltree.c +endif + DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o) diff --git a/dtc.c b/dtc.c index c36994e..64134aa 100644 --- a/dtc.c +++ b/dtc.c @@ -95,6 +95,9 @@ static const char * const usage_opts_help[] = { "\n\tOutput formats are:\n" "\t\tdts - device tree source text\n" "\t\tdtb - device tree blob\n" +#ifndef NO_YAML + "\t\tyaml - device tree encoded as YAML\n" +#endif "\t\tasm - assembler source", "\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)", "\n\tOutput dependency file", @@ -128,6 +131,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback) return fallback; if (!strcasecmp(s, ".dts")) return "dts"; + if (!strcasecmp(s, ".yaml")) + return "yaml"; if (!strcasecmp(s, ".dtb")) return "dtb"; return fallback; @@ -350,6 +355,12 @@ int main(int argc, char *argv[]) if (streq(outform, "dts")) { dt_to_source(outf, dti); +#ifndef NO_YAML + } else if (streq(outform, "yaml")) { + if (!streq(inform, "dts")) + die("YAML output format requires dts input format\n"); + dt_to_yaml(outf, dti); +#endif } else if (streq(outform, "dtb")) { dt_to_blob(outf, dti, outversion); } else if (streq(outform, "asm")) { diff --git a/dtc.h b/dtc.h index bb769d2..cbe5415 100644 --- a/dtc.h +++ b/dtc.h @@ -299,6 +299,10 @@ struct dt_info *dt_from_blob(const char *fname); void dt_to_source(FILE *f, struct dt_info *dti); struct dt_info *dt_from_source(const char *f); +/* YAML source */ + +void dt_to_yaml(FILE *f, struct dt_info *dti); + /* FS trees */ struct dt_info *dt_from_fs(const char *dirname); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index bbdc5c8..adc4dae 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -568,6 +568,14 @@ dtc_tests () { run_wrap_test cmp $tree $tree.test.dts done + # Check -Oyaml output + if pkg-config --exists yaml-0.1; then + for tree in type-preservation; do + run_dtc_test -I dts -O yaml -o $tree.test.dt.yaml $tree.dts + run_wrap_test cmp $tree.dt.yaml $tree.test.dt.yaml + done + fi + # Check version conversions for tree in test_tree1.dtb ; do for aver in 1 2 3 16 17; do diff --git a/tests/type-preservation.dt.yaml b/tests/type-preservation.dt.yaml new file mode 100644 index 0000000..ee8cfde --- /dev/null +++ b/tests/type-preservation.dt.yaml @@ -0,0 +1,20 @@ +--- +- '#address-cells': [[0x1]] + '#size-cells': [[0x0]] + subnode@1: + compatible: ["subnode1"] + reg: [[0x1]] + int-array: [[0x0, 0x1], [0x2, 0x3]] + int8: [!u8 [0x56]] + int8-array: [!u8 [0x0, 0x12, 0x34, 0x56]] + int16: [!u16 [0x3210]] + int16-array: [!u16 [0x1234, 0x5678, 0x90ab, 0xcdef]] + int16-matrix: [!u16 [0x1234, 0x5678], [0x90ab, 0xcdef]] + int64: [!u64 [0x200000000]] + int64-array: [!u64 [0x100000000, 0x0]] + a-string-with-nulls: ["foo\0bar", "baz"] + subsubnode: + compatible: ["subsubnode1", "subsubnode"] + subsubsubnode: + compatible: ["subsubsubnode1", [0x1234], "subsubsubnode"] +... diff --git a/yamltree.c b/yamltree.c new file mode 100644 index 0000000..a00285a --- /dev/null +++ b/yamltree.c @@ -0,0 +1,247 @@ +/* + * (C) Copyright Linaro, Ltd. 2018 + * (C) Copyright Arm Holdings. 2017 + * (C) Copyright David Gibson , IBM Corporation. 2005. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include +#include +#include "dtc.h" +#include "srcpos.h" + +char *yaml_error_name[] = { + [YAML_NO_ERROR] = "no error", + [YAML_MEMORY_ERROR] = "memory error", + [YAML_READER_ERROR] = "reader error", + [YAML_SCANNER_ERROR] = "scanner error", + [YAML_PARSER_ERROR] = "parser error", + [YAML_COMPOSER_ERROR] = "composer error", + [YAML_WRITER_ERROR] = "writer error", + [YAML_EMITTER_ERROR] = "emitter error", +}; + +#define yaml_emitter_emit_or_die(emitter, event) ( \ +{ \ + if (!yaml_emitter_emit(emitter, event)) \ + die("yaml '%s': %s in %s, line %i\n", \ + yaml_error_name[(emitter)->error], \ + (emitter)->problem, __func__, __LINE__); \ +}) + +static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width) +{ + yaml_event_t event; + void *tag; + int off, start_offset = markers->offset; + + switch(width) { + case 1: tag = "!u8"; break; + case 2: tag = "!u16"; break; + case 4: tag = "!u32"; break; + case 8: tag = "!u64"; break; + default: + die("Invalid width %i", width); + } + assert(len % width == 0); + + yaml_sequence_start_event_initialize(&event, NULL, + (yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + + for (off = 0; off < len; off += width) { + char buf[32]; + struct marker *m; + bool is_phandle = false; + + switch(width) { + case 1: + sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off)); + break; + case 2: + sprintf(buf, "0x%"PRIx16, fdt16_to_cpu(*(fdt16_t*)(data + off))); + break; + case 4: + sprintf(buf, "0x%"PRIx32, fdt32_to_cpu(*(fdt32_t*)(data + off))); + m = markers; + is_phandle = false; + for_each_marker_of_type(m, REF_PHANDLE) { + if (m->offset == (start_offset + off)) { + is_phandle = true; + break; + } + } + break; + case 8: + sprintf(buf, "0x%"PRIx64, fdt64_to_cpu(*(fdt64_t*)(data + off))); + break; + } + + if (is_phandle) + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t*)"!phandle", (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, + strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + } + + yaml_sequence_end_event_initialize(&event); + yaml_emitter_emit_or_die(emitter, &event); +} + +static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len) +{ + yaml_event_t event; + int i; + + assert(str[len-1] == '\0'); + + /* Make sure the entire string is in the lower 7-bit ascii range */ + for (i = 0; i < len; i++) + assert(isascii(str[i])); + + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str, + len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); +} + +static void yaml_propval(yaml_emitter_t *emitter, struct property *prop) +{ + yaml_event_t event; + int len = prop->val.len; + struct marker *m = prop->val.markers; + + /* Emit the property name */ + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, (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", + strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + return; + } + + if (!m) + 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); + yaml_emitter_emit_or_die(emitter, &event); + + for_each_marker(m) { + int chunk_len; + char *data = &prop->val.val[m->offset]; + + if (m->type < TYPE_UINT8) + continue; + + chunk_len = type_marker_length(m) ? : len; + assert(chunk_len > 0); + len -= chunk_len; + + switch(m->type) { + case TYPE_UINT16: + yaml_propval_int(emitter, m, data, chunk_len, 2); + break; + case TYPE_UINT32: + yaml_propval_int(emitter, m, data, chunk_len, 4); + break; + case TYPE_UINT64: + yaml_propval_int(emitter, m, data, 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); + break; + } + } + + yaml_sequence_end_event_initialize(&event); + yaml_emitter_emit_or_die(emitter, &event); +} + + +static void yaml_tree(struct node *tree, yaml_emitter_t *emitter) +{ + struct property *prop; + struct node *child; + yaml_event_t event; + + if (tree->deleted) + return; + + yaml_mapping_start_event_initialize(&event, NULL, + (yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + + for_each_property(tree, prop) + yaml_propval(emitter, prop); + + /* 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, + strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + yaml_tree(child, emitter); + } + + yaml_mapping_end_event_initialize(&event); + yaml_emitter_emit_or_die(emitter, &event); +} + +void dt_to_yaml(FILE *f, struct dt_info *dti) +{ + yaml_emitter_t emitter; + yaml_event_t event; + + yaml_emitter_initialize(&emitter); + yaml_emitter_set_output_file(&emitter, f); + yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING); + yaml_emitter_emit_or_die(&emitter, &event); + + 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_emitter_emit_or_die(&emitter, &event); + + yaml_tree(dti->dt, &emitter); + + yaml_sequence_end_event_initialize(&event); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_document_end_event_initialize(&event, 0); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_stream_end_event_initialize(&event); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_emitter_delete(&emitter); +} From d448f9a5fd941a69cceb7008d3ac9ac0396f64d8 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 14 Sep 2018 13:39:06 -0500 Subject: [PATCH 0745/1198] Revert dts output formatting changes of spaces around brackets Commit 32b9c6130762 ("Preserve datatype markers when emitting dts format") add spaces between <> and [] and the encapsulated numbers. Fix this to keep the prior formatting and not break some users needlessly. Fixes: 32b9c6130762 ("Preserve datatype markers when emitting dts format") Reported-by: Stewart Smith Signed-off-by: Rob Herring Signed-off-by: David Gibson --- tests/type-preservation.dts | 24 ++++++++++++------------ treesource.c | 18 ++++++++++-------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/tests/type-preservation.dts b/tests/type-preservation.dts index 62c0c23..06d5778 100644 --- a/tests/type-preservation.dts +++ b/tests/type-preservation.dts @@ -1,27 +1,27 @@ /dts-v1/; / { - #address-cells = < 0x01 >; - #size-cells = < 0x00 >; + #address-cells = <0x01>; + #size-cells = <0x00>; sub1: subnode@1 { prop_label: compatible = value_label: "subnode1"; - reg = < 0x01 >; - int-array = < 0x00 0x01 >, int_value_label: < 0x02 0x03 >; - int8 = [ 56 ]; - int8-array = [ 00 12 34 56 label: ]; - int16 = /bits/ 16 < 0x3210 >; - int16-array = /bits/ 16 < 0x1234 0x5678 0x90ab 0xcdef >; - int16-matrix = /bits/ 16 < 0x1234 0x5678 >, < 0x90ab 0xcdef >; - int64 = /bits/ 64 < 0x200000000 >; - int64-array = /bits/ 64 < 0x100000000 0x00 int64_array_label_end: >; + reg = <0x01>; + int-array = <0x00 0x01>, int_value_label: <0x02 0x03>; + int8 = [56]; + int8-array = [00 12 34 56 label:]; + int16 = /bits/ 16 <0x3210>; + int16-array = /bits/ 16 <0x1234 0x5678 0x90ab 0xcdef>; + int16-matrix = /bits/ 16 <0x1234 0x5678>, <0x90ab 0xcdef>; + int64 = /bits/ 64 <0x200000000>; + int64-array = /bits/ 64 <0x100000000 0x00 int64_array_label_end:>; a-string-with-nulls = "foo\0bar", "baz"; subsub1: subsubnode { compatible = "subsubnode1", "subsubnode"; subsubsub1: subsubsubnode { - compatible = "subsubsubnode1", < 0x1234 >, valuea: valueb: "subsubsubnode"; + compatible = "subsubsubnode1", <0x1234>, valuea: valueb: "subsubsubnode"; }; }; }; diff --git a/treesource.c b/treesource.c index f2874f1..28cd135 100644 --- a/treesource.c +++ b/treesource.c @@ -118,18 +118,20 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) for (; p < end; p += width) { switch (width) { case 1: - fprintf(f, " %02"PRIx8, *(const uint8_t*)p); + 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, fdt16_to_cpu(*(const fdt16_t*)p)); break; case 4: - fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); + fprintf(f, "0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); break; case 8: - fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); + fprintf(f, "0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); break; } + if (p + width < end) + fputc(' ', f); } } @@ -162,10 +164,10 @@ static const char *delim_start[] = { [TYPE_STRING] = "", }; static const char *delim_end[] = { - [TYPE_UINT8] = " ]", - [TYPE_UINT16] = " >", - [TYPE_UINT32] = " >", - [TYPE_UINT64] = " >", + [TYPE_UINT8] = "]", + [TYPE_UINT16] = ">", + [TYPE_UINT32] = ">", + [TYPE_UINT64] = ">", [TYPE_STRING] = "", }; From 8c59a97ce096ab1e25fa828cbff371b3953e990c Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 14 Sep 2018 14:01:09 +0100 Subject: [PATCH 0746/1198] Fix missing labels when emitting dts format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When there is a label inside a sequence of ints at the end of a property, an assertion is hit because write_propval() expects all the labels to be at the very end of the property data. This is clearly wrong behaviour. To reproduce run: "dtc -O dts tests/label01.dts". dtc fails on property /randomnode/blob. Fix by reworking the write_propval() loop to remove the separate iterating over label markers. Instead handle the label markers as part of the main marker iteration loop. This guarantees that each label marker is handled at the right location, even if all the data markers have already been handled, and has the added advantage of making the code simpler. However, a side effect of this code is that a label at the very end of an int sequence will be emitted outside the sequence delimiters. For example: Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:; Output: intprop = < 1 2 >, L1: L2: < 3 4 > L3: L4:; The two representations are equivalent in the data model, but the current test case was looking for the former, but needed to be modified to look for the later. The alternative would be to render labels before closing the sequence, but that makes less sense syntactically because labels between sequences are normally to point at the next one, not the former. For example: Input: intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:; Output: intprop = < 1 2 L1: L2: >, < 3 4 L3: L4: >; DTC doesn't current have the information to know if the label should be inside or outside the sequence, but in common usage, it is more likely that L1 & L2 refer to the second sequence, not the end of the first. Fixes: 32b9c6130762 ("Preserve datatype markers when emitting dts format") Reported-by: Łukasz Dobrowolski Signed-off-by: Grant Likely Cc: David Gibson Cc: Rob Herring Signed-off-by: David Gibson --- tests/type-preservation.dts | 4 ++-- treesource.c | 45 +++++++++++++++---------------------- 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/tests/type-preservation.dts b/tests/type-preservation.dts index 06d5778..3e380ba 100644 --- a/tests/type-preservation.dts +++ b/tests/type-preservation.dts @@ -9,12 +9,12 @@ reg = <0x01>; int-array = <0x00 0x01>, int_value_label: <0x02 0x03>; int8 = [56]; - int8-array = [00 12 34 56 label:]; + int8-array = [00 12 34 56] label:; int16 = /bits/ 16 <0x3210>; int16-array = /bits/ 16 <0x1234 0x5678 0x90ab 0xcdef>; int16-matrix = /bits/ 16 <0x1234 0x5678>, <0x90ab 0xcdef>; int64 = /bits/ 64 <0x200000000>; - int64-array = /bits/ 64 <0x100000000 0x00 int64_array_label_end:>; + int64-array = /bits/ 64 <0x100000000 0x00> int64_array_label_end:; a-string-with-nulls = "foo\0bar", "baz"; subsub1: subsubnode { diff --git a/treesource.c b/treesource.c index 28cd135..c1fdb86 100644 --- a/treesource.c +++ b/treesource.c @@ -216,7 +216,7 @@ static void write_propval(FILE *f, struct property *prop) return; } - fprintf(f, " = "); + fprintf(f, " ="); if (!next_type_marker(m)) { /* data type information missing, need to guess */ @@ -227,32 +227,23 @@ static void write_propval(FILE *f, struct property *prop) m = &dummy_marker; } - struct marker *m_label = prop->val.markers; for_each_marker(m) { - size_t chunk_len; + 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]; - if (!has_data_type_information(m)) - continue; - - chunk_len = type_marker_length(m); - if (!chunk_len) - chunk_len = len - m->offset; - - if (emit_type != TYPE_NONE) - fprintf(f, "%s, ", delim_end[emit_type]); - emit_type = m->type; - - for_each_marker_of_type(m_label, LABEL) { - if (m_label->offset > m->offset) - break; - fprintf(f, "%s: ", m_label->ref); + if (has_data_type_information(m)) { + emit_type = m->type; + fprintf(f, " %s", delim_start[emit_type]); } - fprintf(f, "%s", delim_start[emit_type]); + if (m->type == LABEL) + fprintf(f, " %s:", m->ref); - if (chunk_len <= 0) + if (emit_type == TYPE_NONE) { + assert(chunk_len == 0); continue; + } switch(emit_type) { case TYPE_UINT16: @@ -270,15 +261,15 @@ static void write_propval(FILE *f, struct property *prop) default: write_propval_int(f, p, chunk_len, 1); } - } - /* Wrap up any labels at the end of the value */ - for_each_marker_of_type(m_label, LABEL) { - assert (m_label->offset == len); - fprintf(f, " %s:", m_label->ref); + if (chunk_len == data_len) { + size_t pos = m->offset + chunk_len; + fprintf(f, pos == len ? "%s" : "%s,", + delim_end[emit_type] ? : ""); + emit_type = TYPE_NONE; + } } - - fprintf(f, "%s;\n", delim_end[emit_type] ? : ""); + fprintf(f, ";\n"); } static void write_tree_source_node(FILE *f, struct node *tree, int level) From e84742aa7b934cd6603e3a64f8c0966f683c5711 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 20 Sep 2018 14:30:03 -0700 Subject: [PATCH 0747/1198] checks: fix simple-bus compatible matching Since commit 7975f6422260 ("Fix widespread incorrect use of strneq(), replace with new strprefixeq()") simple-bus checks have been silently skipped. The problem was 'end - str' is one more than the string length and the strnlen in strprefixeq fails. This can't be fixed simply by subtracting one as it is possible to have multiple '\0' at the end of the property. Fix this by making the 'compatible' property string list check a dependency, and then we can assume the property is null terminated and we can just use streq() for comparisons. Add some tests so the problem doesn't happen again. Fixes: 7975f6422260 ("Fix widespread incorrect use of strneq(), replace with new strprefixeq()") Reported-by: Kumar Gala Signed-off-by: Rob Herring Signed-off-by: David Gibson --- checks.c | 5 +++-- tests/run_tests.sh | 4 ++++ tests/unit-addr-simple-bus-compatible.dts | 18 ++++++++++++++++++ tests/unit-addr-simple-bus-reg-mismatch.dts | 18 ++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 tests/unit-addr-simple-bus-compatible.dts create mode 100644 tests/unit-addr-simple-bus-reg-mismatch.dts diff --git a/checks.c b/checks.c index 9c9b0c3..1c398d5 100644 --- a/checks.c +++ b/checks.c @@ -910,7 +910,7 @@ static bool node_is_compatible(struct node *node, const char *compat) for (str = prop->val.val, end = str + prop->val.len; str < end; str += strnlen(str, end - str) + 1) { - if (strprefixeq(str, end - str, compat)) + if (streq(str, compat)) return true; } return false; @@ -921,7 +921,8 @@ static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct if (node_is_compatible(node, "simple-bus")) node->bus = &simple_bus; } -WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells); +WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, + &addr_size_cells, &compatible_is_string_list); static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node) { diff --git a/tests/run_tests.sh b/tests/run_tests.sh index adc4dae..6756f3d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -668,6 +668,10 @@ dtc_tests () { check_tests pci-bridge-bad1.dts pci_bridge check_tests pci-bridge-bad2.dts pci_bridge + check_tests unit-addr-simple-bus-reg-mismatch.dts simple_bus_reg + check_tests unit-addr-simple-bus-compatible.dts simple_bus_reg + + # Check warning options run_sh_test 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 bad-ncells.dts run_sh_test dtc-fails.sh -n test-warn-output.test.dtb -I dts -O dtb bad-ncells.dts diff --git a/tests/unit-addr-simple-bus-compatible.dts b/tests/unit-addr-simple-bus-compatible.dts new file mode 100644 index 0000000..c8f9341 --- /dev/null +++ b/tests/unit-addr-simple-bus-compatible.dts @@ -0,0 +1,18 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + bus@10000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "foo-bus", "simple-bus"; + ranges = <0x0 0x10000000 0x10000>; + + node@100 { + reg = <0x1000 1>; + }; + }; + +}; diff --git a/tests/unit-addr-simple-bus-reg-mismatch.dts b/tests/unit-addr-simple-bus-reg-mismatch.dts new file mode 100644 index 0000000..2823377 --- /dev/null +++ b/tests/unit-addr-simple-bus-reg-mismatch.dts @@ -0,0 +1,18 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + bus@10000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges = <0x0 0x10000000 0x10000>; + + node@100 { + reg = <0x1000 1>; + }; + }; + +}; From 59327523d0d827ba7d8ff311ec89f0f32a1b2ebe Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 8 Aug 2018 17:52:49 +1000 Subject: [PATCH 0748/1198] pylibfdt: We don't need include files from the base directory pylibfdt/setup.py currently adds include flags to the extension module build to allow include files in the base dtc directory. But pylibfdt doesn't rely on any headers there, only on headers in libfdt/ - it also shouldn't rely on dtc headers at any future time. So, remove that from the include list, allowing some simplifications to setup.py. Signed-off-by: David Gibson Reviewed-by: Simon Glass --- pylibfdt/setup.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py index 1a1e832..8d97ab8 100755 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -70,14 +70,12 @@ def GetEnvFromMakefiles(): Returns: Tuple with: - List of swig options Version string List of files to build List of extra C preprocessor flags needed Object directory to use (always '') """ basedir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0]))) - swig_opts = ['-I%s' % basedir] makevars = ParseMakefile(os.path.join(basedir, 'Makefile')) version = '%s.%s.%s' % (makevars['VERSION'], makevars['PATCHLEVEL'], makevars['SUBLEVEL']) @@ -85,9 +83,9 @@ def GetEnvFromMakefiles(): files = makevars['LIBFDT_SRCS'].split() files = [os.path.join(basedir, 'libfdt', fname) for fname in files] files.append('pylibfdt/libfdt.i') - cflags = ['-I%s' % basedir, '-I%s/libfdt' % basedir] + cflags = ['-I%s/libfdt' % basedir] objdir = '' - return swig_opts, version, files, cflags, objdir + return version, files, cflags, objdir progname = sys.argv[0] @@ -95,19 +93,17 @@ files = os.environ.get('SOURCES', '').split() cflags = os.environ.get('CPPFLAGS', '').split() objdir = os.environ.get('OBJDIR') version = os.environ.get('VERSION') -swig_opts = [] # If we were called directly rather than through our Makefile (which is often # the case with Python module installation), read the settings from the # Makefile. if not all((version, files, cflags, objdir)): - swig_opts, version, files, cflags, objdir = GetEnvFromMakefiles() + version, files, cflags, objdir = GetEnvFromMakefiles() libfdt_module = Extension( '_libfdt', sources = files, extra_compile_args = cflags, - swig_opts = swig_opts, ) setup( From dd695d6afb19359f9b1efb8aa649c0e508817f95 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 10 Aug 2018 12:39:18 +1000 Subject: [PATCH 0749/1198] pylibfdt: Correctly set build output directory Our Makefile currently passes PYLIBFDT_objdir into setup.py in an attempt to set the correct place to put the Python extension module output. But that gets passed in the 'package_dir' map in distutils. But that's basically not what package_dir controls. What actually makes us find the module in the right place is the --inplace passed to setup.py (causing the module to go into the current directory), and the following 'mv' in the Makefile to move it into the right final location. We can simplify setup.py by dropping the useless objdir stuff, and get the module put in the right place straight way by instead using the --build-lib setup.py option. Signed-off-by: David Gibson Reviewed-by: Simon Glass --- pylibfdt/Makefile.pylibfdt | 6 ++---- pylibfdt/setup.py | 11 +++-------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 9507d3d..0b5364e 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -6,15 +6,13 @@ PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS)) \ PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so define run_setup - SOURCES="$(1)" CPPFLAGS="$(CPPFLAGS)" OBJDIR="$(PYLIBFDT_objdir)" - VERSION="$(dtc_version)" + SOURCES="$(1)" CPPFLAGS="$(CPPFLAGS)" VERSION="$(dtc_version)" $(PYLIBFDT_objdir)/setup.py --quiet $(2) endef $(PYMODULE): $(PYLIBFDT_srcs) @$(VECHO) PYMOD $@ - $(call run_setup, $^, build_ext --inplace) - mv _libfdt.so $@ + $(call run_setup, $^, build_ext --build-lib=$(PYLIBFDT_objdir)) install_pylibfdt: $(PYMODULE) $(VECHO) INSTALL-PYLIB; \ diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py index 8d97ab8..a9e8051 100755 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -7,7 +7,6 @@ Written by Simon Glass Files to be built into the extension are provided in SOURCES C flags to use are provided in CPPFLAGS -Object file directory is provided in OBJDIR Version is provided in VERSION If these variables are not given they are parsed from the Makefiles. This @@ -73,7 +72,6 @@ def GetEnvFromMakefiles(): Version string List of files to build List of extra C preprocessor flags needed - Object directory to use (always '') """ basedir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0]))) makevars = ParseMakefile(os.path.join(basedir, 'Makefile')) @@ -84,21 +82,19 @@ def GetEnvFromMakefiles(): files = [os.path.join(basedir, 'libfdt', fname) for fname in files] files.append('pylibfdt/libfdt.i') cflags = ['-I%s/libfdt' % basedir] - objdir = '' - return version, files, cflags, objdir + return version, files, cflags progname = sys.argv[0] files = os.environ.get('SOURCES', '').split() cflags = os.environ.get('CPPFLAGS', '').split() -objdir = os.environ.get('OBJDIR') version = os.environ.get('VERSION') # If we were called directly rather than through our Makefile (which is often # the case with Python module installation), read the settings from the # Makefile. -if not all((version, files, cflags, objdir)): - version, files, cflags, objdir = GetEnvFromMakefiles() +if not all((version, files, cflags)): + version, files, cflags= GetEnvFromMakefiles() libfdt_module = Extension( '_libfdt', @@ -112,6 +108,5 @@ setup( author='Simon Glass ', description='Python binding for libfdt', ext_modules=[libfdt_module], - package_dir={'': objdir}, py_modules=['pylibfdt/libfdt'], ) From 47cafbeeb977a896387c06e0cedea30022b19100 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 8 Aug 2018 23:34:11 +1000 Subject: [PATCH 0750/1198] pylibfdt: Link extension module with libfdt rather than rebuilding Currently we build the Python extension module from all the libfdt source files as well as the swig wrapper file. This is a bit silly, since we've already compiled libfdt itself. This changes the build to instead build the extension module from just the swig wrapper, linking it against the libfdt.a we've already build. Signed-off-by: David Gibson Reviewed-by: Simon Glass --- pylibfdt/Makefile.pylibfdt | 14 ++++++-------- pylibfdt/setup.py | 17 ++++++----------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 0b5364e..6b34b01 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -1,22 +1,20 @@ # Makefile.pylibfdt # -PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS)) \ - $(PYLIBFDT_srcdir)/libfdt.i +PYLIBFDT_srcs = $(PYLIBFDT_srcdir)/libfdt.i PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so define run_setup - SOURCES="$(1)" CPPFLAGS="$(CPPFLAGS)" VERSION="$(dtc_version)" - $(PYLIBFDT_objdir)/setup.py --quiet $(2) + CPPFLAGS="$(CPPFLAGS)" VERSION="$(dtc_version)" + $(PYLIBFDT_objdir)/setup.py --quiet $(1) endef -$(PYMODULE): $(PYLIBFDT_srcs) +$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) @$(VECHO) PYMOD $@ - $(call run_setup, $^, build_ext --build-lib=$(PYLIBFDT_objdir)) + $(call run_setup, build_ext --build-lib=$(PYLIBFDT_objdir)) install_pylibfdt: $(PYMODULE) $(VECHO) INSTALL-PYLIB; \ - $(call run_setup, $(PYLIBFDT_srcs), \ - install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX))) + $(call run_setup, install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX))) PYLIBFDT_cleanfiles = libfdt_wrap.c libfdt.py libfdt.pyc _libfdt.so diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py index a9e8051..aafe70d 100755 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -5,7 +5,6 @@ setup.py file for SWIG libfdt Copyright (C) 2017 Google, Inc. Written by Simon Glass -Files to be built into the extension are provided in SOURCES C flags to use are provided in CPPFLAGS Version is provided in VERSION @@ -70,35 +69,31 @@ def GetEnvFromMakefiles(): Returns: Tuple with: Version string - List of files to build List of extra C preprocessor flags needed """ basedir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0]))) makevars = ParseMakefile(os.path.join(basedir, 'Makefile')) version = '%s.%s.%s' % (makevars['VERSION'], makevars['PATCHLEVEL'], makevars['SUBLEVEL']) - makevars = ParseMakefile(os.path.join(basedir, 'libfdt', 'Makefile.libfdt')) - files = makevars['LIBFDT_SRCS'].split() - files = [os.path.join(basedir, 'libfdt', fname) for fname in files] - files.append('pylibfdt/libfdt.i') cflags = ['-I%s/libfdt' % basedir] - return version, files, cflags + return version, cflags progname = sys.argv[0] -files = os.environ.get('SOURCES', '').split() cflags = os.environ.get('CPPFLAGS', '').split() version = os.environ.get('VERSION') # If we were called directly rather than through our Makefile (which is often # the case with Python module installation), read the settings from the # Makefile. -if not all((version, files, cflags)): - version, files, cflags= GetEnvFromMakefiles() +if not all((version, cflags)): + version, cflags= GetEnvFromMakefiles() libfdt_module = Extension( '_libfdt', - sources = files, + sources = ['pylibfdt/libfdt.i'], + libraries = ['fdt'], + library_dirs = ['libfdt'], extra_compile_args = cflags, ) From 855b9963def9cccf1cd6a74a8bb784c44ce497f7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 10 Aug 2018 13:43:50 +1000 Subject: [PATCH 0751/1198] pylibfdt: Simpler CFLAGS handling At the moment we have some fiddly code to either pass in make's CPPFLAGS to setup.py, or have setup.py extract them from the Makefile. But really the only thing we need from here is the include paths. We already know what include paths we need (libfdt/) so we can just set that directly in setup.py. Signed-off-by: David Gibson Reviewed-by: Simon Glass --- pylibfdt/Makefile.pylibfdt | 2 +- pylibfdt/setup.py | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 6b34b01..3c6ae44 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -5,7 +5,7 @@ PYLIBFDT_srcs = $(PYLIBFDT_srcdir)/libfdt.i PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so define run_setup - CPPFLAGS="$(CPPFLAGS)" VERSION="$(dtc_version)" + VERSION="$(dtc_version)" $(PYLIBFDT_objdir)/setup.py --quiet $(1) endef diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py index aafe70d..95f1601 100755 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -5,7 +5,6 @@ setup.py file for SWIG libfdt Copyright (C) 2017 Google, Inc. Written by Simon Glass -C flags to use are provided in CPPFLAGS Version is provided in VERSION If these variables are not given they are parsed from the Makefiles. This @@ -75,26 +74,24 @@ def GetEnvFromMakefiles(): makevars = ParseMakefile(os.path.join(basedir, 'Makefile')) version = '%s.%s.%s' % (makevars['VERSION'], makevars['PATCHLEVEL'], makevars['SUBLEVEL']) - cflags = ['-I%s/libfdt' % basedir] - return version, cflags + return version progname = sys.argv[0] -cflags = os.environ.get('CPPFLAGS', '').split() version = os.environ.get('VERSION') # If we were called directly rather than through our Makefile (which is often # the case with Python module installation), read the settings from the # Makefile. -if not all((version, cflags)): - version, cflags= GetEnvFromMakefiles() +if not version: + version = GetEnvFromMakefiles() libfdt_module = Extension( '_libfdt', sources = ['pylibfdt/libfdt.i'], + include_dirs = ['libfdt'], libraries = ['fdt'], library_dirs = ['libfdt'], - extra_compile_args = cflags, ) setup( From 7691f9d39301aaf411437ee991583559f962ac03 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 10 Aug 2018 13:52:33 +1000 Subject: [PATCH 0752/1198] pylibfdt: Make SETUP make variable This points to the Python setup script, since we reference it in a couple of places. While we're there correct two small problems: 1) setup.py is part of the checked in sources and so lives in $(PYLIBFDT_srcdir) not $(PYLIBFDT_objdir) [this only worked because those are the same by default] 2) The module itself should depend on the setup script so it is rebuilt if the script is changed Signed-off-by: David Gibson Reviewed-by: Simon Glass --- pylibfdt/Makefile.pylibfdt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 3c6ae44..bbd6518 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -4,12 +4,14 @@ PYLIBFDT_srcs = $(PYLIBFDT_srcdir)/libfdt.i PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so +SETUP = $(PYLIBFDT_srcdir)/setup.py + define run_setup VERSION="$(dtc_version)" - $(PYLIBFDT_objdir)/setup.py --quiet $(1) + $(SETUP) --quiet $(1) endef -$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) +$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) @$(VECHO) PYMOD $@ $(call run_setup, build_ext --build-lib=$(PYLIBFDT_objdir)) From 7ba2be6cda5f3d55aad18f0a5d585c0638e57c95 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 10 Aug 2018 13:55:38 +1000 Subject: [PATCH 0753/1198] pylibfdt: Don't silence setup.py when V=1 At the moment we unconditionally pass --quiet to setup.py. Change that to get more debugging output from it when V=1 is passed to make. Signed-off-by: David Gibson Reviewed-by: Simon Glass --- pylibfdt/Makefile.pylibfdt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index bbd6518..005cb25 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -5,10 +5,15 @@ PYLIBFDT_srcs = $(PYLIBFDT_srcdir)/libfdt.i PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so SETUP = $(PYLIBFDT_srcdir)/setup.py +SETUPFLAGS = + +ifndef V +SETUPFLAGS += --quiet +endif define run_setup VERSION="$(dtc_version)" - $(SETUP) --quiet $(1) + $(SETUP) $(SETUPFLAGS) $(1) endef $(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) From 98972f1b3e33f17d290fc39e037a78b863c92cf6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 10 Aug 2018 14:25:42 +1000 Subject: [PATCH 0754/1198] pylibfdt: Improved version extraction Currently setup.py expects the library version in a VERSION environment variable, or it exctracts the version from the Makefile. The latter is for the case where the script is run standalone, rather than from make. But parsing the Makefile is ugly and fragile, and won't always get the same version we put into the C code. This changes to instead extracting the version from the trivial .h file we already generate to put the version into C code. It's still slightly ugly, but it's simpler and since we can control the precise format of that .h, not as fragile. This lets us remove the remains of the makefile parsing code from setup.py. Signed-off-by: David Gibson Reviewed-by: Simon Glass --- pylibfdt/Makefile.pylibfdt | 3 +- pylibfdt/setup.py | 80 ++++---------------------------------- 2 files changed, 9 insertions(+), 74 deletions(-) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 005cb25..5fe5c82 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -12,11 +12,10 @@ SETUPFLAGS += --quiet endif define run_setup - VERSION="$(dtc_version)" $(SETUP) $(SETUPFLAGS) $(1) endef -$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) +$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE) @$(VECHO) PYMOD $@ $(call run_setup, build_ext --build-lib=$(PYLIBFDT_objdir)) diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py index 95f1601..f0f0e10 100755 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -4,13 +4,6 @@ setup.py file for SWIG libfdt Copyright (C) 2017 Google, Inc. Written by Simon Glass - -Version is provided in VERSION - -If these variables are not given they are parsed from the Makefiles. This -allows this script to be run stand-alone, e.g.: - - ./pylibfdt/setup.py install [--prefix=...] """ from distutils.core import setup, Extension @@ -18,73 +11,16 @@ import os import re import sys -# Decodes a Makefile assignment line into key and value (and plus for +=) -RE_KEY_VALUE = re.compile('(?P\w+) *(?P[+])?= *(?P.*)$') + +VERSION_PATTERN = '^#define DTC_VERSION "DTC ([^"]*)"$' -def ParseMakefile(fname): - """Parse a Makefile to obtain its variables. +def get_version(): + version_file = "version_gen.h" + f = open(version_file, 'rt') + m = re.match(VERSION_PATTERN, f.readline()) + return m.group(1) - This collects variable assigments of the form: - - VAR = value - VAR += more - - It does not pick out := assignments, as these are not needed here. It does - handle line continuation. - - Returns a dict: - key: Variable name (e.g. 'VAR') - value: Variable value (e.g. 'value more') - """ - makevars = {} - with open(fname) as fd: - prev_text = '' # Continuation text from previous line(s) - for line in fd.read().splitlines(): - if line and line[-1] == '\\': # Deal with line continuation - prev_text += line[:-1] - continue - elif prev_text: - line = prev_text + line - prev_text = '' # Continuation is now used up - m = RE_KEY_VALUE.match(line) - if m: - value = m.group('value') or '' - key = m.group('key') - - # Appending to a variable inserts a space beforehand - if 'plus' in m.groupdict() and key in makevars: - makevars[key] += ' ' + value - else: - makevars[key] = value - return makevars - -def GetEnvFromMakefiles(): - """Scan the Makefiles to obtain the settings we need. - - This assumes that this script is being run from the top-level directory, - not the pylibfdt directory. - - Returns: - Tuple with: - Version string - List of extra C preprocessor flags needed - """ - basedir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0]))) - makevars = ParseMakefile(os.path.join(basedir, 'Makefile')) - version = '%s.%s.%s' % (makevars['VERSION'], makevars['PATCHLEVEL'], - makevars['SUBLEVEL']) - return version - - -progname = sys.argv[0] -version = os.environ.get('VERSION') - -# If we were called directly rather than through our Makefile (which is often -# the case with Python module installation), read the settings from the -# Makefile. -if not version: - version = GetEnvFromMakefiles() libfdt_module = Extension( '_libfdt', @@ -96,7 +32,7 @@ libfdt_module = Extension( setup( name='libfdt', - version= version, + version= get_version(), author='Simon Glass ', description='Python binding for libfdt', ext_modules=[libfdt_module], From ca399b14956f1d57fff46e4e847f1448b955d0ec Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 10 Aug 2018 14:37:52 +1000 Subject: [PATCH 0755/1198] pylibfdt: Eliminate run_setup make function This function no longer does anything useful, so get rid of it. Signed-off-by: David Gibson Reviewed-by: Simon Glass --- pylibfdt/Makefile.pylibfdt | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 5fe5c82..0dc5e96 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -11,16 +11,12 @@ ifndef V SETUPFLAGS += --quiet endif -define run_setup - $(SETUP) $(SETUPFLAGS) $(1) -endef - $(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE) @$(VECHO) PYMOD $@ - $(call run_setup, build_ext --build-lib=$(PYLIBFDT_objdir)) + $(SETUP) $(SETUPFLAGS) build_ext --build-lib=$(PYLIBFDT_objdir) install_pylibfdt: $(PYMODULE) - $(VECHO) INSTALL-PYLIB; \ - $(call run_setup, install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX))) + @$(VECHO) INSTALL-PYLIB + $(SETUP) $(SETUPFLAGS) install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX)) PYLIBFDT_cleanfiles = libfdt_wrap.c libfdt.py libfdt.pyc _libfdt.so From 1e4a0928f3b3b827824222572e551a60935607e3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 10 Aug 2018 17:33:24 +1000 Subject: [PATCH 0756/1198] pylibfdt: Don't have setup.py depend on where it's invoked from Currently setup.py depends on being invoked from the right directory (specifically it needs to be run from the root of the project). That's a bit confusing. This updates setup.py to no longer depend on the invoking directory by instead having it change directory to the location of the script itself, then using internal paths relative to that. Signed-off-by: David Gibson Reviewed-by: Simon Glass --- pylibfdt/Makefile.pylibfdt | 2 +- pylibfdt/libfdt.i | 4 ++-- pylibfdt/setup.py | 13 ++++++++----- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 0dc5e96..8f00b3d 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -13,7 +13,7 @@ endif $(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE) @$(VECHO) PYMOD $@ - $(SETUP) $(SETUPFLAGS) build_ext --build-lib=$(PYLIBFDT_objdir) + $(SETUP) $(SETUPFLAGS) build_ext --build-lib=../$(PYLIBFDT_objdir) install_pylibfdt: $(PYMODULE) @$(VECHO) INSTALL-PYLIB diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 842e7b6..462b5b0 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -1028,7 +1028,7 @@ class NodeAdder(): */ typedef uint32_t fdt32_t; -%include "libfdt/fdt.h" +%include "fdt.h" %include "typemaps.i" @@ -1134,4 +1134,4 @@ int fdt_property_cell(void *fdt, const char *name, uint32_t val); */ int fdt_property_stub(void *fdt, const char *name, const char *val, int len); -%include <../libfdt/libfdt.h> +%include diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py index f0f0e10..bd8ccf8 100755 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -16,18 +16,21 @@ VERSION_PATTERN = '^#define DTC_VERSION "DTC ([^"]*)"$' def get_version(): - version_file = "version_gen.h" + version_file = "../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 = ['pylibfdt/libfdt.i'], - include_dirs = ['libfdt'], + sources = ['libfdt.i'], + include_dirs = ['../libfdt'], libraries = ['fdt'], - library_dirs = ['libfdt'], + library_dirs = ['../libfdt'], + swig_opts = ['-I../libfdt'], ) setup( @@ -36,5 +39,5 @@ setup( author='Simon Glass ', description='Python binding for libfdt', ext_modules=[libfdt_module], - py_modules=['pylibfdt/libfdt'], + py_modules=['libfdt'], ) From 0fcffda15e9f4510aa8cd2a495bec66242d1898f Mon Sep 17 00:00:00 2001 From: Fredrik Markstrom Date: Mon, 24 Sep 2018 13:27:27 +0200 Subject: [PATCH 0757/1198] Merge nodes with local target label references This change makes sure that nodes with target label references doesn't create additional fragments if the label can been resolved locally. Target path references are not resolved locally and will generate a fragment. Previously the dts below would generate two fragments: /dts-v1/; /plugin/; &x { a: a@0 {};}; &a { b {}; }; This commit essentially reverts part of the commit "Correct overlay syntactic sugar for generating target-path fragments". The main reason we want to do this is that it breaks consumers of dtbo:s that can't resolve references between fragments in the same dtbo (like the linux 4.1 kernel). In addition creating a fragment for each label reference substantially increases the size of the resulting dtbo for some use cases. Signed-off-by: Fredrik Markstrom Signed-off-by: David Gibson --- dtc-lexer.l | 4 ++-- dtc-parser.y | 39 +++++++++++++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 615b7ec..06c0409 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -213,14 +213,14 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...); <*>\&{LABEL} { /* label reference */ DPRINT("Ref: %s\n", yytext+1); yylval.labelref = xstrdup(yytext+1); - return DT_REF; + return DT_LABEL_REF; } <*>"&{/"{PATHCHAR}*\} { /* new-style path reference */ yytext[yyleng-1] = '\0'; DPRINT("Ref: %s\n", yytext+2); yylval.labelref = xstrdup(yytext+2); - return DT_REF; + return DT_PATH_REF; } [0-9a-fA-F]{2} { diff --git a/dtc-parser.y b/dtc-parser.y index dd70ebf..deda663 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -70,7 +70,8 @@ extern bool treesource_error; %token DT_BYTE %token DT_STRING %token DT_LABEL -%token DT_REF +%token DT_LABEL_REF +%token DT_PATH_REF %token DT_INCBIN %type propdata @@ -83,6 +84,7 @@ extern bool treesource_error; %type bytestring %type propdef %type proplist +%type dt_ref %type devicetree %type nodedef @@ -158,6 +160,8 @@ memreserve: } ; +dt_ref: DT_LABEL_REF | DT_PATH_REF; + devicetree: '/' nodedef { @@ -167,7 +171,7 @@ devicetree: { $$ = merge_nodes($1, $3); } - | DT_REF nodedef + | dt_ref nodedef { /* * We rely on the rule being always: @@ -178,7 +182,7 @@ devicetree: ERROR(&@2, "Label or path %s not found", $1); $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1); } - | devicetree DT_LABEL DT_REF nodedef + | devicetree DT_LABEL dt_ref nodedef { struct node *target = get_node_by_ref($1, $3); @@ -189,7 +193,7 @@ devicetree: ERROR(&@3, "Label or path %s not found", $3); $$ = $1; } - | devicetree DT_REF nodedef + | devicetree DT_PATH_REF nodedef { /* * We rely on the rule being always: @@ -208,7 +212,26 @@ devicetree: } $$ = $1; } - | devicetree DT_DEL_NODE DT_REF ';' + | devicetree DT_LABEL_REF nodedef + { + struct node *target = get_node_by_ref($1, $2); + + if (target) { + merge_nodes(target, $3); + } else { + /* + * We rely on the rule being always: + * versioninfo plugindecl memreserves devicetree + * so $-1 is what we want (plugindecl) + */ + if ($-1 & DTSF_PLUGIN) + add_orphan_node($1, $3, $2); + else + ERROR(&@2, "Label or path %s not found", $2); + } + $$ = $1; + } + | devicetree DT_DEL_NODE dt_ref ';' { struct node *target = get_node_by_ref($1, $3); @@ -220,7 +243,7 @@ devicetree: $$ = $1; } - | devicetree DT_OMIT_NO_REF DT_REF ';' + | devicetree DT_OMIT_NO_REF dt_ref ';' { struct node *target = get_node_by_ref($1, $3); @@ -285,7 +308,7 @@ propdata: { $$ = data_merge($1, $3); } - | propdataprefix DT_REF + | propdataprefix dt_ref { $1 = data_add_marker($1, TYPE_STRING, $2); $$ = data_add_marker($1, REF_PATH, $2); @@ -383,7 +406,7 @@ arrayprefix: $$.data = data_append_integer($1.data, $2, $1.bits); } - | arrayprefix DT_REF + | arrayprefix dt_ref { uint64_t val = ~0ULL >> (64 - $1.bits); From e45198c9835901efc4763bcafa3cf50b5bdcb6b5 Mon Sep 17 00:00:00 2001 From: Fredrik Markstrom Date: Tue, 25 Sep 2018 21:32:37 +0200 Subject: [PATCH 0758/1198] Added test cases for target references This commit adds test cases for commits "Correct overlay syntactic sugar for generating target-path fragments" and "Merge nodes with local target label references". It verifies that target path references are not resolved locally and that target label references that can be resolved locally are. Signed-off-by: Fredrik Markstrom [dwg: Fixed some whitespace problems] Signed-off-by: David Gibson --- tests/overlay_overlay_local_merge.dts | 29 +++++++++++++++++++++++++++ tests/run_tests.sh | 5 +++++ 2 files changed, 34 insertions(+) create mode 100644 tests/overlay_overlay_local_merge.dts diff --git a/tests/overlay_overlay_local_merge.dts b/tests/overlay_overlay_local_merge.dts new file mode 100644 index 0000000..3ee622d --- /dev/null +++ b/tests/overlay_overlay_local_merge.dts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * Copyright (c) 2016 Konsulko Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +/plugin/; + +&test { + parent: new-node { + parent-property; + }; +}; + +&parent { + new-merged-property; + new-merged-node { + new-property; + }; +}; + +&{/} { + new-root-node { + new-root-node-property; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 6756f3d..e3e64e8 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -257,6 +257,11 @@ dtc_overlay_tests () { run_test check_path overlay_overlay_bypath.test.dtb not-exists "/__fixups__" run_test check_path overlay_overlay_bypath.test.dtb exists "/__local_fixups__" + # Make sure local target references are resolved and nodes are merged and that path references are not + run_dtc_test -I dts -O dtb -o overlay_overlay_local_merge.test.dtb overlay_overlay_local_merge.dts + run_test check_path overlay_overlay_local_merge.test.dtb exists "/fragment@0/__overlay__/new-node/new-merged-node" + run_test check_path overlay_overlay_local_merge.test.dtb exists "/fragment@1/__overlay__/new-root-node" + # Check building works the same as manual constructions run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_nosugar.test.dtb From 522d81d572f2f8ae683c39089df64f5c74205451 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 26 Sep 2018 14:27:08 -0500 Subject: [PATCH 0759/1198] Fix dts output with a REF_PATH marker Commit 8c59a97ce096 ("Fix missing labels when emitting dts format") fixed label output, but broke output when there is a REF_PATH marker. The problem is a REF_PATH marker causes a zero length string to be emitted. The write_propval_string() function requires a length of at least 1 (including the terminating '\0'), but that was not being checked. For the integer output, a length of 0 is valid as it is possible to have labels inside the starting '<': int-prop = < start: 0x1234>; REF_PHANDLE is another marker that we don't explicitly handle, but it doesn't cause a problem as it is fundamentally just an int. Fixes: 8c59a97ce096 ("Fix missing labels when emitting dts format") Reported-by: Kumar Gala Cc: Grant Likely Signed-off-by: Rob Herring Signed-off-by: David Gibson --- tests/path-references.dts | 2 +- tests/run_tests.sh | 6 ++++++ treesource.c | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/path-references.dts b/tests/path-references.dts index 8c66d80..1fb7d70 100644 --- a/tests/path-references.dts +++ b/tests/path-references.dts @@ -16,7 +16,7 @@ foobar { n3: baz { ref = &{/foo/baz}; - lref = &n4; + lref = start: &n4 end:; }; }; foo { diff --git a/tests/run_tests.sh b/tests/run_tests.sh index e3e64e8..e7ee42b 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -572,6 +572,12 @@ dtc_tests () { run_dtc_test -I dts -O dts $tree.test.dts run_wrap_test cmp $tree $tree.test.dts done + for tree in path-references; do + run_dtc_test -I dts -O dtb -o $tree.test.dtb $tree.dts + run_dtc_test -I dts -O dts -o $tree.test.dts $tree.dts + run_dtc_test -I dts -O dtb -o $tree.test.dts.test.dtb $tree.test.dts + run_test dtbs_equal_ordered $tree.test.dtb $tree.test.dts.test.dtb + done # Check -Oyaml output if pkg-config --exists yaml-0.1; then diff --git a/treesource.c b/treesource.c index c1fdb86..93fd8ac 100644 --- a/treesource.c +++ b/treesource.c @@ -64,6 +64,10 @@ static bool isstring(char c) static void write_propval_string(FILE *f, const char *s, size_t len) { const char *end = s + len - 1; + + if (!len) + return; + assert(*end == '\0'); fprintf(f, "\""); From 8f8b77a0d62dbc0e7abee873a03ef34e9041a051 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Wed, 3 Oct 2018 15:12:11 +0200 Subject: [PATCH 0760/1198] tests: Wrap check_align() calls with base_run_test() Otherwise the FAIL results won't be accounted for in the summary. Easily testable by artifically causing them to fail: - if [ $(($size % $align)) -eq 0 ] ;then + if [ $(($size % $align)) -eq 666 ] ;then Signed-off-by: Lubomir Rintel 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 e7ee42b..bc2cc77 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -730,10 +730,10 @@ dtc_tests () { for align in 2 4 8 16 32 64; do # -p -a run_dtc_test -O dtb -p 1000 -a $align -o align0.dtb subnode_iterate.dts - check_align align0.dtb $align + base_run_test check_align align0.dtb $align # -S -a run_dtc_test -O dtb -S 1999 -a $align -o align1.dtb subnode_iterate.dts - check_align align1.dtb $align + base_run_test check_align align1.dtb $align done # Tests for overlay/plugin generation From da2b691ccf6863b2f5039d98e71f09d4244e5aa1 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 10 Oct 2018 10:19:30 -0500 Subject: [PATCH 0761/1198] treesource: Fix dts output for phandles in middle of a sequence of ints If we have a phandle in the middle of a sequence of numbers and it is not bracketed (e.g. <0x1234 &phandle 0x5678>), the dts output will be corrupted due to missing a space between the phandle value and the following number. Fixes: 8c59a97ce096 ("Fix missing labels when emitting dts format") Cc: Grant Likely Signed-off-by: Rob Herring Signed-off-by: David Gibson --- treesource.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/treesource.c b/treesource.c index 93fd8ac..1529a0a 100644 --- a/treesource.c +++ b/treesource.c @@ -239,10 +239,10 @@ static void write_propval(FILE *f, struct property *prop) if (has_data_type_information(m)) { emit_type = m->type; fprintf(f, " %s", delim_start[emit_type]); - } - - if (m->type == LABEL) + } 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); From 49903aed77832e47f052d094d10ebe75077835e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Hor=C3=A1k?= Date: Mon, 22 Oct 2018 12:14:44 +0200 Subject: [PATCH 0762/1198] use ptrdiff_t modifier for printing pointer differences MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use ptrdiff_t modifier (%tx) for printing a difference between 2 pointers. Currently %zx (size_t) is used, but it fails on platforms where size_t and ptrdiff_t are defined differently (like s390). Comes from https://src.fedoraproject.org/rpms/dtc/c/f3da2d1b00d01d83fef7001d5767baa3d5a6df87?branch=master originally. Signed-off-by: Dan Horák --- fdtdump.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fdtdump.c b/fdtdump.c index 289fff6..760a25c 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -100,7 +100,7 @@ static void dump_blob(void *blob, bool debug) p = p_struct; while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { - dumpf("%04zx: tag: 0x%08"PRIx32" (%s)\n", + dumpf("%04tx: tag: 0x%08"PRIx32" (%s)\n", (uintptr_t)p - blob_off - 4, tag, tagname(tag)); if (tag == FDT_BEGIN_NODE) { @@ -140,8 +140,8 @@ static void dump_blob(void *blob, bool debug) p = PALIGN(p + sz, 4); - dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s); - dumpf("%04zx: value\n", (uintptr_t)t - blob_off); + dumpf("%04tx: string: %s\n", (uintptr_t)s - blob_off, s); + dumpf("%04tx: value\n", (uintptr_t)t - blob_off); printf("%*s%s", depth * shift, "", s); utilfdt_print_data(t, sz); printf(";\n"); @@ -229,14 +229,14 @@ int main(int argc, char *argv[]) if (valid_header(p, this_len)) break; if (debug) - printf("%s: skipping fdt magic at offset %#zx\n", + printf("%s: skipping fdt magic at offset %#tx\n", file, p - buf); } ++p; } if (!p || endp - p < sizeof(struct fdt_header)) die("%s: could not locate fdt magic\n", file); - printf("%s: found fdt at offset %#zx\n", file, p - buf); + printf("%s: found fdt at offset %#tx\n", file, p - buf); buf = p; } else if (!valid_header(buf, len)) die("%s: header is not valid\n", file); From aa7254d9cb173b43714013eef3769475948956f9 Mon Sep 17 00:00:00 2001 From: John Clarke Date: Fri, 2 Nov 2018 12:46:22 +1100 Subject: [PATCH 0763/1198] libfdt: return correct value if #size-cells property is not present According to the device tree specification, the default value for #size-cells is 1, but fdt_size_cells() was returning 2 if this property was not present. This patch also makes fdt_address_cells() and fdt_size_cells() conform to the behaviour documented in libfdt.h. The defaults are only returned if fdt_getprop() returns -FDT_ERR_NOTFOUND, otherwise the actual error is returned. Signed-off-by: John Clarke --- libfdt/fdt_addresses.c | 16 +++++++++++++--- libfdt/libfdt.h | 2 +- tests/addr_size_cells.c | 2 +- tests/addr_size_cells2.c | 2 +- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libfdt/fdt_addresses.c b/libfdt/fdt_addresses.c index 49537b5..f13a87d 100644 --- a/libfdt/fdt_addresses.c +++ b/libfdt/fdt_addresses.c @@ -64,7 +64,7 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name) c = fdt_getprop(fdt, nodeoffset, name, &len); if (!c) - return 2; + return len; if (len != sizeof(*c)) return -FDT_ERR_BADNCELLS; @@ -78,10 +78,20 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name) int fdt_address_cells(const void *fdt, int nodeoffset) { - return fdt_cells(fdt, nodeoffset, "#address-cells"); + int val; + + val = fdt_cells(fdt, nodeoffset, "#address-cells"); + if (val == -FDT_ERR_NOTFOUND) + return 2; + return val; } int fdt_size_cells(const void *fdt, int nodeoffset) { - return fdt_cells(fdt, nodeoffset, "#size-cells"); + int val; + + val = fdt_cells(fdt, nodeoffset, "#size-cells"); + if (val == -FDT_ERR_NOTFOUND) + return 1; + return val; } diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 830b77e..face02c 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1145,7 +1145,7 @@ int fdt_address_cells(const void *fdt, int nodeoffset); * * returns: * 0 <= n < FDT_MAX_NCELLS, on success - * 2, if the node has no #size-cells property + * 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, diff --git a/tests/addr_size_cells.c b/tests/addr_size_cells.c index fcd9ff0..1b196ef 100644 --- a/tests/addr_size_cells.c +++ b/tests/addr_size_cells.c @@ -58,7 +58,7 @@ int main(int argc, char *argv[]) fdt = load_blob(argv[1]); check_node(fdt, "/", 2, 2); - check_node(fdt, "/identity-bus@0", 2, 2); + check_node(fdt, "/identity-bus@0", 2, 1); check_node(fdt, "/simple-bus@1000000", 2, 1); check_node(fdt, "/c0", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS); check_node(fdt, "/c1", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS); diff --git a/tests/addr_size_cells2.c b/tests/addr_size_cells2.c index 38b2c04..52c4eba 100644 --- a/tests/addr_size_cells2.c +++ b/tests/addr_size_cells2.c @@ -57,6 +57,6 @@ int main(int argc, char *argv[]) test_init(argc, argv); fdt = load_blob(argv[1]); - check_node(fdt, "/", 2, 2); + check_node(fdt, "/", 2, 1); PASS(); } From baa1d2cf7894a32bf2f640ef40ebce561b2df565 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 26 Oct 2018 17:44:33 +0200 Subject: [PATCH 0764/1198] annotations: add positions Extend the parser to record positions, in build_node, build_node_delete, and build_property. srcpos structures are added to the property and node types, and to the parameter lists of the above functions that construct these types. Nodes and properties that are created by the compiler rather than from parsing source code have NULL as the srcpos value. merge_nodes, defined in livetree.c, uses srcpos_extend to combine multiple positions, resulting in a list of positions. srcpos_extend is defined in srcpos.c. New elements are added at the end. The srcpos type, define in srcpos.h, is now a list structure with a next field. Another change to srcpos.c is to make srcpos_copy always do a full copy, including a copy of the file substructure. This is required because when dtc is used on the output of cpp, the successive detected file names overwrite the file name in the file structure. The next field does not need to be deep copied, because it is only updated in newly copied positions and the positions to which it points have also been copied. File names are only updated in uncopied position structures. Signed-off-by: Julia Lawall Signed-off-by: David Gibson --- dtc-parser.y | 13 ++++++++----- dtc.h | 10 +++++++--- flattree.c | 4 ++-- fstree.c | 5 +++-- livetree.c | 33 ++++++++++++++++++++++----------- srcpos.c | 22 ++++++++++++++++++++++ srcpos.h | 3 +++ 7 files changed, 67 insertions(+), 23 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index deda663..2ec981e 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -180,7 +180,10 @@ devicetree: */ if (!($-1 & DTSF_PLUGIN)) ERROR(&@2, "Label or path %s not found", $1); - $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1); + $$ = add_orphan_node( + name_node(build_node(NULL, NULL, NULL), + ""), + $2, $1); } | devicetree DT_LABEL dt_ref nodedef { @@ -260,7 +263,7 @@ devicetree: nodedef: '{' proplist subnodes '}' ';' { - $$ = build_node($2, $3); + $$ = build_node($2, $3, &@$); } ; @@ -278,11 +281,11 @@ proplist: propdef: DT_PROPNODENAME '=' propdata ';' { - $$ = build_property($1, $3); + $$ = build_property($1, $3, &@$); } | DT_PROPNODENAME ';' { - $$ = build_property($1, empty_data); + $$ = build_property($1, empty_data, &@$); } | DT_DEL_PROP DT_PROPNODENAME ';' { @@ -563,7 +566,7 @@ subnode: } | DT_DEL_NODE DT_PROPNODENAME ';' { - $$ = name_node(build_node_delete(), $2); + $$ = name_node(build_node_delete(&@$), $2); } | DT_OMIT_NO_REF subnode { diff --git a/dtc.h b/dtc.h index cbe5415..8722cbc 100644 --- a/dtc.h +++ b/dtc.h @@ -158,6 +158,7 @@ struct property { struct property *next; struct label *labels; + struct srcpos *srcpos; }; struct node { @@ -177,6 +178,7 @@ struct node { struct label *labels; const struct bus_type *bus; + struct srcpos *srcpos; bool omit_if_unused, is_referenced; }; @@ -205,13 +207,15 @@ 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(char *name, struct data val, + struct srcpos *srcpos); struct property *build_property_delete(char *name); struct property *chain_property(struct property *first, struct property *list); struct property *reverse_properties(struct property *first); -struct node *build_node(struct property *proplist, struct node *children); -struct node *build_node_delete(void); +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 *omit_node_if_unused(struct node *node); struct node *reference_node(struct node *node); diff --git a/flattree.c b/flattree.c index 851ea87..acf04c3 100644 --- a/flattree.c +++ b/flattree.c @@ -692,7 +692,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf, val = flat_read_data(dtbuf, proplen); - return build_property(name, val); + return build_property(name, val, NULL); } @@ -750,7 +750,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, char *flatname; uint32_t val; - node = build_node(NULL, NULL); + node = build_node(NULL, NULL, NULL); flatname = flat_read_string(dtbuf); diff --git a/fstree.c b/fstree.c index ae7d06c..1e7eeba 100644 --- a/fstree.c +++ b/fstree.c @@ -34,7 +34,7 @@ static struct node *read_fstree(const char *dirname) if (!d) die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno)); - tree = build_node(NULL, NULL); + tree = build_node(NULL, NULL, NULL); while ((de = readdir(d)) != NULL) { char *tmpname; @@ -60,7 +60,8 @@ static struct node *read_fstree(const char *dirname) } else { prop = build_property(xstrdup(de->d_name), data_copy_file(pfile, - st.st_size)); + st.st_size), + NULL); add_property(tree, prop); fclose(pfile); } diff --git a/livetree.c b/livetree.c index 4ff0679..7a2e644 100644 --- a/livetree.c +++ b/livetree.c @@ -19,6 +19,7 @@ */ #include "dtc.h" +#include "srcpos.h" /* * Tree building functions @@ -50,7 +51,8 @@ void delete_labels(struct label **labels) label->deleted = 1; } -struct property *build_property(char *name, struct data val) +struct property *build_property(char *name, struct data val, + struct srcpos *srcpos) { struct property *new = xmalloc(sizeof(*new)); @@ -58,6 +60,7 @@ struct property *build_property(char *name, struct data val) new->name = name; new->val = val; + new->srcpos = srcpos_copy(srcpos); return new; } @@ -97,7 +100,8 @@ struct property *reverse_properties(struct property *first) return head; } -struct node *build_node(struct property *proplist, struct node *children) +struct node *build_node(struct property *proplist, struct node *children, + struct srcpos *srcpos) { struct node *new = xmalloc(sizeof(*new)); struct node *child; @@ -106,6 +110,7 @@ struct node *build_node(struct property *proplist, struct node *children) new->proplist = reverse_properties(proplist); new->children = children; + new->srcpos = srcpos_copy(srcpos); for_each_child(new, child) { child->parent = new; @@ -114,13 +119,14 @@ struct node *build_node(struct property *proplist, struct node *children) return new; } -struct node *build_node_delete(void) +struct node *build_node_delete(struct srcpos *srcpos) { struct node *new = xmalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); new->deleted = 1; + new->srcpos = srcpos_copy(srcpos); return new; } @@ -183,6 +189,8 @@ 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); + old_prop->srcpos = new_prop->srcpos; free(new_prop); new_prop = NULL; break; @@ -223,6 +231,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) add_child(old_node, new_child); } + old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos); + /* The new node contents are now merged into the old node. Free * the new node. */ free(new_node); @@ -241,18 +251,18 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) if (ref[0] == '/') { d = data_append_data(d, ref, strlen(ref) + 1); - p = build_property("target-path", d); + p = build_property("target-path", d, NULL); } else { d = data_add_marker(d, REF_PHANDLE, ref); d = data_append_integer(d, 0xffffffff, 32); - p = build_property("target", d); + p = build_property("target", d, NULL); } xasprintf(&name, "fragment@%u", next_orphan_fragment++); name_node(new_node, "__overlay__"); - node = build_node(p, new_node); + node = build_node(p, new_node, NULL); name_node(node, name); add_child(dt, node); @@ -351,7 +361,7 @@ void append_to_property(struct node *node, p->val = d; } else { d = data_append_data(empty_data, data, len); - p = build_property(name, d); + p = build_property(name, d, NULL); add_property(node, p); } } @@ -609,11 +619,11 @@ cell_t get_node_phandle(struct node *root, struct node *node) if (!get_property(node, "linux,phandle") && (phandle_format & PHANDLE_LEGACY)) - add_property(node, build_property("linux,phandle", d)); + 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)); + add_property(node, build_property("phandle", d, NULL)); /* If the node *does* have a phandle property, we must * be dealing with a self-referencing phandle, which will be @@ -787,7 +797,7 @@ static struct node *build_and_name_child_node(struct node *parent, char *name) { struct node *node; - node = build_node(NULL, NULL); + node = build_node(NULL, NULL, NULL); name_node(node, xstrdup(name)); add_child(parent, node); @@ -849,7 +859,8 @@ static void generate_label_tree_internal(struct dt_info *dti, /* insert it */ p = build_property(l->label, data_copy_mem(node->fullpath, - strlen(node->fullpath) + 1)); + strlen(node->fullpath) + 1), + NULL); add_property(an, p); } diff --git a/srcpos.c b/srcpos.c index cb6ed0e..cba1c0f 100644 --- a/srcpos.c +++ b/srcpos.c @@ -207,6 +207,7 @@ struct srcpos srcpos_empty = { .last_line = 0, .last_column = 0, .file = NULL, + .next = NULL, }; void srcpos_update(struct srcpos *pos, const char *text, int len) @@ -234,13 +235,34 @@ struct srcpos * srcpos_copy(struct srcpos *pos) { struct srcpos *pos_new; + struct srcfile_state *srcfile_state; + + if (!pos) + return NULL; pos_new = xmalloc(sizeof(struct srcpos)); memcpy(pos_new, pos, sizeof(struct srcpos)); + /* allocate without free */ + srcfile_state = xmalloc(sizeof(struct srcfile_state)); + memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state)); + pos_new->file = srcfile_state; + return pos_new; } +struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail) +{ + struct srcpos *p; + + if (!pos) + return newtail; + + for (p = pos; p->next != NULL; p = p->next); + p->next = newtail; + return pos; +} + char * srcpos_string(struct srcpos *pos) { diff --git a/srcpos.h b/srcpos.h index 9ded12a..d88e7cb 100644 --- a/srcpos.h +++ b/srcpos.h @@ -74,6 +74,7 @@ struct srcpos { int last_line; int last_column; struct srcfile_state *file; + struct srcpos *next; }; #define YYLTYPE struct srcpos @@ -105,6 +106,8 @@ extern struct srcpos srcpos_empty; 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 char *srcpos_string(struct srcpos *pos); extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix, From 403cc79f06a135aee00f35cea975f068a72dbd92 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 13 Nov 2018 16:40:10 -0600 Subject: [PATCH 0765/1198] checks: Update SPI bus check for 'spi-slave' If the SPI bus controller is being used for 'spi-slave' mode some of the checks we have need to change: In 'spi-slave' mode #address-cells should be 0, as any children don't have a reg property. Signed-off-by: Kumar Gala Signed-off-by: David Gibson --- checks.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/checks.c b/checks.c index 1c398d5..ed84e03 100644 --- a/checks.c +++ b/checks.c @@ -1036,6 +1036,7 @@ static const struct bus_type spi_bus = { static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) { + int spi_addr_cells = 1; if (strprefixeq(node->name, node->basenamelen, "spi")) { node->bus = &spi_bus; @@ -1064,7 +1065,9 @@ static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct no if (node->bus != &spi_bus || !node->children) return; - if (node_addr_cells(node) != 1) + if (get_property(node, "spi-slave")) + spi_addr_cells = 0; + if (node_addr_cells(node) != spi_addr_cells) FAIL(c, dti, node, "incorrect #address-cells for SPI bus"); if (node_size_cells(node) != 0) FAIL(c, dti, node, "incorrect #size-cells for SPI bus"); @@ -1083,6 +1086,9 @@ static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node if (!node->parent || (node->parent->bus != &spi_bus)) return; + if (get_property(node->parent, "spi-slave")) + return; + prop = get_property(node, "reg"); if (prop) cells = (cell_t *)prop->val.val; From a3143fafbf83868748c99aa14daf274de5549826 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 14 Nov 2018 15:24:49 +1100 Subject: [PATCH 0766/1198] Revert "annotations: add positions" This reverts commit baa1d2cf7894a32bf2f640ef40ebce561b2df565. Turns out this introduced memory badness. valgrind picks it up on x86, but it straight out SEGVs on x86. Signed-off-by: David Gibson --- dtc-parser.y | 13 +++++-------- dtc.h | 10 +++------- flattree.c | 4 ++-- fstree.c | 5 ++--- livetree.c | 33 +++++++++++---------------------- srcpos.c | 22 ---------------------- srcpos.h | 3 --- 7 files changed, 23 insertions(+), 67 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index 2ec981e..deda663 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -180,10 +180,7 @@ devicetree: */ if (!($-1 & DTSF_PLUGIN)) ERROR(&@2, "Label or path %s not found", $1); - $$ = add_orphan_node( - name_node(build_node(NULL, NULL, NULL), - ""), - $2, $1); + $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1); } | devicetree DT_LABEL dt_ref nodedef { @@ -263,7 +260,7 @@ devicetree: nodedef: '{' proplist subnodes '}' ';' { - $$ = build_node($2, $3, &@$); + $$ = build_node($2, $3); } ; @@ -281,11 +278,11 @@ proplist: propdef: DT_PROPNODENAME '=' propdata ';' { - $$ = build_property($1, $3, &@$); + $$ = build_property($1, $3); } | DT_PROPNODENAME ';' { - $$ = build_property($1, empty_data, &@$); + $$ = build_property($1, empty_data); } | DT_DEL_PROP DT_PROPNODENAME ';' { @@ -566,7 +563,7 @@ subnode: } | DT_DEL_NODE DT_PROPNODENAME ';' { - $$ = name_node(build_node_delete(&@$), $2); + $$ = name_node(build_node_delete(), $2); } | DT_OMIT_NO_REF subnode { diff --git a/dtc.h b/dtc.h index 8722cbc..cbe5415 100644 --- a/dtc.h +++ b/dtc.h @@ -158,7 +158,6 @@ struct property { struct property *next; struct label *labels; - struct srcpos *srcpos; }; struct node { @@ -178,7 +177,6 @@ struct node { struct label *labels; const struct bus_type *bus; - struct srcpos *srcpos; bool omit_if_unused, is_referenced; }; @@ -207,15 +205,13 @@ 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 srcpos *srcpos); +struct property *build_property(char *name, struct data val); struct property *build_property_delete(char *name); struct property *chain_property(struct property *first, struct property *list); 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 *build_node(struct property *proplist, struct node *children); +struct node *build_node_delete(void); struct node *name_node(struct node *node, char *name); struct node *omit_node_if_unused(struct node *node); struct node *reference_node(struct node *node); diff --git a/flattree.c b/flattree.c index acf04c3..851ea87 100644 --- a/flattree.c +++ b/flattree.c @@ -692,7 +692,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf, val = flat_read_data(dtbuf, proplen); - return build_property(name, val, NULL); + return build_property(name, val); } @@ -750,7 +750,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, char *flatname; uint32_t val; - node = build_node(NULL, NULL, NULL); + node = build_node(NULL, NULL); flatname = flat_read_string(dtbuf); diff --git a/fstree.c b/fstree.c index 1e7eeba..ae7d06c 100644 --- a/fstree.c +++ b/fstree.c @@ -34,7 +34,7 @@ static struct node *read_fstree(const char *dirname) if (!d) die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno)); - tree = build_node(NULL, NULL, NULL); + tree = build_node(NULL, NULL); while ((de = readdir(d)) != NULL) { char *tmpname; @@ -60,8 +60,7 @@ static struct node *read_fstree(const char *dirname) } else { prop = build_property(xstrdup(de->d_name), data_copy_file(pfile, - st.st_size), - NULL); + st.st_size)); add_property(tree, prop); fclose(pfile); } diff --git a/livetree.c b/livetree.c index 7a2e644..4ff0679 100644 --- a/livetree.c +++ b/livetree.c @@ -19,7 +19,6 @@ */ #include "dtc.h" -#include "srcpos.h" /* * Tree building functions @@ -51,8 +50,7 @@ void delete_labels(struct label **labels) label->deleted = 1; } -struct property *build_property(char *name, struct data val, - struct srcpos *srcpos) +struct property *build_property(char *name, struct data val) { struct property *new = xmalloc(sizeof(*new)); @@ -60,7 +58,6 @@ struct property *build_property(char *name, struct data val, new->name = name; new->val = val; - new->srcpos = srcpos_copy(srcpos); return new; } @@ -100,8 +97,7 @@ struct property *reverse_properties(struct property *first) return head; } -struct node *build_node(struct property *proplist, struct node *children, - struct srcpos *srcpos) +struct node *build_node(struct property *proplist, struct node *children) { struct node *new = xmalloc(sizeof(*new)); struct node *child; @@ -110,7 +106,6 @@ struct node *build_node(struct property *proplist, struct node *children, new->proplist = reverse_properties(proplist); new->children = children; - new->srcpos = srcpos_copy(srcpos); for_each_child(new, child) { child->parent = new; @@ -119,14 +114,13 @@ struct node *build_node(struct property *proplist, struct node *children, return new; } -struct node *build_node_delete(struct srcpos *srcpos) +struct node *build_node_delete(void) { struct node *new = xmalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); new->deleted = 1; - new->srcpos = srcpos_copy(srcpos); return new; } @@ -189,8 +183,6 @@ 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); - old_prop->srcpos = new_prop->srcpos; free(new_prop); new_prop = NULL; break; @@ -231,8 +223,6 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) add_child(old_node, new_child); } - old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos); - /* The new node contents are now merged into the old node. Free * the new node. */ free(new_node); @@ -251,18 +241,18 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) if (ref[0] == '/') { d = data_append_data(d, ref, strlen(ref) + 1); - p = build_property("target-path", d, NULL); + p = build_property("target-path", d); } else { d = data_add_marker(d, REF_PHANDLE, ref); d = data_append_integer(d, 0xffffffff, 32); - p = build_property("target", d, NULL); + p = build_property("target", d); } xasprintf(&name, "fragment@%u", next_orphan_fragment++); name_node(new_node, "__overlay__"); - node = build_node(p, new_node, NULL); + node = build_node(p, new_node); name_node(node, name); add_child(dt, node); @@ -361,7 +351,7 @@ void append_to_property(struct node *node, p->val = d; } else { d = data_append_data(empty_data, data, len); - p = build_property(name, d, NULL); + p = build_property(name, d); add_property(node, p); } } @@ -619,11 +609,11 @@ cell_t get_node_phandle(struct node *root, struct node *node) if (!get_property(node, "linux,phandle") && (phandle_format & PHANDLE_LEGACY)) - add_property(node, build_property("linux,phandle", d, NULL)); + add_property(node, build_property("linux,phandle", d)); if (!get_property(node, "phandle") && (phandle_format & PHANDLE_EPAPR)) - add_property(node, build_property("phandle", d, NULL)); + add_property(node, build_property("phandle", d)); /* If the node *does* have a phandle property, we must * be dealing with a self-referencing phandle, which will be @@ -797,7 +787,7 @@ static struct node *build_and_name_child_node(struct node *parent, char *name) { struct node *node; - node = build_node(NULL, NULL, NULL); + node = build_node(NULL, NULL); name_node(node, xstrdup(name)); add_child(parent, node); @@ -859,8 +849,7 @@ static void generate_label_tree_internal(struct dt_info *dti, /* insert it */ p = build_property(l->label, data_copy_mem(node->fullpath, - strlen(node->fullpath) + 1), - NULL); + strlen(node->fullpath) + 1)); add_property(an, p); } diff --git a/srcpos.c b/srcpos.c index cba1c0f..cb6ed0e 100644 --- a/srcpos.c +++ b/srcpos.c @@ -207,7 +207,6 @@ struct srcpos srcpos_empty = { .last_line = 0, .last_column = 0, .file = NULL, - .next = NULL, }; void srcpos_update(struct srcpos *pos, const char *text, int len) @@ -235,34 +234,13 @@ struct srcpos * srcpos_copy(struct srcpos *pos) { struct srcpos *pos_new; - struct srcfile_state *srcfile_state; - - if (!pos) - return NULL; pos_new = xmalloc(sizeof(struct srcpos)); memcpy(pos_new, pos, sizeof(struct srcpos)); - /* allocate without free */ - srcfile_state = xmalloc(sizeof(struct srcfile_state)); - memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state)); - pos_new->file = srcfile_state; - return pos_new; } -struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail) -{ - struct srcpos *p; - - if (!pos) - return newtail; - - for (p = pos; p->next != NULL; p = p->next); - p->next = newtail; - return pos; -} - char * srcpos_string(struct srcpos *pos) { diff --git a/srcpos.h b/srcpos.h index d88e7cb..9ded12a 100644 --- a/srcpos.h +++ b/srcpos.h @@ -74,7 +74,6 @@ struct srcpos { int last_line; int last_column; struct srcfile_state *file; - struct srcpos *next; }; #define YYLTYPE struct srcpos @@ -106,8 +105,6 @@ extern struct srcpos srcpos_empty; 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 char *srcpos_string(struct srcpos *pos); extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix, From 5062516fb8cb52e2a8739695a27abc533da9abcd Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 14 Nov 2018 16:12:43 +1100 Subject: [PATCH 0767/1198] srcpos: Remove srcpos_empty Nothing was actually using it. Signed-off-by: David Gibson --- srcpos.c | 12 ------------ srcpos.h | 7 ------- 2 files changed, 19 deletions(-) diff --git a/srcpos.c b/srcpos.c index cb6ed0e..ea82d88 100644 --- a/srcpos.c +++ b/srcpos.c @@ -197,18 +197,6 @@ void srcfile_add_search_path(const char *dirname) search_path_tail = &node->next; } -/* - * The empty source position. - */ - -struct srcpos srcpos_empty = { - .first_line = 0, - .first_column = 0, - .last_line = 0, - .last_column = 0, - .file = NULL, -}; - void srcpos_update(struct srcpos *pos, const char *text, int len) { int i; diff --git a/srcpos.h b/srcpos.h index 9ded12a..1c74efd 100644 --- a/srcpos.h +++ b/srcpos.h @@ -96,13 +96,6 @@ struct srcpos { } while (0) -/* - * Fictional source position used for IR nodes that are - * created without otherwise knowing a true source position. - * For example,constant definitions from the command line. - */ -extern struct srcpos srcpos_empty; - extern void srcpos_update(struct srcpos *pos, const char *text, int len); extern struct srcpos *srcpos_copy(struct srcpos *pos); extern char *srcpos_string(struct srcpos *pos); From 43366bb4eeee868bf44f15be220e0b16d77ddd34 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 14 Nov 2018 16:13:30 +1100 Subject: [PATCH 0768/1198] tests: Property count valgrind errors in wrapped tests The logic in wrap_test() was effectively squashing valgrind errors into the "FAIL" bucket rather than their own bucket as intended. Correct it. Signed-off-by: David Gibson --- tests/run_tests.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index bc2cc77..547aedc 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -88,6 +88,9 @@ wrap_test () { if [ "$ret" -gt 127 ]; then signame=$(kill -l $((ret - 128))) FAIL "Killed by SIG$signame" + elif [ "$ret" -eq $VGCODE ]; then + echo "VALGRIND ERROR" + exit $VGCODE else FAIL "Returned error code $ret" fi From ca930e20bb54d823a90598f1f861a76bd18bc7c7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 14 Nov 2018 16:37:39 +1100 Subject: [PATCH 0769/1198] tests: Don't lose errors from make checkm For unclear reasons we had some code to copy a transcript of "make checkm" runs to a vglog.XXX file. It's not really clear why this was there, and it had the nasty side effect of discarding errors from run_tests.sh, meaning that an error on the valgrind run wouldn't show up clearly in Travis CI builds. Remove that logic so that we see errors more clearly. Signed-off-by: David Gibson --- tests/Makefile.tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index bd1c8ef..6ddf444 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -88,7 +88,7 @@ checkm: @echo "make checkm requires valgrind, but NO_VALGRIND=1" else checkm: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) - cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$ + cd $(TESTS_PREFIX); ./run_tests.sh -m endif checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) From 8e20ccf52f90ed7e5ee29f870c7ee8bd0854794c Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 16 Nov 2018 17:29:59 +0100 Subject: [PATCH 0770/1198] annotations: add positions Extend the parser to record positions, in build_node, build_node_delete, and build_property. srcpos structures are added to the property and node types, and to the parameter lists of the above functions that construct these types. Nodes and properties that are created by the compiler rather than from parsing source code have NULL as the srcpos value. merge_nodes, defined in livetree.c, uses srcpos_extend to combine multiple positions, resulting in a list of positions. srcpos_extend is defined in srcpos.c. New elements are added at the end. This requires the srcpos type, define in srcpos.h, to be a list structure with a next field. This next field is initialized to NULL in srcpos.h, in the macro YYLLOC_DEFAULT invoked implicitly by the generated parser code. Another change to srcpos.c is to make srcpos_copy always do a full copy, including a copy of the file substructure. This is required because when dtc is used on the output of cpp, the successive detected file names overwrite the file name in the file structure. The next field does not need to be deep copied, because it is always NULL when srcpos_copy is called; an assert checks for this. File names are only updated in uncopied position structures. Signed-off-by: Julia Lawall Signed-off-by: David Gibson --- dtc-parser.y | 13 ++++++++----- dtc.h | 10 +++++++--- flattree.c | 4 ++-- fstree.c | 5 +++-- livetree.c | 33 ++++++++++++++++++++++----------- srcpos.c | 22 ++++++++++++++++++++++ srcpos.h | 4 ++++ 7 files changed, 68 insertions(+), 23 deletions(-) diff --git a/dtc-parser.y b/dtc-parser.y index deda663..2ec981e 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -180,7 +180,10 @@ devicetree: */ if (!($-1 & DTSF_PLUGIN)) ERROR(&@2, "Label or path %s not found", $1); - $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1); + $$ = add_orphan_node( + name_node(build_node(NULL, NULL, NULL), + ""), + $2, $1); } | devicetree DT_LABEL dt_ref nodedef { @@ -260,7 +263,7 @@ devicetree: nodedef: '{' proplist subnodes '}' ';' { - $$ = build_node($2, $3); + $$ = build_node($2, $3, &@$); } ; @@ -278,11 +281,11 @@ proplist: propdef: DT_PROPNODENAME '=' propdata ';' { - $$ = build_property($1, $3); + $$ = build_property($1, $3, &@$); } | DT_PROPNODENAME ';' { - $$ = build_property($1, empty_data); + $$ = build_property($1, empty_data, &@$); } | DT_DEL_PROP DT_PROPNODENAME ';' { @@ -563,7 +566,7 @@ subnode: } | DT_DEL_NODE DT_PROPNODENAME ';' { - $$ = name_node(build_node_delete(), $2); + $$ = name_node(build_node_delete(&@$), $2); } | DT_OMIT_NO_REF subnode { diff --git a/dtc.h b/dtc.h index cbe5415..8722cbc 100644 --- a/dtc.h +++ b/dtc.h @@ -158,6 +158,7 @@ struct property { struct property *next; struct label *labels; + struct srcpos *srcpos; }; struct node { @@ -177,6 +178,7 @@ struct node { struct label *labels; const struct bus_type *bus; + struct srcpos *srcpos; bool omit_if_unused, is_referenced; }; @@ -205,13 +207,15 @@ 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(char *name, struct data val, + struct srcpos *srcpos); struct property *build_property_delete(char *name); struct property *chain_property(struct property *first, struct property *list); struct property *reverse_properties(struct property *first); -struct node *build_node(struct property *proplist, struct node *children); -struct node *build_node_delete(void); +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 *omit_node_if_unused(struct node *node); struct node *reference_node(struct node *node); diff --git a/flattree.c b/flattree.c index 851ea87..acf04c3 100644 --- a/flattree.c +++ b/flattree.c @@ -692,7 +692,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf, val = flat_read_data(dtbuf, proplen); - return build_property(name, val); + return build_property(name, val, NULL); } @@ -750,7 +750,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, char *flatname; uint32_t val; - node = build_node(NULL, NULL); + node = build_node(NULL, NULL, NULL); flatname = flat_read_string(dtbuf); diff --git a/fstree.c b/fstree.c index ae7d06c..1e7eeba 100644 --- a/fstree.c +++ b/fstree.c @@ -34,7 +34,7 @@ static struct node *read_fstree(const char *dirname) if (!d) die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno)); - tree = build_node(NULL, NULL); + tree = build_node(NULL, NULL, NULL); while ((de = readdir(d)) != NULL) { char *tmpname; @@ -60,7 +60,8 @@ static struct node *read_fstree(const char *dirname) } else { prop = build_property(xstrdup(de->d_name), data_copy_file(pfile, - st.st_size)); + st.st_size), + NULL); add_property(tree, prop); fclose(pfile); } diff --git a/livetree.c b/livetree.c index 4ff0679..7a2e644 100644 --- a/livetree.c +++ b/livetree.c @@ -19,6 +19,7 @@ */ #include "dtc.h" +#include "srcpos.h" /* * Tree building functions @@ -50,7 +51,8 @@ void delete_labels(struct label **labels) label->deleted = 1; } -struct property *build_property(char *name, struct data val) +struct property *build_property(char *name, struct data val, + struct srcpos *srcpos) { struct property *new = xmalloc(sizeof(*new)); @@ -58,6 +60,7 @@ struct property *build_property(char *name, struct data val) new->name = name; new->val = val; + new->srcpos = srcpos_copy(srcpos); return new; } @@ -97,7 +100,8 @@ struct property *reverse_properties(struct property *first) return head; } -struct node *build_node(struct property *proplist, struct node *children) +struct node *build_node(struct property *proplist, struct node *children, + struct srcpos *srcpos) { struct node *new = xmalloc(sizeof(*new)); struct node *child; @@ -106,6 +110,7 @@ struct node *build_node(struct property *proplist, struct node *children) new->proplist = reverse_properties(proplist); new->children = children; + new->srcpos = srcpos_copy(srcpos); for_each_child(new, child) { child->parent = new; @@ -114,13 +119,14 @@ struct node *build_node(struct property *proplist, struct node *children) return new; } -struct node *build_node_delete(void) +struct node *build_node_delete(struct srcpos *srcpos) { struct node *new = xmalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); new->deleted = 1; + new->srcpos = srcpos_copy(srcpos); return new; } @@ -183,6 +189,8 @@ 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); + old_prop->srcpos = new_prop->srcpos; free(new_prop); new_prop = NULL; break; @@ -223,6 +231,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) add_child(old_node, new_child); } + old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos); + /* The new node contents are now merged into the old node. Free * the new node. */ free(new_node); @@ -241,18 +251,18 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) if (ref[0] == '/') { d = data_append_data(d, ref, strlen(ref) + 1); - p = build_property("target-path", d); + p = build_property("target-path", d, NULL); } else { d = data_add_marker(d, REF_PHANDLE, ref); d = data_append_integer(d, 0xffffffff, 32); - p = build_property("target", d); + p = build_property("target", d, NULL); } xasprintf(&name, "fragment@%u", next_orphan_fragment++); name_node(new_node, "__overlay__"); - node = build_node(p, new_node); + node = build_node(p, new_node, NULL); name_node(node, name); add_child(dt, node); @@ -351,7 +361,7 @@ void append_to_property(struct node *node, p->val = d; } else { d = data_append_data(empty_data, data, len); - p = build_property(name, d); + p = build_property(name, d, NULL); add_property(node, p); } } @@ -609,11 +619,11 @@ cell_t get_node_phandle(struct node *root, struct node *node) if (!get_property(node, "linux,phandle") && (phandle_format & PHANDLE_LEGACY)) - add_property(node, build_property("linux,phandle", d)); + 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)); + add_property(node, build_property("phandle", d, NULL)); /* If the node *does* have a phandle property, we must * be dealing with a self-referencing phandle, which will be @@ -787,7 +797,7 @@ static struct node *build_and_name_child_node(struct node *parent, char *name) { struct node *node; - node = build_node(NULL, NULL); + node = build_node(NULL, NULL, NULL); name_node(node, xstrdup(name)); add_child(parent, node); @@ -849,7 +859,8 @@ static void generate_label_tree_internal(struct dt_info *dti, /* insert it */ p = build_property(l->label, data_copy_mem(node->fullpath, - strlen(node->fullpath) + 1)); + strlen(node->fullpath) + 1), + NULL); add_property(an, p); } diff --git a/srcpos.c b/srcpos.c index ea82d88..77b50c9 100644 --- a/srcpos.c +++ b/srcpos.c @@ -222,13 +222,35 @@ struct srcpos * srcpos_copy(struct srcpos *pos) { struct srcpos *pos_new; + struct srcfile_state *srcfile_state; + + if (!pos) + return NULL; pos_new = xmalloc(sizeof(struct srcpos)); + assert(pos->next == NULL); memcpy(pos_new, pos, sizeof(struct srcpos)); + /* allocate without free */ + srcfile_state = xmalloc(sizeof(struct srcfile_state)); + memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state)); + pos_new->file = srcfile_state; + return pos_new; } +struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail) +{ + struct srcpos *p; + + if (!pos) + return newtail; + + for (p = pos; p->next != NULL; p = p->next); + p->next = newtail; + return pos; +} + char * srcpos_string(struct srcpos *pos) { diff --git a/srcpos.h b/srcpos.h index 1c74efd..8dc118f 100644 --- a/srcpos.h +++ b/srcpos.h @@ -74,6 +74,7 @@ struct srcpos { int last_line; int last_column; struct srcfile_state *file; + struct srcpos *next; }; #define YYLTYPE struct srcpos @@ -93,11 +94,14 @@ struct srcpos { YYRHSLOC(Rhs, 0).last_column; \ (Current).file = YYRHSLOC (Rhs, 0).file; \ } \ + (Current).next = NULL; \ } while (0) 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 char *srcpos_string(struct srcpos *pos); extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix, From 5667e7ef9a9a30c54a572ae976ed5b65ccf24d8b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 16 Nov 2018 17:30:00 +0100 Subject: [PATCH 0771/1198] annotations: add the annotation functionality Provide the new command-line option: --annotate (abbreviated -T) --annotate provides one or more filenames and line numbers indicating the origin of a given line. The filename is expressed relative the the filename provided on the command line. Nothing is printed for overlays, etc. -T can be repeated giving more verbose annotations. These consist of one or more tuples of: filename, starting line, starting column, ending line ending column. The full path is given for the file name. Overlays, etc are annotated with :. The verbose annotations may be too verbose for normal use. There are numerous changes in srcpos.c to provide the relative filenames (variables initial_path, initial_pathlen and initial_cpp, new functions set_initial_path and shorten_to_initial_path, and changes in srcfile_push and srcpos_set_line). The change in srcpos_set_line takes care of the case where cpp is used as a preprocessor. In that case the initial file name is not the one provided on the command line but the one found at the beginnning of the cpp output. shorten_to_initial_path only returns a string if it has some shortening to do. Otherwise it returns NULL and relies on the caller to use the initial string. This simplifies memory management, by making clear to the caller whether a new string is allocated. The new functions srcpos_string_comment, srcpos_string_first, and srcpos_string_last print the annotations. srcpos_string_comment is recursive to print a list of source file positions. Various changes are sprinkled throughout treesource.c to print the annotations. Signed-off-by: Julia Lawall Signed-off-by: David Gibson --- dtc.c | 11 ++++- dtc.h | 1 + srcpos.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++-- srcpos.h | 3 ++ treesource.c | 46 +++++++++++++++++--- 5 files changed, 170 insertions(+), 10 deletions(-) diff --git a/dtc.c b/dtc.c index 64134aa..695e1f7 100644 --- a/dtc.c +++ b/dtc.c @@ -35,6 +35,8 @@ 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 */ int auto_label_aliases; /* auto generate labels -> aliases */ +int annotate; /* Level of annotation: 1 for input source location + >1 for full input source location. */ static int is_power_of_2(int x) { @@ -60,7 +62,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:@Ahv"; +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv"; static struct option const usage_long_opts[] = { {"quiet", no_argument, NULL, 'q'}, {"in-format", a_argument, NULL, 'I'}, @@ -81,6 +83,7 @@ static struct option const usage_long_opts[] = { {"error", a_argument, NULL, 'E'}, {"symbols", no_argument, NULL, '@'}, {"auto-alias", no_argument, NULL, 'A'}, + {"annotate", no_argument, NULL, 'T'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {NULL, no_argument, NULL, 0x0}, @@ -117,6 +120,7 @@ static const char * const usage_opts_help[] = { "\n\tEnable/disable errors (prefix with \"no-\")", "\n\tEnable generation of symbols", "\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", "\n\tPrint version and exit", NULL, @@ -264,6 +268,9 @@ int main(int argc, char *argv[]) case 'A': auto_label_aliases = 1; break; + case 'T': + annotate++; + break; case 'h': usage(NULL); @@ -302,6 +309,8 @@ int main(int argc, char *argv[]) outform = "dts"; } } + if (annotate && (!streq(inform, "dts") || !streq(outform, "dts"))) + die("--annotate requires -I dts -O dts\n"); if (streq(inform, "dts")) dti = dt_from_source(arg); else if (streq(inform, "fs")) diff --git a/dtc.h b/dtc.h index 8722cbc..789e0b1 100644 --- a/dtc.h +++ b/dtc.h @@ -58,6 +58,7 @@ 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 */ extern int auto_label_aliases; /* auto generate labels -> aliases */ +extern int annotate; /* annotate .dts with input source location */ #define PHANDLE_LEGACY 0x1 #define PHANDLE_EPAPR 0x2 diff --git a/srcpos.c b/srcpos.c index 77b50c9..41f8370 100644 --- a/srcpos.c +++ b/srcpos.c @@ -33,6 +33,9 @@ struct search_path { /* This is the list of directories that we search for source files */ static struct search_path *search_path_head, **search_path_tail; +/* Detect infinite include recursion. */ +#define MAX_SRCFILE_DEPTH (100) +static int srcfile_depth; /* = 0 */ static char *get_dirname(const char *path) { @@ -51,11 +54,51 @@ static char *get_dirname(const char *path) FILE *depfile; /* = NULL */ struct srcfile_state *current_srcfile; /* = NULL */ +static char *initial_path; /* = NULL */ +static int initial_pathlen; /* = 0 */ +static bool initial_cpp = true; -/* Detect infinite include recursion. */ -#define MAX_SRCFILE_DEPTH (100) -static int srcfile_depth; /* = 0 */ +static void set_initial_path(char *fname) +{ + int i, len = strlen(fname); + xasprintf(&initial_path, "%s", fname); + initial_pathlen = 0; + for (i = 0; i != len; i++) + if (initial_path[i] == '/') + initial_pathlen++; +} + +static char *shorten_to_initial_path(char *fname) +{ + char *p1, *p2, *prevslash1 = NULL; + int slashes = 0; + + for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) { + if (*p1 != *p2) + break; + if (*p1 == '/') { + prevslash1 = p1; + slashes++; + } + } + p1 = prevslash1 + 1; + if (prevslash1) { + int diff = initial_pathlen - slashes, i, j; + int restlen = strlen(fname) - (p1 - fname); + char *res; + + res = xmalloc((3 * diff) + restlen + 1); + for (i = 0, j = 0; i != diff; i++) { + res[j++] = '.'; + res[j++] = '.'; + res[j++] = '/'; + } + strcpy(res + j, p1); + return res; + } + return NULL; +} /** * Try to open a file in a given directory. @@ -157,6 +200,9 @@ void srcfile_push(const char *fname) srcfile->colno = 1; current_srcfile = srcfile; + + if (srcfile_depth == 1) + set_initial_path(srcfile->name); } bool srcfile_pop(void) @@ -276,6 +322,68 @@ srcpos_string(struct srcpos *pos) return pos_str; } +static char * +srcpos_string_comment(struct srcpos *pos, bool first_line, int level) +{ + char *pos_str, *fname, *first, *rest; + bool fresh_fname = false; + + if (!pos) { + if (level > 1) { + xasprintf(&pos_str, ":"); + return pos_str; + } else { + return NULL; + } + } + + if (!pos->file) + fname = ""; + else if (!pos->file->name) + fname = ""; + else if (level > 1) + fname = pos->file->name; + else { + fname = shorten_to_initial_path(pos->file->name); + if (fname) + fresh_fname = true; + else + fname = pos->file->name; + } + + if (level > 1) + xasprintf(&first, "%s:%d:%d-%d:%d", fname, + pos->first_line, pos->first_column, + pos->last_line, pos->last_column); + else + xasprintf(&first, "%s:%d", fname, + first_line ? pos->first_line : pos->last_line); + + if (fresh_fname) + free(fname); + + if (pos->next != NULL) { + rest = srcpos_string_comment(pos->next, first_line, level); + xasprintf(&pos_str, "%s, %s", first, rest); + free(first); + free(rest); + } else { + pos_str = first; + } + + return pos_str; +} + +char *srcpos_string_first(struct srcpos *pos, int level) +{ + return srcpos_string_comment(pos, true, level); +} + +char *srcpos_string_last(struct srcpos *pos, int level) +{ + return srcpos_string_comment(pos, false, level); +} + void srcpos_verror(struct srcpos *pos, const char *prefix, const char *fmt, va_list va) { @@ -304,4 +412,9 @@ void srcpos_set_line(char *f, int l) { current_srcfile->name = f; current_srcfile->lineno = l; + + if (initial_cpp) { + initial_cpp = false; + set_initial_path(f); + } } diff --git a/srcpos.h b/srcpos.h index 8dc118f..6326a95 100644 --- a/srcpos.h +++ b/srcpos.h @@ -103,6 +103,9 @@ extern struct srcpos *srcpos_copy(struct srcpos *pos); extern struct srcpos *srcpos_extend(struct srcpos *new_srcpos, struct srcpos *old_srcpos); 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); + extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix, const char *fmt, va_list va); diff --git a/treesource.c b/treesource.c index 1529a0a..1af3662 100644 --- a/treesource.c +++ b/treesource.c @@ -214,9 +214,18 @@ static void write_propval(FILE *f, struct property *prop) struct marker *m = prop->val.markers; struct marker dummy_marker; enum markertype emit_type = TYPE_NONE; + char *srcstr; if (len == 0) { - fprintf(f, ";\n"); + fprintf(f, ";"); + if (annotate) { + srcstr = srcpos_string_first(prop->srcpos, annotate); + if (srcstr) { + fprintf(f, " /* %s */", srcstr); + free(srcstr); + } + } + fprintf(f, "\n"); return; } @@ -273,7 +282,15 @@ static void write_propval(FILE *f, struct property *prop) emit_type = TYPE_NONE; } } - fprintf(f, ";\n"); + fprintf(f, ";"); + if (annotate) { + srcstr = srcpos_string_first(prop->srcpos, annotate); + if (srcstr) { + fprintf(f, " /* %s */", srcstr); + free(srcstr); + } + } + fprintf(f, "\n"); } static void write_tree_source_node(FILE *f, struct node *tree, int level) @@ -281,14 +298,24 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) struct property *prop; struct node *child; struct label *l; + char *srcstr; write_prefix(f, level); for_each_label(tree->labels, l) fprintf(f, "%s: ", l->label); if (tree->name && (*tree->name)) - fprintf(f, "%s {\n", tree->name); + fprintf(f, "%s {", tree->name); else - fprintf(f, "/ {\n"); + fprintf(f, "/ {"); + + if (annotate) { + srcstr = srcpos_string_first(tree->srcpos, annotate); + if (srcstr) { + fprintf(f, " /* %s */", srcstr); + free(srcstr); + } + } + fprintf(f, "\n"); for_each_property(tree, prop) { write_prefix(f, level+1); @@ -302,10 +329,17 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) write_tree_source_node(f, child, level+1); } write_prefix(f, level); - fprintf(f, "};\n"); + fprintf(f, "};"); + if (annotate) { + srcstr = srcpos_string_last(tree->srcpos, annotate); + if (srcstr) { + fprintf(f, " /* %s */", srcstr); + free(srcstr); + } + } + fprintf(f, "\n"); } - void dt_to_source(FILE *f, struct dt_info *dti) { struct reserve_info *re; From 86a288a7367086bb8dad60ea293811d62f59671b Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 21 Nov 2018 15:53:57 -0600 Subject: [PATCH 0772/1198] checks: Restructure check_msg to decrease indentation The entire check_msg function is under the if condition except for va_start/va_end. Move these and invert the if condition saving a level of indentation. Signed-off-by: Rob Herring Signed-off-by: David Gibson --- checks.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/checks.c b/checks.c index ed84e03..4d8dffd 100644 --- a/checks.c +++ b/checks.c @@ -78,23 +78,23 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); - if ((c->warn && (quiet < 1)) - || (c->error && (quiet < 2))) { - fprintf(stderr, "%s: %s (%s): ", - strcmp(dti->outname, "-") ? dti->outname : "", - (c->error) ? "ERROR" : "Warning", c->name); - if (node) { - fprintf(stderr, "%s", node->fullpath); - if (prop) - fprintf(stderr, ":%s", prop->name); - fputs(": ", stderr); - } - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2))) + return; + + fprintf(stderr, "%s: %s (%s): ", + strcmp(dti->outname, "-") ? dti->outname : "", + (c->error) ? "ERROR" : "Warning", c->name); + if (node) { + fprintf(stderr, "%s", node->fullpath); + if (prop) + fprintf(stderr, ":%s", prop->name); + fputs(": ", stderr); } + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); va_end(ap); + fprintf(stderr, "\n"); } #define FAIL(c, dti, node, ...) \ From 11738cf01f150afae913b88fb68675a272803d63 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 19 Nov 2018 16:36:15 +1100 Subject: [PATCH 0773/1198] libfdt: Don't use memcpy to handle unaligned reads on ARM 6dcb8ba4 "libfdt: Add helpers for accessing unaligned words" introduced the fdt32_ld() and fdt64_ld() helpers for loading values from the FDT blob which might not be naturally aligned. This matters for ARM, where attempting a plain unaligned load will often cause an exception. However, it seems the memcpy() we used here was surprisingly expensive, making libfdt nearly 6x slower on at least some ARM platforms. This patch takes an alternative approach, using a bunch of 1-byte loads and shifts to implement the helpers. Signed-off-by: David Gibson --- libfdt/libfdt.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index face02c..fdaa3e6 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -163,18 +163,26 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); static inline uint32_t fdt32_ld(const fdt32_t *p) { - fdt32_t v; + const uint8_t *bp = (const uint8_t *)p; - memcpy(&v, p, sizeof(v)); - return fdt32_to_cpu(v); + return ((uint32_t)bp[0] << 24) + | ((uint32_t)bp[1] << 16) + | ((uint32_t)bp[2] << 8) + | bp[3]; } static inline uint64_t fdt64_ld(const fdt64_t *p) { - fdt64_t v; + const uint8_t *bp = (const uint8_t *)p; - memcpy(&v, p, sizeof(v)); - return fdt64_to_cpu(v); + 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]; } /**********************************************************************/ From 8113c00b99d303c8073a2493f6b8978600e54967 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Mon, 9 Jul 2018 12:38:59 +0200 Subject: [PATCH 0774/1198] pylibfdt: Allow switch to Python 3 via environment variable PYTHON Python 2 is still the default but it can be changed by setting environment variable PYTHON before build/test. Signed-off-by: Lumir Balhar Signed-off-by: David Gibson --- Makefile | 3 ++- pylibfdt/Makefile.pylibfdt | 4 ++-- tests/Makefile.tests | 6 +++--- tests/run_tests.sh | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 7a472b7..d9495f0 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ BISON = bison LEX = flex SWIG = swig PKG_CONFIG ?= pkg-config +PYTHON ?= python2 INSTALL = /usr/bin/install INSTALL_PROGRAM = $(INSTALL) @@ -147,7 +148,7 @@ 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 python2 >/dev/null 2>&1; then \ + if $(PKG_CONFIG) --cflags $(PYTHON) >/dev/null 2>&1; then \ if which swig >/dev/null 2>&1; then \ can_build=yes; \ fi; \ diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 8f00b3d..f6abe02 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -13,10 +13,10 @@ endif $(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE) @$(VECHO) PYMOD $@ - $(SETUP) $(SETUPFLAGS) build_ext --build-lib=../$(PYLIBFDT_objdir) + $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=../$(PYLIBFDT_objdir) install_pylibfdt: $(PYMODULE) @$(VECHO) INSTALL-PYLIB - $(SETUP) $(SETUPFLAGS) install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX)) + $(PYTHON) $(SETUP) $(SETUPFLAGS) install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX)) PYLIBFDT_cleanfiles = libfdt_wrap.c libfdt.py libfdt.pyc _libfdt.so diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 6ddf444..8b63f60 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -81,18 +81,18 @@ tests_clean: rm -rf $(TESTS_CLEANDIRS) check: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) - cd $(TESTS_PREFIX); ./run_tests.sh + cd $(TESTS_PREFIX); PYTHON=$(PYTHON) ./run_tests.sh ifeq ($(NO_VALGRIND),1) checkm: @echo "make checkm requires valgrind, but NO_VALGRIND=1" else checkm: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) - cd $(TESTS_PREFIX); ./run_tests.sh -m + cd $(TESTS_PREFIX); PYTHON=$(PYTHON) ./run_tests.sh -m endif checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) - cd $(TESTS_PREFIX); ./run_tests.sh -v + cd $(TESTS_PREFIX); PYTHON=$(PYTHON) ./run_tests.sh -v ifneq ($(DEPTARGETS),) -include $(TESTS_DEPFILES) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 547aedc..23e6176 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -933,7 +933,7 @@ fdtoverlay_tests() { pylibfdt_tests () { run_dtc_test -I dts -O dtb -o test_props.dtb test_props.dts TMP=/tmp/tests.stderr.$$ - python pylibfdt_tests.py -v 2> $TMP + $PYTHON pylibfdt_tests.py -v 2> $TMP # Use the 'ok' message meaning the test passed, 'ERROR' meaning it failed # and the summary line for total tests (e.g. 'Ran 17 tests in 0.002s'). From 08380fc43aa2dd7e01b65bd87e8b20519db0d397 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 23 Nov 2018 17:47:41 +1100 Subject: [PATCH 0775/1198] tests: Use modern octal literals for Python Python3 removes support for C-style octal literals, using 0oXXXX instead. Python2 also supports this form, so move to the new style. Reported-by: Lumir Balhar Signed-off-by: David Gibson --- tests/pylibfdt_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index fbb1ce2..34c680d 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -69,7 +69,7 @@ TEST_ADDR_2H = 0 TEST_ADDR_2L = 123456789 TEST_ADDR_2 = (TEST_ADDR_2H << 32) | TEST_ADDR_2L TEST_SIZE_2H = 0 -TEST_SIZE_2L = 010000 +TEST_SIZE_2L = 0o10000 TEST_SIZE_2 = (TEST_SIZE_2H << 32) | TEST_SIZE_2L TEST_VALUE_1 = 0xdeadbeef @@ -422,7 +422,7 @@ class PyLibfdtBasicTests(unittest.TestCase): self.assertEquals(2, self.fdt.num_mem_rsv()) self.assertEquals([ 0xdeadbeef00000000, 0x100000], self.fdt.get_mem_rsv(0)) - self.assertEquals([123456789, 010000], self.fdt.get_mem_rsv(1)) + self.assertEquals([123456789, 0o10000], self.fdt.get_mem_rsv(1)) def testEmpty(self): """Test that we can create an empty tree""" From a4629cfaedfbcab98619757554f0636de06e25e2 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 23 Nov 2018 21:11:47 +1100 Subject: [PATCH 0776/1198] Refine libfdt_clean target Move it to the libfdt Makefile piece, use neater make syntax, and remove redundant command (already included in STD_CLEANFILES). Signed-off-by: David Gibson --- Makefile | 5 ----- libfdt/Makefile.libfdt | 4 ++++ 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index d9495f0..0edd9e4 100644 --- a/Makefile +++ b/Makefile @@ -197,11 +197,6 @@ libfdt: $(LIBFDT_archive) $(LIBFDT_lib) $(LIBFDT_archive): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) $(LIBFDT_lib): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) -libfdt_clean: - @$(VECHO) CLEAN "(libfdt)" - rm -f $(addprefix $(LIBFDT_objdir)/,$(STD_CLEANFILES)) - rm -f $(LIBFDT_objdir)/*.so - ifneq ($(DEPTARGETS),) -include $(LIBFDT_OBJS:%.o=$(LIBFDT_objdir)/%.d) endif diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index 098b3f3..9ec8e2d 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -9,3 +9,7 @@ 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 LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) + +libfdt_clean: + @$(VECHO) CLEAN "(libfdt)" + rm -f $(STD_CLEANFILES:%=$(LIBFDT_objdir)/%) From 99284c4db9cbb5a8d2f0c8d16fd8490b1ea19bea Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 23 Nov 2018 21:24:44 +1100 Subject: [PATCH 0777/1198] Refine pylibfdt_clean target Move it to the subdir Makefile, generalize some of the patterns, remove the 'build' directory made by setup.py and __pycache__ directory made by Python3. Signed-off-by: David Gibson --- Makefile | 4 ---- pylibfdt/Makefile.pylibfdt | 9 ++++++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 0edd9e4..4de1d81 100644 --- a/Makefile +++ b/Makefile @@ -271,10 +271,6 @@ include $(PYLIBFDT_srcdir)/Makefile.pylibfdt .PHONY: pylibfdt pylibfdt: $(PYLIBFDT_objdir)/_libfdt.so -pylibfdt_clean: - @$(VECHO) CLEAN "(pylibfdt)" - rm -f $(addprefix $(PYLIBFDT_objdir)/,$(PYLIBFDT_cleanfiles)) - # # Release signing and uploading # This is for maintainer convenience, don't try this at home. diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index f6abe02..ae8d0c8 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -3,6 +3,10 @@ PYLIBFDT_srcs = $(PYLIBFDT_srcdir)/libfdt.i PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so +PYLIBFDT_CLEANFILES_L = libfdt_wrap.c libfdt.py *.pyc *.so +PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_objdir)/%) +PYLIBFDT_CLEANDIRS_L = build __pycache__ +PYLIBFDT_CLEANDIRS = $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_objdir)/%) SETUP = $(PYLIBFDT_srcdir)/setup.py SETUPFLAGS = @@ -19,4 +23,7 @@ install_pylibfdt: $(PYMODULE) @$(VECHO) INSTALL-PYLIB $(PYTHON) $(SETUP) $(SETUPFLAGS) install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX)) -PYLIBFDT_cleanfiles = libfdt_wrap.c libfdt.py libfdt.pyc _libfdt.so +pylibfdt_clean: + @$(VECHO) CLEAN "(pylibfdt)" + rm -f $(PYLIBFDT_CLEANFILES) + rm -rf $(PYLIBFDT_CLEANDIRS) From d45bf1f5f2a6b8e46c5c600dc5879ff4662344d8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 23 Nov 2018 21:33:28 +1100 Subject: [PATCH 0778/1198] Refine make tests_clean target Remove some redundancy, and also clean up *.test.dt.yaml files generated during the tests. Also add the latter to gitignore. Signed-off-by: David Gibson --- tests/.gitignore | 1 + tests/Makefile.tests | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/.gitignore b/tests/.gitignore index 70a8c95..dfa3bd1 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,6 +1,7 @@ *.dtb *.dts.test.s *.test.dts +*.test.dt.yaml tmp.* /fs/ /add_subnode_with_nops diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 8b63f60..aabc906 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -47,8 +47,9 @@ TESTS_TARGETS = $(TESTS) $(TESTS_TREES) TESTS_DEPFILES = $(TESTS:%=%.d) \ $(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d) -TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts *.dtsv1 tmp.* -TESTS_CLEANFILES_L += dumptrees +TESTS_CLEANFILES_L = $(STD_CLEANFILES) \ + *.dtb *.test.dts *.test.dt.yaml *.dtsv1 tmp.* \ + dumptrees TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) TESTS_CLEANDIRS_L = fs TESTS_CLEANDIRS = $(TESTS_CLEANDIRS_L:%=$(TESTS_PREFIX)%) @@ -76,7 +77,6 @@ $(TESTS_TREES): $(TESTS_PREFIX)dumptrees tests_clean: @$(VECHO) CLEAN "(tests)" - rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%) rm -f $(TESTS_CLEANFILES) rm -rf $(TESTS_CLEANDIRS) @@ -97,4 +97,3 @@ checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) ifneq ($(DEPTARGETS),) -include $(TESTS_DEPFILES) endif - From 5182b5e6f28cbe3563ed058988801b90a97b6b70 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 23 Nov 2018 21:51:35 +1100 Subject: [PATCH 0779/1198] pylibfdt: Use common PREFIX variable For no particularly good reason, the install target for the Python library uses a different PREFIX variable to give the installation destination to the rest of dtc & libfdt. Make it use the same one. 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 ae8d0c8..41256fc 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -21,7 +21,7 @@ $(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE) install_pylibfdt: $(PYMODULE) @$(VECHO) INSTALL-PYLIB - $(PYTHON) $(SETUP) $(SETUPFLAGS) install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX)) + $(PYTHON) $(SETUP) $(SETUPFLAGS) install --prefix=$(PREFIX) pylibfdt_clean: @$(VECHO) CLEAN "(pylibfdt)" From f9c0a425b64817ba91563a84d9a7ea9033e3c14f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 23 Nov 2018 21:58:42 +1100 Subject: [PATCH 0780/1198] Remove broken objdir / srcdir support The dtc makefiles have support for building into a separate directory from the sources... except that it's broken and probably always has been. Remove the pretense. Signed-off-by: David Gibson --- Makefile | 26 ++++++++++++-------------- libfdt/Makefile.libfdt | 2 +- pylibfdt/Makefile.pylibfdt | 12 ++++++------ 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index 4de1d81..8c9e326 100644 --- a/Makefile +++ b/Makefile @@ -182,23 +182,22 @@ endif # # Rules for libfdt # -LIBFDT_objdir = libfdt -LIBFDT_srcdir = libfdt -LIBFDT_archive = $(LIBFDT_objdir)/libfdt.a -LIBFDT_lib = $(LIBFDT_objdir)/libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) -LIBFDT_include = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES)) -LIBFDT_version = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_VERSION)) +LIBFDT_dir = libfdt +LIBFDT_archive = $(LIBFDT_dir)/libfdt.a +LIBFDT_lib = $(LIBFDT_dir)/libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) +LIBFDT_include = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_INCLUDES)) +LIBFDT_version = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_VERSION)) -include $(LIBFDT_srcdir)/Makefile.libfdt +include $(LIBFDT_dir)/Makefile.libfdt .PHONY: libfdt libfdt: $(LIBFDT_archive) $(LIBFDT_lib) -$(LIBFDT_archive): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) -$(LIBFDT_lib): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) +$(LIBFDT_archive): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) +$(LIBFDT_lib): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) ifneq ($(DEPTARGETS),) --include $(LIBFDT_OBJS:%.o=$(LIBFDT_objdir)/%.d) +-include $(LIBFDT_OBJS:%.o=$(LIBFDT_dir)/%.d) endif # This stops make from generating the lex and bison output during @@ -263,13 +262,12 @@ dist: # # Rules for pylibfdt # -PYLIBFDT_srcdir = pylibfdt -PYLIBFDT_objdir = pylibfdt +PYLIBFDT_dir = pylibfdt -include $(PYLIBFDT_srcdir)/Makefile.pylibfdt +include $(PYLIBFDT_dir)/Makefile.pylibfdt .PHONY: pylibfdt -pylibfdt: $(PYLIBFDT_objdir)/_libfdt.so +pylibfdt: $(PYLIBFDT_dir)/_libfdt.so # # Release signing and uploading diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index 9ec8e2d..3af3656 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -12,4 +12,4 @@ LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) libfdt_clean: @$(VECHO) CLEAN "(libfdt)" - rm -f $(STD_CLEANFILES:%=$(LIBFDT_objdir)/%) + rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 41256fc..3dfe05a 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -1,14 +1,14 @@ # Makefile.pylibfdt # -PYLIBFDT_srcs = $(PYLIBFDT_srcdir)/libfdt.i -PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so +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_objdir)/%) +PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%) PYLIBFDT_CLEANDIRS_L = build __pycache__ -PYLIBFDT_CLEANDIRS = $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_objdir)/%) +PYLIBFDT_CLEANDIRS = $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%) -SETUP = $(PYLIBFDT_srcdir)/setup.py +SETUP = $(PYLIBFDT_dir)/setup.py SETUPFLAGS = ifndef V @@ -17,7 +17,7 @@ endif $(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE) @$(VECHO) PYMOD $@ - $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=../$(PYLIBFDT_objdir) + $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=../$(PYLIBFDT_dir) install_pylibfdt: $(PYMODULE) @$(VECHO) INSTALL-PYLIB From 607b8586b3837f60221c0da2af4f5333a34e50cc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 23 Nov 2018 22:11:33 +1100 Subject: [PATCH 0781/1198] PEP8 / Flake8 cleanups for setup.py Signed-off-by: David Gibson --- pylibfdt/setup.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py index bd8ccf8..9e84359 100755 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -21,21 +21,22 @@ def get_version(): 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'], - libraries = ['fdt'], - library_dirs = ['../libfdt'], - swig_opts = ['-I../libfdt'], + sources=['libfdt.i'], + include_dirs=['../libfdt'], + libraries=['fdt'], + library_dirs=['../libfdt'], + swig_opts=['-I../libfdt'], ) setup( name='libfdt', - version= get_version(), + version=get_version(), author='Simon Glass ', description='Python binding for libfdt', ext_modules=[libfdt_module], From 82a52ce4573b7cd0039786f65b280fb99431fe5d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 22 Nov 2018 13:15:06 -0700 Subject: [PATCH 0782/1198] libfdt: Add a test for fdt_getprop_by_offset() This function does not have its own test at present. Add one. Signed-off-by: Simon Glass Signed-off-by: David Gibson --- tests/.gitignore | 1 + tests/Makefile.tests | 2 +- tests/get_prop_offset.c | 56 +++++++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 1 + tests/tests.h | 10 ++++++++ tests/testutils.c | 25 ++++++++++++++++++ 6 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 tests/get_prop_offset.c diff --git a/tests/.gitignore b/tests/.gitignore index dfa3bd1..12af438 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -28,6 +28,7 @@ tmp.* /get_path /get_phandle /getprop +/get_prop_offset /incbin /integer-expressions /fs_tree1 diff --git a/tests/Makefile.tests b/tests/Makefile.tests index aabc906..b02d8bf 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -1,6 +1,6 @@ LIB_TESTS_L = get_mem_rsv \ root_node find_property subnode_offset path_offset \ - get_name getprop get_phandle \ + get_name getprop get_prop_offset get_phandle \ get_path supernode_atdepth_offset parent_offset \ node_offset_by_prop_value node_offset_by_phandle \ node_check_compatible node_offset_by_compatible \ diff --git a/tests/get_prop_offset.c b/tests/get_prop_offset.c new file mode 100644 index 0000000..3daef74 --- /dev/null +++ b/tests/get_prop_offset.c @@ -0,0 +1,56 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_getprop_by_offset() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + bool found_prop_int = false; + bool found_prop_str = false; + int poffset; + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + fdt_for_each_property_offset(poffset, fdt, 0) { + if (check_get_prop_offset_cell(fdt, poffset, "prop-int", + TEST_VALUE_1)) + found_prop_int = true; + if (check_get_prop_offset(fdt, poffset, "prop-str", + strlen(TEST_STRING_1) + 1, + TEST_STRING_1)) + found_prop_str = true; + } + if (!found_prop_int) + FAIL("Property 'prop-int' not found"); + if (!found_prop_str) + FAIL("Property 'prop-str' not found"); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 23e6176..ca3fc86 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -303,6 +303,7 @@ tree1_tests () { run_test path_offset $TREE run_test get_name $TREE run_test getprop $TREE + run_test get_prop_offset $TREE run_test get_phandle $TREE run_test get_path $TREE run_test supernode_atdepth_offset $TREE diff --git a/tests/tests.h b/tests/tests.h index b7daa26..dc8120e 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -118,6 +118,16 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name, }) #define check_getprop_string(fdt, nodeoffset, name, s) \ check_getprop((fdt), (nodeoffset), (name), strlen(s)+1, (s)) + +/* Returns non-NULL if the property at poffset has the name in_name */ +const void *check_get_prop_offset(void *fdt, int poffset, const char *in_name, + int in_len, const void *in_val); +#define check_get_prop_offset_cell(fdt, poffset, name, val) \ + ({ \ + fdt32_t x = cpu_to_fdt32(val); \ + check_get_prop_offset(fdt, poffset, name, sizeof(x), &x); \ + }) + int nodename_eq(const char *s1, const char *s2); void vg_prepare_blob(void *fdt, size_t bufsize); void *load_blob(const char *filename); diff --git a/tests/testutils.c b/tests/testutils.c index 0217b02..bbfda90 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -160,6 +160,31 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name, return propval; } +const void *check_get_prop_offset(void *fdt, int poffset, const char *exp_name, + int exp_len, const void *exp_val) +{ + const void *propval; + const char *name; + int proplen; + + propval = fdt_getprop_by_offset(fdt, poffset, &name, &proplen); + if (!propval) + FAIL("fdt_getprop(\"%s\"): %s", name, fdt_strerror(proplen)); + + /* Not testing for this field, so ignore */ + if (strcmp(name, exp_name)) + return NULL; + + if (proplen != exp_len) + FAIL("Size mismatch on property \"%s\": %d insead of %d", + name, proplen, exp_len); + if (exp_len && memcmp(exp_val, propval, exp_len)) + FAIL("Data mismatch on property \"%s\"", name); + + return propval; +} + + int nodename_eq(const char *s1, const char *s2) { int len = strlen(s2); From a1eff70c02cfd3a6263adfd6aab25290211f31aa Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Sat, 24 Nov 2018 14:47:54 -0600 Subject: [PATCH 0783/1198] util: Add xa{v}sprintf_append functions Add variadic and va_list functions, xa{v}sprintf, which appends a formatted string to an existing string and re-allocate the string buffer if necessary. xasprintf becomes just a special case of xasprintf_append with a NULL starting string. Rather than looping to get a big enough buffer, simply the implementation by assuming we have a C99 compliant vsnprintf implementation to return the necessary size. A side effect is glibc 2.0 support is dropped which seems unnecessary. Signed-off-by: Rob Herring Signed-off-by: David Gibson --- util.c | 60 ++++++++++++++++++++++++++++++++++++++-------------------- util.h | 2 ++ 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/util.c b/util.c index a69b7a1..9c6fb5f 100644 --- a/util.c +++ b/util.c @@ -46,36 +46,54 @@ char *xstrdup(const char *s) return d; } -/* based in part from (3) vsnprintf */ -int xasprintf(char **strp, const char *fmt, ...) +int xavsprintf_append(char **strp, const char *fmt, va_list ap) { - int n, size = 128; /* start with 128 bytes */ + int n, size = 0; /* start with 128 bytes */ char *p; - va_list ap; + va_list ap_copy; - /* initial pointer is NULL making the fist realloc to be malloc */ - p = NULL; - while (1) { - p = xrealloc(p, size); + p = *strp; + if (p) + size = strlen(p); - /* Try to print in the allocated space. */ - va_start(ap, fmt); - n = vsnprintf(p, size, fmt, ap); - va_end(ap); + va_copy(ap_copy, ap); + n = vsnprintf(NULL, 0, fmt, ap_copy) + 1; + va_end(ap_copy); + + p = xrealloc(p, size + n); + + n = vsnprintf(p + size, n, fmt, ap); - /* If that worked, return the string. */ - if (n > -1 && n < size) - break; - /* Else try again with more space. */ - if (n > -1) /* glibc 2.1 */ - size = n + 1; /* precisely what is needed */ - else /* glibc 2.0 */ - size *= 2; /* twice the old size */ - } *strp = p; return strlen(p); } +int xasprintf_append(char **strp, const char *fmt, ...) +{ + int n; + va_list ap; + + va_start(ap, fmt); + n = xavsprintf_append(strp, fmt, ap); + va_end(ap); + + return n; +} + +int xasprintf(char **strp, const char *fmt, ...) +{ + int n; + va_list ap; + + *strp = NULL; + + va_start(ap, fmt); + n = xavsprintf_append(strp, fmt, ap); + va_end(ap); + + return n; +} + char *join_path(const char *path, const char *name) { int lenp = strlen(path); diff --git a/util.h b/util.h index f6cea82..7658781 100644 --- a/util.h +++ b/util.h @@ -72,6 +72,8 @@ static inline void *xrealloc(void *p, size_t len) extern char *xstrdup(const char *s); 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 char *join_path(const char *path, const char *name); /** From 2bdbd07a1223e26c73caccb54f9af51f958c5b8f Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Sat, 24 Nov 2018 14:47:55 -0600 Subject: [PATCH 0784/1198] checks: Make each message output atomic Printing to stderr as we build up the check message results in interleaving of messages when multiple instances of dtc are running. Change the message output to use an intermediate buffer for constructing the message and then output the message to stderr with a single fputs. While perhaps there is no guarantee that fputs will be atomic, this gets rid of any interleaved output that previously occurred on Linux. Signed-off-by: Rob Herring Signed-off-by: David Gibson --- checks.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/checks.c b/checks.c index 4d8dffd..32e0d7a 100644 --- a/checks.c +++ b/checks.c @@ -78,23 +78,28 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti, const char *fmt, ...) { va_list ap; + char *str = NULL; if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2))) return; - fprintf(stderr, "%s: %s (%s): ", + xasprintf(&str, "%s: %s (%s): ", strcmp(dti->outname, "-") ? dti->outname : "", (c->error) ? "ERROR" : "Warning", c->name); if (node) { - fprintf(stderr, "%s", node->fullpath); if (prop) - fprintf(stderr, ":%s", prop->name); - fputs(": ", stderr); + xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name); + else + xasprintf_append(&str, "%s: ", node->fullpath); } + va_start(ap, fmt); - vfprintf(stderr, fmt, ap); + xavsprintf_append(&str, fmt, ap); va_end(ap); - fprintf(stderr, "\n"); + + xasprintf_append(&str, "\n"); + + fputs(str, stderr); } #define FAIL(c, dti, node, ...) \ From 3616b9a811b66744b4b818c2930462b480ddae44 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Sat, 24 Nov 2018 14:47:56 -0600 Subject: [PATCH 0785/1198] checks: Use source position information for check failures Now that we retain source position information of nodes and properties, make that the preferred file name (and position) to print out in check failures. This will greatly simplify finding and fixing check errors because most errors are in included source .dtsi files and they get duplicated every time the source file is included. Signed-off-by: Rob Herring Signed-off-by: David Gibson --- checks.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/checks.c b/checks.c index 32e0d7a..4dfdf48 100644 --- a/checks.c +++ b/checks.c @@ -19,6 +19,7 @@ */ #include "dtc.h" +#include "srcpos.h" #ifdef TRACE_CHECKS #define TRACE(c, ...) \ @@ -79,13 +80,30 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti, { va_list ap; char *str = NULL; + struct srcpos *pos = NULL; + char *file_str; if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2))) return; - xasprintf(&str, "%s: %s (%s): ", - strcmp(dti->outname, "-") ? dti->outname : "", - (c->error) ? "ERROR" : "Warning", c->name); + if (prop && prop->srcpos) + pos = prop->srcpos; + else if (node && node->srcpos) + pos = node->srcpos; + + if (pos) { + file_str = srcpos_string(pos); + xasprintf(&str, "%s", file_str); + free(file_str); + } else if (streq(dti->outname, "-")) { + xasprintf(&str, ""); + } else { + xasprintf(&str, "%s", dti->outname); + } + + xasprintf_append(&str, ": %s (%s): ", + (c->error) ? "ERROR" : "Warning", c->name); + if (node) { if (prop) xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name); @@ -99,6 +117,17 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti, xasprintf_append(&str, "\n"); + if (!prop && pos) { + pos = node->srcpos; + while (pos->next) { + pos = pos->next; + + file_str = srcpos_string(pos); + str += xasprintf_append(&str, " also defined at %s\n", file_str); + free(file_str); + } + } + fputs(str, stderr); } From f267e674d1452d381bb2f180695801454d3549ad Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 27 Nov 2018 08:16:30 -0600 Subject: [PATCH 0786/1198] checks: Fix crash with multiple source annotations Commit 3616b9a811b6 ("checks: Use source position information for check failures") causes crashes when there's a check message with multiple source annotations. Drop the errant addition to the str pointer left over from the previous version. Signed-off-by: Rob Herring Signed-off-by: David Gibson --- checks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks.c b/checks.c index 4dfdf48..4834e44 100644 --- a/checks.c +++ b/checks.c @@ -123,7 +123,7 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti, pos = pos->next; file_str = srcpos_string(pos); - str += xasprintf_append(&str, " also defined at %s\n", file_str); + xasprintf_append(&str, " also defined at %s\n", file_str); free(file_str); } } From 7cbc550f903b23f2291c7ca5d347ae0236ce27b6 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 13 Dec 2018 13:30:14 -0600 Subject: [PATCH 0787/1198] checks: Add unit address check if node is enabled There are various SoCs that have 2 different peripheral blocks at the same register offset. However, we might have one block marked as status = "disabled" and the other status = "ok". In such cases we shouldn't warn about duplicate unit-address. Here's a cut down example that we would warning about before: /dts-v1/; / { #address-cells = <0x01>; #size-cells = <0x01>; soc { #address-cells = <0x01>; #size-cells = <0x01>; compatible = "simple-bus"; ranges; i2c0: i2c@40003000 { compatible = "nordic,nrf-i2c"; reg = <0x40003000 0x1000>; status = "ok"; }; spi0: spi@40003000 { compatible = "nordic,nrf-spi"; reg = <0x40003000 0x1000>; status = "disabled"; }; }; }; We introduce 'unique_unit_address_if_enabled' check that is disabled by default. Signed-off-by: Kumar Gala Signed-off-by: David Gibson --- checks.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/checks.c b/checks.c index 4834e44..c0ed45e 100644 --- a/checks.c +++ b/checks.c @@ -1212,8 +1212,24 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d } WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); -static void check_unique_unit_address(struct check *c, struct dt_info *dti, - struct node *node) +static bool node_is_disabled(struct node *node) +{ + struct property *prop; + + prop = get_property(node, "status"); + if (prop) { + char *str = prop->val.val; + if (streq("disabled", str)) + return true; + } + + return false; +} + +static void check_unique_unit_address_common(struct check *c, + struct dt_info *dti, + struct node *node, + bool disable_check) { struct node *childa; @@ -1230,18 +1246,38 @@ static void check_unique_unit_address(struct check *c, struct dt_info *dti, if (!strlen(addr_a)) continue; + if (disable_check && node_is_disabled(childa)) + continue; + for_each_child(node, childb) { const char *addr_b = get_unitname(childb); if (childa == childb) break; + if (disable_check && node_is_disabled(childb)) + continue; + if (streq(addr_a, addr_b)) FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath); } } } + +static void check_unique_unit_address(struct check *c, struct dt_info *dti, + struct node *node) +{ + check_unique_unit_address_common(c, dti, node, false); +} WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size); +static void check_unique_unit_address_if_enabled(struct check *c, struct dt_info *dti, + struct node *node) +{ + check_unique_unit_address_common(c, dti, node, true); +} +CHECK_ENTRY(unique_unit_address_if_enabled, check_unique_unit_address_if_enabled, + NULL, false, false, &avoid_default_addr_size); + static void check_obsolete_chosen_interrupt_controller(struct check *c, struct dt_info *dti, struct node *node) @@ -1769,6 +1805,7 @@ static struct check *check_table[] = { &avoid_default_addr_size, &avoid_unnecessary_addr_size, &unique_unit_address, + &unique_unit_address_if_enabled, &obsolete_chosen_interrupt_controller, &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path, From 5aafd7ca43e0beb6b078388e789088b3ea1a51f5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 21 Dec 2018 14:01:32 +0100 Subject: [PATCH 0788/1198] libfdt: Fix fdt_getprop_by_offset() parameter name in documentation The second parameter of fdt_getprop_by_offset() is called "offset", not "ffset". Signed-off-by: Geert Uytterhoeven 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 fdaa3e6..263b7ad 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -669,7 +669,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, /** * fdt_getprop_by_offset - retrieve the value of a property at a given offset * @fdt: pointer to the device tree blob - * @ffset: offset of the property to read + * @offset: offset of the property to read * @namep: pointer to a string variable (will be overwritten) or NULL * @lenp: pointer to an integer variable (will be overwritten) or NULL * From ea7a8f6dad67d1d668df7e12adecf7783ac1874b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 21 Dec 2018 17:32:23 +0100 Subject: [PATCH 0789/1198] libfdt: Fix FDT_ERR_NOTFOUND typos in documentation The actual error is FDT_ERR_NOTFOUND, not FDT_ERR_NOT_FOUND. Fixes: d29126c90acb0d70 ("libfdt: Add iterator over properties") Fixes: 902d0f0953d0074b ("libfdt: Add a subnodes iterator macro") Signed-off-by: Geert Uytterhoeven Signed-off-by: David Gibson --- libfdt/libfdt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 263b7ad..a470d1d 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -227,7 +227,7 @@ int fdt_next_subnode(const void *fdt, int offset); * ... * } * - * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) { + * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { * Error handling * } * @@ -566,7 +566,7 @@ int fdt_next_property_offset(const void *fdt, int offset); * ... * } * - * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) { + * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) { * Error handling * } * From 78e113e81c9d33d0f33704b187a46399d5a75419 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Wed, 2 Jan 2019 12:30:13 +0100 Subject: [PATCH 0790/1198] Use PRIxPTR for printing uintptr_t values Fixes: 49903aed77 ("use ptrdiff_t modifier for printing pointer differences") Signed-off-by: Andreas Schwab --- fdtdump.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fdtdump.c b/fdtdump.c index 760a25c..200fb06 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -100,7 +100,7 @@ static void dump_blob(void *blob, bool debug) p = p_struct; while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { - dumpf("%04tx: tag: 0x%08"PRIx32" (%s)\n", + dumpf("%04"PRIxPTR": tag: 0x%08"PRIx32" (%s)\n", (uintptr_t)p - blob_off - 4, tag, tagname(tag)); if (tag == FDT_BEGIN_NODE) { @@ -140,8 +140,8 @@ static void dump_blob(void *blob, bool debug) p = PALIGN(p + sz, 4); - dumpf("%04tx: string: %s\n", (uintptr_t)s - blob_off, s); - dumpf("%04tx: value\n", (uintptr_t)t - blob_off); + dumpf("%04"PRIxPTR": string: %s\n", (uintptr_t)s - blob_off, s); + dumpf("%04"PRIxPTR": value\n", (uintptr_t)t - blob_off); printf("%*s%s", depth * shift, "", s); utilfdt_print_data(t, sz); printf(";\n"); From 4b68c6b3605ac3ef47e1594c0cde415f6f286134 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Mon, 18 Feb 2019 17:48:52 +0100 Subject: [PATCH 0791/1198] pylibfdt: Proper handling of bytes/unicode strings and octal literals Signed-off-by: Lumir Balhar Message-Id: <20190218164856.23861-1-frenzy@frenzy.cz> Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 14 +++++++++++--- tests/pylibfdt_tests.py | 20 ++++++++++---------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 462b5b0..6f1f1dc 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -669,7 +669,7 @@ class Fdt(FdtRo): Raises: FdtException if no parent found or other error occurs """ - val = val.encode('utf-8') + '\0' + val = val.encode('utf-8') + b'\0' return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val, len(val)), quiet) @@ -1074,12 +1074,20 @@ typedef uint32_t fdt32_t; if (!$1) $result = Py_None; else - $result = Py_BuildValue("s#", $1, *arg4); + %#if PY_VERSION_HEX >= 0x03000000 + $result = Py_BuildValue("y#", $1, *arg4); + %#else + $result = Py_BuildValue("s#", $1, *arg4); + %#endif } /* typemap used for fdt_setprop() */ %typemap(in) (const void *val) { - $1 = PyString_AsString($input); /* char *str */ + %#if PY_VERSION_HEX >= 0x03000000 + $1 = PyBytes_AsString($input); + %#else + $1 = PyString_AsString($input); /* char *str */ + %#endif } /* typemaps used for fdt_next_node() */ diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 34c680d..4761c52 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -84,7 +84,7 @@ PHANDLE_2 = 0x2001 TEST_STRING_1 = 'hello world' TEST_STRING_2 = 'hi world' -TEST_STRING_3 = u'unicode ' + unichr(467) +TEST_STRING_3 = u'unicode \u01d3' def get_err(err_code): @@ -107,7 +107,7 @@ def _ReadFdt(fname): Returns: Fdt bytearray suitable for passing to libfdt functions """ - return libfdt.Fdt(open(fname).read()) + return libfdt.Fdt(open(fname, mode='rb').read()) class PyLibfdtBasicTests(unittest.TestCase): """Test class for basic pylibfdt access functions @@ -164,7 +164,7 @@ class PyLibfdtBasicTests(unittest.TestCase): def testBadFdt(self): """Check that a filename provided accidentally is not accepted""" with self.assertRaises(FdtException) as e: - fdt = libfdt.Fdt('a string') + fdt = libfdt.Fdt(b'a string') self.assertEquals(e.exception.err, -libfdt.BADMAGIC) def testSubnodeOffset(self): @@ -239,7 +239,7 @@ class PyLibfdtBasicTests(unittest.TestCase): poffset = self.fdt.first_property_offset(root) prop = self.fdt.get_property_by_offset(poffset) self.assertEquals(prop.name, 'compatible') - self.assertEquals(prop, 'test_tree1\0') + self.assertEquals(prop, b'test_tree1\0') with self.assertRaises(FdtException) as e: self.fdt.get_property_by_offset(-2) @@ -252,7 +252,7 @@ class PyLibfdtBasicTests(unittest.TestCase): """Check that we can read the contents of a property by name""" root = self.fdt.path_offset('/') value = self.fdt.getprop(root, "compatible") - self.assertEquals(value, 'test_tree1\0') + self.assertEquals(value, b'test_tree1\0') self.assertEquals(-libfdt.NOTFOUND, self.fdt.getprop(root, 'missing', QUIET_NOTFOUND)) @@ -262,7 +262,7 @@ class PyLibfdtBasicTests(unittest.TestCase): node = self.fdt.path_offset('/subnode@1/subsubnode') value = self.fdt.getprop(node, "compatible") - self.assertEquals(value, 'subsubnode1\0subsubnode\0') + self.assertEquals(value, b'subsubnode1\0subsubnode\0') def testStrError(self): """Check that we can get an error string""" @@ -591,7 +591,7 @@ class PyLibfdtSwTests(unittest.TestCase): # Make sure we can read from the tree too node = sw.path_offset('/subnode@1') - self.assertEqual('subnode1' + chr(0), sw.getprop(node, 'compatible')) + self.assertEqual(b'subnode1\0', sw.getprop(node, 'compatible')) # Make sure we did at least two resizes self.assertTrue(len(fdt.as_bytearray()) > FdtSw.INC_SIZE * 2) @@ -609,15 +609,15 @@ class PyLibfdtRoTests(unittest.TestCase): def setUp(self): """Read in the device tree we use for testing""" - self.fdt = libfdt.FdtRo(open('test_tree1.dtb').read()) + self.fdt = libfdt.FdtRo(open('test_tree1.dtb', mode='rb').read()) def testAccess(self): """Basic sanity check for the FdtRo class""" node = self.fdt.path_offset('/subnode@1') - self.assertEqual('subnode1' + chr(0), + self.assertEqual(b'subnode1\0', self.fdt.getprop(node, 'compatible')) node = self.fdt.first_subnode(node) - self.assertEqual('this is a placeholder string\0string2\0', + self.assertEqual(b'this is a placeholder string\0string2\0', self.fdt.getprop(node, 'placeholder')) From cb0f454f73cc85019b0b844e3fd66caa2d219d5c Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Mon, 18 Feb 2019 17:48:53 +0100 Subject: [PATCH 0792/1198] pylibfdt: check_err accepts only integer as a first argument. A list passed as an argument to check_err() means that there is no error code to check and therefore it should be returned back. Signed-off-by: Lumir Balhar Message-Id: <20190218164856.23861-2-frenzy@frenzy.cz> Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 6f1f1dc..084bc5b 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -137,7 +137,7 @@ def check_err(val, quiet=()): Raises FdtException if val < 0 """ - if val < 0: + if isinstance(val, int) and val < 0: if -val not in quiet: raise FdtException(val) return val From 364631626bb78a40c1a1c70d5502ab0e953a7829 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 18 Feb 2019 17:48:54 +0100 Subject: [PATCH 0793/1198] pylibfdt: Test fdt.setprop take bytes on Python 3, add error handling Signed-off-by: Petr Viktorin Message-Id: <20190218164856.23861-3-frenzy@frenzy.cz> Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 4 ++++ tests/pylibfdt_tests.py | 12 +++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 084bc5b..4f14403 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -1084,6 +1084,10 @@ typedef uint32_t fdt32_t; /* typemap used for fdt_setprop() */ %typemap(in) (const void *val) { %#if PY_VERSION_HEX >= 0x03000000 + if (!PyBytes_Check($input)) { + SWIG_exception_fail(SWIG_TypeError, "bytes expected in method '" "$symname" + "', argument " "$argnum"" of type '" "$type""'"); + } $1 = PyBytes_AsString($input); %#else $1 = PyString_AsString($input); /* char *str */ diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 4761c52..e6c13ff 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -82,6 +82,8 @@ TEST_VALUE64_1 = (TEST_VALUE64_1H << 32) | TEST_VALUE64_1L PHANDLE_1 = 0x2000 PHANDLE_2 = 0x2001 +TEST_BYTES_1 = b'hello world' + TEST_STRING_1 = 'hello world' TEST_STRING_2 = 'hi world' TEST_STRING_3 = u'unicode \u01d3' @@ -443,21 +445,21 @@ class PyLibfdtBasicTests(unittest.TestCase): def testSetProp(self): """Test that we can update and create properties""" node = self.fdt.path_offset('/subnode@1') - self.fdt.setprop(node, 'compatible', TEST_STRING_1) - self.assertEquals(TEST_STRING_1, self.fdt.getprop(node, 'compatible')) + self.fdt.setprop(node, 'compatible', TEST_BYTES_1) + self.assertEquals(TEST_BYTES_1, self.fdt.getprop(node, 'compatible')) # Check that this property is missing, and that we don't have space to # add it self.assertEquals(-libfdt.NOTFOUND, self.fdt.getprop(node, 'missing', QUIET_NOTFOUND)) self.assertEquals(-libfdt.NOSPACE, - self.fdt.setprop(node, 'missing', TEST_STRING_1, + self.fdt.setprop(node, 'missing', TEST_BYTES_1, quiet=(libfdt.NOSPACE,))) # Expand the device tree so we now have room self.fdt.resize(self.fdt.totalsize() + 50) - self.fdt.setprop(node, 'missing', TEST_STRING_1) - self.assertEquals(TEST_STRING_1, self.fdt.getprop(node, 'missing')) + self.fdt.setprop(node, 'missing', TEST_BYTES_1) + self.assertEquals(TEST_BYTES_1, self.fdt.getprop(node, 'missing')) def testSetPropU32(self): """Test that we can update and create integer properties""" From 625dd8aaf20f8fc403c30385c9a1d423fb8e3957 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Mon, 18 Feb 2019 17:48:55 +0100 Subject: [PATCH 0794/1198] pylibfdt: Change how passing tests are recognized When some warning appears in test result, "ok" is still at the end of the line but without three dots. Signed-off-by: Lumir Balhar Message-Id: <20190218164856.23861-4-frenzy@frenzy.cz> 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 ca3fc86..1fa14ff 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -940,7 +940,7 @@ pylibfdt_tests () { # and the summary line for total tests (e.g. 'Ran 17 tests in 0.002s'). # We could add pass + fail to get total tests, but this provides a useful # sanity check. - pass_count=$(grep "\.\.\. ok$" $TMP | wc -l) + pass_count=$(grep "ok$" $TMP | wc -l) fail_count=$(grep "^ERROR: " $TMP | wc -l) total_tests=$(sed -n 's/^Ran \([0-9]*\) tests.*$/\1/p' $TMP) cat $TMP From a4b1a307ff3a1ae7ca9d4a8ac212025ab07f17eb Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Mon, 18 Feb 2019 17:48:56 +0100 Subject: [PATCH 0795/1198] pylibfdt:tests: Extend the way how to find a Python module Python 3 C extensions have suffix containing platform, Python version and another details in the name so the condition has to be extended. Signed-off-by: Lumir Balhar Message-Id: <20190218164856.23861-5-frenzy@frenzy.cz> 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 1fa14ff..04fc1e8 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -973,7 +973,7 @@ if [ -z "$TESTSETS" ]; then TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget fdtput fdtdump fdtoverlay" # Test pylibfdt if the libfdt Python module is available. - if [ -f ../pylibfdt/_libfdt.so ]; then + if [ -f ../pylibfdt/_libfdt.so ] || [ -f ../pylibfdt/_libfdt.cpython-3*.so ]; then TESTSETS="$TESTSETS pylibfdt" fi fi From d37f6b20107e952064e3f77e9d6915a9c09d10a6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 6 Mar 2019 15:51:37 +1100 Subject: [PATCH 0796/1198] Bump version to v1.5.0 We've accumulated several new features as well as a number of bugfixes, so prepare for another release. Signed-off-by: David Gibson --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 8c9e326..e6b32cf 100644 --- a/Makefile +++ b/Makefile @@ -9,8 +9,8 @@ # CONFIG_LOCALVERSION from some future config system. # VERSION = 1 -PATCHLEVEL = 4 -SUBLEVEL = 7 +PATCHLEVEL = 5 +SUBLEVEL = 0 EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = From 4762ad051ee0a654a17c67eb6d8e33196b475b81 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Mon, 11 Mar 2019 18:24:20 +0000 Subject: [PATCH 0797/1198] checks: Fix spelling in check_graph_endpoint Should be "endpoint" rather than "endpont" Signed-off-by: Leonard Crestez Message-Id: <6fcb6e160163467b706c312ffe307ee8a5d9255d.1552328099.git.leonard.crestez@nxp.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 c0ed45e..5865234 100644 --- a/checks.c +++ b/checks.c @@ -1750,7 +1750,7 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti, return; if (!strprefixeq(node->name, node->basenamelen, "endpoint")) - FAIL(c, dti, node, "graph endpont node name should be 'endpoint'"); + FAIL(c, dti, node, "graph endpoint node name should be 'endpoint'"); check_graph_reg(c, dti, node); From 54ea41c22415cb0e283d22faf71202051c89400c Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 20 Mar 2019 16:10:03 +0100 Subject: [PATCH 0798/1198] libfdt: Add phandle generation helper The new fdt_generate_phandle() function can be used to generate a new, unused phandle given a specific device tree blob. The implementation is somewhat naive in that it simply walks the entire device tree to find the highest phandle value and then returns a phandle value one higher than that. A more clever implementation might try to find holes in the current set of phandle values and fill them. But this implementation is relatively simple and works reliably. Also add a test that validates that phandles generated by this new API are indeed unique. Signed-off-by: Thierry Reding Message-Id: <20190320151003.28941-1-thierry.reding@gmail.com> Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 31 +++++++++++++++++++++++++++++++ libfdt/libfdt.h | 19 +++++++++++++++++++ libfdt/libfdt_env.h | 1 + libfdt/version.lds | 1 + tests/get_phandle.c | 31 ++++++++++++++++++++++++++++++- tests/multilabel.dts | 5 +++++ tests/multilabel_merge.dts | 5 +++++ tests/references.c | 19 +++++++++++++++++-- tests/references.dts | 5 +++++ 9 files changed, 114 insertions(+), 3 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index eafc142..97cdcda 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -170,6 +170,37 @@ uint32_t fdt_get_max_phandle(const void *fdt) return 0; } +int fdt_generate_phandle(const void *fdt, uint32_t *phandle) +{ + uint32_t max = 0; + int offset = -1; + + while (true) { + uint32_t value; + + offset = fdt_next_node(fdt, offset, NULL); + if (offset < 0) { + if (offset == -FDT_ERR_NOTFOUND) + break; + + return offset; + } + + value = fdt_get_phandle(fdt, offset); + + if (value > max) + max = value; + } + + if (max == FDT_MAX_PHANDLE) + return -FDT_ERR_NOPHANDLES; + + if (phandle) + *phandle = max + 1; + + return 0; +} + static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) { int offset = n * sizeof(struct fdt_reserve_entry); diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index a470d1d..7e102d1 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -140,6 +140,10 @@ #define FDT_ERR_MAX 17 +/* constants */ +#define FDT_MAX_PHANDLE 0xfffffffe + /* Valid values for phandles range from 1 to 2^32-2. */ + /**********************************************************************/ /* Low-level functions (you probably don't need these) */ /**********************************************************************/ @@ -376,6 +380,21 @@ const char *fdt_string(const void *fdt, int stroffset); */ uint32_t fdt_get_max_phandle(const void *fdt); +/** + * fdt_generate_phandle - return a new, unused phandle for a device tree blob + * @fdt: pointer to the device tree blob + * @phandle: return location for the new phandle + * + * Walks the device tree blob and looks for the highest phandle value. On + * success, the new, unused phandle value (one higher than the previously + * 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 + */ +int fdt_generate_phandle(const void *fdt, uint32_t *phandle); + /** * fdt_num_mem_rsv - retrieve the number of memory reserve map entries * @fdt: pointer to the device tree blob diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h index eb20538..4d1cdfa 100644 --- a/libfdt/libfdt_env.h +++ b/libfdt/libfdt_env.h @@ -52,6 +52,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include diff --git a/libfdt/version.lds b/libfdt/version.lds index 9f5d708..5897f1e 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -66,6 +66,7 @@ LIBFDT_1.2 { fdt_resize; fdt_overlay_apply; fdt_get_string; + fdt_generate_phandle; local: *; }; diff --git a/tests/get_phandle.c b/tests/get_phandle.c index 22bd7b8..d87aee5 100644 --- a/tests/get_phandle.c +++ b/tests/get_phandle.c @@ -17,6 +17,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include @@ -42,10 +43,32 @@ static void check_phandle(void *fdt, const char *path, uint32_t checkhandle) path, phandle, checkhandle); } +static void check_phandle_unique(const void *fdt, uint32_t checkhandle) +{ + uint32_t phandle; + int offset = -1; + + while (true) { + offset = fdt_next_node(fdt, offset, NULL); + if (offset < 0) { + if (offset == -FDT_ERR_NOTFOUND) + break; + + FAIL("error looking for phandle %#x", checkhandle); + } + + phandle = fdt_get_phandle(fdt, offset); + + if (phandle == checkhandle) + FAIL("generated phandle already exists"); + } +} + int main(int argc, char *argv[]) { - uint32_t max; + uint32_t max, phandle; void *fdt; + int err; test_init(argc, argv); fdt = load_blob_arg(argc, argv); @@ -59,5 +82,11 @@ int main(int argc, char *argv[]) FAIL("fdt_get_max_phandle returned 0x%x instead of 0x%x\n", max, PHANDLE_2); + err = fdt_generate_phandle(fdt, &phandle); + if (err < 0) + FAIL("failed to generate phandle: %d", err); + + check_phandle_unique(fdt, phandle); + PASS(); } diff --git a/tests/multilabel.dts b/tests/multilabel.dts index 77da06c..d80ebe1 100644 --- a/tests/multilabel.dts +++ b/tests/multilabel.dts @@ -41,4 +41,9 @@ m1: mq: /memreserve/ 0 0x1000; n2 = &n2; n3 = &n3; }; + + node6 { + linux,phandle = <0xfffffffe>; + phandle = <0xfffffffe>; + }; }; diff --git a/tests/multilabel_merge.dts b/tests/multilabel_merge.dts index 3e80298..a27d856 100644 --- a/tests/multilabel_merge.dts +++ b/tests/multilabel_merge.dts @@ -39,6 +39,11 @@ m1: mq: /memreserve/ 0 0x1000; n2 = &n2; n3 = &n3; }; + + node6 { + linux,phandle = <0xfffffffe>; + phandle = <0xfffffffe>; + }; }; / { diff --git a/tests/references.c b/tests/references.c index cab70f6..5b233a4 100644 --- a/tests/references.c +++ b/tests/references.c @@ -76,8 +76,8 @@ static void check_rref(const void *fdt) int main(int argc, char *argv[]) { void *fdt; - int n1, n2, n3, n4, n5; - uint32_t h1, h2, h4, h5; + int n1, n2, n3, n4, n5, n6, err; + uint32_t h1, h2, h4, h5, h6, hn; test_init(argc, argv); fdt = load_blob_arg(argc, argv); @@ -97,11 +97,15 @@ int main(int argc, char *argv[]) n5 = fdt_path_offset(fdt, "/node5"); if (n5 < 0) FAIL("fdt_path_offset(/node5): %s", fdt_strerror(n5)); + n6 = fdt_path_offset(fdt, "/node6"); + if (n6 < 0) + FAIL("fdt_path_offset(/node6): %s", fdt_strerror(n6)); h1 = fdt_get_phandle(fdt, n1); h2 = fdt_get_phandle(fdt, n2); h4 = fdt_get_phandle(fdt, n4); h5 = fdt_get_phandle(fdt, n5); + h6 = fdt_get_phandle(fdt, n6); if (h1 != 0x2000) FAIL("/node1 has wrong phandle, 0x%x instead of 0x%x", @@ -109,6 +113,9 @@ int main(int argc, char *argv[]) if (h2 != 0x1) FAIL("/node2 has wrong phandle, 0x%x instead of 0x%x", h2, 0x1); + if (h6 != FDT_MAX_PHANDLE) + FAIL("/node6 has wrong phandle, 0x%x instead of 0x%x", + h6, FDT_MAX_PHANDLE); if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0)) FAIL("/node4 has bad phandle, 0x%x", h4); @@ -117,6 +124,14 @@ int main(int argc, char *argv[]) if ((h5 == h4) || (h5 == h2) || (h5 == h1)) FAIL("/node5 has duplicate phandle, 0x%x", h5); + /* + * /node6 has phandle FDT_MAX_PHANDLE, so fdt_generate_phandle() is + * expected to fail. + */ + err = fdt_generate_phandle(fdt, &hn); + if (err != -FDT_ERR_NOPHANDLES) + FAIL("generated invalid phandle 0x%x\n", hn); + check_ref(fdt, n1, h2); check_ref(fdt, n2, h1); check_ref(fdt, n3, h4); diff --git a/tests/references.dts b/tests/references.dts index f783e8b..b390639 100644 --- a/tests/references.dts +++ b/tests/references.dts @@ -33,4 +33,9 @@ linux,phandle = <&n5>; phandle = <&n5>; }; + + node6 { + linux,phandle = <0xfffffffe>; + phandle = <0xfffffffe>; + }; }; From f67b47135523863c17a4af55d31de8f47d672834 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 25 Mar 2019 14:51:27 +1100 Subject: [PATCH 0799/1198] Revert "libfdt: Add phandle generation helper" This reverts commit 54ea41c22415cb0e283d22faf71202051c89400c. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 31 ------------------------------- libfdt/libfdt.h | 19 ------------------- libfdt/libfdt_env.h | 1 - libfdt/version.lds | 1 - tests/get_phandle.c | 31 +------------------------------ tests/multilabel.dts | 5 ----- tests/multilabel_merge.dts | 5 ----- tests/references.c | 19 ++----------------- tests/references.dts | 5 ----- 9 files changed, 3 insertions(+), 114 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 97cdcda..eafc142 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -170,37 +170,6 @@ uint32_t fdt_get_max_phandle(const void *fdt) return 0; } -int fdt_generate_phandle(const void *fdt, uint32_t *phandle) -{ - uint32_t max = 0; - int offset = -1; - - while (true) { - uint32_t value; - - offset = fdt_next_node(fdt, offset, NULL); - if (offset < 0) { - if (offset == -FDT_ERR_NOTFOUND) - break; - - return offset; - } - - value = fdt_get_phandle(fdt, offset); - - if (value > max) - max = value; - } - - if (max == FDT_MAX_PHANDLE) - return -FDT_ERR_NOPHANDLES; - - if (phandle) - *phandle = max + 1; - - return 0; -} - static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) { int offset = n * sizeof(struct fdt_reserve_entry); diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 7e102d1..a470d1d 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -140,10 +140,6 @@ #define FDT_ERR_MAX 17 -/* constants */ -#define FDT_MAX_PHANDLE 0xfffffffe - /* Valid values for phandles range from 1 to 2^32-2. */ - /**********************************************************************/ /* Low-level functions (you probably don't need these) */ /**********************************************************************/ @@ -380,21 +376,6 @@ const char *fdt_string(const void *fdt, int stroffset); */ uint32_t fdt_get_max_phandle(const void *fdt); -/** - * fdt_generate_phandle - return a new, unused phandle for a device tree blob - * @fdt: pointer to the device tree blob - * @phandle: return location for the new phandle - * - * Walks the device tree blob and looks for the highest phandle value. On - * success, the new, unused phandle value (one higher than the previously - * 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 - */ -int fdt_generate_phandle(const void *fdt, uint32_t *phandle); - /** * fdt_num_mem_rsv - retrieve the number of memory reserve map entries * @fdt: pointer to the device tree blob diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h index 4d1cdfa..eb20538 100644 --- a/libfdt/libfdt_env.h +++ b/libfdt/libfdt_env.h @@ -52,7 +52,6 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include diff --git a/libfdt/version.lds b/libfdt/version.lds index 5897f1e..9f5d708 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -66,7 +66,6 @@ LIBFDT_1.2 { fdt_resize; fdt_overlay_apply; fdt_get_string; - fdt_generate_phandle; local: *; }; diff --git a/tests/get_phandle.c b/tests/get_phandle.c index d87aee5..22bd7b8 100644 --- a/tests/get_phandle.c +++ b/tests/get_phandle.c @@ -17,7 +17,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include #include #include @@ -43,32 +42,10 @@ static void check_phandle(void *fdt, const char *path, uint32_t checkhandle) path, phandle, checkhandle); } -static void check_phandle_unique(const void *fdt, uint32_t checkhandle) -{ - uint32_t phandle; - int offset = -1; - - while (true) { - offset = fdt_next_node(fdt, offset, NULL); - if (offset < 0) { - if (offset == -FDT_ERR_NOTFOUND) - break; - - FAIL("error looking for phandle %#x", checkhandle); - } - - phandle = fdt_get_phandle(fdt, offset); - - if (phandle == checkhandle) - FAIL("generated phandle already exists"); - } -} - int main(int argc, char *argv[]) { - uint32_t max, phandle; + uint32_t max; void *fdt; - int err; test_init(argc, argv); fdt = load_blob_arg(argc, argv); @@ -82,11 +59,5 @@ int main(int argc, char *argv[]) FAIL("fdt_get_max_phandle returned 0x%x instead of 0x%x\n", max, PHANDLE_2); - err = fdt_generate_phandle(fdt, &phandle); - if (err < 0) - FAIL("failed to generate phandle: %d", err); - - check_phandle_unique(fdt, phandle); - PASS(); } diff --git a/tests/multilabel.dts b/tests/multilabel.dts index d80ebe1..77da06c 100644 --- a/tests/multilabel.dts +++ b/tests/multilabel.dts @@ -41,9 +41,4 @@ m1: mq: /memreserve/ 0 0x1000; n2 = &n2; n3 = &n3; }; - - node6 { - linux,phandle = <0xfffffffe>; - phandle = <0xfffffffe>; - }; }; diff --git a/tests/multilabel_merge.dts b/tests/multilabel_merge.dts index a27d856..3e80298 100644 --- a/tests/multilabel_merge.dts +++ b/tests/multilabel_merge.dts @@ -39,11 +39,6 @@ m1: mq: /memreserve/ 0 0x1000; n2 = &n2; n3 = &n3; }; - - node6 { - linux,phandle = <0xfffffffe>; - phandle = <0xfffffffe>; - }; }; / { diff --git a/tests/references.c b/tests/references.c index 5b233a4..cab70f6 100644 --- a/tests/references.c +++ b/tests/references.c @@ -76,8 +76,8 @@ static void check_rref(const void *fdt) int main(int argc, char *argv[]) { void *fdt; - int n1, n2, n3, n4, n5, n6, err; - uint32_t h1, h2, h4, h5, h6, hn; + int n1, n2, n3, n4, n5; + uint32_t h1, h2, h4, h5; test_init(argc, argv); fdt = load_blob_arg(argc, argv); @@ -97,15 +97,11 @@ int main(int argc, char *argv[]) n5 = fdt_path_offset(fdt, "/node5"); if (n5 < 0) FAIL("fdt_path_offset(/node5): %s", fdt_strerror(n5)); - n6 = fdt_path_offset(fdt, "/node6"); - if (n6 < 0) - FAIL("fdt_path_offset(/node6): %s", fdt_strerror(n6)); h1 = fdt_get_phandle(fdt, n1); h2 = fdt_get_phandle(fdt, n2); h4 = fdt_get_phandle(fdt, n4); h5 = fdt_get_phandle(fdt, n5); - h6 = fdt_get_phandle(fdt, n6); if (h1 != 0x2000) FAIL("/node1 has wrong phandle, 0x%x instead of 0x%x", @@ -113,9 +109,6 @@ int main(int argc, char *argv[]) if (h2 != 0x1) FAIL("/node2 has wrong phandle, 0x%x instead of 0x%x", h2, 0x1); - if (h6 != FDT_MAX_PHANDLE) - FAIL("/node6 has wrong phandle, 0x%x instead of 0x%x", - h6, FDT_MAX_PHANDLE); if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0)) FAIL("/node4 has bad phandle, 0x%x", h4); @@ -124,14 +117,6 @@ int main(int argc, char *argv[]) if ((h5 == h4) || (h5 == h2) || (h5 == h1)) FAIL("/node5 has duplicate phandle, 0x%x", h5); - /* - * /node6 has phandle FDT_MAX_PHANDLE, so fdt_generate_phandle() is - * expected to fail. - */ - err = fdt_generate_phandle(fdt, &hn); - if (err != -FDT_ERR_NOPHANDLES) - FAIL("generated invalid phandle 0x%x\n", hn); - check_ref(fdt, n1, h2); check_ref(fdt, n2, h1); check_ref(fdt, n3, h4); diff --git a/tests/references.dts b/tests/references.dts index b390639..f783e8b 100644 --- a/tests/references.dts +++ b/tests/references.dts @@ -33,9 +33,4 @@ linux,phandle = <&n5>; phandle = <&n5>; }; - - node6 { - linux,phandle = <0xfffffffe>; - phandle = <0xfffffffe>; - }; }; From eac2ad495b29f15d78daa2a7226653f36515cd7a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 25 Mar 2019 14:52:47 +1100 Subject: [PATCH 0800/1198] Update version.lds again Yet again, we've added several functions to libfdt that were supposed to be exported, but forgotten to add them to the versio.lds script. This adds them. Signed-off-by: David Gibson --- libfdt/version.lds | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libfdt/version.lds b/libfdt/version.lds index 9f5d708..a5fe62d 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -66,6 +66,10 @@ LIBFDT_1.2 { fdt_resize; fdt_overlay_apply; fdt_get_string; + fdt_get_max_phandle; + fdt_check_full; + fdt_setprop_placeholder; + fdt_property_placeholder; local: *; }; From ae795b2db7a43f8f076a8b688761244ed0f93128 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 27 Mar 2019 11:53:52 +0800 Subject: [PATCH 0801/1198] checks: Do not omit nodes with labels if symbol generation is requested Commit 4038fd90056e ("dtc: add ability to make nodes conditional on them being referenced") added the new /omit-if-no-ref/ directive to mark nodes as eligible to be discarded if not referenced. The mechanism to process this happens before the symbol generation phase. This means even if symbol generation is requested and the node has a label, it will be discarded if there are no references to it within the same file. This is probably not what people expect. When using symbol generation to compile base device trees for applying overlays, nodes with labels could be referenced by the overlays, and therefore should be preserved. Check if the node has a label and symbol generation was requested before dropping the node. Signed-off-by: Chen-Yu Tsai Message-Id: <20190327035352.24036-1-wens@csie.org> Signed-off-by: David Gibson --- checks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/checks.c b/checks.c index 5865234..0524d41 100644 --- a/checks.c +++ b/checks.c @@ -660,6 +660,8 @@ ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names); static void fixup_omit_unused_nodes(struct check *c, struct dt_info *dti, struct node *node) { + if (generate_symbols && node->labels) + return; if (node->omit_if_unused && !node->is_referenced) delete_node(node); } From 7fcf8208b8a98f65ce938a64fab674add3656f27 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Wed, 27 Mar 2019 15:15:52 +0900 Subject: [PATCH 0802/1198] libfdt: add fdt_append_addrrange() This function will append an address range property using parent node's "#address-cells" and "#size-cells" properties. It will be used in implementing kdump with kexec_file_load system call at linux kernel for arm64 once it is merged into kernel tree. Signed-off-by: AKASHI Takahiro Message-Id: <20190327061552.17170-2-takahiro.akashi@linaro.org> [dwg: Correct a SEGV error in the testcase] Signed-off-by: David Gibson --- libfdt/fdt_addresses.c | 47 +++++++++++++++ libfdt/libfdt.h | 61 ++++++++++++++++++++ tests/.gitignore | 1 + tests/Makefile.tests | 1 + tests/appendprop_addrrange.c | 108 +++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 5 ++ tests/testdata.h | 6 ++ tests/tests.h | 3 + tests/testutils.c | 58 +++++++++++++++++++ 9 files changed, 290 insertions(+) create mode 100644 tests/appendprop_addrrange.c diff --git a/libfdt/fdt_addresses.c b/libfdt/fdt_addresses.c index f13a87d..2cc997e 100644 --- a/libfdt/fdt_addresses.c +++ b/libfdt/fdt_addresses.c @@ -95,3 +95,50 @@ int fdt_size_cells(const void *fdt, int nodeoffset) return 1; return val; } + +/* This function assumes that [address|size]_cells is 1 or 2 */ +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, uint64_t addr, uint64_t size) +{ + int addr_cells, size_cells, ret; + uint8_t data[sizeof(fdt64_t) * 2], *prop; + + ret = fdt_address_cells(fdt, parent); + if (ret < 0) + return ret; + addr_cells = ret; + + ret = fdt_size_cells(fdt, parent); + if (ret < 0) + return ret; + size_cells = ret; + + /* check validity of address */ + prop = data; + if (addr_cells == 1) { + if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size)) + return -FDT_ERR_BADVALUE; + + fdt32_st(prop, (uint32_t)addr); + } else if (addr_cells == 2) { + fdt64_st(prop, addr); + } else { + return -FDT_ERR_BADNCELLS; + } + + /* check validity of size */ + prop += addr_cells * sizeof(fdt32_t); + if (size_cells == 1) { + if (size > UINT32_MAX) + return -FDT_ERR_BADVALUE; + + fdt32_st(prop, (uint32_t)size); + } else if (size_cells == 2) { + fdt64_st(prop, size); + } else { + return -FDT_ERR_BADNCELLS; + } + + return fdt_appendprop(fdt, nodeoffset, name, data, + (addr_cells + size_cells) * sizeof(fdt32_t)); +} diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index a470d1d..e70f5bf 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -171,6 +171,16 @@ static inline uint32_t fdt32_ld(const fdt32_t *p) | bp[3]; } +static inline void fdt32_st(void *property, uint32_t value) +{ + uint8_t *bp = property; + + bp[0] = value >> 24; + bp[1] = (value >> 16) & 0xff; + bp[2] = (value >> 8) & 0xff; + bp[3] = value & 0xff; +} + static inline uint64_t fdt64_ld(const fdt64_t *p) { const uint8_t *bp = (const uint8_t *)p; @@ -185,6 +195,20 @@ static inline uint64_t fdt64_ld(const fdt64_t *p) | bp[7]; } +static inline void fdt64_st(void *property, uint64_t value) +{ + uint8_t *bp = property; + + bp[0] = value >> 56; + bp[1] = (value >> 48) & 0xff; + bp[2] = (value >> 40) & 0xff; + bp[3] = (value >> 32) & 0xff; + bp[4] = (value >> 24) & 0xff; + bp[5] = (value >> 16) & 0xff; + bp[6] = (value >> 8) & 0xff; + bp[7] = value & 0xff; +} + /**********************************************************************/ /* Traversal functions */ /**********************************************************************/ @@ -1831,6 +1855,43 @@ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, #define fdt_appendprop_string(fdt, nodeoffset, name, str) \ fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) +/** + * fdt_appendprop_addrrange - append a address range property + * @fdt: pointer to the device tree blob + * @parent: offset of the parent node + * @nodeoffset: offset of the node to add a property at + * @name: name of property + * @addr: start address of a given range + * @size: size of a given range + * + * fdt_appendprop_addrrange() appends an address range value (start + * 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 + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #address-cells property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain a new property + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, uint64_t addr, uint64_t size); + /** * fdt_delprop - delete a property * @fdt: pointer to the device tree blob diff --git a/tests/.gitignore b/tests/.gitignore index 12af438..0bc78aa 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -8,6 +8,7 @@ tmp.* /addr_size_cells /addr_size_cells2 /appendprop[12] +/appendprop_addrrange /asm_tree_dump /boot-cpuid /char_literal diff --git a/tests/Makefile.tests b/tests/Makefile.tests index b02d8bf..b77f121 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -10,6 +10,7 @@ LIB_TESTS_L = get_mem_rsv \ notfound \ addr_size_cells \ addr_size_cells2 \ + appendprop_addrrange \ stringlist \ setprop_inplace nop_property nop_node \ sw_tree1 sw_states \ diff --git a/tests/appendprop_addrrange.c b/tests/appendprop_addrrange.c new file mode 100644 index 0000000..b079fba --- /dev/null +++ b/tests/appendprop_addrrange.c @@ -0,0 +1,108 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_appendprop_addrrange() + * Copyright (C) 2018 AKASHI Takahiro, Linaro Limited + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + void *fdt, *buf; + int offset, xac, xsc, num, i, err; + uint64_t addr, size; + + if (argc != 5) + CONFIG("Usage: %s \n", + argv[0]); + + test_init(argc, argv); + fdt = load_blob(argv[1]); + xac = strtol(argv[2], NULL, 10); + xsc = strtol(argv[3], NULL, 10); + num = strtol(argv[4], NULL, 10); + + buf = xmalloc(0x1000); + if (!buf) + FAIL("Couldn't allocate temporary buffer"); + err = fdt_open_into(fdt, buf, 0x1000); + if (err) + FAIL("fdt_open_into(): %s", fdt_strerror(err)); + + fdt = buf; + + /* Set up */ + err = fdt_setprop_cell(fdt, 0, "#address-cells", xac); + if (err) + FAIL("fdt_setprop_cell(\"#address-cells\"): %s", + fdt_strerror(err)); + err = fdt_setprop_cell(fdt, 0, "#size-cells", xsc); + if (err) + FAIL("fdt_setprop_cell(\"#size-cells\"): %s", + fdt_strerror(err)); + + offset = fdt_path_offset(fdt, "/node@1"); + if (offset < 0) + FAIL("Couldn't find path %s", "/node@1"); + + addr = TEST_MEMREGION_ADDR; + if (xac > 1) + addr += TEST_MEMREGION_ADDR_HI; + size = TEST_MEMREGION_SIZE; + if (xsc > 1) + size += TEST_MEMREGION_SIZE_HI; + + /* + * Do test + */ + /* 1. repeat append's */ + for (i = 0; i < num; i++) { + err = fdt_appendprop_addrrange(fdt, 0, offset, + "prop-memregion", addr, size); + if (err) + FAIL("Failed to append[%d] \"prop-memregion\": %s", + i, fdt_strerror(err)); + + check_getprop_addrrange(fdt, 0, offset, "prop-memregion", + i + 1); + + addr += size; + size += TEST_MEMREGION_SIZE_INC; + } + + /* 2. default property name */ + addr = TEST_MEMREGION_ADDR; + if (xac > 1) + addr += TEST_MEMREGION_ADDR_HI; + size = TEST_MEMREGION_SIZE; + if (xsc > 1) + size += TEST_MEMREGION_SIZE_HI; + + 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); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 04fc1e8..f6b308f 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -424,6 +424,11 @@ libfdt_tests () { run_dtc_test -I dts -O dtb -o property_iterate.dtb property_iterate.dts run_test property_iterate property_iterate.dtb + run_dtc_test -I dts -O dtb -o unit-addr-without-reg.dtb unit-addr-without-reg.dts + run_test appendprop_addrrange unit-addr-without-reg.dtb 1 1 1 + run_test appendprop_addrrange unit-addr-without-reg.dtb 2 2 2 + run_test appendprop_addrrange unit-addr-without-reg.dtb 2 1 3 + # Tests for behaviour on various sorts of corrupted trees run_test truncated_property run_test truncated_string diff --git a/tests/testdata.h b/tests/testdata.h index 68dcbac..0d08efb 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -40,6 +40,12 @@ #define TEST_CHAR4 '\'' #define TEST_CHAR5 '\xff' +#define TEST_MEMREGION_ADDR 0x12345678 +#define TEST_MEMREGION_ADDR_HI 0x8765432100000000 +#define TEST_MEMREGION_SIZE 0x9abcdef0 +#define TEST_MEMREGION_SIZE_HI 0x0fedcba900000000 +#define TEST_MEMREGION_SIZE_INC 0x1000 + #ifndef __ASSEMBLY__ extern struct fdt_header test_tree1; extern struct fdt_header truncated_property; diff --git a/tests/tests.h b/tests/tests.h index dc8120e..75735d6 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -128,6 +128,9 @@ const void *check_get_prop_offset(void *fdt, int poffset, const char *in_name, check_get_prop_offset(fdt, poffset, name, sizeof(x), &x); \ }) +const void *check_getprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, int num); + int nodename_eq(const char *s1, const char *s2); void vg_prepare_blob(void *fdt, size_t bufsize); void *load_blob(const char *filename); diff --git a/tests/testutils.c b/tests/testutils.c index bbfda90..a250d5a 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -45,6 +45,7 @@ static inline void VALGRIND_MAKE_MEM_DEFINED(void *p, size_t len) #include #include "tests.h" +#include "testdata.h" /* For FDT_SW_MAGIC */ #include "libfdt_internal.h" @@ -184,6 +185,63 @@ const void *check_get_prop_offset(void *fdt, int poffset, const char *exp_name, return propval; } +const void *check_getprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, int num) +{ + const void *propval; + int xac, xsc, buf_size, cells, i; + char *buf, *p; + uint64_t addr, size; + fdt32_t val; + + xac = fdt_address_cells(fdt, parent); + xsc = fdt_size_cells(fdt, parent); + + if (xac <= 0) + FAIL("Couldn't identify #address-cells: %s", + fdt_strerror(xac)); + if (xsc <= 0) + FAIL("Couldn't identify #size-cells: %s", + fdt_strerror(xsc)); + + buf_size = (xac + xsc) * sizeof(fdt32_t) * num; + buf = malloc(buf_size); + if (!buf) + FAIL("Couldn't allocate temporary buffer"); + + /* expected value */ + addr = TEST_MEMREGION_ADDR; + if (xac > 1) + addr += TEST_MEMREGION_ADDR_HI; + size = TEST_MEMREGION_SIZE; + if (xsc > 1) + size += TEST_MEMREGION_SIZE_HI; + for (p = buf, i = 0; i < num; i++) { + cells = xac; + while (cells) { + val = cpu_to_fdt32(addr >> (32 * (--cells))); + memcpy(p, &val, sizeof(val)); + p += sizeof(val); + } + cells = xsc; + while (cells) { + val = cpu_to_fdt32(size >> (32 * (--cells))); + memcpy(p, &val, sizeof(val)); + p += sizeof(val); + } + + addr += size; + size += TEST_MEMREGION_SIZE_INC; + } + + /* check */ + propval = check_getprop(fdt, nodeoffset, name, buf_size, + (const void *)buf); + + free(buf); + + return propval; +} int nodename_eq(const char *s1, const char *s2) { From 2bc5b66d7f6c441bf6183a6f769a95de6f90297b Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 26 Mar 2019 16:33:00 +0100 Subject: [PATCH 0803/1198] libfdt: Add new maximum phandle lookup function The fdt_get_max_phandle() function has some shortcomings. On one hand it returns just a uint32_t which means to check for the "negative" error code a caller has to explicitly check against the error code (uint32_t)-1. In addition, the -1 is the only error code that can be returned, so a caller cannot tell the difference between the various failures. Fix this by adding a new fdt_find_max_phandle() function that returns an error code on failure and 0 on success, just like other APIs, and stores the maximum phandle value in an output argument on success. This also refactors fdt_get_max_phandle() to use the new function. Add a note pointing out that the new fdt_find_max_phandle() function should be preferred over fdt_get_max_phandle(). Signed-off-by: Thierry Reding Message-Id: <20190326153302.17109-1-thierry.reding@gmail.com> [dwg: Reword for some inaccuracies in the commit message] Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 44 +++++++++++++++++++++++++++++--------------- libfdt/libfdt.h | 16 ++++++++++++++++ libfdt/libfdt_env.h | 1 + libfdt/version.lds | 1 + tests/get_phandle.c | 9 +++++++++ 5 files changed, 56 insertions(+), 15 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index eafc142..1d0335e 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -144,32 +144,46 @@ static int fdt_string_eq_(const void *fdt, int stroffset, return p && (slen == len) && (memcmp(p, s, len) == 0); } -uint32_t fdt_get_max_phandle(const void *fdt) +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle) { - uint32_t max_phandle = 0; - int offset; + uint32_t max = 0; + int offset = -1; - for (offset = fdt_next_node(fdt, -1, NULL);; - offset = fdt_next_node(fdt, offset, NULL)) { - uint32_t phandle; + while (true) { + uint32_t value; - if (offset == -FDT_ERR_NOTFOUND) - return max_phandle; + offset = fdt_next_node(fdt, offset, NULL); + if (offset < 0) { + if (offset == -FDT_ERR_NOTFOUND) + break; - if (offset < 0) - return (uint32_t)-1; + return offset; + } - phandle = fdt_get_phandle(fdt, offset); - if (phandle == (uint32_t)-1) - continue; + value = fdt_get_phandle(fdt, offset); - if (phandle > max_phandle) - max_phandle = phandle; + if (value > max) + max = value; } + if (phandle) + *phandle = max; + return 0; } +uint32_t fdt_get_max_phandle(const void *fdt) +{ + uint32_t phandle; + int err; + + err = fdt_find_max_phandle(fdt, &phandle); + if (err < 0) + return (uint32_t)-1; + + return phandle; +} + static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) { int offset = n * sizeof(struct fdt_reserve_entry); diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index e70f5bf..e1498c3 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -385,6 +385,20 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); */ const char *fdt_string(const void *fdt, int stroffset); +/** + * fdt_find_max_phandle - find and return the highest phandle in a tree + * @fdt: pointer to the device tree blob + * @phandle: return location for the highest phandle value found in the tree + * + * fdt_find_max_phandle() finds the highest phandle value in the given device + * tree. The value returned in @phandle is only valid if the function returns + * success. + * + * returns: + * 0 on success or a negative error code on failure + */ +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle); + /** * fdt_get_max_phandle - retrieves the highest phandle in a tree * @fdt: pointer to the device tree blob @@ -393,6 +407,8 @@ const char *fdt_string(const void *fdt, int stroffset); * device tree. This will ignore badly formatted phandles, or phandles * with a value of 0 or -1. * + * This function is deprecated in favour of fdt_find_max_phandle(). + * * returns: * the highest phandle on success * 0, if no phandle was found in the device tree diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h index eb20538..4d1cdfa 100644 --- a/libfdt/libfdt_env.h +++ b/libfdt/libfdt_env.h @@ -52,6 +52,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include diff --git a/libfdt/version.lds b/libfdt/version.lds index a5fe62d..87bbb2f 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -66,6 +66,7 @@ LIBFDT_1.2 { fdt_resize; fdt_overlay_apply; fdt_get_string; + fdt_find_max_phandle; fdt_get_max_phandle; fdt_check_full; fdt_setprop_placeholder; diff --git a/tests/get_phandle.c b/tests/get_phandle.c index 22bd7b8..6973ee4 100644 --- a/tests/get_phandle.c +++ b/tests/get_phandle.c @@ -46,6 +46,7 @@ int main(int argc, char *argv[]) { uint32_t max; void *fdt; + int err; test_init(argc, argv); fdt = load_blob_arg(argc, argv); @@ -54,6 +55,14 @@ int main(int argc, char *argv[]) check_phandle(fdt, "/subnode@2", PHANDLE_1); check_phandle(fdt, "/subnode@2/subsubnode@0", PHANDLE_2); + err = fdt_find_max_phandle(fdt, &max); + if (err < 0) + FAIL("fdt_find_max_phandle returned %d instead of 0\n", err); + + if (max != PHANDLE_2) + FAIL("fdt_find_max_phandle found 0x%x instead of 0x%x", max, + PHANDLE_2); + max = fdt_get_max_phandle(fdt); if (max != PHANDLE_2) FAIL("fdt_get_max_phandle returned 0x%x instead of 0x%x\n", From 7dfb61ba96b130ab12afa24c7d15f4706ecbb619 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 26 Mar 2019 16:33:01 +0100 Subject: [PATCH 0804/1198] libfdt: Use fdt_find_max_phandle() Use the fdt_find_max_phandle() function instead of the deprecated fdt_get_max_phandle() function. Signed-off-by: Thierry Reding Message-Id: <20190326153302.17109-2-thierry.reding@gmail.com> Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index 5fdab6c..2ad93d2 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -863,12 +863,16 @@ static int overlay_symbol_update(void *fdt, void *fdto) int fdt_overlay_apply(void *fdt, void *fdto) { - uint32_t delta = fdt_get_max_phandle(fdt); + uint32_t delta; int ret; FDT_RO_PROBE(fdt); FDT_RO_PROBE(fdto); + ret = fdt_find_max_phandle(fdt, &delta); + if (ret) + goto err; + ret = overlay_adjust_local_phandles(fdto, delta); if (ret) goto err; From 730875016a6a94bd43e4e88b34a73a814e1051e7 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 26 Mar 2019 16:33:02 +0100 Subject: [PATCH 0805/1198] libfdt: Add phandle generation helper The new fdt_generate_phandle() function can be used to generate a new, unused phandle given a specific device tree blob. The implementation is somewhat naive in that it simply walks the entire device tree to find the highest phandle value and then returns a phandle value one higher than that. A more clever implementation might try to find holes in the current set of phandle values and fill them. But this implementation is relatively simple and works reliably. Also add a test that validates that phandles generated by this new API are indeed unique. Signed-off-by: Thierry Reding Message-Id: <20190326153302.17109-3-thierry.reding@gmail.com> Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 18 ++++++++++++++++++ libfdt/libfdt.h | 19 +++++++++++++++++++ libfdt/version.lds | 1 + tests/get_phandle.c | 30 +++++++++++++++++++++++++++++- tests/multilabel.dts | 5 +++++ tests/multilabel_merge.dts | 5 +++++ tests/references.c | 19 +++++++++++++++++-- tests/references.dts | 5 +++++ 8 files changed, 99 insertions(+), 3 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 1d0335e..817ac39 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -184,6 +184,24 @@ uint32_t fdt_get_max_phandle(const void *fdt) return phandle; } +int fdt_generate_phandle(const void *fdt, uint32_t *phandle) +{ + uint32_t max; + int err; + + err = fdt_find_max_phandle(fdt, &max); + if (err < 0) + return err; + + if (max == FDT_MAX_PHANDLE) + return -FDT_ERR_NOPHANDLES; + + if (phandle) + *phandle = max + 1; + + return 0; +} + static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) { int offset = n * sizeof(struct fdt_reserve_entry); diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index e1498c3..39ff6d5 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -140,6 +140,10 @@ #define FDT_ERR_MAX 17 +/* constants */ +#define FDT_MAX_PHANDLE 0xfffffffe + /* Valid values for phandles range from 1 to 2^32-2. */ + /**********************************************************************/ /* Low-level functions (you probably don't need these) */ /**********************************************************************/ @@ -416,6 +420,21 @@ int fdt_find_max_phandle(const void *fdt, uint32_t *phandle); */ uint32_t fdt_get_max_phandle(const void *fdt); +/** + * fdt_generate_phandle - return a new, unused phandle for a device tree blob + * @fdt: pointer to the device tree blob + * @phandle: return location for the new phandle + * + * Walks the device tree blob and looks for the highest phandle value. On + * success, the new, unused phandle value (one higher than the previously + * 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 + */ +int fdt_generate_phandle(const void *fdt, uint32_t *phandle); + /** * fdt_num_mem_rsv - retrieve the number of memory reserve map entries * @fdt: pointer to the device tree blob diff --git a/libfdt/version.lds b/libfdt/version.lds index 87bbb2f..a8422af 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -68,6 +68,7 @@ LIBFDT_1.2 { fdt_get_string; fdt_find_max_phandle; fdt_get_max_phandle; + fdt_generate_phandle; fdt_check_full; fdt_setprop_placeholder; fdt_property_placeholder; diff --git a/tests/get_phandle.c b/tests/get_phandle.c index 6973ee4..e97b49c 100644 --- a/tests/get_phandle.c +++ b/tests/get_phandle.c @@ -17,6 +17,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include @@ -42,9 +43,30 @@ static void check_phandle(void *fdt, const char *path, uint32_t checkhandle) path, phandle, checkhandle); } +static void check_phandle_unique(const void *fdt, uint32_t checkhandle) +{ + uint32_t phandle; + int offset = -1; + + while (true) { + offset = fdt_next_node(fdt, offset, NULL); + if (offset < 0) { + if (offset == -FDT_ERR_NOTFOUND) + break; + + FAIL("error looking for phandle %#x", checkhandle); + } + + phandle = fdt_get_phandle(fdt, offset); + + if (phandle == checkhandle) + FAIL("generated phandle already exists"); + } +} + int main(int argc, char *argv[]) { - uint32_t max; + uint32_t max, phandle; void *fdt; int err; @@ -68,5 +90,11 @@ int main(int argc, char *argv[]) FAIL("fdt_get_max_phandle returned 0x%x instead of 0x%x\n", max, PHANDLE_2); + err = fdt_generate_phandle(fdt, &phandle); + if (err < 0) + FAIL("failed to generate phandle: %d", err); + + check_phandle_unique(fdt, phandle); + PASS(); } diff --git a/tests/multilabel.dts b/tests/multilabel.dts index 77da06c..d80ebe1 100644 --- a/tests/multilabel.dts +++ b/tests/multilabel.dts @@ -41,4 +41,9 @@ m1: mq: /memreserve/ 0 0x1000; n2 = &n2; n3 = &n3; }; + + node6 { + linux,phandle = <0xfffffffe>; + phandle = <0xfffffffe>; + }; }; diff --git a/tests/multilabel_merge.dts b/tests/multilabel_merge.dts index 3e80298..a27d856 100644 --- a/tests/multilabel_merge.dts +++ b/tests/multilabel_merge.dts @@ -39,6 +39,11 @@ m1: mq: /memreserve/ 0 0x1000; n2 = &n2; n3 = &n3; }; + + node6 { + linux,phandle = <0xfffffffe>; + phandle = <0xfffffffe>; + }; }; / { diff --git a/tests/references.c b/tests/references.c index cab70f6..5b233a4 100644 --- a/tests/references.c +++ b/tests/references.c @@ -76,8 +76,8 @@ static void check_rref(const void *fdt) int main(int argc, char *argv[]) { void *fdt; - int n1, n2, n3, n4, n5; - uint32_t h1, h2, h4, h5; + int n1, n2, n3, n4, n5, n6, err; + uint32_t h1, h2, h4, h5, h6, hn; test_init(argc, argv); fdt = load_blob_arg(argc, argv); @@ -97,11 +97,15 @@ int main(int argc, char *argv[]) n5 = fdt_path_offset(fdt, "/node5"); if (n5 < 0) FAIL("fdt_path_offset(/node5): %s", fdt_strerror(n5)); + n6 = fdt_path_offset(fdt, "/node6"); + if (n6 < 0) + FAIL("fdt_path_offset(/node6): %s", fdt_strerror(n6)); h1 = fdt_get_phandle(fdt, n1); h2 = fdt_get_phandle(fdt, n2); h4 = fdt_get_phandle(fdt, n4); h5 = fdt_get_phandle(fdt, n5); + h6 = fdt_get_phandle(fdt, n6); if (h1 != 0x2000) FAIL("/node1 has wrong phandle, 0x%x instead of 0x%x", @@ -109,6 +113,9 @@ int main(int argc, char *argv[]) if (h2 != 0x1) FAIL("/node2 has wrong phandle, 0x%x instead of 0x%x", h2, 0x1); + if (h6 != FDT_MAX_PHANDLE) + FAIL("/node6 has wrong phandle, 0x%x instead of 0x%x", + h6, FDT_MAX_PHANDLE); if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0)) FAIL("/node4 has bad phandle, 0x%x", h4); @@ -117,6 +124,14 @@ int main(int argc, char *argv[]) if ((h5 == h4) || (h5 == h2) || (h5 == h1)) FAIL("/node5 has duplicate phandle, 0x%x", h5); + /* + * /node6 has phandle FDT_MAX_PHANDLE, so fdt_generate_phandle() is + * expected to fail. + */ + err = fdt_generate_phandle(fdt, &hn); + if (err != -FDT_ERR_NOPHANDLES) + FAIL("generated invalid phandle 0x%x\n", hn); + check_ref(fdt, n1, h2); check_ref(fdt, n2, h1); check_ref(fdt, n3, h4); diff --git a/tests/references.dts b/tests/references.dts index f783e8b..b390639 100644 --- a/tests/references.dts +++ b/tests/references.dts @@ -33,4 +33,9 @@ linux,phandle = <&n5>; phandle = <&n5>; }; + + node6 { + linux,phandle = <0xfffffffe>; + phandle = <0xfffffffe>; + }; }; From cca6546244cba043d8c17c1a1c5224393b544066 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 29 Mar 2019 13:59:04 +1100 Subject: [PATCH 0806/1198] libfdt: Make fdt_get_max_phandle() an inline It's now a trivial wrapper around fdt_find_max_phandle() so we might as well inline it. We also remove it from the versioning linker script. Theoretically, that's a breaking ABI change except that we haven't yet released a version with it exposed in the shared object, so we can get away with it. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 12 ------------ libfdt/libfdt.h | 12 +++++++++++- libfdt/version.lds | 1 - 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 817ac39..2c393a1 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -172,18 +172,6 @@ int fdt_find_max_phandle(const void *fdt, uint32_t *phandle) return 0; } -uint32_t fdt_get_max_phandle(const void *fdt) -{ - uint32_t phandle; - int err; - - err = fdt_find_max_phandle(fdt, &phandle); - if (err < 0) - return (uint32_t)-1; - - return phandle; -} - int fdt_generate_phandle(const void *fdt, uint32_t *phandle) { uint32_t max; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 39ff6d5..1f44177 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -418,7 +418,17 @@ int fdt_find_max_phandle(const void *fdt, uint32_t *phandle); * 0, if no phandle was found in the device tree * -1, if an error occurred */ -uint32_t fdt_get_max_phandle(const void *fdt); +static inline uint32_t fdt_get_max_phandle(const void *fdt) +{ + uint32_t phandle; + int err; + + err = fdt_find_max_phandle(fdt, &phandle); + if (err < 0) + return (uint32_t)-1; + + return phandle; +} /** * fdt_generate_phandle - return a new, unused phandle for a device tree blob diff --git a/libfdt/version.lds b/libfdt/version.lds index a8422af..fbee212 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -67,7 +67,6 @@ LIBFDT_1.2 { fdt_overlay_apply; fdt_get_string; fdt_find_max_phandle; - fdt_get_max_phandle; fdt_generate_phandle; fdt_check_full; fdt_setprop_placeholder; From 26ee65a16c38d7bed4fd6e25962f887115540ced Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 29 Mar 2019 15:13:10 +1100 Subject: [PATCH 0807/1198] Use Python3 by default Python2 is deprecated upstream, lets try to move forwards. Along with it generalize the .gitignore file so we ignore the .pyc files in the new location that Python3 uses. Signed-off-by: David Gibson --- Makefile | 2 +- pylibfdt/.gitignore | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index e6b32cf..275ac5b 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ BISON = bison LEX = flex SWIG = swig PKG_CONFIG ?= pkg-config -PYTHON ?= python2 +PYTHON ?= python3 INSTALL = /usr/bin/install INSTALL_PROGRAM = $(INSTALL) diff --git a/pylibfdt/.gitignore b/pylibfdt/.gitignore index 5e8c5e3..f63a8f1 100644 --- a/pylibfdt/.gitignore +++ b/pylibfdt/.gitignore @@ -1,3 +1,3 @@ libfdt.py -libfdt.pyc +*.pyc libfdt_wrap.c From 6ef8fcd05b740cbedf11d980e0a9ec0c87969448 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 29 Mar 2019 14:14:46 +1100 Subject: [PATCH 0808/1198] Rebuild libfdt shared object if versioning linker script changes The usable content of the shared library varies depending on the symbol versions given in the version.lds linker script, however it's not currently in the make dependencies. Correct that, and move the libfdt rules together for consistency while we're at it. Signed-off-by: David Gibson --- Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 275ac5b..07d618b 100644 --- a/Makefile +++ b/Makefile @@ -194,7 +194,11 @@ include $(LIBFDT_dir)/Makefile.libfdt libfdt: $(LIBFDT_archive) $(LIBFDT_lib) $(LIBFDT_archive): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) -$(LIBFDT_lib): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) + +$(LIBFDT_lib): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) $(LIBFDT_version) + @$(VECHO) LD $@ + $(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) \ + $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) ifneq ($(DEPTARGETS),) -include $(LIBFDT_OBJS:%.o=$(LIBFDT_dir)/%.d) @@ -356,10 +360,6 @@ clean: libfdt_clean pylibfdt_clean tests_clean @$(VECHO) AR $@ $(AR) $(ARFLAGS) $@ $^ -$(LIBFDT_lib): - @$(VECHO) LD $@ - $(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) $^ - %.lex.c: %.l @$(VECHO) LEX $@ $(LEX) -o$@ $< From c5d45188f92344759fbd70275483576c0ce42d82 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 29 Mar 2019 16:15:08 +1100 Subject: [PATCH 0809/1198] Clean up LDLIBS handling We currently set LDLIBS to include libyaml globally if we're using it. However only dtc itself actually needs to link with libyaml - the other tool binaries don't. Avoid that unnecessary inclusion by making LDLIBS handling per-target. Signed-off-by: David Gibson --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 07d618b..ff2b4d1 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ NO_YAML := $(shell $(PKG_CONFIG) --exists yaml-0.1; echo $$?) ifeq ($(NO_YAML),1) CFLAGS += -DNO_YAML else - LDLIBS += $(shell $(PKG_CONFIG) --libs yaml-0.1) + LDLIBS_dtc += $(shell $(PKG_CONFIG) --libs yaml-0.1) endif ifeq ($(HOSTOS),darwin) @@ -330,7 +330,7 @@ clean: libfdt_clean pylibfdt_clean tests_clean # %: %.o @$(VECHO) LD $@ - $(LINK.c) -o $@ $^ $(LDLIBS) + $(LINK.c) -o $@ $^ $(LDLIBS_$*) %.o: %.c @$(VECHO) CC $@ From 00f9febf9c16d932380243a3135ee5aed1adc410 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 29 Mar 2019 16:31:39 +1100 Subject: [PATCH 0810/1198] tests: Rename tests.sh to testutils.sh tests.sh has a bunch of shell setup that's sourced in a number of other scripts. It _doesn't_ actually run a bunch of tests, which is kind of what the name suggests. So rename it to be more obvious. Signed-off-by: David Gibson --- tests/dtc-checkfails.sh | 2 +- tests/dtc-fails.sh | 2 +- tests/dtc-fatal.sh | 2 +- tests/fdtdump-runtest.sh | 2 +- tests/fdtget-runtest.sh | 2 +- tests/fdtoverlay-runtest.sh | 2 +- tests/fdtput-runtest.sh | 2 +- tests/run_tests.sh | 2 +- tests/{tests.sh => testutils.sh} | 0 9 files changed, 8 insertions(+), 8 deletions(-) rename tests/{tests.sh => testutils.sh} (100%) diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh index 7319597..0e8beb4 100755 --- a/tests/dtc-checkfails.sh +++ b/tests/dtc-checkfails.sh @@ -1,6 +1,6 @@ #! /bin/sh -. ./tests.sh +. ./testutils.sh for x; do shift diff --git a/tests/dtc-fails.sh b/tests/dtc-fails.sh index 4ddcb27..4543203 100755 --- a/tests/dtc-fails.sh +++ b/tests/dtc-fails.sh @@ -1,6 +1,6 @@ #! /bin/sh -. ./tests.sh +. ./testutils.sh if [ "$1" = "-n" ]; then NEG="$1" diff --git a/tests/dtc-fatal.sh b/tests/dtc-fatal.sh index 6781ced..22eea69 100644 --- a/tests/dtc-fatal.sh +++ b/tests/dtc-fatal.sh @@ -1,6 +1,6 @@ #! /bin/sh -. ./tests.sh +. ./testutils.sh verbose_run $VALGRIND "$DTC" -o/dev/null "$@" ret="$?" diff --git a/tests/fdtdump-runtest.sh b/tests/fdtdump-runtest.sh index 77593cf..616c737 100644 --- a/tests/fdtdump-runtest.sh +++ b/tests/fdtdump-runtest.sh @@ -4,7 +4,7 @@ # $1 - source file to compile and compare with fdtdump output of the # compiled file. -. ./tests.sh +. ./testutils.sh dts="$1" dtb="${dts}.dtb" diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh index 8d8b058..21044f3 100755 --- a/tests/fdtget-runtest.sh +++ b/tests/fdtget-runtest.sh @@ -1,6 +1,6 @@ #! /bin/sh -. ./tests.sh +. ./testutils.sh LOG=tmp.log.$$ EXPECT=tmp.expect.$$ diff --git a/tests/fdtoverlay-runtest.sh b/tests/fdtoverlay-runtest.sh index 06c1169..c7dbc0f 100644 --- a/tests/fdtoverlay-runtest.sh +++ b/tests/fdtoverlay-runtest.sh @@ -6,7 +6,7 @@ # Usage # fdtoverlay-runtest.sh name expected_output dtb_file node property flags value -. ./tests.sh +. ./testutils.sh LOG=tmp.log.$$ EXPECT=tmp.expect.$$ diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh index 527a968..b5beb90 100644 --- a/tests/fdtput-runtest.sh +++ b/tests/fdtput-runtest.sh @@ -6,7 +6,7 @@ # Usage # fdtput-runtest.sh name expected_output dtb_file node property flags value -. ./tests.sh +. ./testutils.sh LOG=tmp.log.$$ EXPECT=tmp.expect.$$ diff --git a/tests/run_tests.sh b/tests/run_tests.sh index f6b308f..e951959 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -1,6 +1,6 @@ #! /bin/sh -. ./tests.sh +. ./testutils.sh if [ -z "$CC" ]; then CC=gcc diff --git a/tests/tests.sh b/tests/testutils.sh similarity index 100% rename from tests/tests.sh rename to tests/testutils.sh From 5c3513f68921cc15231af7ae6806c1f61c517c7c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 29 Mar 2019 17:20:16 +1100 Subject: [PATCH 0811/1198] Link tools and tests against libfdt shared library Currently the libfdt based tools (fdtput, fdtget, etc.) and all the test binaries using libfdt are linked against the static version of libfdt. That's made it very easy in the past to forget to properly update the version.lds file which is needed to make functions publicaly accessible from the shared library. To avoid problems like that in future, alter the build so that we link and run the tests against the shared library version of libfdt. That immediately points out several important symbols that are still missing from the version.lds, so fix those as well. Signed-off-by: David Gibson --- Makefile | 9 +++++---- libfdt/.gitignore | 1 + libfdt/Makefile.libfdt | 2 ++ libfdt/version.lds | 3 +++ tests/Makefile.tests | 6 +++--- tests/run_tests.sh | 3 +++ 6 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 libfdt/.gitignore diff --git a/Makefile b/Makefile index ff2b4d1..95c2662 100644 --- a/Makefile +++ b/Makefile @@ -184,7 +184,7 @@ endif # LIBFDT_dir = libfdt LIBFDT_archive = $(LIBFDT_dir)/libfdt.a -LIBFDT_lib = $(LIBFDT_dir)/libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) +LIBFDT_lib = $(LIBFDT_dir)/$(LIBFDT_LIB) LIBFDT_include = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_INCLUDES)) LIBFDT_version = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_VERSION)) @@ -199,6 +199,7 @@ $(LIBFDT_lib): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) $(LIBFDT_version) @$(VECHO) LD $@ $(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) \ $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) + ln -s $(LIBFDT_LIB) $(LIBFDT_dir)/$(LIBFDT_soname) ifneq ($(DEPTARGETS),) -include $(LIBFDT_OBJS:%.o=$(LIBFDT_dir)/%.d) @@ -250,11 +251,11 @@ convert-dtsv0: $(CONVERT_OBJS) fdtdump: $(FDTDUMP_OBJS) -fdtget: $(FDTGET_OBJS) $(LIBFDT_archive) +fdtget: $(FDTGET_OBJS) $(LIBFDT_lib) -fdtput: $(FDTPUT_OBJS) $(LIBFDT_archive) +fdtput: $(FDTPUT_OBJS) $(LIBFDT_lib) -fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_archive) +fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_lib) dist: git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \ diff --git a/libfdt/.gitignore b/libfdt/.gitignore new file mode 100644 index 0000000..fed4603 --- /dev/null +++ b/libfdt/.gitignore @@ -0,0 +1 @@ +libfdt.so.1 diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index 3af3656..193da8c 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -9,7 +9,9 @@ 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 LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) +LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) libfdt_clean: @$(VECHO) CLEAN "(libfdt)" rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%) + rm -f $(LIBFDT_dir)/$(LIBFDT_soname) diff --git a/libfdt/version.lds b/libfdt/version.lds index fbee212..9a92652 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -71,6 +71,9 @@ LIBFDT_1.2 { fdt_check_full; fdt_setprop_placeholder; fdt_property_placeholder; + fdt_header_size_; + fdt_appendprop_addrrange; + fdt_setprop_inplace_namelen_partial; local: *; }; diff --git a/tests/Makefile.tests b/tests/Makefile.tests index b77f121..1f8feed 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -58,17 +58,17 @@ TESTS_CLEANDIRS = $(TESTS_CLEANDIRS_L:%=$(TESTS_PREFIX)%) .PHONY: tests tests: $(TESTS) $(TESTS_TREES) -$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive) +$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib) # 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_archive) +$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib) @$(VECHO) LD [libdl] $@ $(LINK.c) -o $@ $^ $(LIBDL) $(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \ - util.o $(LIBFDT_archive) + util.o $(LIBFDT_lib) $(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o diff --git a/tests/run_tests.sh b/tests/run_tests.sh index e951959..489a3d2 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -18,6 +18,9 @@ if [ -z "$STATSZ" ]; then fi fi +# Help things find the libfdt shared object +export LD_LIBRARY_PATH=../libfdt + export QUIET_TEST=1 STOP_ON_FAIL=0 From 8f695676227be42074711f3464d8c9f82bd80999 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 6 May 2019 17:00:07 +1000 Subject: [PATCH 0812/1198] Avoid assertion in check_interrupts_property() If running on a tree with an 'interrupt-parent' property which contains an invalid phandle (0 or -1, not merely for a node which doesn't exist), then check_interrupts_property() will trip the assertion in get_node_by_phandle(). There's logic that almost detects this, but it only handles the overlay case, where we can't fully check because the links will be fixed up later. For the non-overlay case, this is definitely a bad property, but we shouldn't crash. Fix it by failing the check early. Fixes: c1e55a5513e9 ("checks: fix handling of unresolved phandles for dts plugins") Fixes: ee3d26f6960b ("checks: add interrupts property check") Signed-off-by: David Gibson --- checks.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/checks.c b/checks.c index 0524d41..4719d65 100644 --- a/checks.c +++ b/checks.c @@ -1580,10 +1580,14 @@ static void check_interrupts_property(struct check *c, prop = get_property(parent, "interrupt-parent"); if (prop) { phandle = propval_cell(prop); - /* Give up if this is an overlay with external references */ - if ((phandle == 0 || phandle == -1) && - (dti->dtsflags & DTSF_PLUGIN)) + if ((phandle == 0) || (phandle == -1)) { + /* Give up if this is an overlay with + * external references */ + if (dti->dtsflags & DTSF_PLUGIN) return; + FAIL_PROP(c, dti, parent, prop, "Invalid phandle"); + continue; + } irq_node = get_node_by_phandle(root, phandle); if (!irq_node) { From 228a44cce857feeae55362a0c95689bc82123ed6 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 9 May 2019 19:41:20 +1000 Subject: [PATCH 0813/1198] libfdt: Ensure fdt_add_property frees allocated name string on failure If fdt_add_property or fdt_property_placeholder fail after allocating a string for the name, they return without freeing that string. This does not change the structure of the tree, but in very specific cases it could lead to undesirable space consumption. Fix this by rolling back the string allocation in this situation. Signed-off-by: Nicholas Piggin Message-Id: <20190509094122.834-2-npiggin@gmail.com> Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 22 ++++++++-- libfdt/fdt_sw.c | 23 +++++++++-- tests/.gitignore | 1 + tests/Makefile.tests | 2 +- tests/run_tests.sh | 2 + tests/rw_oom.c | 96 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 tests/rw_oom.c diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 2e49855..9e76615 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -136,6 +136,14 @@ static int fdt_splice_struct_(void *fdt, void *p, return 0; } +/* Must only be used to roll back in case of error */ +static void fdt_del_last_string_(void *fdt, const char *s) +{ + int newlen = strlen(s) + 1; + + fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen); +} + static int fdt_splice_string_(void *fdt, int newlen) { void *p = (char *)fdt @@ -149,7 +157,7 @@ static int fdt_splice_string_(void *fdt, int newlen) return 0; } -static int fdt_find_add_string_(void *fdt, const char *s) +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) { char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); const char *p; @@ -157,6 +165,8 @@ static int fdt_find_add_string_(void *fdt, const char *s) int len = strlen(s) + 1; int err; + *allocated = 0; + p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); if (p) /* found it */ @@ -167,6 +177,8 @@ static int fdt_find_add_string_(void *fdt, const char *s) if (err) return err; + *allocated = 1; + memcpy(new, s, len); return (new - strtab); } @@ -225,11 +237,12 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, int nextoffset; int namestroff; int err; + int allocated; if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) return nextoffset; - namestroff = fdt_find_add_string_(fdt, name); + namestroff = fdt_find_add_string_(fdt, name, &allocated); if (namestroff < 0) return namestroff; @@ -237,8 +250,11 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, proplen = sizeof(**prop) + FDT_TAGALIGN(len); err = fdt_splice_struct_(fdt, *prop, 0, proplen); - if (err) + if (err) { + if (allocated) + fdt_del_last_string_(fdt, name); return err; + } (*prop)->tag = cpu_to_fdt32(FDT_PROP); (*prop)->nameoff = cpu_to_fdt32(namestroff); diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 9fa4a94..113f28a 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -262,7 +262,16 @@ int fdt_end_node(void *fdt) return 0; } -static int fdt_find_add_string_(void *fdt, const char *s) +/* Must only be used to roll back in case of error */ +static void fdt_del_last_string_(void *fdt, const char *s) +{ + int strtabsize = fdt_size_dt_strings(fdt); + int len = strlen(s) + 1; + + fdt_set_size_dt_strings(fdt, strtabsize - len); +} + +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) { char *strtab = (char *)fdt + fdt_totalsize(fdt); const char *p; @@ -270,11 +279,15 @@ static int fdt_find_add_string_(void *fdt, const char *s) int len = strlen(s) + 1; int struct_top, offset; + *allocated = 0; + p = fdt_find_string_(strtab - strtabsize, strtabsize, s); if (p) return p - strtab; /* Add it */ + *allocated = 1; + offset = -strtabsize - len; struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); if (fdt_totalsize(fdt) + offset < struct_top) @@ -289,16 +302,20 @@ int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) { struct fdt_property *prop; int nameoff; + int allocated; FDT_SW_PROBE_STRUCT(fdt); - nameoff = fdt_find_add_string_(fdt, name); + nameoff = fdt_find_add_string_(fdt, name, &allocated); if (nameoff == 0) return -FDT_ERR_NOSPACE; prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); - if (! prop) + if (! prop) { + if (allocated) + fdt_del_last_string_(fdt, name); return -FDT_ERR_NOSPACE; + } prop->tag = cpu_to_fdt32(FDT_PROP); prop->nameoff = cpu_to_fdt32(nameoff); diff --git a/tests/.gitignore b/tests/.gitignore index 0bc78aa..d3f1434 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -56,6 +56,7 @@ tmp.* /references /root_node /rw_tree1 +/rw_oom /set_name /setprop /setprop_inplace diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 1f8feed..5093aaa 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -15,7 +15,7 @@ LIB_TESTS_L = get_mem_rsv \ setprop_inplace nop_property nop_node \ sw_tree1 sw_states \ move_and_save mangle-layout nopulate \ - open_pack rw_tree1 set_name setprop del_property del_node \ + 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 \ diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 489a3d2..d350c3d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -421,6 +421,8 @@ libfdt_tests () { tree1_tests_rw noppy.$basetree done + run_test rw_oom + run_dtc_test -I dts -O dtb -o subnode_iterate.dtb subnode_iterate.dts run_test subnode_iterate subnode_iterate.dtb diff --git a/tests/rw_oom.c b/tests/rw_oom.c new file mode 100644 index 0000000..a787dc2 --- /dev/null +++ b/tests/rw_oom.c @@ -0,0 +1,96 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_nop_node() + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +/* This is not derived programatically. May require adjustment to changes. */ +#define SPACE 285 + +#define CHECK(code) \ + { \ + err = (code); \ + if (err) \ + FAIL(#code ": %s", fdt_strerror(err)); \ + } + +#define OFF_CHECK(off, code) \ + { \ + (off) = (code); \ + if (off < 0) \ + FAIL(#code ": %s", fdt_strerror(off)); \ + } + +int main(int argc, char *argv[]) +{ + void *fdt; + int err; + int offset, s1; + int strsize1, strsize2; + + /* + * Check OOM path, and check that property is cleaned up if it fails + * with OOM, rather than adding an orphan name. + * + * SW OOM is tested with the realloc/resize strategies. + */ + test_init(argc, argv); + + fdt = xmalloc(SPACE); + + /* First create empty tree with SW */ + CHECK(fdt_create_empty_tree(fdt, SPACE)); + + CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_1, TEST_SIZE_1)); + CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2)); + + CHECK(fdt_setprop_string(fdt, 0, "compatible", "test_oom")); + CHECK(fdt_setprop_u32(fdt, 0, "prop-int", TEST_VALUE_1)); + CHECK(fdt_setprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1)); + CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1)); + + OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@1")); + s1 = offset; + + strsize1 = fdt_size_dt_strings(fdt); + err = fdt_setprop_string(fdt, s1, "unique", "subnode1"); + if (err != -FDT_ERR_NOSPACE) + FAIL("fdt_setprop_string(fdt, s1, \"compatible\", \"subnode1\"): %s", fdt_strerror(err)); + strsize2 = fdt_size_dt_strings(fdt); + + if (strsize1 != strsize2) + FAIL("fdt_setprop NOSPACE error failed to clean up allocated string\n"); + err = 0; + + /* Ensure we failed in the right place */ + CHECK(fdt_setprop_string(fdt, s1, "unique", "")); + + CHECK(fdt_pack(fdt)); + + PASS(); +} From fbb62754ce4529bee382390b8caa5e5b47519928 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 9 May 2019 19:41:21 +1000 Subject: [PATCH 0814/1198] libfdt: Introduce fdt_create_with_flags() There is a need to be able to specify some options when building an FDT with the SW interface. This can be accomplished with minimal changes by storing intermediate data in the fdt header itself, in fields that are not otherwise needed during the creation process and can be set by fdt_finish(). The fdt.magic field is already used exactly this way, as a state to check with callers that the FDT has been created but not yet finished. fdt.version and fdt.last_comp_version are used to make room for more intermediate state. These are adjacent and unused during the building process. last_comp_version is not yet used for intermediate state, but it is zeroed and treated as used, so as to allow future growth easily. A new interface, fdt_create_with_flags() is added, which takes 32-bit flag value to control creation. Signed-off-by: Nicholas Piggin Message-Id: <20190509094122.834-3-npiggin@gmail.com> Signed-off-by: David Gibson --- libfdt/fdt_strerror.c | 1 + libfdt/fdt_sw.c | 30 ++++++++++++++++++++++++++++-- libfdt/libfdt.h | 38 +++++++++++++++++++++++++++++++++++++- libfdt/version.lds | 1 + 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c index 9677a18..0e6b4fd 100644 --- a/libfdt/fdt_strerror.c +++ b/libfdt/fdt_strerror.c @@ -82,6 +82,7 @@ static struct fdt_errtabent fdt_errtable[] = { FDT_ERRTABENT(FDT_ERR_BADVALUE), FDT_ERRTABENT(FDT_ERR_BADOVERLAY), FDT_ERRTABENT(FDT_ERR_NOPHANDLES), + FDT_ERRTABENT(FDT_ERR_BADFLAGS), }; #define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 113f28a..ba05868 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -121,6 +121,12 @@ static int fdt_sw_probe_struct_(void *fdt) return err; \ } +static inline uint32_t sw_flags(void *fdt) +{ + /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */ + return fdt_last_comp_version(fdt); +} + /* 'complete' state: Enter this state after fdt_finish() * * Allowed functions: none @@ -141,7 +147,7 @@ static void *fdt_grab_space_(void *fdt, size_t len) return fdt_offset_ptr_w_(fdt, offset); } -int fdt_create(void *buf, int bufsize) +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)); @@ -150,11 +156,22 @@ int fdt_create(void *buf, int bufsize) if (bufsize < hdrsize) return -FDT_ERR_NOSPACE; + if (flags & ~FDT_CREATE_FLAGS_ALL) + return -FDT_ERR_BADFLAGS; + memset(buf, 0, bufsize); + /* + * magic and last_comp_version keep intermediate state during the fdt + * creation process, which is replaced with the proper FDT format by + * fdt_finish(). + * + * flags should be accessed with sw_flags(). + */ fdt_set_magic(fdt, FDT_SW_MAGIC); fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); - fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); + fdt_set_last_comp_version(fdt, flags); + fdt_set_totalsize(fdt, bufsize); fdt_set_off_mem_rsvmap(fdt, hdrsize); @@ -164,6 +181,11 @@ int fdt_create(void *buf, int bufsize) return 0; } +int fdt_create(void *buf, int bufsize) +{ + return fdt_create_with_flags(buf, bufsize, 0); +} + int fdt_resize(void *fdt, void *buf, int bufsize) { size_t headsize, tailsize; @@ -377,6 +399,10 @@ int fdt_finish(void *fdt) /* Finally, adjust the header */ 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_magic(fdt, FDT_MAGIC); + return 0; } diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 1f44177..c2dee3e 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -138,7 +138,11 @@ /* FDT_ERR_NOPHANDLES: The device tree doesn't have any * phandle available anymore without causing an overflow */ -#define FDT_ERR_MAX 17 +#define FDT_ERR_BADFLAGS 18 + /* 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 /* constants */ #define FDT_MAX_PHANDLE 0xfffffffe @@ -1429,7 +1433,39 @@ int fdt_nop_node(void *fdt, int nodeoffset); /* Sequential write functions */ /**********************************************************************/ +#define FDT_CREATE_FLAGS_ALL 0 + +/** + * fdt_create_with_flags - begin creation of a new fdt + * @fdt: 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. + * + * 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. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt + * -FDT_ERR_BADFLAGS, flags is not valid + */ +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 + * @bufsize: size of the memory space at fdt + * + * fdt_create() is equivalent to fdt_create_with_flags() with flags=0. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt + */ int fdt_create(void *buf, int bufsize); + int fdt_resize(void *fdt, void *buf, int bufsize); int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); int fdt_finish_reservemap(void *fdt); diff --git a/libfdt/version.lds b/libfdt/version.lds index 9a92652..0d52217 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -74,6 +74,7 @@ LIBFDT_1.2 { fdt_header_size_; fdt_appendprop_addrrange; fdt_setprop_inplace_namelen_partial; + fdt_create_with_flags; local: *; }; From ce01b21098a48da11c5c6d39ba288f17a91c17f4 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 9 May 2019 19:41:22 +1000 Subject: [PATCH 0815/1198] libfdt: Add FDT_CREATE_FLAG_NO_NAME_DEDUP flag that trades size for speed Searching for duplicate names scales O(n^2) with the number of names added to a fdt, which can cause a noticable slowdown with larger device trees and very slow CPU cores. Add FDT_CREATE_FLAG_NO_NAME_DEDUP that allow the caller to trade fdt size for speed in the creation process. Signed-off-by: Nicholas Piggin Message-Id: <20190509094122.834-4-npiggin@gmail.com> Signed-off-by: David Gibson --- libfdt/fdt_sw.c | 39 ++++++++++++++++++++++++++------------- libfdt/libfdt.h | 8 +++++++- tests/run_tests.sh | 26 ++++++++++++++------------ tests/sw_tree1.c | 45 +++++++++++++++++++++++++++++++++++++-------- 4 files changed, 84 insertions(+), 34 deletions(-) diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index ba05868..e773157 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -284,6 +284,23 @@ int fdt_end_node(void *fdt) return 0; } +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; + + offset = -strtabsize - len; + struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + if (fdt_totalsize(fdt) + offset < struct_top) + return 0; /* no more room :( */ + + memcpy(strtab + offset, s, len); + fdt_set_size_dt_strings(fdt, strtabsize + len); + return offset; +} + /* Must only be used to roll back in case of error */ static void fdt_del_last_string_(void *fdt, const char *s) { @@ -296,10 +313,8 @@ static void fdt_del_last_string_(void *fdt, const char *s) static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) { char *strtab = (char *)fdt + fdt_totalsize(fdt); - const char *p; int strtabsize = fdt_size_dt_strings(fdt); - int len = strlen(s) + 1; - int struct_top, offset; + const char *p; *allocated = 0; @@ -307,17 +322,9 @@ static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) if (p) return p - strtab; - /* Add it */ *allocated = 1; - offset = -strtabsize - len; - struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); - if (fdt_totalsize(fdt) + offset < struct_top) - return 0; /* no more room :( */ - - memcpy(strtab + offset, s, len); - fdt_set_size_dt_strings(fdt, strtabsize + len); - return offset; + return fdt_add_string_(fdt, s); } int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) @@ -328,7 +335,13 @@ int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) FDT_SW_PROBE_STRUCT(fdt); - nameoff = fdt_find_add_string_(fdt, name, &allocated); + /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */ + if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) { + allocated = 1; + nameoff = fdt_add_string_(fdt, name); + } else { + nameoff = fdt_find_add_string_(fdt, name, &allocated); + } if (nameoff == 0) return -FDT_ERR_NOSPACE; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index c2dee3e..0684ec2 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1433,7 +1433,13 @@ int fdt_nop_node(void *fdt, int nodeoffset); /* Sequential write functions */ /**********************************************************************/ -#define FDT_CREATE_FLAGS_ALL 0 +/* fdt_create_with_flags flags */ +#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1 + /* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property + * names in the fdt. This can result in faster creation times, but + * a larger fdt. */ + +#define FDT_CREATE_FLAGS_ALL (FDT_CREATE_FLAG_NO_NAME_DEDUP) /** * fdt_create_with_flags - begin creation of a new fdt diff --git a/tests/run_tests.sh b/tests/run_tests.sh index d350c3d..07c3489 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -354,19 +354,21 @@ libfdt_tests () { run_dtc_test -I dts -O dtb -o stringlist.test.dtb stringlist.dts run_test stringlist stringlist.test.dtb - # Sequential write tests - run_test sw_tree1 - tree1_tests sw_tree1.test.dtb - tree1_tests unfinished_tree1.test.dtb - run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb - run_test sw_states + for flags in default no_name_dedup; do + # Sequential write tests + run_test sw_tree1 fixed $flags + tree1_tests sw_tree1.test.dtb + tree1_tests unfinished_tree1.test.dtb + run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb + run_test sw_states - # Resizing tests - for mode in resize realloc newalloc; do - run_test sw_tree1 $mode - tree1_tests sw_tree1.test.dtb - tree1_tests unfinished_tree1.test.dtb - run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb + # Resizing tests + for mode in resize realloc newalloc; do + run_test sw_tree1 $mode $flags + tree1_tests sw_tree1.test.dtb + tree1_tests unfinished_tree1.test.dtb + run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb + done done # fdt_move tests diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 2a67c12..08b39b3 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -114,14 +114,19 @@ int main(int argc, char *argv[]) void *place; const char place_str[] = "this is a placeholder string\0string2"; int place_len = sizeof(place_str); + int create_flags; test_init(argc, argv); - if (argc == 1) { - alloc_mode = FIXED; - size = SPACE; - } else if (argc == 2) { - if (streq(argv[1], "resize")) { + alloc_mode = FIXED; + size = SPACE; + create_flags = 0; + + if (argc == 2 || argc == 3) { + if (streq(argv[1], "fixed")) { + alloc_mode = FIXED; + size = SPACE; + } else if (streq(argv[1], "resize")) { alloc_mode = REALLOC; size = 0; } else if (streq(argv[1], "realloc")) { @@ -140,12 +145,36 @@ int main(int argc, char *argv[]) CONFIG("Bad allocation mode \"%s\" specified", argv[1]); } - } else { - CONFIG("sw_tree1 []"); + } + if (argc == 3) { + char *str = argv[2], *saveptr, *tok; + bool default_flag = false; + + while ((tok = strtok_r(str, ",", &saveptr)) != NULL) { + str = NULL; + if (streq(tok, "default")) { + default_flag = true; + } else if (streq(tok, "no_name_dedup")) { + create_flags |= FDT_CREATE_FLAG_NO_NAME_DEDUP; + } else if (streq(tok, "bad")) { + create_flags |= 0xffffffff; + } else { + CONFIG("Bad creation flags \"%s\" specified", + argv[2]); + } + } + + if (default_flag && create_flags != 0) + CONFIG("Bad creation flags \"%s\" specified", + argv[2]); + } + + if (argc > 3) { + CONFIG("sw_tree1 [] []"); } fdt = xmalloc(size); - CHECK(fdt_create(fdt, size)); + CHECK(fdt_create_with_flags(fdt, size, create_flags)); created = true; From 243176c4ce84256913fcf8f99ffbdd82ff6c7593 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 10 May 2019 11:57:19 +1000 Subject: [PATCH 0816/1198] Fix bogus error on rebuild Currently if a file is touched requiring libfdt.so rebuild, it will fail because the ln -s command will attempt to replace an already existing link an error. Correct this by using ln -sf. Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 95c2662..0cb2bfe 100644 --- a/Makefile +++ b/Makefile @@ -199,7 +199,7 @@ $(LIBFDT_lib): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) $(LIBFDT_version) @$(VECHO) LD $@ $(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) \ $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) - ln -s $(LIBFDT_LIB) $(LIBFDT_dir)/$(LIBFDT_soname) + ln -sf $(LIBFDT_LIB) $(LIBFDT_dir)/$(LIBFDT_soname) ifneq ($(DEPTARGETS),) -include $(LIBFDT_OBJS:%.o=$(LIBFDT_dir)/%.d) From 25bb080c18d1a8a96760e26257bf8c80ec7fcab4 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 20 May 2019 09:27:20 +0200 Subject: [PATCH 0817/1198] Update the GPL2 text to the latest revision This patch replaces the GPL2 text with the latest one from: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt The FSF moved to a different location quite a while ago already, and the latest revision recommends to use the LGPL-2.1 ("Lesser" license) instead of the LGPL-2.0 ("Library" license) in certain cases. Signed-off-by: Thomas Huth Message-Id: <20190520072720.14755-1-thuth@redhat.com> Signed-off-by: David Gibson --- GPL | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/GPL b/GPL index d60c31a..d159169 100644 --- a/GPL +++ b/GPL @@ -1,12 +1,12 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to +the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not @@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. - - GNU GENERAL PUBLIC LICENSE + + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains @@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions: License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) - + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in @@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - + 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is @@ -225,7 +225,7 @@ impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - + 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License @@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) year name of author + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. @@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names: This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General +library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. From 825146d13dc0430e72c1c65b61cb1aa35e559fca Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 20 May 2019 10:12:09 +0200 Subject: [PATCH 0818/1198] Fix typos in various documentation and source files The typos have been discovered with the "codespell" utility. Signed-off-by: Thomas Huth Message-Id: <20190520081209.20415-1-thuth@redhat.com> Signed-off-by: David Gibson --- Documentation/manual.txt | 12 ++++++------ README.license | 4 ++-- flattree.c | 2 +- libfdt/fdt_overlay.c | 4 ++-- livetree.c | 2 +- tests/fdtoverlay-runtest.sh | 2 +- tests/fdtput-runtest.sh | 2 +- tests/integer-expressions.c | 2 +- tests/run_tests.sh | 4 ++-- tests/rw_oom.c | 2 +- tests/sourceoutput.dts | 2 +- tests/testutils.c | 2 +- util.h | 4 ++-- 13 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Documentation/manual.txt b/Documentation/manual.txt index db32dd7..adf5ccb 100644 --- a/Documentation/manual.txt +++ b/Documentation/manual.txt @@ -37,7 +37,7 @@ The upstream repository is here: git://git.kernel.org/pub/scm/utils/dtc/dtc.git https://git.kernel.org/pub/scm/utils/dtc/dtc.git -The gitweb interface for the upstream respository is: +The gitweb interface for the upstream repository is: https://git.kernel.org/cgit/utils/dtc/dtc.git/ @@ -234,7 +234,7 @@ For example: "childnode at address". It in turn has a string property called "childprop". - childnode@addresss { + childnode@address { childprop = "hello\n"; }; @@ -253,7 +253,7 @@ Labels may be applied to nodes or properties. Labels appear before a node name, and are referenced using an ampersand: &label. Absolute node path names are also allowed in node references. -In this exmaple, a node is labled "mpic" and then referenced: +In this example, a node is labeled "mpic" and then referenced: mpic: interrupt-controller@40000 { ... @@ -264,7 +264,7 @@ In this exmaple, a node is labled "mpic" and then referenced: ... }; -And used in properties, lables may appear before or after any value: +And used in properties, labels may appear before or after any value: randomnode { prop: string = data: "mystring\n" data_end: ; @@ -418,7 +418,7 @@ value of r3. among others, by kexec. If you are on an SMP system, this value should match the content of the "reg" property of the CPU node in the device-tree corresponding to the CPU calling the kernel entry - point (see further chapters for more informations on the required + point (see further chapters for more information on the required device-tree contents) - size_dt_strings @@ -584,7 +584,7 @@ looks like in practice. This tree is almost a minimal tree. It pretty much contains the minimal set of required nodes and properties to boot a linux kernel; -that is, some basic model informations at the root, the CPUs, and the +that is, some basic model information at the root, the CPUs, and the physical memory layout. It also includes misc information passed through /chosen, like in this example, the platform type (mandatory) and the kernel command line arguments (optional). diff --git a/README.license b/README.license index d56c88f..50e9fca 100644 --- a/README.license +++ b/README.license @@ -4,7 +4,7 @@ Licensing and contribution policy of dtc and libfdt This dtc package contains two pieces of software: dtc itself, and libfdt which comprises the files in the libfdt/ subdirectory. These two pieces of software, although closely related, are quite distinct. -dtc does not incoporate or rely on libfdt for its operation, nor vice +dtc does not incorporate or rely on libfdt for its operation, nor vice versa. It is important that these two pieces of software have different license conditions. @@ -33,7 +33,7 @@ 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 rocket science; so the incentive for such impolite behaviour is small, -and the inconvenience caused therby is not dire. +and the inconvenience caused thereby is not dire. Licenses such as the LGPL which would allow code to be used in non-GPL software, but also require contributions to be returned were diff --git a/flattree.c b/flattree.c index acf04c3..f7f7076 100644 --- a/flattree.c +++ b/flattree.c @@ -525,7 +525,7 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version) fprintf(f, "/* Memory reserve map from source file */\n"); /* - * Use .long on high and low halfs of u64s to avoid .quad + * Use .long on high and low halves of u64s to avoid .quad * as it appears .quad isn't available in some assemblers. */ for (re = dti->reservelist; re; re = re->next) { diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index 2ad93d2..d3e9ab2 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -93,11 +93,11 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) * @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 targetting is + * device tree of a fragment, no matter how the actual targeting is * done (through a phandle or a path) * * returns: - * the targetted node offset in the base device tree + * 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, diff --git a/livetree.c b/livetree.c index 7a2e644..ae47e1a 100644 --- a/livetree.c +++ b/livetree.c @@ -970,7 +970,7 @@ static void add_local_fixup_entry(struct dt_info *dti, char **compp; int i, depth; - /* walk back retreiving depth */ + /* walk back retrieving depth */ depth = 0; for (wn = node; wn; wn = wn->parent) depth++; diff --git a/tests/fdtoverlay-runtest.sh b/tests/fdtoverlay-runtest.sh index c7dbc0f..7c54beb 100644 --- a/tests/fdtoverlay-runtest.sh +++ b/tests/fdtoverlay-runtest.sh @@ -1,7 +1,7 @@ #! /bin/sh # Run script for fdtoverlay tests -# We run fdtoverlay to generate a target device tree, thn fdtget to check it +# We run fdtoverlay to generate a target device tree, then fdtget to check it # Usage # fdtoverlay-runtest.sh name expected_output dtb_file node property flags value diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh index b5beb90..a1f7b85 100644 --- a/tests/fdtput-runtest.sh +++ b/tests/fdtput-runtest.sh @@ -1,7 +1,7 @@ #! /bin/sh # Run script for fdtput tests -# We run fdtput to update the device tree, thn fdtget to check it +# We run fdtput to update the device tree, then fdtget to check it # Usage # fdtput-runtest.sh name expected_output dtb_file node property flags value diff --git a/tests/integer-expressions.c b/tests/integer-expressions.c index ed1f967..b0b2d8b 100644 --- a/tests/integer-expressions.c +++ b/tests/integer-expressions.c @@ -97,7 +97,7 @@ int main(int argc, char *argv[]) res = fdt_getprop(fdt, 0, "expressions", &reslen); if (!res) - FAIL("Error retreiving expression results: %s\n", + FAIL("Error retrieving expression results: %s\n", fdt_strerror(reslen)); if (reslen != (ARRAY_SIZE(expr_table) * sizeof(uint32_t))) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 07c3489..646a4d9 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -287,7 +287,7 @@ dtc_overlay_tests () { run_dtc_test -I dts -O dtb -o overlay_overlay_decompile.test.dtb overlay_overlay_decompile.test.dts run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_decompile.test.dtb - # Test generation of aliases insted of symbols + # Test generation of aliases instead of symbols run_dtc_test -A -I dts -O dtb -o overlay_base_with_aliases.dtb overlay_base.dts run_test check_path overlay_base_with_aliases.dtb exists "/aliases" run_test check_path overlay_base_with_aliases.dtb not-exists "/__symbols__" @@ -874,7 +874,7 @@ fdtput_tests () { "-ts" "fine wine" run_wrap_test $DTPUT $dtb -p /you/are/drunk/sir/winston slurp -ts twice - # Test expansion of the blob when insufficent room for a new node + # Test expansion of the blob when insufficient room for a new node run_wrap_test $DTPUT $dtb -cp "$(cat $text $text)/longish" # Allowed to create an existing node with -p diff --git a/tests/rw_oom.c b/tests/rw_oom.c index a787dc2..24bfe05 100644 --- a/tests/rw_oom.c +++ b/tests/rw_oom.c @@ -29,7 +29,7 @@ #include "tests.h" #include "testdata.h" -/* This is not derived programatically. May require adjustment to changes. */ +/* This is not derived programmatically. May require adjustment to changes. */ #define SPACE 285 #define CHECK(code) \ diff --git a/tests/sourceoutput.dts b/tests/sourceoutput.dts index 477762f..5a7459b 100644 --- a/tests/sourceoutput.dts +++ b/tests/sourceoutput.dts @@ -2,7 +2,7 @@ / { /* Some versions had an off-by-2 bug which caused an abort - * when outputing labels within strings like this in source + * when outputting labels within strings like this in source * format */ prop1: prop1 = start1: "foo", mid1: "bar" end1: ; diff --git a/tests/testutils.c b/tests/testutils.c index a250d5a..24bd81e 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -112,7 +112,7 @@ void check_property(void *fdt, int nodeoffset, const char *name, prop = fdt_get_property(fdt, nodeoffset, name, &retlen); verbose_printf("pointer %p\n", prop); if (! prop) - FAIL("Error retreiving \"%s\" pointer: %s", name, + FAIL("Error retrieving \"%s\" pointer: %s", name, fdt_strerror(retlen)); tag = fdt32_to_cpu(prop->tag); diff --git a/util.h b/util.h index 7658781..fc3c0d0 100644 --- a/util.h +++ b/util.h @@ -122,7 +122,7 @@ int utilfdt_read_err(const char *filename, char **buffp, size_t *len); * stderr. * * @param filename The filename to write, or - for stdout - * @param blob Poiner to buffer containing fdt + * @param blob Pointer to buffer containing fdt * @return 0 if ok, -1 on error */ int utilfdt_write(const char *filename, const void *blob); @@ -133,7 +133,7 @@ int utilfdt_write(const char *filename, const void *blob); * an error message for the user. * * @param filename The filename to write, or - for stdout - * @param blob Poiner to buffer containing fdt + * @param blob Pointer to buffer containing fdt * @return 0 if ok, else an errno value representing the error */ int utilfdt_write_err(const char *filename, const void *blob); From 87963ee2069337d0a2fb54ae7bcd003ecfd53eeb Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 17 May 2019 15:28:04 -0500 Subject: [PATCH 0819/1198] livetree: add missing type markers in generated overlay properties The YAML output fails for overlays and when symbol generation are enabled due to missing markers in the generated properties. Add type markers when generating properties under '__symbols__' and '__fixups__' nodes as well as target-path properties. As a side effect of append_to_property() changes, this also sets type markers in '__local_fixups__' node properties. Signed-off-by: Rob Herring Message-Id: <20190517202804.9084-1-robh@kernel.org> Signed-off-by: David Gibson --- dtc.h | 3 ++- livetree.c | 18 +++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/dtc.h b/dtc.h index 789e0b1..0d5fa21 100644 --- a/dtc.h +++ b/dtc.h @@ -231,7 +231,8 @@ void add_child(struct node *parent, struct node *child); void delete_node_by_name(struct node *parent, char *name); void delete_node(struct node *node); void append_to_property(struct node *node, - char *name, const void *data, int len); + char *name, const void *data, int len, + enum markertype type); const char *get_unitname(struct node *node); struct property *get_property(struct node *node, const char *propname); diff --git a/livetree.c b/livetree.c index ae47e1a..21c2741 100644 --- a/livetree.c +++ b/livetree.c @@ -249,6 +249,7 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) char *name; if (ref[0] == '/') { + d = data_add_marker(d, TYPE_STRING, ref); d = data_append_data(d, ref, strlen(ref) + 1); p = build_property("target-path", d, NULL); @@ -350,17 +351,20 @@ void delete_node(struct node *node) } void append_to_property(struct node *node, - char *name, const void *data, int len) + 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_append_data(p->val, data, len); + d = data_add_marker(p->val, type, name); + d = data_append_data(d, data, len); p->val = d; } else { - d = data_append_data(empty_data, data, len); + d = data_add_marker(empty_data, type, name); + d = data_append_data(d, data, len); p = build_property(name, d, NULL); add_property(node, p); } @@ -858,8 +862,8 @@ static void generate_label_tree_internal(struct dt_info *dti, /* insert it */ p = build_property(l->label, - data_copy_mem(node->fullpath, - strlen(node->fullpath) + 1), + data_copy_escape_string(node->fullpath, + strlen(node->fullpath)), NULL); add_property(an, p); } @@ -910,7 +914,7 @@ 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); + append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING); free(entry); } @@ -993,7 +997,7 @@ 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)); + append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32); } static void generate_local_fixups_tree_internal(struct dt_info *dti, From acfe84f2c47ed26de26071a56c6d6979ca295e6e Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 20 Jun 2019 15:19:38 -0600 Subject: [PATCH 0820/1198] dtc: Replace GPLv2 boilerplate/reference with SPDX tags Replace instances of GPLv2 or later boilerplate with SPDX tags. Signed-off-by: Rob Herring Message-Id: <20190620211944.9378-2-robh@kernel.org> Signed-off-by: David Gibson --- Makefile.dtc | 1 + checks.c | 17 +---------------- convert-dtsv0-lexer.l | 16 +--------------- data.c | 17 +---------------- dtc-lexer.l | 17 +---------------- dtc-parser.y | 17 +---------------- dtc.c | 17 +---------------- dtc.h | 17 +---------------- fdtget.c | 16 +--------------- fdtoverlay.c | 16 +--------------- fdtput.c | 16 +--------------- flattree.c | 17 +---------------- fstree.c | 17 +---------------- livetree.c | 17 +---------------- srcpos.c | 16 +--------------- srcpos.h | 16 +--------------- treesource.c | 17 +---------------- util.c | 16 +--------------- util.h | 16 +--------------- yamltree.c | 16 +--------------- 20 files changed, 20 insertions(+), 295 deletions(-) diff --git a/Makefile.dtc b/Makefile.dtc index d437563..9c467b0 100644 --- a/Makefile.dtc +++ b/Makefile.dtc @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later # Makefile.dtc # # This is not a complete Makefile of itself. Instead, it is designed to diff --git a/checks.c b/checks.c index 4719d65..d7986ee 100644 --- a/checks.c +++ b/checks.c @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2007. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include "dtc.h" diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l index d6d68cd..f52e8a1 100644 --- a/convert-dtsv0-lexer.l +++ b/convert-dtsv0-lexer.l @@ -1,20 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * (C) Copyright David Gibson , IBM Corporation. 2005, 2008. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ %option noyywrap nounput noinput never-interactive diff --git a/data.c b/data.c index 4a20414..0a43b6d 100644 --- a/data.c +++ b/data.c @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include "dtc.h" diff --git a/dtc-lexer.l b/dtc-lexer.l index 06c0409..5c6c3fd 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -1,21 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ %option noyywrap nounput noinput never-interactive diff --git a/dtc-parser.y b/dtc-parser.y index 2ec981e..2ed4dc1 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ %{ #include diff --git a/dtc.c b/dtc.c index 695e1f7..bdb3f59 100644 --- a/dtc.c +++ b/dtc.c @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include diff --git a/dtc.h b/dtc.h index 0d5fa21..6e74ece 100644 --- a/dtc.h +++ b/dtc.h @@ -1,24 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef DTC_H #define DTC_H /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include diff --git a/fdtget.c b/fdtget.c index a79c3b2..777582e 100644 --- a/fdtget.c +++ b/fdtget.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. * @@ -6,21 +7,6 @@ * Based on code written by: * Pantelis Antoniou and * Matthew McClintock - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA */ #include diff --git a/fdtoverlay.c b/fdtoverlay.c index 6b0154d..af909de 100644 --- a/fdtoverlay.c +++ b/fdtoverlay.c @@ -1,23 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2017 Konsulko Group Inc. All rights reserved. * * Author: * Pantelis Antoniou - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA */ #include diff --git a/fdtput.c b/fdtput.c index 9e739bd..428745a 100644 --- a/fdtput.c +++ b/fdtput.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA */ #include diff --git a/flattree.c b/flattree.c index f7f7076..bd6977e 100644 --- a/flattree.c +++ b/flattree.c @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include "dtc.h" diff --git a/fstree.c b/fstree.c index 1e7eeba..9871689 100644 --- a/fstree.c +++ b/fstree.c @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include "dtc.h" diff --git a/livetree.c b/livetree.c index 21c2741..0c03999 100644 --- a/livetree.c +++ b/livetree.c @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include "dtc.h" diff --git a/srcpos.c b/srcpos.c index 41f8370..f5205fb 100644 --- a/srcpos.c +++ b/srcpos.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #define _GNU_SOURCE diff --git a/srcpos.h b/srcpos.h index 6326a95..4318d7a 100644 --- a/srcpos.h +++ b/srcpos.h @@ -1,20 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #ifndef SRCPOS_H diff --git a/treesource.c b/treesource.c index 1af3662..c9d980c 100644 --- a/treesource.c +++ b/treesource.c @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include "dtc.h" diff --git a/util.c b/util.c index 9c6fb5f..48af961 100644 --- a/util.c +++ b/util.c @@ -1,24 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright 2011 The Chromium Authors, All Rights Reserved. * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. * * util_is_printable_string contributed by * Pantelis Antoniou - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include diff --git a/util.h b/util.h index fc3c0d0..ca5cb52 100644 --- a/util.h +++ b/util.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef UTIL_H #define UTIL_H @@ -8,21 +9,6 @@ /* * Copyright 2011 The Chromium Authors, All Rights Reserved. * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #ifdef __GNUC__ diff --git a/yamltree.c b/yamltree.c index a00285a..5b6ea8e 100644 --- a/yamltree.c +++ b/yamltree.c @@ -1,22 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright Linaro, Ltd. 2018 * (C) Copyright Arm Holdings. 2017 * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include From 7fb0f4db2eb7cf5a60ed769a9daefd44123575e4 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 20 Jun 2019 15:19:39 -0600 Subject: [PATCH 0821/1198] libfdt: Replace GPL/BSD boilerplate/reference with SPDX tags Replace instances of dual GPLv2 or BSD license boilerplate with SPDX tags. Signed-off-by: Rob Herring Message-Id: <20190620211944.9378-3-robh@kernel.org> Signed-off-by: David Gibson --- libfdt/fdt.c | 47 +--------------------------------------- libfdt/fdt.h | 47 +--------------------------------------- libfdt/fdt_addresses.c | 47 +--------------------------------------- libfdt/fdt_empty_tree.c | 47 +--------------------------------------- libfdt/fdt_overlay.c | 47 +--------------------------------------- libfdt/fdt_ro.c | 47 +--------------------------------------- libfdt/fdt_rw.c | 47 +--------------------------------------- libfdt/fdt_strerror.c | 46 +-------------------------------------- libfdt/fdt_sw.c | 47 +--------------------------------------- libfdt/fdt_wip.c | 47 +--------------------------------------- libfdt/libfdt.h | 47 +--------------------------------------- libfdt/libfdt_env.h | 47 +--------------------------------------- libfdt/libfdt_internal.h | 47 +--------------------------------------- 13 files changed, 13 insertions(+), 597 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index ae03b11..179168e 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -1,52 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/libfdt/fdt.h b/libfdt/fdt.h index 74961f9..f2e6880 100644 --- a/libfdt/fdt.h +++ b/libfdt/fdt.h @@ -1,55 +1,10 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ #ifndef FDT_H #define FDT_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright 2012 Kim Phillips, Freescale Semiconductor. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __ASSEMBLY__ diff --git a/libfdt/fdt_addresses.c b/libfdt/fdt_addresses.c index 2cc997e..d8ba8ec 100644 --- a/libfdt/fdt_addresses.c +++ b/libfdt/fdt_addresses.c @@ -1,53 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2014 David Gibson * Copyright (C) 2018 embedded brains GmbH - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/libfdt/fdt_empty_tree.c b/libfdt/fdt_empty_tree.c index f2ae9b7..49d54d4 100644 --- a/libfdt/fdt_empty_tree.c +++ b/libfdt/fdt_empty_tree.c @@ -1,52 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2012 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index d3e9ab2..e97f12b 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -1,53 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2016 Free Electrons * Copyright (C) 2016 NextThing Co. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 2c393a1..6fd9ec1 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -1,52 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 9e76615..8795947 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -1,52 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c index 0e6b4fd..768db66 100644 --- a/libfdt/fdt_strerror.c +++ b/libfdt/fdt_strerror.c @@ -1,51 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index e773157..76bea22 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -1,52 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c index 534c1cb..f64139e 100644 --- a/libfdt/fdt_wip.c +++ b/libfdt/fdt_wip.c @@ -1,52 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 0684ec2..8037f39 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -1,54 +1,9 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ #ifndef LIBFDT_H #define LIBFDT_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h index 4d1cdfa..73b6d40 100644 --- a/libfdt/libfdt_env.h +++ b/libfdt/libfdt_env.h @@ -1,55 +1,10 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ #ifndef LIBFDT_ENV_H #define LIBFDT_ENV_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright 2012 Kim Phillips, Freescale Semiconductor. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 4109f89..7830e55 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -1,54 +1,9 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ #ifndef LIBFDT_INTERNAL_H #define LIBFDT_INTERNAL_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include From a5ac29baacd2f362bb8f10d6e8c572fd50dc4cb8 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 20 Jun 2019 15:19:40 -0600 Subject: [PATCH 0822/1198] pylibfdt: Replace dual GPLv2/BSD license boilerplate with SPDX tags Replace pylibfdt GPLv2/BSD license boilerplate and add missing license with SPDX tags. Signed-off-by: Rob Herring Message-Id: <20190620211944.9378-4-robh@kernel.org> Signed-off-by: David Gibson --- pylibfdt/Makefile.pylibfdt | 1 + pylibfdt/libfdt.i | 47 +------------------------------------- pylibfdt/setup.py | 1 + 3 files changed, 3 insertions(+), 46 deletions(-) diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt index 3dfe05a..6866a0b 100644 --- a/pylibfdt/Makefile.pylibfdt +++ b/pylibfdt/Makefile.pylibfdt @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) # Makefile.pylibfdt # diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index 4f14403..643f95d 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -1,53 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * pylibfdt - Flat Device Tree manipulation in Python * Copyright (C) 2017 Google, Inc. * Written by Simon Glass - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ %module libfdt diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py index 9e84359..a00bf8b 100755 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -1,4 +1,5 @@ #!/usr/bin/env python2 +# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) """ setup.py file for SWIG libfdt From c4ffc05574b1d81ddb890747465c0768d76a2cd0 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 20 Jun 2019 15:19:41 -0600 Subject: [PATCH 0823/1198] tests: Replace license boilerplate with SPDX tags Replace instances in tests of mostly LGPL-2.1 license boilerplate with SPDX tags. Signed-off-by: Rob Herring Message-Id: <20190620211944.9378-5-robh@kernel.org> Signed-off-by: David Gibson --- tests/add_subnode_with_nops.c | 15 +--------- tests/addr_size_cells.c | 15 +--------- tests/addr_size_cells2.c | 15 +--------- tests/appendprop1.c | 15 +--------- tests/appendprop2.c | 15 +--------- tests/appendprop_addrrange.c | 15 +--------- tests/asm_tree_dump.c | 15 +--------- tests/boot-cpuid.c | 15 +--------- tests/char_literal.c | 15 +--------- tests/check_full.c | 15 +--------- tests/check_header.c | 15 +--------- tests/check_path.c | 15 +--------- tests/del_node.c | 15 +--------- tests/del_property.c | 15 +--------- tests/dtb_reverse.c | 15 +--------- tests/dtbs_equal_ordered.c | 15 +--------- tests/dtbs_equal_unordered.c | 15 +--------- tests/dumptrees.c | 17 +---------- tests/extra-terminating-null.c | 15 +--------- tests/find_property.c | 15 +--------- tests/fs_tree1.c | 15 +--------- tests/get_alias.c | 15 +--------- tests/get_mem_rsv.c | 15 +--------- tests/get_name.c | 15 +--------- tests/get_path.c | 15 +--------- tests/get_phandle.c | 15 +--------- tests/get_prop_offset.c | 15 +--------- tests/getprop.c | 15 +--------- tests/incbin.c | 15 +--------- tests/integer-expressions.c | 15 +--------- tests/mangle-layout.c | 15 +--------- tests/move_and_save.c | 15 +--------- tests/node_check_compatible.c | 15 +--------- tests/node_offset_by_compatible.c | 15 +--------- tests/node_offset_by_phandle.c | 15 +--------- tests/node_offset_by_prop_value.c | 15 +--------- tests/nop_node.c | 15 +--------- tests/nop_property.c | 15 +--------- tests/nopulate.c | 15 +--------- tests/notfound.c | 15 +--------- tests/open_pack.c | 15 +--------- tests/overlay.c | 15 +--------- tests/overlay_bad_fixup.c | 15 +--------- tests/parent_offset.c | 15 +--------- tests/path-references.c | 15 +--------- tests/path_offset.c | 15 +--------- tests/path_offset_aliases.c | 15 +--------- tests/phandle_format.c | 15 +--------- tests/property_iterate.c | 15 +--------- tests/propname_escapes.c | 15 +--------- tests/pylibfdt_tests.py | 47 +------------------------------ tests/references.c | 15 +--------- tests/root_node.c | 15 +--------- tests/rw_oom.c | 15 +--------- tests/rw_tree1.c | 15 +--------- tests/set_name.c | 15 +--------- tests/setprop.c | 15 +--------- tests/setprop_inplace.c | 15 +--------- tests/sized_cells.c | 15 +--------- tests/string_escapes.c | 15 +--------- tests/stringlist.c | 15 +--------- tests/subnode_iterate.c | 15 +--------- tests/subnode_offset.c | 15 +--------- tests/supernode_atdepth_offset.c | 15 +--------- tests/sw_states.c | 15 +--------- tests/sw_tree1.c | 15 +--------- tests/tests.h | 15 +--------- tests/testutils.c | 15 +--------- tests/truncated_memrsv.c | 15 +--------- tests/truncated_property.c | 15 +--------- tests/truncated_string.c | 15 +--------- tests/utilfdt_test.c | 15 +--------- tests/value-labels.c | 15 +--------- 73 files changed, 73 insertions(+), 1056 deletions(-) diff --git a/tests/add_subnode_with_nops.c b/tests/add_subnode_with_nops.c index 95ddf6a..29bd34b 100644 --- a/tests/add_subnode_with_nops.c +++ b/tests/add_subnode_with_nops.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_nop_node() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/addr_size_cells.c b/tests/addr_size_cells.c index 1b196ef..0d90d53 100644 --- a/tests/addr_size_cells.c +++ b/tests/addr_size_cells.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for #address-cells and #size-cells handling * Copyright (C) 2014 David Gibson, - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/addr_size_cells2.c b/tests/addr_size_cells2.c index 52c4eba..d97541b 100644 --- a/tests/addr_size_cells2.c +++ b/tests/addr_size_cells2.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for #address-cells and #size-cells handling * Copyright (C) 2014 David Gibson, - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/appendprop1.c b/tests/appendprop1.c index 9d6b3ad..a7b502a 100644 --- a/tests/appendprop1.c +++ b/tests/appendprop1.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_appendprop() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/appendprop2.c b/tests/appendprop2.c index ca1446c..a0c1f6f 100644 --- a/tests/appendprop2.c +++ b/tests/appendprop2.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_appendprop() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/appendprop_addrrange.c b/tests/appendprop_addrrange.c index b079fba..538afcf 100644 --- a/tests/appendprop_addrrange.c +++ b/tests/appendprop_addrrange.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_appendprop_addrrange() * Copyright (C) 2018 AKASHI Takahiro, Linaro Limited - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/asm_tree_dump.c b/tests/asm_tree_dump.c index bd12eda..8236172 100644 --- a/tests/asm_tree_dump.c +++ b/tests/asm_tree_dump.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Tests if an asm tree built into a shared object matches a given dtb * Copyright (C) 2008 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/boot-cpuid.c b/tests/boot-cpuid.c index ca39f4b..5ed4f9a 100644 --- a/tests/boot-cpuid.c +++ b/tests/boot-cpuid.c @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * Copyright (C) 2008 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/char_literal.c b/tests/char_literal.c index da1f964..3a69e28 100644 --- a/tests/char_literal.c +++ b/tests/char_literal.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for character literals in dtc * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright (C) 2011 The Chromium Authors. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/check_full.c b/tests/check_full.c index 04c0bc1..b6d5fc3 100644 --- a/tests/check_full.c +++ b/tests/check_full.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Tests if two given dtbs are structurally equal (including order) * Copyright (C) 2007 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/check_header.c b/tests/check_header.c index 5e37813..ca26ec1 100644 --- a/tests/check_header.c +++ b/tests/check_header.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_check_header * Copyright (C) 2018 David Gibson - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/check_path.c b/tests/check_path.c index f12f950..cc9757a 100644 --- a/tests/check_path.c +++ b/tests/check_path.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for node existence * Copyright (C) 2016 Konsulko Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/del_node.c b/tests/del_node.c index 45cb060..10846df 100644 --- a/tests/del_node.c +++ b/tests/del_node.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_nop_node() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/del_property.c b/tests/del_property.c index 42fd7cb..37e8303 100644 --- a/tests/del_property.c +++ b/tests/del_property.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_delprop() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/dtb_reverse.c b/tests/dtb_reverse.c index 527fd71..95b6c1c 100644 --- a/tests/dtb_reverse.c +++ b/tests/dtb_reverse.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Tests if two given dtbs are structurally equal (including order) * Copyright (C) 2010 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/dtbs_equal_ordered.c b/tests/dtbs_equal_ordered.c index 98bf0e7..90c7344 100644 --- a/tests/dtbs_equal_ordered.c +++ b/tests/dtbs_equal_ordered.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Tests if two given dtbs are structurally equal (including order) * Copyright (C) 2007 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/dtbs_equal_unordered.c b/tests/dtbs_equal_unordered.c index 47baa84..e5ff9e8 100644 --- a/tests/dtbs_equal_unordered.c +++ b/tests/dtbs_equal_unordered.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Tests if two given dtbs are structurally equal (including order) * Copyright (C) 2007 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/dumptrees.c b/tests/dumptrees.c index ff5818d..b2f5b26 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -1,23 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * dumptrees - utility for libfdt testing * * (C) Copyright David Gibson , IBM Corporation. 2006. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include #include diff --git a/tests/extra-terminating-null.c b/tests/extra-terminating-null.c index dc1fe89..0fa2ca8 100644 --- a/tests/extra-terminating-null.c +++ b/tests/extra-terminating-null.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for properties with more than one terminating null * Copyright (C) 2009 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/find_property.c b/tests/find_property.c index 4dc3030..0404ea0 100644 --- a/tests/find_property.c +++ b/tests/find_property.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_property_offset() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/fs_tree1.c b/tests/fs_tree1.c index 5762465..dff3880 100644 --- a/tests/fs_tree1.c +++ b/tests/fs_tree1.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase/tool constructing an fs tree for further test * Copyright (C) 2018 David Gibson, Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/get_alias.c b/tests/get_alias.c index 5060795..fb2c38c 100644 --- a/tests/get_alias.c +++ b/tests/get_alias.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_get_alias() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/get_mem_rsv.c b/tests/get_mem_rsv.c index 1812639..f977d19 100644 --- a/tests/get_mem_rsv.c +++ b/tests/get_mem_rsv.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_get_mem_rsv() and fdt_num_mem_rsv() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/get_name.c b/tests/get_name.c index c6ca9f9..5a35103 100644 --- a/tests/get_name.c +++ b/tests/get_name.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_get_name() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/get_path.c b/tests/get_path.c index 7701dba..7349898 100644 --- a/tests/get_path.c +++ b/tests/get_path.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_get_path() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/get_phandle.c b/tests/get_phandle.c index e97b49c..157b522 100644 --- a/tests/get_phandle.c +++ b/tests/get_phandle.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_get_phandle() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/get_prop_offset.c b/tests/get_prop_offset.c index 3daef74..cff3c18 100644 --- a/tests/get_prop_offset.c +++ b/tests/get_prop_offset.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_getprop_by_offset() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/getprop.c b/tests/getprop.c index 6255bad..cccc8e2 100644 --- a/tests/getprop.c +++ b/tests/getprop.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_getprop() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/incbin.c b/tests/incbin.c index 4100ba0..fd02609 100644 --- a/tests/incbin.c +++ b/tests/incbin.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for string escapes in dtc * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/integer-expressions.c b/tests/integer-expressions.c index b0b2d8b..6f33d81 100644 --- a/tests/integer-expressions.c +++ b/tests/integer-expressions.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * Testcase for dtc expression support * * Copyright (C) 2008 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c index ae01a55..59b1604 100644 --- a/tests/mangle-layout.c +++ b/tests/mangle-layout.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase/tool for rearranging blocks of a dtb * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/move_and_save.c b/tests/move_and_save.c index 393b60a..a89f8de 100644 --- a/tests/move_and_save.c +++ b/tests/move_and_save.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Basic testcase for read-only access * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/node_check_compatible.c b/tests/node_check_compatible.c index 486f9c6..81efe62 100644 --- a/tests/node_check_compatible.c +++ b/tests/node_check_compatible.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_node_check_compatible() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/node_offset_by_compatible.c b/tests/node_offset_by_compatible.c index f62b591..a9e6783 100644 --- a/tests/node_offset_by_compatible.c +++ b/tests/node_offset_by_compatible.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_node_offset_by_compatible() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/node_offset_by_phandle.c b/tests/node_offset_by_phandle.c index becff0f..60af78a 100644 --- a/tests/node_offset_by_phandle.c +++ b/tests/node_offset_by_phandle.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_node_offset_by_phandle() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/node_offset_by_prop_value.c b/tests/node_offset_by_prop_value.c index 286f1e7..48ab1d9 100644 --- a/tests/node_offset_by_prop_value.c +++ b/tests/node_offset_by_prop_value.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_path_offset() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/nop_node.c b/tests/nop_node.c index c316444..ee972d2 100644 --- a/tests/nop_node.c +++ b/tests/nop_node.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_nop_node() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/nop_property.c b/tests/nop_property.c index 644b0a6..6593828 100644 --- a/tests/nop_property.c +++ b/tests/nop_property.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_nop_property() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/nopulate.c b/tests/nopulate.c index 94ce8ad..2ae1753 100644 --- a/tests/nopulate.c +++ b/tests/nopulate.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase/tool for rearranging blocks of a dtb * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/notfound.c b/tests/notfound.c index dc623d6..70acbcd 100644 --- a/tests/notfound.c +++ b/tests/notfound.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for behaviour on searching for a non-existent node * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/open_pack.c b/tests/open_pack.c index 407ef6c..6ed4df7 100644 --- a/tests/open_pack.c +++ b/tests/open_pack.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Basic testcase for read-only access * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/overlay.c b/tests/overlay.c index 3093eec..91afa72 100644 --- a/tests/overlay.c +++ b/tests/overlay.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for DT overlays() * Copyright (C) 2016 Free Electrons * Copyright (C) 2016 NextThing Co. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/overlay_bad_fixup.c b/tests/overlay_bad_fixup.c index 5014f5e..029bc79 100644 --- a/tests/overlay_bad_fixup.c +++ b/tests/overlay_bad_fixup.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for DT overlays() * Copyright (C) 2016 Free Electrons * Copyright (C) 2016 NextThing Co. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/parent_offset.c b/tests/parent_offset.c index d4ab3cf..a935a53 100644 --- a/tests/parent_offset.c +++ b/tests/parent_offset.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_parent_offset() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/path-references.c b/tests/path-references.c index 5e332e8..4db61a5 100644 --- a/tests/path-references.c +++ b/tests/path-references.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for string references in dtc * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/path_offset.c b/tests/path_offset.c index bfebe9f..82527d4 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_path_offset() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/path_offset_aliases.c b/tests/path_offset_aliases.c index 78d5a46..0112e72 100644 --- a/tests/path_offset_aliases.c +++ b/tests/path_offset_aliases.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_path_offset() * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright 2008 Kumar Gala, Freescale Semiconductor, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/phandle_format.c b/tests/phandle_format.c index 5874ae7..d00618f 100644 --- a/tests/phandle_format.c +++ b/tests/phandle_format.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for phandle format options * Copyright (C) 2009 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/property_iterate.c b/tests/property_iterate.c index b5cedbe..9a67f49 100644 --- a/tests/property_iterate.c +++ b/tests/property_iterate.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Tests that fdt_next_subnode() works as expected @@ -5,20 +6,6 @@ * Copyright (C) 2013 Google, Inc * * Copyright (C) 2007 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/propname_escapes.c b/tests/propname_escapes.c index e91bd99..3e41e63 100644 --- a/tests/propname_escapes.c +++ b/tests/propname_escapes.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_getprop() * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index e6c13ff..c055f01 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -1,53 +1,8 @@ +# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) # pylibfdt - Tests for Flat Device Tree manipulation in Python # Copyright (C) 2017 Google, Inc. # Written by Simon Glass # -# libfdt is dual licensed: you can use it either under the terms of -# the GPL, or the BSD license, at your option. -# -# a) This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public -# License along with this library; if not, write to the Free -# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -# MA 02110-1301 USA -# -# Alternatively, -# -# b) Redistribution and use in source and binary forms, with or -# without modification, are permitted provided that the following -# conditions are met: -# -# 1. Redistributions of source code must retain the above -# copyright notice, this list of conditions and the following -# disclaimer. -# 2. Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials -# provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# import struct import sys diff --git a/tests/references.c b/tests/references.c index 5b233a4..d18e722 100644 --- a/tests/references.c +++ b/tests/references.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for phandle references in dtc * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/root_node.c b/tests/root_node.c index 58aebf6..37e6f05 100644 --- a/tests/root_node.c +++ b/tests/root_node.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Basic testcase for read-only access * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/rw_oom.c b/tests/rw_oom.c index 24bfe05..39fc312 100644 --- a/tests/rw_oom.c +++ b/tests/rw_oom.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_nop_node() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c index efd4718..1fe2351 100644 --- a/tests/rw_tree1.c +++ b/tests/rw_tree1.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_nop_node() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/set_name.c b/tests/set_name.c index 9861587..a62cb58 100644 --- a/tests/set_name.c +++ b/tests/set_name.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_set_name() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/setprop.c b/tests/setprop.c index be1b147..fa3938d 100644 --- a/tests/setprop.c +++ b/tests/setprop.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_setprop() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c index 80447a0..7e1198d 100644 --- a/tests/setprop_inplace.c +++ b/tests/setprop_inplace.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_setprop_inplace() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/sized_cells.c b/tests/sized_cells.c index 0b2b8dc..9ca5a59 100644 --- a/tests/sized_cells.c +++ b/tests/sized_cells.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for variable sized cells in dtc * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright (C) 2011 The Chromium Authors. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/string_escapes.c b/tests/string_escapes.c index 8cdee4b..53c9dfc 100644 --- a/tests/string_escapes.c +++ b/tests/string_escapes.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for string escapes in dtc * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/stringlist.c b/tests/stringlist.c index 23cfece..bbc3020 100644 --- a/tests/stringlist.c +++ b/tests/stringlist.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for string handling * Copyright (C) 2015 NVIDIA Corporation - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/subnode_iterate.c b/tests/subnode_iterate.c index 7be5706..2dc9b2d 100644 --- a/tests/subnode_iterate.c +++ b/tests/subnode_iterate.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Tests that fdt_next_subnode() works as expected @@ -5,20 +6,6 @@ * Copyright (C) 2013 Google, Inc * * Copyright (C) 2007 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c index 231fcb5..1362f99 100644 --- a/tests/subnode_offset.c +++ b/tests/subnode_offset.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_subnode_offset() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/supernode_atdepth_offset.c b/tests/supernode_atdepth_offset.c index 43e120d..4435b49 100644 --- a/tests/supernode_atdepth_offset.c +++ b/tests/supernode_atdepth_offset.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_supernode_atdepth_offset() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/sw_states.c b/tests/sw_states.c index 2fd471d..42d57ae 100644 --- a/tests/sw_states.c +++ b/tests/sw_states.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for error handling with sequential write states * Copyright (C) 2018 David Gibson, Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c index 08b39b3..7069ace 100644 --- a/tests/sw_tree1.c +++ b/tests/sw_tree1.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_nop_node() * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/tests.h b/tests/tests.h index 75735d6..1017366 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -1,23 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef TESTS_H #define TESTS_H /* * libfdt - Flat Device Tree manipulation * Testcase definitions * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define DEBUG diff --git a/tests/testutils.c b/tests/testutils.c index 24bd81e..5e494c5 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase common utility functions * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE /* for strsignal() in glibc. FreeBSD has it either way */ diff --git a/tests/truncated_memrsv.c b/tests/truncated_memrsv.c index 82d0198..d78036c 100644 --- a/tests/truncated_memrsv.c +++ b/tests/truncated_memrsv.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for misbehaviour on a truncated string * Copyright (C) 2018 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/truncated_property.c b/tests/truncated_property.c index f4b6770..d9d52b2 100644 --- a/tests/truncated_property.c +++ b/tests/truncated_property.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for misbehaviour on a truncated property * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/truncated_string.c b/tests/truncated_string.c index 5365f69..d745414 100644 --- a/tests/truncated_string.c +++ b/tests/truncated_string.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Testcase for misbehaviour on a truncated string * Copyright (C) 2018 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff --git a/tests/utilfdt_test.c b/tests/utilfdt_test.c index 274c3d6..c621759 100644 --- a/tests/utilfdt_test.c +++ b/tests/utilfdt_test.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * Copyright 2011 The Chromium Authors, All Rights Reserved. * * utilfdt_test - Tests for utilfdt library - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include diff --git a/tests/value-labels.c b/tests/value-labels.c index 8aced74..e318357 100644 --- a/tests/value-labels.c +++ b/tests/value-labels.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* * libfdt - Flat Device Tree manipulation * Test labels within values * Copyright (C) 2008 David Gibson, IBM Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include From 94f87cd5b7c5ec835a29e1a02f5dc4b5d61e301f Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 20 Jun 2019 15:19:42 -0600 Subject: [PATCH 0824/1198] libfdt: Add dual GPL/BSD SPDX tags to files missing license text A couple of libfdt files are missing licenses. Add (GPL-2.0-or-later OR BSD-2-Clause) SPDX tag to them. Signed-off-by: Rob Herring Message-Id: <20190620211944.9378-6-robh@kernel.org> Signed-off-by: David Gibson --- libfdt/Makefile.libfdt | 1 + libfdt/version.lds | 1 + 2 files changed, 2 insertions(+) diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index 193da8c..e546397 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) # Makefile.libfdt # # This is not a complete Makefile of itself. Instead, it is designed to diff --git a/libfdt/version.lds b/libfdt/version.lds index 0d52217..ae32924 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ LIBFDT_1.2 { global: fdt_next_node; From 4097bbffcf1d8f3da56bedf9d0eb9414eeb7113f Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 20 Jun 2019 15:19:43 -0600 Subject: [PATCH 0825/1198] dtc: Add GPLv2 SPDX tags to files missing license text A couple of dtc files are missing licenses. Add GPL-2.0-or-later SPDX tag to them. Signed-off-by: Rob Herring Message-Id: <20190620211944.9378-7-robh@kernel.org> Signed-off-by: David Gibson --- Makefile | 1 + Makefile.convert-dtsv0 | 1 + Makefile.utils | 1 + dtdiff | 1 + fdtdump.c | 1 + scripts/kup-dtc | 1 + scripts/setlocalversion | 1 + 7 files changed, 7 insertions(+) diff --git a/Makefile b/Makefile index 0cb2bfe..98f74b1 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later # # Device Tree Compiler # diff --git a/Makefile.convert-dtsv0 b/Makefile.convert-dtsv0 index 08ea40a..c12ed40 100644 --- a/Makefile.convert-dtsv0 +++ b/Makefile.convert-dtsv0 @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later # # This is not a complete Makefile of itself. # Instead, it is designed to be easily embeddable diff --git a/Makefile.utils b/Makefile.utils index e028922..9436b34 100644 --- a/Makefile.utils +++ b/Makefile.utils @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later # # This is not a complete Makefile of itself. Instead, it is designed to # be easily embeddable into other systems of Makefiles. diff --git a/dtdiff b/dtdiff index 5fa772b..cdbf079 100644 --- a/dtdiff +++ b/dtdiff @@ -1,4 +1,5 @@ #! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later # This script uses the bash <(...) extension. # If you want to change this to work with a generic /bin/sh, make sure diff --git a/fdtdump.c b/fdtdump.c index 200fb06..9613bef 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * fdtdump.c - Contributed by Pantelis Antoniou */ diff --git a/scripts/kup-dtc b/scripts/kup-dtc index e18abbb..3c3376c 100755 --- a/scripts/kup-dtc +++ b/scripts/kup-dtc @@ -1,4 +1,5 @@ #! /bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later REMOTE_GIT=/pub/scm/utils/dtc/dtc.git REMOTE_PATH=/pub/software/utils/dtc diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 82e4993..ea333e7 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -1,4 +1,5 @@ #!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later # Print additional version information for non-release trees. usage() { From 702c1b6c0e73d2bcf24f0b8398aca6a940863e48 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 20 Jun 2019 15:19:44 -0600 Subject: [PATCH 0826/1198] README.license: Update to reflect SPDX tag usage Update README.license since files now have SPDX tags rather than license text. Adding a copy of BSD-2-Clause license since that no longer exists within the project. Signed-off-by: Rob Herring Message-Id: <20190620211944.9378-8-robh@kernel.org> Signed-off-by: David Gibson --- BSD-2-Clause | 32 ++++++++++++++++++++++++++++++++ README.license | 10 +++++----- 2 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 BSD-2-Clause diff --git a/BSD-2-Clause b/BSD-2-Clause new file mode 100644 index 0000000..da366e2 --- /dev/null +++ b/BSD-2-Clause @@ -0,0 +1,32 @@ +Valid-License-Identifier: BSD-2-Clause +SPDX-URL: https://spdx.org/licenses/BSD-2-Clause.html +Usage-Guide: + To use the BSD 2-clause "Simplified" License put the following SPDX + tag/value pair into a comment according to the placement guidelines in + the licensing rules documentation: + SPDX-License-Identifier: BSD-2-Clause +License-Text: + +Copyright (c) . All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/README.license b/README.license index 50e9fca..102b004 100644 --- a/README.license +++ b/README.license @@ -8,7 +8,7 @@ dtc does not incorporate or rely on libfdt for its operation, nor vice versa. It is important that these two pieces of software have different license conditions. -As the copyright banners in each source file attest, dtc is licensed +As SPDX license tags in each source file attest, dtc is licensed under the GNU GPL. The full text of the GPL can be found in the file entitled 'GPL' which should be included in this package. dtc code, therefore, may not be incorporated into works which do not have a GPL @@ -16,10 +16,10 @@ compatible license. libfdt, however, is GPL/BSD dual-licensed. That is, it may be used either under the terms of the GPL, or under the terms of the 2-clause -BSD license (aka the ISC license). The full terms of that license are -given in the copyright banners of each of the libfdt source files. -This is, in practice, equivalent to being BSD licensed, since the -terms of the BSD license are strictly more permissive than the GPL. +BSD license (aka the ISC license). The full terms of that license can +be found are in the file entitled 'BSD-2-Clause'. This is, in +practice, equivalent to being BSD licensed, since the terms of the BSD +license are strictly more permissive than the GPL. I made the decision to license libfdt in this way because I want to encourage widespread and correct usage of flattened device trees, From 297f5abb362e4844ee313fdcd342fa4912e9894d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 30 Jun 2019 14:58:31 +1000 Subject: [PATCH 0827/1198] fdtoverlay: Check for truncated overlay blobs The fdtoverlay helper program checks if it has read a base blob which is incomplete: that is, where the amount of data read in is less that the declared size of the blob. This applies the same check for safety to each overlay blob as well. Signed-off-by: David Gibson --- fdtoverlay.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fdtoverlay.c b/fdtoverlay.c index af909de..b2ac2e7 100644 --- a/fdtoverlay.c +++ b/fdtoverlay.c @@ -46,7 +46,7 @@ static int do_fdtoverlay(const char *input_filename, { char *blob = NULL; char **ovblob = NULL; - size_t blob_len, ov_len, total_len; + size_t blob_len, total_len; int i, ret = -1; blob = utilfdt_read(input_filename, &blob_len); @@ -70,12 +70,20 @@ static int do_fdtoverlay(const char *input_filename, /* read and keep track of the overlay blobs */ total_len = 0; for (i = 0; i < argc; i++) { + size_t ov_len; ovblob[i] = utilfdt_read(argv[i], &ov_len); if (!ovblob[i]) { fprintf(stderr, "\nFailed to read overlay %s\n", argv[i]); goto out_err; } + if (fdt_totalsize(ovblob[i]) > ov_len) { + fprintf(stderr, +"\nOverlay '%s' is incomplete (%lu / %" PRIu32 " bytes read)\n", + argv[i], (unsigned long)ov_len, + fdt_totalsize(ovblob[i])); + goto out_err; + } total_len += ov_len; } From 6c2e61f08396871a34d641b8f18a05d35d552792 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 30 Jun 2019 15:01:01 +1000 Subject: [PATCH 0828/1198] fdtoverlay: Improve error messages Make several improvements to the error messages from the fdtoverlay helper program: improve brevity, consistently quote filenames and print symbolic errors from libfdt rather than a raw error number. Signed-off-by: David Gibson --- fdtoverlay.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/fdtoverlay.c b/fdtoverlay.c index b2ac2e7..40c249e 100644 --- a/fdtoverlay.c +++ b/fdtoverlay.c @@ -51,8 +51,7 @@ static int do_fdtoverlay(const char *input_filename, blob = utilfdt_read(input_filename, &blob_len); if (!blob) { - fprintf(stderr, "\nFailed to read base blob %s\n", - input_filename); + fprintf(stderr, "\nFailed to read '%s'\n", input_filename); goto out_err; } if (fdt_totalsize(blob) > blob_len) { @@ -73,8 +72,7 @@ static int do_fdtoverlay(const char *input_filename, size_t ov_len; ovblob[i] = utilfdt_read(argv[i], &ov_len); if (!ovblob[i]) { - fprintf(stderr, "\nFailed to read overlay %s\n", - argv[i]); + fprintf(stderr, "\nFailed to read '%s'\n", argv[i]); goto out_err; } if (fdt_totalsize(ovblob[i]) > ov_len) { @@ -96,8 +94,8 @@ static int do_fdtoverlay(const char *input_filename, for (i = 0; i < argc; i++) { ret = fdt_overlay_apply(blob, ovblob[i]); if (ret) { - fprintf(stderr, "\nFailed to apply %s (%d)\n", - argv[i], ret); + fprintf(stderr, "\nFailed to apply '%s': %s\n", + argv[i], fdt_strerror(ret)); goto out_err; } } @@ -105,8 +103,8 @@ static int do_fdtoverlay(const char *input_filename, fdt_pack(blob); ret = utilfdt_write(output_filename, blob); if (ret) - fprintf(stderr, "\nFailed to write output blob %s\n", - output_filename); + fprintf(stderr, "\nFailed to write '%s'\n", + output_filename); out_err: if (ovblob) { From bbe3b36f542bb2c274f5fd030456ea840cc31d94 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 30 Jun 2019 15:46:25 +1000 Subject: [PATCH 0829/1198] fdtoverlay: Rework output allocation At present the fdtoverlay tool allocates space for its output based on a calculation of the worse case size based on the size of the input blobs. Except.. that certain edge cases with very long target paths can actually exceed that "worst case" calculation. This reworks the code to instead dynamically reallocate the output buffer if we run out of space at any point. Signed-off-by: David Gibson --- fdtoverlay.c | 74 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/fdtoverlay.c b/fdtoverlay.c index 40c249e..8a1d11b 100644 --- a/fdtoverlay.c +++ b/fdtoverlay.c @@ -18,6 +18,8 @@ #include "util.h" +#define BUF_INCREMENT 65536 + /* Usage related data. */ static const char usage_synopsis[] = "apply a number of overlays to a base blob\n" @@ -40,34 +42,81 @@ static const char * const usage_opts_help[] = { int verbose = 0; +static void *apply_one(char *base, const char *overlay, size_t *buf_len, + const char *name) +{ + char *tmp = NULL; + char *tmpo; + int ret; + + /* + * We take a copies first, because a a failed apply can trash + * both the base blob and the overlay + */ + tmpo = xmalloc(fdt_totalsize(overlay)); + + do { + tmp = xrealloc(tmp, *buf_len); + ret = fdt_open_into(base, tmp, *buf_len); + if (ret) { + fprintf(stderr, + "\nFailed to make temporary copy: %s\n", + fdt_strerror(ret)); + goto fail; + } + + memcpy(tmpo, overlay, fdt_totalsize(overlay)); + + ret = fdt_overlay_apply(tmp, tmpo); + if (ret == -FDT_ERR_NOSPACE) { + *buf_len += BUF_INCREMENT; + } + } while (ret == -FDT_ERR_NOSPACE); + + if (ret) { + fprintf(stderr, "\nFailed to apply '%s': %s\n", + name, fdt_strerror(ret)); + goto fail; + } + + free(base); + free(tmpo); + return tmp; + +fail: + free(tmpo); + if (tmp) + free(tmp); + + return NULL; +} static int do_fdtoverlay(const char *input_filename, const char *output_filename, int argc, char *argv[]) { char *blob = NULL; char **ovblob = NULL; - size_t blob_len, total_len; + size_t buf_len; int i, ret = -1; - blob = utilfdt_read(input_filename, &blob_len); + blob = utilfdt_read(input_filename, &buf_len); if (!blob) { fprintf(stderr, "\nFailed to read '%s'\n", input_filename); goto out_err; } - if (fdt_totalsize(blob) > blob_len) { + if (fdt_totalsize(blob) > buf_len) { fprintf(stderr, "\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n", - (unsigned long)blob_len, fdt_totalsize(blob)); + (unsigned long)buf_len, fdt_totalsize(blob)); goto out_err; } ret = 0; /* allocate blob pointer array */ - ovblob = malloc(sizeof(*ovblob) * argc); + ovblob = xmalloc(sizeof(*ovblob) * argc); memset(ovblob, 0, sizeof(*ovblob) * argc); /* read and keep track of the overlay blobs */ - total_len = 0; for (i = 0; i < argc; i++) { size_t ov_len; ovblob[i] = utilfdt_read(argv[i], &ov_len); @@ -82,22 +131,15 @@ static int do_fdtoverlay(const char *input_filename, fdt_totalsize(ovblob[i])); goto out_err; } - total_len += ov_len; } - /* grow the blob to worst case */ - blob_len = fdt_totalsize(blob) + total_len; - blob = xrealloc(blob, blob_len); - fdt_open_into(blob, blob, blob_len); + buf_len = fdt_totalsize(blob); /* apply the overlays in sequence */ for (i = 0; i < argc; i++) { - ret = fdt_overlay_apply(blob, ovblob[i]); - if (ret) { - fprintf(stderr, "\nFailed to apply '%s': %s\n", - argv[i], fdt_strerror(ret)); + blob = apply_one(blob, ovblob[i], &buf_len, argv[i]); + if (!blob) goto out_err; - } } fdt_pack(blob); From ad57e4574a379e8f383058f730e4e8e1939b4fc7 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 3 Oct 2018 09:55:02 +0200 Subject: [PATCH 0830/1198] tests: Add a failed test case for 'fdtoverlay' with long target path This adds a test case to demonstrate some issue seen when applying overlays using 'fdtoverlay'. It fails with FDT_ERR_NOSPACE: - with long target path - symbols in order to use these nodes in possible subsequent overlay. This is seen with this patch, by running: $ make check # Reports a failed test $ ./fdtoverlay -i tests/overlay_base.test.dtb -o out.dtb \ tests/overlay_overlay_long_path.fdoverlay.test.dtb Failed to apply tests/overlay_overlay_long_path.fdoverlay.test.dtb (-3) This overlay fails to apply, because dtb size is close to modulo 1024 bytes chunk: utilfdt_read() -> utilfdt_read_err() -> bufsize = 1024. As there is not much extra space in the blob to resolve symbols (long target path), it fails with FDT_ERR_NOSPACE. In fdtoverlay, size is : /* grow the blob to worst case */ blob_len = fdt_totalsize(blob) + total_len; I can see assumption is made that result should be lower than: - base fdt size + overlay size. Is there a simple way to find to know what the final size is? I'm not sure what the correct fix might be, for such (worst) case? Similar issue is also seen in u-boot/common/image-fit.c that implements similar approach (e.g. base fdt size + overlay size). Signed-off-by: Fabrice Gasnier Message-Id: <1538553302-1353-1-git-send-email-fabrice.gasnier@st.com> [dwg: To avoid breaking bisection, I committed this after a fix, so the "failed" description is no longer accurate] Signed-off-by: David Gibson --- tests/overlay_base.dts | 4 ++++ tests/overlay_overlay_long_path.dts | 32 +++++++++++++++++++++++++++++ tests/run_tests.sh | 8 ++++++++ 3 files changed, 44 insertions(+) create mode 100644 tests/overlay_overlay_long_path.dts diff --git a/tests/overlay_base.dts b/tests/overlay_base.dts index 2603adb..a5e55b2 100644 --- a/tests/overlay_base.dts +++ b/tests/overlay_base.dts @@ -14,6 +14,10 @@ subtest: sub-test-node { sub-test-property; + + subtest_with_long_path: sub-test-node-with-very-long-target-path { + long-test-path-property; + }; }; }; }; diff --git a/tests/overlay_overlay_long_path.dts b/tests/overlay_overlay_long_path.dts new file mode 100644 index 0000000..4f0d40b --- /dev/null +++ b/tests/overlay_overlay_long_path.dts @@ -0,0 +1,32 @@ +/dts-v1/; +/plugin/; + +&subtest_with_long_path { + lpath_0: test-0 { + prop = "lpath"; + }; + + lpath_1: test-1 { + prop = "lpath"; + }; + + lpath_2: test-2 { + prop = "lpath"; + }; + + lpath_3: test-3 { + prop = "lpath"; + }; + + lpath_4: test-4 { + prop = "lpath"; + }; + + lpath_5: test-5 { + prop = "lpath"; + }; + + lpath_6: test-6 { + prop = "lpath"; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 646a4d9..d368ad5 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -941,6 +941,14 @@ fdtoverlay_tests() { # test that baz correctly inserted the property run_fdtoverlay_test baz "/foonode/barnode/baznode" "baz-property" "-ts" ${stacked_basedtb} ${stacked_targetdtb} ${stacked_bardtb} ${stacked_bazdtb} + + overlay_long_path=overlay_overlay_long_path.dts + overlay_long_pathdtb=overlay_overlay_long_path.fdoverlay.test.dtb + target_long_pathdtb=overlay_overlay_long_path_target.fdoverlay.test.dtb + run_dtc_test -@ -I dts -O dtb -o $overlay_long_pathdtb $overlay_long_path + + # test that fdtoverlay manages to apply overlays with long target path + run_fdtoverlay_test lpath "/test-node/sub-test-node/sub-test-node-with-very-long-target-path/test-0" "prop" "-ts" ${basedtb} ${target_long_pathdtb} ${overlay_long_pathdtb} } pylibfdt_tests () { From 1c17714dbb3aa43e5b7927dfc073e5e88ae20655 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 2 Jul 2019 18:08:15 -0600 Subject: [PATCH 0831/1198] pylibfdt: Correct the FdtSw example At present this example is incorrect since it is missing the call to finish_reservemap() and does not add a root node. Fix these problems. Signed-off-by: Simon Glass Message-Id: <20190703000815.102459-1-sjg@chromium.org> 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 643f95d..ecec4dd 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -727,8 +727,10 @@ class FdtSw(FdtRo): # First create the device tree with a node and property: sw = FdtSw() - with sw.add_node('node'): - sw.property_u32('reg', 2) + sw.finish_reservemap() + with sw.add_node(''): + with sw.add_node('node'): + sw.property_u32('reg', 2) fdt = sw.as_fdt() # Now we can use it as a real device tree From d6de81b81b68f9e559adf42366574233be338fd8 Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Wed, 3 Jul 2019 10:38:07 +0530 Subject: [PATCH 0832/1198] pylibfdt: Add support for fdt_get_alias() Add this into the class to simplify use of this function. Signed-off-by: Appana Durga Kedareswara rao Message-Id: <1562130487-27028-1-git-send-email-appana.durga.rao@xilinx.com> Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 12 ++++++++++++ tests/pylibfdt_tests.py | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index ecec4dd..feb8c9c 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -431,6 +431,18 @@ class FdtRo(object): """ return fdt_get_phandle(self._fdt, nodeoffset) + def get_alias(self, name): + """Get the full path referenced by a given alias + + Args: + name: name of the alias to lookup + + Returns: + Full path to the node for the alias named 'name', if it exists + None, if the given alias or the /aliases node does not exist + """ + return fdt_get_alias(self._fdt, name) + def parent_offset(self, nodeoffset, quiet=()): """Get the offset of a node's parent diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index c055f01..42f31ba 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -77,6 +77,7 @@ class PyLibfdtBasicTests(unittest.TestCase): """Read in the device tree we use for testing""" self.fdt = _ReadFdt('test_tree1.dtb') self.fdt2 = _ReadFdt('test_props.dtb') + self.fdt3 = _ReadFdt('aliases.dtb') def GetPropList(self, node_path): """Read a list of properties from a node @@ -340,6 +341,12 @@ class PyLibfdtBasicTests(unittest.TestCase): node2 = self.fdt.path_offset('/subnode@2') self.assertEquals(0x2000, self.fdt.get_phandle(node2)) + def testGetAlias(self): + """Test for the get_alias() method""" + self.assertEquals("/subnode@1", self.fdt3.get_alias('s1')) + self.assertEquals("/subnode@1/subsubnode", self.fdt3.get_alias('ss1')) + self.assertEquals("/subnode@1/subsubnode/subsubsubnode", self.fdt3.get_alias('sss1')) + def testParentOffset(self): """Test for the parent_offset() method""" self.assertEquals(-libfdt.NOTFOUND, From b99353474850969a1f856d344d273325ddb069c7 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 4 Jul 2019 14:39:02 +1000 Subject: [PATCH 0833/1198] fdtoverlay: Allow adding labels to __overlay__ nodes in overlays When applying overlays, we merge symbols from the overlay into the target tree. At the moment the logic for this assumes all symbols in the overlay are attached to a node of the form: /fragment@XXX/__overlay__/relative/path And will end up applied to the relative/path node under the fragment's target. However, this disallows the case of a symbol in the form just: /fragment@XXX/__overlay__ This does have a pretty obvious sensible meaning: attach the new symbol directly to the fragment's target, but we don't currently do that. It's pretty easy to workaround this limitation in one's overlays, but it's also easy to handle in the overlay applying code, so we might as well extend it to cover this case. Reported-by: Christophe Braillon Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 17 +++++++++++------ tests/run_tests.sh | 12 ++++++++++++ tests/stacked_overlay_addlabel.dts | 13 +++++++++++++ tests/stacked_overlay_base_nolabel.dts | 6 ++++++ 4 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 tests/stacked_overlay_addlabel.dts create mode 100644 tests/stacked_overlay_base_nolabel.dts diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index e97f12b..7fbf58c 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -733,8 +733,6 @@ static int overlay_symbol_update(void *fdt, void *fdto) /* keep end marker to avoid strlen() */ e = path + path_len; - /* format: //__overlay__/ */ - if (*path != '/') return -FDT_ERR_BADVALUE; @@ -748,11 +746,18 @@ static int overlay_symbol_update(void *fdt, void *fdto) /* verify format; safe since "s" lies in \0 terminated prop */ len = sizeof("/__overlay__/") - 1; - if ((e - s) < len || memcmp(s, "/__overlay__/", len)) + if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) { + /* //__overlay__/ */ + rel_path = s + len; + rel_path_len = e - rel_path; + } else if ((e - s) == len + && (memcmp(s, "/__overlay__", len - 1) == 0)) { + /* //__overlay__ */ + rel_path = ""; + rel_path_len = 0; + } else { return -FDT_ERR_BADOVERLAY; - - rel_path = s + len; - rel_path_len = e - rel_path; + } /* find the fragment index in which the symbol lies */ ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, diff --git a/tests/run_tests.sh b/tests/run_tests.sh index d368ad5..2620332 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -949,6 +949,18 @@ fdtoverlay_tests() { # test that fdtoverlay manages to apply overlays with long target path run_fdtoverlay_test lpath "/test-node/sub-test-node/sub-test-node-with-very-long-target-path/test-0" "prop" "-ts" ${basedtb} ${target_long_pathdtb} ${overlay_long_pathdtb} + + # test adding a label to the root of a fragment + stacked_base_nolabel=stacked_overlay_base_nolabel.dts + stacked_base_nolabeldtb=stacked_overlay_base_nolabel.test.dtb + stacked_addlabel=stacked_overlay_addlabel.dts + stacked_addlabeldtb=stacked_overlay_addlabel.test.dtb + stacked_addlabel_targetdtb=stacked_overlay_target_nolabel.fdtoverlay.test.dtb + + run_dtc_test -@ -I dts -O dtb -o $stacked_base_nolabeldtb $stacked_base_nolabel + 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} } pylibfdt_tests () { diff --git a/tests/stacked_overlay_addlabel.dts b/tests/stacked_overlay_addlabel.dts new file mode 100644 index 0000000..e5c158f --- /dev/null +++ b/tests/stacked_overlay_addlabel.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; +/ { + fragment@1 { + target-path = "/foonode"; + foo: __overlay__ { + overlay-1-property; + bar: barnode { + bar-property = "bar"; + }; + }; + }; +}; diff --git a/tests/stacked_overlay_base_nolabel.dts b/tests/stacked_overlay_base_nolabel.dts new file mode 100644 index 0000000..0c47f0d --- /dev/null +++ b/tests/stacked_overlay_base_nolabel.dts @@ -0,0 +1,6 @@ +/dts-v1/; +/ { + foonode { + foo-property = "foo"; + }; +}; From 5c715a44776a450106d8a59ad5abc9ac5830bc1d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 4 Jul 2019 15:10:01 +1000 Subject: [PATCH 0834/1198] fdtoverlay: Ignore symbols in overlays which don't apply to the target tree Symbols from overlays are merged into the target tree, and are required to have the form: /fragment@XXX/__overlay__/... If any symbols don't have this form, the overlay is rejected. But there's not really anything wrong with an overlay having "local" labels referring to a fragment node or some other metadata, that's not expected to end up in a target tree. So change our overlay application to simply ignore such symbols rather than fail. Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 11 ++++++++--- tests/stacked_overlay_addlabel.dts | 4 +++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index 7fbf58c..be71873 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -738,8 +738,11 @@ static int overlay_symbol_update(void *fdt, void *fdto) /* get fragment name first */ s = strchr(path + 1, '/'); - if (!s) - return -FDT_ERR_BADOVERLAY; + if (!s) { + /* Symbol refers to something that won't end + * up in the target tree */ + continue; + } frag_name = path + 1; frag_name_len = s - path - 1; @@ -756,7 +759,9 @@ static int overlay_symbol_update(void *fdt, void *fdto) rel_path = ""; rel_path_len = 0; } else { - return -FDT_ERR_BADOVERLAY; + /* Symbol refers to something that won't end + * up in the target tree */ + continue; } /* find the fragment index in which the symbol lies */ diff --git a/tests/stacked_overlay_addlabel.dts b/tests/stacked_overlay_addlabel.dts index e5c158f..e7187a3 100644 --- a/tests/stacked_overlay_addlabel.dts +++ b/tests/stacked_overlay_addlabel.dts @@ -1,8 +1,10 @@ /dts-v1/; /plugin/; / { - fragment@1 { + frag1: fragment@1 { target-path = "/foonode"; + local: localinfo { + }; foo: __overlay__ { overlay-1-property; bar: barnode { From 812b1956a07603fb56139f812395eb369727dd82 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 5 Jul 2019 13:42:40 +1000 Subject: [PATCH 0835/1198] libfdt: Tweak data handling to satisfy Coverity In libfdt we often sanity test fdt_totalsize(fdt) fairly early, then trust it (but *only* that header field) for the remainder of our work. However, Coverity gets confused by this - it sees the byteswap in fdt32_ld() and assumes that means it is coming from an untrusted source everytime, resulting in many tainted data warnings. Most of these end up with logic in fdt_get_string() as the unsafe destination for this tainted data, so let's tweak the logic there to make it clearer to Coverity that this is ok. We add a sanity test on fdt_totalsize() to fdt_probe_ro_(). Because the interface allows bare ints to be used for offsets, we already have the assumption that totalsize must be 31-bits or less (2GiB would be a ludicrously large fdt). This makes this more explicit. We also make fdt_probe_ro() return the size for convenience, and change the logic in fdt_get_string() to keep it in a local so that Coverity can see that it has already been bounds-checked. Signed-off-by: David Gibson --- libfdt/fdt.c | 9 +++++++-- libfdt/fdt_ro.c | 11 ++++++----- libfdt/libfdt_internal.h | 10 +++++----- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 179168e..d6ce7c0 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -15,8 +15,10 @@ * that the given buffer contains what appears to be a flattened * device tree with sane information in its header. */ -int fdt_ro_probe_(const void *fdt) +int32_t fdt_ro_probe_(const void *fdt) { + uint32_t totalsize = fdt_totalsize(fdt); + if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) @@ -31,7 +33,10 @@ int fdt_ro_probe_(const void *fdt) return -FDT_ERR_BADMAGIC; } - return 0; + if (totalsize < INT32_MAX) + return totalsize; + else + return -FDT_ERR_TRUNCATED; } static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 6fd9ec1..a5c2797 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -33,19 +33,20 @@ static int fdt_nodename_eq_(const void *fdt, int offset, const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) { + int32_t totalsize = fdt_ro_probe_(fdt); uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt); size_t len; int err; const char *s, *n; - err = fdt_ro_probe_(fdt); - if (err != 0) + err = totalsize; + if (totalsize < 0) goto fail; err = -FDT_ERR_BADOFFSET; - if (absoffset >= fdt_totalsize(fdt)) + if (absoffset >= totalsize) goto fail; - len = fdt_totalsize(fdt) - absoffset; + len = totalsize - absoffset; if (fdt_magic(fdt) == FDT_MAGIC) { if (stroffset < 0) @@ -288,7 +289,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) const char *nameptr; int err; - if (((err = fdt_ro_probe_(fdt)) != 0) + if (((err = fdt_ro_probe_(fdt)) < 0) || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) goto fail; diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 7830e55..741eeb3 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -11,11 +11,11 @@ #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) int fdt_ro_probe_(const void *fdt); -#define FDT_RO_PROBE(fdt) \ - { \ - int err_; \ - if ((err_ = fdt_ro_probe_(fdt)) != 0) \ - return err_; \ +#define FDT_RO_PROBE(fdt) \ + { \ + int totalsize_; \ + if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \ + return totalsize_; \ } int fdt_check_node_offset_(const void *fdt, int offset); From 184f51099471341715bc81a4c09b56a3c6f9d687 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Mon, 22 Jul 2019 12:32:44 +0930 Subject: [PATCH 0836/1198] Makefile: Add EXTRA_CFLAGS variable Distributions packaging dtc may need to set extra flags. Currently when they do that it overrides the ones set by the makefile. This is particularly problematic when compiling without yaml, as the yaml detection is ignored. ld: dtc.o: in function `main': dtc.c:(.text.startup+0x718): undefined reference to `dt_to_yaml' This patch provides a EXTRA_CFLAGS variable that is added to the list of CFLAGS, and can be set on the command line when packaging. Signed-off-by: Joel Stanley Message-Id: <20190722030244.9580-1-joel@jms.id.au> Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 98f74b1..e955242 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ CONFIG_LOCALVERSION = CPPFLAGS = -I libfdt -I . WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \ -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow -CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) +CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS) BISON = bison LEX = flex From b8d6eca78210952c6d93235c38ebd5836d6409c4 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 28 Jul 2019 16:25:51 +1000 Subject: [PATCH 0837/1198] libfdt: Allow #size-cells of 0 c12b2b0c20eb "libfdt: fdt_address_cells() and fdt_size_cells()" introduced a bug as it consolidated code between the helpers for getting #address-cells and #size-cells. Specifically #size-cells is allowed to be 0, and is frequently found so in practice for /cpus. IEEE1275 only requires implementations to handle 1..4 for #address-cells, although one could make a case for #address-cells == #size-cells == 0 being used to represent a bridge with a single port. While we're there, it's not totally obvious that the existing implicit cast of a u32 to int will give the correct results according to strict C, although it does work in practice. Straighten that up to cast only after we've made our range checks. Reported-by: yonghuhaige via https://github.com/dgibson/dtc/issues/28 Signed-off-by: David Gibson --- libfdt/fdt_addresses.c | 8 +++++--- tests/addr_size_cells.c | 2 ++ tests/addresses.dts | 10 ++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/libfdt/fdt_addresses.c b/libfdt/fdt_addresses.c index d8ba8ec..9a82cd0 100644 --- a/libfdt/fdt_addresses.c +++ b/libfdt/fdt_addresses.c @@ -14,7 +14,7 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name) { const fdt32_t *c; - int val; + uint32_t val; int len; c = fdt_getprop(fdt, nodeoffset, name, &len); @@ -25,10 +25,10 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name) return -FDT_ERR_BADNCELLS; val = fdt32_to_cpu(*c); - if ((val <= 0) || (val > FDT_MAX_NCELLS)) + if (val > FDT_MAX_NCELLS) return -FDT_ERR_BADNCELLS; - return val; + return (int)val; } int fdt_address_cells(const void *fdt, int nodeoffset) @@ -36,6 +36,8 @@ int fdt_address_cells(const void *fdt, int nodeoffset) int val; val = fdt_cells(fdt, nodeoffset, "#address-cells"); + if (val == 0) + return -FDT_ERR_BADNCELLS; if (val == -FDT_ERR_NOTFOUND) return 2; return val; diff --git a/tests/addr_size_cells.c b/tests/addr_size_cells.c index 0d90d53..783574d 100644 --- a/tests/addr_size_cells.c +++ b/tests/addr_size_cells.c @@ -47,8 +47,10 @@ int main(int argc, char *argv[]) check_node(fdt, "/", 2, 2); check_node(fdt, "/identity-bus@0", 2, 1); check_node(fdt, "/simple-bus@1000000", 2, 1); + check_node(fdt, "/discrete-bus@2000000", 1, 0); check_node(fdt, "/c0", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS); check_node(fdt, "/c1", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS); check_node(fdt, "/c2", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS); + check_node(fdt, "/c3", -FDT_ERR_BADNCELLS, 0); PASS(); } diff --git a/tests/addresses.dts b/tests/addresses.dts index fab6b19..1b307ab 100644 --- a/tests/addresses.dts +++ b/tests/addresses.dts @@ -13,6 +13,11 @@ #size-cells = <1>; }; + discrete-bus@2000000 { + #address-cells = <1>; + #size-cells = <0>; + }; + c0@0 { #address-cells = <1 1>; #size-cells = <1 1>; @@ -27,4 +32,9 @@ #address-cells = <5>; #size-cells = <5>; }; + + c3@0 { + #address-cells = <0>; + #size-cells = <0>; + }; }; From 5345db19f615b9147b3d0d8e04e83767b7457e92 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Tue, 27 Aug 2019 23:41:48 +0300 Subject: [PATCH 0838/1198] livetree: simplify condition in get_node_by_path The "strlen && strprefixeq" check in get_node_by_path is excessive, since strlen is checked in strprefixeq macro internally. Thus, "strlen(child->name) == p-path" conjunct duplicates after macro expansion and could be removed. Signed-off-by: Denis Efremov Message-Id: <20190827204148.20604-1-efremov@linux.com> Signed-off-by: David Gibson --- livetree.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/livetree.c b/livetree.c index 0c03999..032df58 100644 --- a/livetree.c +++ b/livetree.c @@ -526,8 +526,7 @@ struct node *get_node_by_path(struct node *tree, const char *path) p = strchr(path, '/'); for_each_child(tree, child) { - if (p && (strlen(child->name) == p-path) && - strprefixeq(path, p - path, child->name)) + if (p && strprefixeq(path, p - path, child->name)) return get_node_by_path(child, p+1); else if (!p && streq(path, child->name)) return child; From 95ce19c14064170e2a3998e487892f07fc5cbdac Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Sat, 17 Aug 2019 23:25:32 +0200 Subject: [PATCH 0839/1198] README: update for Python 3 Convert the usage to be compatible with Python 3 and the current API. Signed-off-by: Luca Weiss Message-Id: <20190817212532.15661-2-luca@z3ntu.xyz> Reviewed-by: Simon Glass Signed-off-by: David Gibson --- README | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/README b/README index 15232ab..9465ee5 100644 --- a/README +++ b/README @@ -14,45 +14,43 @@ 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 python-dev + sudo apt-get install swig python3-dev The library provides an Fdt class which you can use like this: -$ PYTHONPATH=../pylibfdt python +$ PYTHONPATH=../pylibfdt python3 >>> import libfdt ->>> fdt = libfdt.Fdt(open('test_tree1.dtb').read()) +>>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read()) >>> node = fdt.path_offset('/subnode@1') ->>> print node +>>> print(node) 124 >>> prop_offset = fdt.first_property_offset(node) >>> prop = fdt.get_property_by_offset(prop_offset) ->>> print '%s=%r' % (prop.name, prop.value) -compatible=bytearray(b'subnode1\x00') ->>> print '%s=%s' % (prop.name, prop.value) +>>> print('%s=%s' % (prop.name, prop.as_str())) compatible=subnode1 >>> node2 = fdt.path_offset('/') ->>> print fdt.getprop(node2, 'compatible') +>>> 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 - $ python -c "import libfdt; help(libfdt)" + $ python3 -c "import libfdt; help(libfdt)" If you add new features, please check code coverage: - $ sudo apt-get install python-pip python-pytest - $ sudo pip install coverage + $ sudo apt-get install python3-coverage $ cd tests - $ coverage run pylibfdt_tests.py - $ coverage html + # It's just 'coverage' on most other distributions + $ python3-coverage run pylibfdt_tests.py + $ python3-coverage html # Open 'htmlcov/index.html' in your browser To install the library via the normal setup.py method, use: - ./pylibfdt/setup.py [--prefix=/path/to/install_dir] + ./pylibfdt/setup.py install [--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 From 60e0db3d65a1218b0d5a29474e769f28a18e3ca6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 4 Sep 2019 14:58:28 +1000 Subject: [PATCH 0840/1198] Ignore phandle properties in /aliases The 'alias_paths' check verifies that each property in /aliases is a valid path to another node. However this can cans false positives trees where the /aliases node has a phandle property, which isn't in this format but is allowed. In particular this situation can be common with trees dumped from some real OF systems (which typically generate a phandle for every node). Special case this to avoid the spurious error. Signed-off-by: David Gibson --- checks.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/checks.c b/checks.c index d7986ee..756f0fa 100644 --- a/checks.c +++ b/checks.c @@ -691,6 +691,11 @@ static void check_alias_paths(struct check *c, struct dt_info *dti, return; for_each_property(node, prop) { + if (streq(prop->name, "phandle") + || streq(prop->name, "linux,phandle")) { + continue; + } + if (!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); From b111122ea5eb15325c493dde43fdf94732c97d44 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Sat, 7 Sep 2019 17:25:31 +0200 Subject: [PATCH 0841/1198] pylibfdt: use python3 shebang The default Python version for pylibfdt is already Python 3 but if called without specifiying an interpreter, the setup.py script gets called with Python 2. It's of course still possible to call setup.py with python2 directly. Signed-off-by: Luca Weiss Message-Id: <20190907152530.25102-1-luca@z3ntu.xyz> Signed-off-by: David Gibson --- pylibfdt/setup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py index a00bf8b..53f2bef 100755 --- a/pylibfdt/setup.py +++ b/pylibfdt/setup.py @@ -1,6 +1,9 @@ -#!/usr/bin/env python2 +#!/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. From 67f790c1adccdf56f6560739a2a6194b99fdc838 Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Tue, 10 Sep 2019 12:48:24 +0200 Subject: [PATCH 0842/1198] libfdt.h: add explicit cast from void* to uint8_t* in fdt(32|64)_st MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Including libfdt.h in a C++ project fails during compilation with recent version of GCC or Clang. This simple example: extern "C" { #include } int main(void) { return 0; } leads to the following errors with GCC 9.1.0: /usr/include/libfdt.h: In function ‘void fdt32_st(void*, uint32_t)’: /usr/include/libfdt.h:139:16: error: invalid conversion from ‘void*’ to ‘uint8_t*’ {aka ‘unsigned char*’} [-fpermissive] 139 | uint8_t *bp = property; | ^~~~~~~~ | | | void* /usr/include/libfdt.h: In function ‘void fdt64_st(void*, uint64_t)’: /usr/include/libfdt.h:163:16: error: invalid conversion from ‘void*’ to ‘uint8_t*’ {aka ‘unsigned char*’} [-fpermissive] 163 | uint8_t *bp = property; | ^~~~~~~~ | | | void* This commit adds an explicit cast to uint8_t* to fix this issue. Signed-off-by: Luc Michel Message-Id: <20190910104824.1321594-1-luc.michel@greensocs.com> Signed-off-by: David Gibson --- libfdt/libfdt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 8037f39..fc4c496 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -136,7 +136,7 @@ static inline uint32_t fdt32_ld(const fdt32_t *p) static inline void fdt32_st(void *property, uint32_t value) { - uint8_t *bp = property; + uint8_t *bp = (uint8_t *)property; bp[0] = value >> 24; bp[1] = (value >> 16) & 0xff; @@ -160,7 +160,7 @@ static inline uint64_t fdt64_ld(const fdt64_t *p) static inline void fdt64_st(void *property, uint64_t value) { - uint8_t *bp = property; + uint8_t *bp = (uint8_t *)property; bp[0] = value >> 56; bp[1] = (value >> 48) & 0xff; From 18d7b2f4ee45fec422b7d82bab0b3c762ee907e4 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 18 Sep 2019 13:35:34 -0500 Subject: [PATCH 0843/1198] yamltree: Ensure consistent bracketing of properties with phandles The dts syntax allows for '<>' around phandles and arg cells or not which it didn't matter until adding type information. However, the YAML encoding expects each phandle + args to be bracketed. If TYPE_UINT32 markers are not present before each REF_PHANDLE, fix up the markers and add the TYPE_UINT32 markers. This allows the subsequent YAML emitting code to work as-is. Adding the markers at an earlier stage doesn't work because of possible labels in dts output. We'd have to define the ordering of labels and brackets. Also, it is probably best to have dts output match the input. Signed-off-by: Rob Herring Message-Id: <20190918183534.24205-1-robh@kernel.org> Signed-off-by: David Gibson --- yamltree.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/yamltree.c b/yamltree.c index 5b6ea8e..43ca869 100644 --- a/yamltree.c +++ b/yamltree.c @@ -138,6 +138,27 @@ static void yaml_propval(yaml_emitter_t *emitter, struct property *prop) (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE); yaml_emitter_emit_or_die(emitter, &event); + /* Ensure we have a type marker before any phandle */ + for_each_marker(m) { + int last_offset = 0; + struct marker *type_m; + + if (m->type >= TYPE_UINT8) + last_offset = m->offset; + + if (!(m->next && m->next->type == REF_PHANDLE && + last_offset < m->next->offset)) + continue; + + type_m = xmalloc(sizeof(*type_m)); + type_m->offset = m->next->offset; + type_m->type = TYPE_UINT32; + type_m->ref = NULL; + type_m->next = m->next; + m->next = type_m; + } + + m = prop->val.markers; for_each_marker(m) { int chunk_len; char *data = &prop->val.val[m->offset]; From 4605eb047b38f5b3d0d03182d90273f01c68a857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 9 Oct 2019 14:20:16 +0400 Subject: [PATCH 0844/1198] Add .editorconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set code style for various editors. Signed-off-by: Marc-André Lureau Message-Id: <20191009102025.10179-2-marcandre.lureau@redhat.com> Signed-off-by: David Gibson --- .editorconfig | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..d7e68fb --- /dev/null +++ b/.editorconfig @@ -0,0 +1,30 @@ +# EditorConfig is a file format and collection of text editor plugins +# for maintaining consistent coding styles between different editors +# and IDEs. Most popular editors support this either natively or via +# plugin. +# +# Check https://editorconfig.org for details. + +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space + +[Makefile*] +indent_style = tab +indent_size = 8 +file_type_emacs = makefile + +[*.[ch]] +indent_style = tab +indent_size = 8 + +[*.py] +indent_size = 4 + +[meson.build] +indent_style = space +indent_size = 2 From 0d0d0fa51b1f9703d324bac1d8cf000adca6be62 Mon Sep 17 00:00:00 2001 From: Valter Minute Date: Wed, 9 Oct 2019 12:33:52 +0000 Subject: [PATCH 0845/1198] fdtoverlay: Return non-zero exit code if overlays can't be applied At present the tool terminates its execution if one of the overlays passed as command-line arguments can't be successfully read or applied, but the exit code of the process is zero, making failures hard to detect inside scripts. Signed-off-by: Valter Minute Message-Id: <20191009123256.14248-1-valter.minute@toradex.com> Signed-off-by: David Gibson --- fdtoverlay.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fdtoverlay.c b/fdtoverlay.c index 8a1d11b..5350af6 100644 --- a/fdtoverlay.c +++ b/fdtoverlay.c @@ -110,7 +110,6 @@ static int do_fdtoverlay(const char *input_filename, (unsigned long)buf_len, fdt_totalsize(blob)); goto out_err; } - ret = 0; /* allocate blob pointer array */ ovblob = xmalloc(sizeof(*ovblob) * argc); From aa522da9fff610e9fdad62f5d191e9cbd4ff0fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 9 Oct 2019 14:20:17 +0400 Subject: [PATCH 0846/1198] tests: allow out-of-tree test run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit meson runs out-of-tree, add absolute path location where necessary. Signed-off-by: Marc-André Lureau Message-Id: <20191009102025.10179-3-marcandre.lureau@redhat.com> Signed-off-by: David Gibson --- tests/dtc-checkfails.sh | 3 +- tests/dtc-fails.sh | 3 +- tests/dtc-fatal.sh | 3 +- tests/fdtdump-runtest.sh | 3 +- tests/fdtget-runtest.sh | 3 +- tests/fdtoverlay-runtest.sh | 3 +- tests/fdtput-runtest.sh | 3 +- tests/incbin.c | 7 +- tests/run_tests.sh | 326 ++++++++++++++++++------------------ 9 files changed, 183 insertions(+), 171 deletions(-) mode change 100644 => 100755 tests/dtc-fatal.sh mode change 100644 => 100755 tests/fdtdump-runtest.sh mode change 100644 => 100755 tests/fdtoverlay-runtest.sh mode change 100644 => 100755 tests/fdtput-runtest.sh diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh index 0e8beb4..4fd9691 100755 --- a/tests/dtc-checkfails.sh +++ b/tests/dtc-checkfails.sh @@ -1,6 +1,7 @@ #! /bin/sh -. ./testutils.sh +SRCDIR=`dirname "$0"` +. "$SRCDIR/testutils.sh" for x; do shift diff --git a/tests/dtc-fails.sh b/tests/dtc-fails.sh index 4543203..855b623 100755 --- a/tests/dtc-fails.sh +++ b/tests/dtc-fails.sh @@ -1,6 +1,7 @@ #! /bin/sh -. ./testutils.sh +SRCDIR=`dirname "$0"` +. "$SRCDIR/testutils.sh" if [ "$1" = "-n" ]; then NEG="$1" diff --git a/tests/dtc-fatal.sh b/tests/dtc-fatal.sh old mode 100644 new mode 100755 index 22eea69..08a4d29 --- a/tests/dtc-fatal.sh +++ b/tests/dtc-fatal.sh @@ -1,6 +1,7 @@ #! /bin/sh -. ./testutils.sh +SRCDIR=`dirname "$0"` +. "$SRCDIR/testutils.sh" verbose_run $VALGRIND "$DTC" -o/dev/null "$@" ret="$?" diff --git a/tests/fdtdump-runtest.sh b/tests/fdtdump-runtest.sh old mode 100644 new mode 100755 index 616c737..71ac861 --- a/tests/fdtdump-runtest.sh +++ b/tests/fdtdump-runtest.sh @@ -4,7 +4,8 @@ # $1 - source file to compile and compare with fdtdump output of the # compiled file. -. ./testutils.sh +SRCDIR=`dirname "$0"` +. "$SRCDIR/testutils.sh" dts="$1" dtb="${dts}.dtb" diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh index 21044f3..18b7404 100755 --- a/tests/fdtget-runtest.sh +++ b/tests/fdtget-runtest.sh @@ -1,6 +1,7 @@ #! /bin/sh -. ./testutils.sh +SRCDIR=`dirname "$0"` +. "$SRCDIR/testutils.sh" LOG=tmp.log.$$ EXPECT=tmp.expect.$$ diff --git a/tests/fdtoverlay-runtest.sh b/tests/fdtoverlay-runtest.sh old mode 100644 new mode 100755 index 7c54beb..0c648f4 --- a/tests/fdtoverlay-runtest.sh +++ b/tests/fdtoverlay-runtest.sh @@ -6,7 +6,8 @@ # Usage # fdtoverlay-runtest.sh name expected_output dtb_file node property flags value -. ./testutils.sh +SRCDIR=`dirname "$0"` +. "$SRCDIR/testutils.sh" LOG=tmp.log.$$ EXPECT=tmp.expect.$$ diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh old mode 100644 new mode 100755 index a1f7b85..1210eab --- a/tests/fdtput-runtest.sh +++ b/tests/fdtput-runtest.sh @@ -6,7 +6,8 @@ # Usage # fdtput-runtest.sh name expected_output dtb_file node property flags value -. ./testutils.sh +SRCDIR=`dirname "$0"` +. "$SRCDIR/testutils.sh" LOG=tmp.log.$$ EXPECT=tmp.expect.$$ diff --git a/tests/incbin.c b/tests/incbin.c index fd02609..36ff669 100644 --- a/tests/incbin.c +++ b/tests/incbin.c @@ -52,8 +52,11 @@ int main(int argc, char *argv[]) test_init(argc, argv); - incbin = load_file("incbin.bin", &len); - fdt = load_blob_arg(argc, argv); + if (argc != 3) + CONFIG("Usage: %s ", argv[0]); + + incbin = load_file(argv[1], &len); + fdt = load_blob(argv[2]); check_getprop(fdt, 0, "incbin", len, incbin); check_getprop(fdt, 0, "incbin-partial", 17, incbin + 13); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 2620332..081f1ee 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -1,6 +1,7 @@ #! /bin/sh -. ./testutils.sh +SRCDIR=`dirname "$0"` +. "$SRCDIR/testutils.sh" if [ -z "$CC" ]; then CC=gcc @@ -149,7 +150,7 @@ run_dtc_test () { } asm_to_so () { - $CC -shared -o $1.test.so data.S $1.test.s + $CC -shared -o $1.test.so "$SRCDIR/data.S" $1.test.s } asm_to_so_test () { @@ -160,7 +161,7 @@ run_fdtget_test () { expect="$1" shift printf "fdtget-runtest.sh %s $*: " "$(echo $expect)" - base_run_test sh fdtget-runtest.sh "$expect" "$@" + base_run_test sh "$SRCDIR/fdtget-runtest.sh" "$expect" "$@" } run_fdtput_test () { @@ -168,14 +169,14 @@ run_fdtput_test () { shift shorten_echo fdtput-runtest.sh "$expect" "$@" printf ": " - base_run_test sh fdtput-runtest.sh "$expect" "$@" + base_run_test sh "$SRCDIR/fdtput-runtest.sh" "$expect" "$@" } run_fdtdump_test() { file="$1" shorten_echo fdtdump-runtest.sh "$file" printf ": " - base_run_test sh fdtdump-runtest.sh "$file" 2>/dev/null + base_run_test sh "$SRCDIR/fdtdump-runtest.sh" "$file" 2>/dev/null } run_fdtoverlay_test() { @@ -183,7 +184,7 @@ run_fdtoverlay_test() { shift shorten_echo fdtoverlay-runtest.sh "$expect" "$@" printf ": " - base_run_test sh fdtoverlay-runtest.sh "$expect" "$@" + base_run_test sh "$SRCDIR/fdtoverlay-runtest.sh" "$expect" "$@" } BAD_FIXUP_TREES="bad_index \ @@ -198,12 +199,12 @@ BAD_FIXUP_TREES="bad_index \ # Test to exercise libfdt overlay application without dtc's overlay support libfdt_overlay_tests () { # First test a doctored overlay which requires only local fixups - run_dtc_test -I dts -O dtb -o overlay_base_no_symbols.test.dtb overlay_base.dts + run_dtc_test -I dts -O dtb -o overlay_base_no_symbols.test.dtb "$SRCDIR/overlay_base.dts" run_test check_path overlay_base_no_symbols.test.dtb not-exists "/__symbols__" run_test check_path overlay_base_no_symbols.test.dtb not-exists "/__fixups__" run_test check_path overlay_base_no_symbols.test.dtb not-exists "/__local_fixups__" - run_dtc_test -I dts -O dtb -o overlay_overlay_no_fixups.test.dtb overlay_overlay_no_fixups.dts + run_dtc_test -I dts -O dtb -o overlay_overlay_no_fixups.test.dtb "$SRCDIR/overlay_overlay_no_fixups.dts" run_test check_path overlay_overlay_no_fixups.test.dtb not-exists "/__symbols__" run_test check_path overlay_overlay_no_fixups.test.dtb not-exists "/__fixups__" run_test check_path overlay_overlay_no_fixups.test.dtb exists "/__local_fixups__" @@ -211,12 +212,12 @@ libfdt_overlay_tests () { run_test overlay overlay_base_no_symbols.test.dtb overlay_overlay_no_fixups.test.dtb # Then test with manually constructed fixups - run_dtc_test -I dts -O dtb -o overlay_base_manual_symbols.test.dtb overlay_base_manual_symbols.dts + run_dtc_test -I dts -O dtb -o overlay_base_manual_symbols.test.dtb "$SRCDIR/overlay_base_manual_symbols.dts" run_test check_path overlay_base_manual_symbols.test.dtb exists "/__symbols__" run_test check_path overlay_base_manual_symbols.test.dtb not-exists "/__fixups__" run_test check_path overlay_base_manual_symbols.test.dtb not-exists "/__local_fixups__" - run_dtc_test -I dts -O dtb -o overlay_overlay_manual_fixups.test.dtb overlay_overlay_manual_fixups.dts + run_dtc_test -I dts -O dtb -o overlay_overlay_manual_fixups.test.dtb "$SRCDIR/overlay_overlay_manual_fixups.dts" run_test check_path overlay_overlay_manual_fixups.test.dtb not-exists "/__symbols__" run_test check_path overlay_overlay_manual_fixups.test.dtb exists "/__fixups__" run_test check_path overlay_overlay_manual_fixups.test.dtb exists "/__local_fixups__" @@ -224,7 +225,7 @@ libfdt_overlay_tests () { run_test overlay overlay_base_manual_symbols.test.dtb overlay_overlay_manual_fixups.test.dtb # test simplified plugin syntax - run_dtc_test -@ -I dts -O dtb -o overlay_overlay_simple.dtb overlay_overlay_simple.dts + run_dtc_test -@ -I dts -O dtb -o overlay_overlay_simple.dtb "$SRCDIR/overlay_overlay_simple.dts" # verify non-generation of local fixups run_test check_path overlay_overlay_simple.dtb not-exists "/__local_fixups__" @@ -232,7 +233,7 @@ libfdt_overlay_tests () { # Bad fixup tests for test in $BAD_FIXUP_TREES; do tree="overlay_bad_fixup_$test" - run_dtc_test -I dts -O dtb -o $tree.test.dtb $tree.dts + 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 } @@ -240,45 +241,45 @@ libfdt_overlay_tests () { # Tests to exercise dtc's overlay generation support dtc_overlay_tests () { # Overlay tests for dtc - run_dtc_test -@ -I dts -O dtb -o overlay_base.test.dtb overlay_base.dts + run_dtc_test -@ -I dts -O dtb -o overlay_base.test.dtb "$SRCDIR/overlay_base.dts" run_test check_path overlay_base.test.dtb exists "/__symbols__" run_test check_path overlay_base.test.dtb not-exists "/__fixups__" run_test check_path overlay_base.test.dtb not-exists "/__local_fixups__" # With syntactic sugar - run_dtc_test -I dts -O dtb -o overlay_overlay.test.dtb overlay_overlay.dts + run_dtc_test -I dts -O dtb -o overlay_overlay.test.dtb "$SRCDIR/overlay_overlay.dts" run_test check_path overlay_overlay.test.dtb not-exists "/__symbols__" run_test check_path overlay_overlay.test.dtb exists "/__fixups__" 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 overlay_overlay.dts + run_dtc_test -I dts -O dtb -o overlay_overlay_nosugar.test.dtb "$SRCDIR/overlay_overlay.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__" # Using target-path - run_dtc_test -I dts -O dtb -o overlay_overlay_bypath.test.dtb overlay_overlay_bypath.dts + run_dtc_test -I dts -O dtb -o overlay_overlay_bypath.test.dtb "$SRCDIR/overlay_overlay_bypath.dts" run_test check_path overlay_overlay_bypath.test.dtb not-exists "/__symbols__" run_test check_path overlay_overlay_bypath.test.dtb not-exists "/__fixups__" run_test check_path overlay_overlay_bypath.test.dtb exists "/__local_fixups__" # Make sure local target references are resolved and nodes are merged and that path references are not - run_dtc_test -I dts -O dtb -o overlay_overlay_local_merge.test.dtb overlay_overlay_local_merge.dts + run_dtc_test -I dts -O dtb -o overlay_overlay_local_merge.test.dtb "$SRCDIR/overlay_overlay_local_merge.dts" run_test check_path overlay_overlay_local_merge.test.dtb exists "/fragment@0/__overlay__/new-node/new-merged-node" run_test check_path overlay_overlay_local_merge.test.dtb exists "/fragment@1/__overlay__/new-root-node" # Check building works the same as manual constructions run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_nosugar.test.dtb - run_dtc_test -I dts -O dtb -o overlay_overlay_manual_fixups.test.dtb overlay_overlay_manual_fixups.dts + run_dtc_test -I dts -O dtb -o overlay_overlay_manual_fixups.test.dtb "$SRCDIR/overlay_overlay_manual_fixups.dts" run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_manual_fixups.test.dtb - run_dtc_test -I dts -O dtb -o overlay_overlay_no_fixups.test.dtb overlay_overlay_no_fixups.dts + run_dtc_test -I dts -O dtb -o overlay_overlay_no_fixups.test.dtb "$SRCDIR/overlay_overlay_no_fixups.dts" run_test dtbs_equal_ordered overlay_overlay_bypath.test.dtb overlay_overlay_no_fixups.test.dtb # Check we can actually apply the result - run_dtc_test -I dts -O dtb -o overlay_base_no_symbols.test.dtb overlay_base.dts + run_dtc_test -I dts -O dtb -o overlay_base_no_symbols.test.dtb "$SRCDIR/overlay_base.dts" run_test overlay overlay_base.test.dtb overlay_overlay.test.dtb run_test overlay overlay_base_no_symbols.test.dtb overlay_overlay_bypath.test.dtb @@ -288,7 +289,7 @@ dtc_overlay_tests () { run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_decompile.test.dtb # Test generation of aliases instead of symbols - run_dtc_test -A -I dts -O dtb -o overlay_base_with_aliases.dtb overlay_base.dts + run_dtc_test -A -I dts -O dtb -o overlay_base_with_aliases.dtb "$SRCDIR/overlay_base.dts" run_test check_path overlay_base_with_aliases.dtb exists "/aliases" run_test check_path overlay_base_with_aliases.dtb not-exists "/__symbols__" run_test check_path overlay_base_with_aliases.dtb not-exists "/__fixups__" @@ -336,9 +337,9 @@ tree1_tests_rw () { check_tests () { tree="$1" shift - run_sh_test dtc-checkfails.sh "$@" -- -I dts -O dtb $tree + 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 dtc-checkfails.sh "$@" -- -I dtb -O dtb $tree.test.dtb + run_sh_test "$SRCDIR/dtc-checkfails.sh" "$@" -- -I dtb -O dtb $tree.test.dtb } ALL_LAYOUTS="mts mst tms tsm smt stm" @@ -346,12 +347,12 @@ ALL_LAYOUTS="mts mst tms tsm smt stm" libfdt_tests () { tree1_tests test_tree1.dtb - run_dtc_test -I dts -O dtb -o addresses.test.dtb addresses.dts + run_dtc_test -I dts -O dtb -o addresses.test.dtb "$SRCDIR/addresses.dts" run_test addr_size_cells addresses.test.dtb - run_dtc_test -I dts -O dtb -o addresses2.test.dtb empty.dts + run_dtc_test -I dts -O dtb -o addresses2.test.dtb "$SRCDIR/empty.dts" run_test addr_size_cells2 addresses2.test.dtb - run_dtc_test -I dts -O dtb -o stringlist.test.dtb stringlist.dts + run_dtc_test -I dts -O dtb -o stringlist.test.dtb "$SRCDIR/stringlist.dts" run_test stringlist stringlist.test.dtb for flags in default no_name_dedup; do @@ -412,7 +413,7 @@ libfdt_tests () { tree1_tests_rw rw_tree1.test.dtb run_test appendprop1 run_test appendprop2 appendprop1.test.dtb - run_dtc_test -I dts -O dtb -o appendprop.test.dtb appendprop.dts + run_dtc_test -I dts -O dtb -o appendprop.test.dtb "$SRCDIR/appendprop.dts" run_test dtbs_equal_ordered appendprop2.test.dtb appendprop.test.dtb libfdt_overlay_tests @@ -425,13 +426,13 @@ libfdt_tests () { run_test rw_oom - run_dtc_test -I dts -O dtb -o subnode_iterate.dtb subnode_iterate.dts + run_dtc_test -I dts -O dtb -o subnode_iterate.dtb "$SRCDIR/subnode_iterate.dts" run_test subnode_iterate subnode_iterate.dtb - run_dtc_test -I dts -O dtb -o property_iterate.dtb property_iterate.dts + run_dtc_test -I dts -O dtb -o property_iterate.dtb "$SRCDIR/property_iterate.dts" run_test property_iterate property_iterate.dtb - run_dtc_test -I dts -O dtb -o unit-addr-without-reg.dtb unit-addr-without-reg.dts + run_dtc_test -I dts -O dtb -o unit-addr-without-reg.dtb "$SRCDIR/unit-addr-without-reg.dts" run_test appendprop_addrrange unit-addr-without-reg.dtb 1 1 1 run_test appendprop_addrrange unit-addr-without-reg.dtb 2 2 2 run_test appendprop_addrrange unit-addr-without-reg.dtb 2 1 3 @@ -442,26 +443,26 @@ libfdt_tests () { run_test truncated_memrsv # Check aliases support in fdt_path_offset - run_dtc_test -I dts -O dtb -o aliases.dtb aliases.dts + run_dtc_test -I dts -O dtb -o aliases.dtb "$SRCDIR/aliases.dts" run_test get_alias aliases.dtb run_test path_offset_aliases aliases.dtb # Specific bug tests run_test add_subnode_with_nops - run_dtc_test -I dts -O dts -o sourceoutput.test.dts sourceoutput.dts - run_dtc_test -I dts -O dtb -o sourceoutput.test.dtb sourceoutput.dts + run_dtc_test -I dts -O dts -o sourceoutput.test.dts "$SRCDIR/sourceoutput.dts" + run_dtc_test -I dts -O dtb -o sourceoutput.test.dtb "$SRCDIR/sourceoutput.dts" run_dtc_test -I dts -O dtb -o sourceoutput.test.dts.test.dtb sourceoutput.test.dts run_test dtbs_equal_ordered sourceoutput.test.dtb sourceoutput.test.dts.test.dtb - run_dtc_test -I dts -O dtb -o embedded_nul.test.dtb embedded_nul.dts - run_dtc_test -I dts -O dtb -o embedded_nul_equiv.test.dtb embedded_nul_equiv.dts + run_dtc_test -I dts -O dtb -o embedded_nul.test.dtb "$SRCDIR/embedded_nul.dts" + run_dtc_test -I dts -O dtb -o embedded_nul_equiv.test.dtb "$SRCDIR/embedded_nul_equiv.dts" run_test dtbs_equal_ordered embedded_nul.test.dtb embedded_nul_equiv.test.dtb - run_dtc_test -I dts -O dtb bad-size-cells.dts + 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_dtc_test -I dts -O dtb nul-in-escape.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 @@ -488,62 +489,62 @@ libfdt_tests () { } dtc_tests () { - run_dtc_test -I dts -O dtb -o dtc_tree1.test.dtb test_tree1.dts + run_dtc_test -I dts -O dtb -o dtc_tree1.test.dtb "$SRCDIR/test_tree1.dts" tree1_tests dtc_tree1.test.dtb tree1_tests_rw dtc_tree1.test.dtb run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb - run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb propname_escapes.dts + run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb "$SRCDIR/propname_escapes.dts" run_test propname_escapes dtc_escapes.test.dtb - run_dtc_test -I dts -O dtb -o line_directives.test.dtb line_directives.dts + run_dtc_test -I dts -O dtb -o line_directives.test.dtb "$SRCDIR/line_directives.dts" - run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts + run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb "$SRCDIR/escapes.dts" run_test string_escapes dtc_escapes.test.dtb - run_dtc_test -I dts -O dtb -o dtc_char_literal.test.dtb char_literal.dts + run_dtc_test -I dts -O dtb -o dtc_char_literal.test.dtb "$SRCDIR/char_literal.dts" run_test char_literal dtc_char_literal.test.dtb - run_dtc_test -I dts -O dtb -o dtc_sized_cells.test.dtb sized_cells.dts + run_dtc_test -I dts -O dtb -o dtc_sized_cells.test.dtb "$SRCDIR/sized_cells.dts" run_test sized_cells dtc_sized_cells.test.dtb - run_dtc_test -I dts -O dtb -o dtc_extra-terminating-null.test.dtb extra-terminating-null.dts + run_dtc_test -I dts -O dtb -o dtc_extra-terminating-null.test.dtb "$SRCDIR/extra-terminating-null.dts" run_test extra-terminating-null dtc_extra-terminating-null.test.dtb - run_dtc_test -I dts -O dtb -o dtc_references.test.dtb references.dts + run_dtc_test -I dts -O dtb -o dtc_references.test.dtb "$SRCDIR/references.dts" run_test references dtc_references.test.dtb - run_dtc_test -I dts -O dtb -o dtc_path-references.test.dtb path-references.dts + run_dtc_test -I dts -O dtb -o dtc_path-references.test.dtb "$SRCDIR/path-references.dts" run_test path-references dtc_path-references.test.dtb run_test phandle_format dtc_references.test.dtb epapr for f in legacy epapr both; do - run_dtc_test -I dts -O dtb -H $f -o dtc_references.test.$f.dtb references.dts + run_dtc_test -I dts -O dtb -H $f -o dtc_references.test.$f.dtb "$SRCDIR/references.dts" run_test phandle_format dtc_references.test.$f.dtb $f done - run_dtc_test -I dts -O dtb -o multilabel.test.dtb multilabel.dts + run_dtc_test -I dts -O dtb -o multilabel.test.dtb "$SRCDIR/multilabel.dts" run_test references multilabel.test.dtb - run_dtc_test -I dts -O dtb -o label_repeated.test.dtb label_repeated.dts + run_dtc_test -I dts -O dtb -o label_repeated.test.dtb "$SRCDIR/label_repeated.dts" - run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb comments.dts - run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts + run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb "$SRCDIR/comments.dts" + run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb "$SRCDIR/comments-cmp.dts" run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb # Check /include/ directive - run_dtc_test -I dts -O dtb -o includes.test.dtb include0.dts + run_dtc_test -I dts -O dtb -o includes.test.dtb "$SRCDIR/include0.dts" run_test dtbs_equal_ordered includes.test.dtb test_tree1.dtb # Check /incbin/ directive - run_dtc_test -I dts -O dtb -o incbin.test.dtb incbin.dts - run_test incbin incbin.test.dtb + run_dtc_test -I dts -O dtb -o incbin.test.dtb "$SRCDIR/incbin.dts" + run_test incbin "$SRCDIR/incbin.bin" incbin.test.dtb # Check boot_cpuid_phys handling - run_dtc_test -I dts -O dtb -o boot_cpuid.test.dtb boot-cpuid.dts + run_dtc_test -I dts -O dtb -o boot_cpuid.test.dtb "$SRCDIR/boot-cpuid.dts" run_test boot-cpuid boot_cpuid.test.dtb 16 - run_dtc_test -I dts -O dtb -b 17 -o boot_cpuid_17.test.dtb boot-cpuid.dts + run_dtc_test -I dts -O dtb -b 17 -o boot_cpuid_17.test.dtb "$SRCDIR/boot-cpuid.dts" run_test boot-cpuid boot_cpuid_17.test.dtb 17 run_dtc_test -I dtb -O dtb -o preserve_boot_cpuid.test.dtb boot_cpuid.test.dtb @@ -565,9 +566,9 @@ dtc_tests () { for tree in test_tree1.dts escapes.dts references.dts path-references.dts \ comments.dts aliases.dts include0.dts incbin.dts \ value-labels.dts ; do - run_dtc_test -I dts -O asm -o oasm_$tree.test.s $tree + 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 $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 done @@ -584,13 +585,13 @@ dtc_tests () { # Check -Odts preserving type information for tree in type-preservation.dts; do - run_dtc_test -I dts -O dts -o $tree.test.dts $tree + run_dtc_test -I dts -O dts -o $tree.test.dts "$SRCDIR/$tree" run_dtc_test -I dts -O dts $tree.test.dts - run_wrap_test cmp $tree $tree.test.dts + run_wrap_test cmp "$SRCDIR/$tree" $tree.test.dts done for tree in path-references; do - run_dtc_test -I dts -O dtb -o $tree.test.dtb $tree.dts - run_dtc_test -I dts -O dts -o $tree.test.dts $tree.dts + run_dtc_test -I dts -O dtb -o $tree.test.dtb "$SRCDIR/$tree.dts" + run_dtc_test -I dts -O dts -o $tree.test.dts "$SRCDIR/$tree.dts" run_dtc_test -I dts -O dtb -o $tree.test.dts.test.dtb $tree.test.dts run_test dtbs_equal_ordered $tree.test.dtb $tree.test.dts.test.dtb done @@ -598,8 +599,8 @@ dtc_tests () { # Check -Oyaml output if pkg-config --exists yaml-0.1; then for tree in type-preservation; do - run_dtc_test -I dts -O yaml -o $tree.test.dt.yaml $tree.dts - run_wrap_test cmp $tree.dt.yaml $tree.test.dt.yaml + run_dtc_test -I dts -O yaml -o $tree.test.dt.yaml "$SRCDIR/$tree.dts" + run_wrap_test cmp "$SRCDIR/$tree.dt.yaml" $tree.test.dt.yaml done fi @@ -617,102 +618,102 @@ dtc_tests () { done # Check merge/overlay functionality - run_dtc_test -I dts -O dtb -o dtc_tree1_merge.test.dtb test_tree1_merge.dts + run_dtc_test -I dts -O dtb -o dtc_tree1_merge.test.dtb "$SRCDIR/test_tree1_merge.dts" tree1_tests dtc_tree1_merge.test.dtb test_tree1.dtb - run_dtc_test -I dts -O dtb -o dtc_tree1_merge_labelled.test.dtb test_tree1_merge_labelled.dts + run_dtc_test -I dts -O dtb -o dtc_tree1_merge_labelled.test.dtb "$SRCDIR/test_tree1_merge_labelled.dts" tree1_tests dtc_tree1_merge_labelled.test.dtb test_tree1.dtb - run_dtc_test -I dts -O dtb -o dtc_tree1_label_noderef.test.dtb test_tree1_label_noderef.dts + run_dtc_test -I dts -O dtb -o dtc_tree1_label_noderef.test.dtb "$SRCDIR/test_tree1_label_noderef.dts" run_test dtbs_equal_unordered dtc_tree1_label_noderef.test.dtb test_tree1.dtb - run_dtc_test -I dts -O dtb -o multilabel_merge.test.dtb multilabel_merge.dts + run_dtc_test -I dts -O dtb -o multilabel_merge.test.dtb "$SRCDIR/multilabel_merge.dts" run_test references multilabel.test.dtb run_test dtbs_equal_ordered multilabel.test.dtb multilabel_merge.test.dtb - run_dtc_test -I dts -O dtb -o dtc_tree1_merge_path.test.dtb test_tree1_merge_path.dts + run_dtc_test -I dts -O dtb -o dtc_tree1_merge_path.test.dtb "$SRCDIR/test_tree1_merge_path.dts" tree1_tests dtc_tree1_merge_path.test.dtb test_tree1.dtb - run_wrap_error_test $DTC -I dts -O dtb -o /dev/null test_label_ref.dts + run_wrap_error_test $DTC -I dts -O dtb -o /dev/null "$SRCDIR/test_label_ref.dts" # Check prop/node delete functionality - run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb test_tree1_delete.dts + 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 # Check omit-if-no-ref functionality - run_dtc_test -I dts -O dtb -o omit-no-ref.test.dtb omit-no-ref.dts + run_dtc_test -I dts -O dtb -o omit-no-ref.test.dtb "$SRCDIR/omit-no-ref.dts" run_test check_path omit-no-ref.test.dtb not-exists "/node1" run_test check_path omit-no-ref.test.dtb not-exists "/node2" run_test check_path omit-no-ref.test.dtb exists "/node3" run_test check_path omit-no-ref.test.dtb exists "/node4" - run_dtc_test -I dts -O dts -o delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel.dts - run_wrap_test cmp delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel_ref.dts + run_dtc_test -I dts -O dts -o delete_reinstate_multilabel.dts.test.dts "$SRCDIR/delete_reinstate_multilabel.dts" + run_wrap_test cmp delete_reinstate_multilabel.dts.test.dts "$SRCDIR/delete_reinstate_multilabel_ref.dts" # Check some checks - check_tests dup-nodename.dts duplicate_node_names - check_tests dup-propname.dts duplicate_property_names - check_tests dup-phandle.dts explicit_phandles - check_tests zero-phandle.dts explicit_phandles - check_tests minusone-phandle.dts explicit_phandles - run_sh_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-node-ref.dts - run_sh_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-label-ref.dts - run_sh_test dtc-fatal.sh -I dts -O dtb nonexist-node-ref2.dts - check_tests bad-name-property.dts name_properties + check_tests "$SRCDIR/dup-nodename.dts" duplicate_node_names + check_tests "$SRCDIR/dup-propname.dts" duplicate_property_names + check_tests "$SRCDIR/dup-phandle.dts" explicit_phandles + check_tests "$SRCDIR/zero-phandle.dts" explicit_phandles + check_tests "$SRCDIR/minusone-phandle.dts" explicit_phandles + run_sh_test "$SRCDIR/dtc-checkfails.sh" phandle_references -- -I dts -O dtb "$SRCDIR/nonexist-node-ref.dts" + run_sh_test "$SRCDIR/dtc-checkfails.sh" phandle_references -- -I dts -O dtb "$SRCDIR/nonexist-label-ref.dts" + 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 bad-ncells.dts address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell - check_tests 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 bad-chosen.dts chosen_node_is_root - check_tests bad-chosen.dts chosen_node_bootargs - check_tests bad-chosen.dts chosen_node_stdout_path - check_tests bad-reg-ranges.dts reg_format ranges_format - check_tests bad-empty-ranges.dts ranges_format - check_tests reg-ranges-root.dts reg_format ranges_format - check_tests default-addr-size.dts avoid_default_addr_size - check_tests obsolete-chosen-interrupt-controller.dts obsolete_chosen_interrupt_controller - check_tests reg-without-unit-addr.dts unit_address_vs_reg - check_tests unit-addr-without-reg.dts unit_address_vs_reg - check_tests unit-addr-leading-0x.dts unit_address_format - check_tests unit-addr-leading-0s.dts unit_address_format - check_tests unit-addr-unique.dts unique_unit_address - check_tests bad-phandle-cells.dts interrupts_extended_property - check_tests bad-gpio.dts gpios_property - check_tests bad-graph.dts graph_child_address - check_tests bad-graph.dts graph_port - check_tests bad-graph.dts graph_endpoint - run_sh_test dtc-checkfails.sh deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb bad-gpio.dts - check_tests bad-interrupt-cells.dts interrupts_property - run_sh_test dtc-checkfails.sh node_name_chars -- -I dtb -O dtb bad_node_char.dtb - run_sh_test dtc-checkfails.sh node_name_format -- -I dtb -O dtb bad_node_format.dtb - run_sh_test dtc-checkfails.sh property_name_chars -- -I dtb -O dtb bad_prop_char.dtb + check_tests "$SRCDIR/bad-ncells.dts" address_cells_is_cell size_cells_is_cell interrupt_cells_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 + check_tests "$SRCDIR/bad-chosen.dts" chosen_node_stdout_path + check_tests "$SRCDIR/bad-reg-ranges.dts" reg_format ranges_format + check_tests "$SRCDIR/bad-empty-ranges.dts" ranges_format + check_tests "$SRCDIR/reg-ranges-root.dts" reg_format ranges_format + check_tests "$SRCDIR/default-addr-size.dts" avoid_default_addr_size + check_tests "$SRCDIR/obsolete-chosen-interrupt-controller.dts" obsolete_chosen_interrupt_controller + check_tests "$SRCDIR/reg-without-unit-addr.dts" unit_address_vs_reg + check_tests "$SRCDIR/unit-addr-without-reg.dts" unit_address_vs_reg + check_tests "$SRCDIR/unit-addr-leading-0x.dts" unit_address_format + check_tests "$SRCDIR/unit-addr-leading-0s.dts" unit_address_format + 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/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" + check_tests "$SRCDIR/bad-interrupt-cells.dts" interrupts_property + 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 - run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label1.dts - run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label2.dts - run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label3.dts - run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label4.dts - run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label5.dts - run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label6.dts + run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label1.dts" + run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label2.dts" + run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label3.dts" + run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label4.dts" + run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label5.dts" + run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label6.dts" run_test check_path test_tree1.dtb exists "/subnode@1" run_test check_path test_tree1.dtb not-exists "/subnode@10" - check_tests pci-bridge-ok.dts -n pci_bridge - check_tests pci-bridge-bad1.dts pci_bridge - check_tests pci-bridge-bad2.dts pci_bridge + check_tests "$SRCDIR/pci-bridge-ok.dts" -n pci_bridge + check_tests "$SRCDIR/pci-bridge-bad1.dts" pci_bridge + check_tests "$SRCDIR/pci-bridge-bad2.dts" pci_bridge - check_tests unit-addr-simple-bus-reg-mismatch.dts simple_bus_reg - check_tests unit-addr-simple-bus-compatible.dts simple_bus_reg + check_tests "$SRCDIR/unit-addr-simple-bus-reg-mismatch.dts" simple_bus_reg + check_tests "$SRCDIR/unit-addr-simple-bus-compatible.dts" simple_bus_reg # Check warning options - run_sh_test 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 bad-ncells.dts - run_sh_test dtc-fails.sh -n test-warn-output.test.dtb -I dts -O dtb bad-ncells.dts - run_sh_test dtc-fails.sh test-error-output.test.dtb -I dts -O dtb bad-ncells.dts -Esize_cells_is_cell - run_sh_test dtc-checkfails.sh always_fail -- -Walways_fail -I dts -O dtb test_tree1.dts - run_sh_test dtc-checkfails.sh -n always_fail -- -Walways_fail -Wno_always_fail -I dts -O dtb test_tree1.dts - run_sh_test dtc-fails.sh test-negation-1.test.dtb -Ealways_fail -I dts -O dtb test_tree1.dts - run_sh_test dtc-fails.sh -n test-negation-2.test.dtb -Ealways_fail -Eno_always_fail -I dts -O dtb test_tree1.dts - run_sh_test dtc-fails.sh test-negation-3.test.dtb -Ealways_fail -Wno_always_fail -I dts -O dtb test_tree1.dts - run_sh_test dtc-fails.sh -n test-negation-4.test.dtb -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb bad-ncells.dts - run_sh_test dtc-checkfails.sh size_cells_is_cell -- -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb bad-ncells.dts + 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-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" + 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" + run_sh_test "$SRCDIR/dtc-fails.sh" -n test-negation-2.test.dtb -Ealways_fail -Eno_always_fail -I dts -O dtb "$SRCDIR/test_tree1.dts" + run_sh_test "$SRCDIR/dtc-fails.sh" test-negation-3.test.dtb -Ealways_fail -Wno_always_fail -I dts -O dtb "$SRCDIR/test_tree1.dts" + run_sh_test "$SRCDIR/dtc-fails.sh" -n test-negation-4.test.dtb -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb "$SRCDIR/bad-ncells.dts" + run_sh_test "$SRCDIR/dtc-checkfails.sh" size_cells_is_cell -- -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb "$SRCDIR/bad-ncells.dts" # Check for proper behaviour reading from stdin - run_dtc_test -I dts -O dtb -o stdin_dtc_tree1.test.dtb - < test_tree1.dts + run_dtc_test -I dts -O dtb -o stdin_dtc_tree1.test.dtb - < "$SRCDIR/test_tree1.dts" run_wrap_test cmp stdin_dtc_tree1.test.dtb dtc_tree1.test.dtb 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 @@ -723,32 +724,33 @@ dtc_tests () { run_test integer-expressions integer-expressions.test.dtb # Check for graceful failure in some error conditions - run_sh_test dtc-fatal.sh -I dts -O dtb nosuchfile.dts - run_sh_test dtc-fatal.sh -I dtb -O dtb nosuchfile.dtb - run_sh_test dtc-fatal.sh -I fs -O dtb nosuchfile + run_sh_test "$SRCDIR/dtc-fatal.sh" -I dts -O dtb nosuchfile.dts + run_sh_test "$SRCDIR/dtc-fatal.sh" -I dtb -O dtb nosuchfile.dtb + run_sh_test "$SRCDIR/dtc-fatal.sh" -I fs -O dtb nosuchfile # Dependencies - run_dtc_test -I dts -O dtb -o dependencies.test.dtb -d dependencies.test.d dependencies.dts - run_wrap_test cmp dependencies.test.d dependencies.cmp + run_dtc_test -I dts -O dtb -o dependencies.test.dtb -d dependencies.test.d "$SRCDIR/dependencies.dts" + sed -i "s,$SRCDIR/,,g" dependencies.test.d + run_wrap_test cmp dependencies.test.d "$SRCDIR/dependencies.cmp" # Search paths - run_wrap_error_test $DTC -I dts -O dtb -o search_paths.dtb search_paths.dts - run_dtc_test -i search_dir -I dts -O dtb -o search_paths.dtb \ - search_paths.dts - run_wrap_error_test $DTC -i search_dir_b -I dts -O dtb \ - -o search_paths_b.dtb search_paths_b.dts - run_dtc_test -i search_dir_b -i search_dir -I dts -O dtb \ - -o search_paths_b.dtb search_paths_b.dts + run_wrap_error_test $DTC -I dts -O dtb -o search_paths.dtb "$SRCDIR/search_paths.dts" + run_dtc_test -i "$SRCDIR/search_dir" -I dts -O dtb -o search_paths.dtb \ + "$SRCDIR/search_paths.dts" + run_wrap_error_test $DTC -i "$SRCDIR/search_dir_b" -I dts -O dtb \ + -o search_paths_b.dtb "$SRCDIR/search_paths_b.dts" + run_dtc_test -i "$SRCDIR/search_dir_b" -i "$SRCDIR/search_dir" -I dts -O dtb \ + -o search_paths_b.dtb "$SRCDIR/search_paths_b.dts" run_dtc_test -I dts -O dtb -o search_paths_subdir.dtb \ - search_dir_b/search_paths_subdir.dts + "$SRCDIR/search_dir_b/search_paths_subdir.dts" # Check -a option for align in 2 4 8 16 32 64; do # -p -a - run_dtc_test -O dtb -p 1000 -a $align -o align0.dtb subnode_iterate.dts + run_dtc_test -O dtb -p 1000 -a $align -o align0.dtb "$SRCDIR/subnode_iterate.dts" base_run_test check_align align0.dtb $align # -S -a - run_dtc_test -O dtb -S 1999 -a $align -o align1.dtb subnode_iterate.dts + run_dtc_test -O dtb -S 1999 -a $align -o align1.dtb "$SRCDIR/subnode_iterate.dts" base_run_test check_align align1.dtb $align done @@ -789,7 +791,7 @@ cmp_tests () { dtbs_equal_tests () { WRONG_TREE1="" for x in 1 2 3 4 5 6 7 8 9; do - run_dtc_test -I dts -O dtb -o test_tree1_wrong$x.test.dtb test_tree1_wrong$x.dts + run_dtc_test -I dts -O dtb -o test_tree1_wrong$x.test.dtb "$SRCDIR/test_tree1_wrong$x.dts" WRONG_TREE1="$WRONG_TREE1 test_tree1_wrong$x.test.dtb" done cmp_tests test_tree1.dtb $WRONG_TREE1 @@ -798,7 +800,7 @@ dtbs_equal_tests () { fdtget_tests () { dts=label01.dts dtb=$dts.fdtget.test.dtb - run_dtc_test -O dtb -o $dtb $dts + run_dtc_test -O dtb -o $dtb "$SRCDIR/$dts" # run_fdtget_test [] run_fdtget_test "MyBoardName" $dtb / model @@ -832,10 +834,10 @@ fdtget_tests () { fdtput_tests () { dts=label01.dts dtb=$dts.fdtput.test.dtb - text=lorem.txt + text="$SRCDIR/lorem.txt" # Allow just enough space for $text - run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb $dts + run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb "$SRCDIR/$dts" # run_fdtput_test run_fdtput_test "a_model" $dtb / model -ts "a_model" @@ -854,7 +856,7 @@ fdtput_tests () { run_fdtput_test "$(cat $text $text)" $dtb /randomnode blob -ts "$(cat $text $text)" # Start again with a fresh dtb - run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb $dts + run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb "$SRCDIR/$dts" # Node creation run_wrap_error_test $DTPUT $dtb -c /baldrick sod @@ -882,7 +884,7 @@ fdtput_tests () { run_wrap_test $DTPUT $dtb -cp /chosen/son # Start again with a fresh dtb - run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb $dts + run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb "$SRCDIR/$dts" # Node delete run_wrap_test $DTPUT $dtb -c /chosen/node1 /chosen/node2 /chosen/node3 @@ -911,13 +913,13 @@ utilfdt_tests () { } fdtdump_tests () { - run_fdtdump_test fdtdump.dts + run_fdtdump_test "$SRCDIR/fdtdump.dts" } fdtoverlay_tests() { - base=overlay_base.dts + base="$SRCDIR/overlay_base.dts" basedtb=overlay_base.fdoverlay.test.dtb - overlay=overlay_overlay_manual_fixups.dts + overlay="$SRCDIR/overlay_overlay_manual_fixups.dts" overlaydtb=overlay_overlay_manual_fixups.fdoverlay.test.dtb targetdtb=target.fdoverlay.test.dtb @@ -927,11 +929,11 @@ fdtoverlay_tests() { # test that the new property is installed run_fdtoverlay_test foobar "/test-node" "test-str-property" "-ts" ${basedtb} ${targetdtb} ${overlaydtb} - stacked_base=stacked_overlay_base.dts + stacked_base="$SRCDIR/stacked_overlay_base.dts" stacked_basedtb=stacked_overlay_base.fdtoverlay.test.dtb - stacked_bar=stacked_overlay_bar.dts + stacked_bar="$SRCDIR/stacked_overlay_bar.dts" stacked_bardtb=stacked_overlay_bar.fdtoverlay.test.dtb - stacked_baz=stacked_overlay_baz.dts + stacked_baz="$SRCDIR/stacked_overlay_baz.dts" stacked_bazdtb=stacked_overlay_baz.fdtoverlay.test.dtb stacked_targetdtb=stacked_overlay_target.fdtoverlay.test.dtb @@ -942,7 +944,7 @@ fdtoverlay_tests() { # test that baz correctly inserted the property run_fdtoverlay_test baz "/foonode/barnode/baznode" "baz-property" "-ts" ${stacked_basedtb} ${stacked_targetdtb} ${stacked_bardtb} ${stacked_bazdtb} - overlay_long_path=overlay_overlay_long_path.dts + overlay_long_path="$SRCDIR/overlay_overlay_long_path.dts" overlay_long_pathdtb=overlay_overlay_long_path.fdoverlay.test.dtb target_long_pathdtb=overlay_overlay_long_path_target.fdoverlay.test.dtb run_dtc_test -@ -I dts -O dtb -o $overlay_long_pathdtb $overlay_long_path @@ -951,9 +953,9 @@ fdtoverlay_tests() { run_fdtoverlay_test lpath "/test-node/sub-test-node/sub-test-node-with-very-long-target-path/test-0" "prop" "-ts" ${basedtb} ${target_long_pathdtb} ${overlay_long_pathdtb} # test adding a label to the root of a fragment - stacked_base_nolabel=stacked_overlay_base_nolabel.dts + stacked_base_nolabel="$SRCDIR/stacked_overlay_base_nolabel.dts" stacked_base_nolabeldtb=stacked_overlay_base_nolabel.test.dtb - stacked_addlabel=stacked_overlay_addlabel.dts + stacked_addlabel="$SRCDIR/stacked_overlay_addlabel.dts" stacked_addlabeldtb=stacked_overlay_addlabel.test.dtb stacked_addlabel_targetdtb=stacked_overlay_target_nolabel.fdtoverlay.test.dtb @@ -964,9 +966,9 @@ fdtoverlay_tests() { } pylibfdt_tests () { - run_dtc_test -I dts -O dtb -o test_props.dtb test_props.dts + run_dtc_test -I dts -O dtb -o test_props.dtb "$SRCDIR/test_props.dts" TMP=/tmp/tests.stderr.$$ - $PYTHON pylibfdt_tests.py -v 2> $TMP + $PYTHON "$SRCDIR/pylibfdt_tests.py" -v 2> $TMP # Use the 'ok' message meaning the test passed, 'ERROR' meaning it failed # and the summary line for total tests (e.g. 'Ran 17 tests in 0.002s'). From 4c3c4ccb9916411aaa682cb60acfbfd7d6232a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 9 Oct 2019 14:20:18 +0400 Subject: [PATCH 0847/1198] dumptrees: pass outputdir as first argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of outputing files to current directory, allow to specificy an output directory. This helps with meson build system out-of-tree support. Signed-off-by: Marc-André Lureau Message-Id: <20191009102025.10179-4-marcandre.lureau@redhat.com> Signed-off-by: David Gibson --- tests/Makefile.tests | 2 +- tests/dumptrees.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 5093aaa..51259f0 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -74,7 +74,7 @@ $(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o $(TESTS_TREES): $(TESTS_PREFIX)dumptrees @$(VECHO) DUMPTREES - cd $(TESTS_PREFIX); ./dumptrees >/dev/null + cd $(TESTS_PREFIX); ./dumptrees . >/dev/null tests_clean: @$(VECHO) CLEAN "(tests)" diff --git a/tests/dumptrees.c b/tests/dumptrees.c index b2f5b26..aecb326 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -32,6 +32,16 @@ int main(int argc, char *argv[]) { int i; + if (argc != 2) { + fprintf(stderr, "Missing output directory argument\n"); + return 1; + } + + if (chdir(argv[1]) != 0) { + perror("chdir()"); + return 1; + } + for (i = 0; i < NUM_TREES; i++) { void *blob = trees[i].blob; const char *filename = trees[i].filename; From bc876708ab1dbb41f3890fa801b69e9ca01cefa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 9 Oct 2019 14:20:21 +0400 Subject: [PATCH 0848/1198] fstree: replace lstat with stat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes mingw cross-compilation. lstat() doesn't exist on win32. It seems to me that stat() is the right function there, to return informations about the file it refers to. Signed-off-by: Marc-André Lureau Message-Id: <20191009102025.10179-7-marcandre.lureau@redhat.com> Signed-off-by: David Gibson --- fstree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fstree.c b/fstree.c index 9871689..5e59594 100644 --- a/fstree.c +++ b/fstree.c @@ -30,7 +30,7 @@ static struct node *read_fstree(const char *dirname) tmpname = join_path(dirname, de->d_name); - if (lstat(tmpname, &st) < 0) + if (stat(tmpname, &st) < 0) die("stat(%s): %s\n", tmpname, strerror(errno)); if (S_ISREG(st.st_mode)) { From 588a29ff2e4e9291143d837daa6b9b5f0a9fa91c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 9 Oct 2019 14:20:22 +0400 Subject: [PATCH 0849/1198] util: use gnu_printf format attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dtc uses non-portable formats. Using gnu_printf attributes (for warnings) in combination with __USE_MINGW_ANSI_STDIO allows to build for win32. Signed-off-by: Marc-André Lureau Message-Id: <20191009102025.10179-8-marcandre.lureau@redhat.com> Signed-off-by: David Gibson --- util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.h b/util.h index ca5cb52..347b305 100644 --- a/util.h +++ b/util.h @@ -12,7 +12,7 @@ */ #ifdef __GNUC__ -#define PRINTF(i, j) __attribute__((format (printf, i, j))) +#define PRINTF(i, j) __attribute__((format (gnu_printf, i, j))) #define NORETURN __attribute__((noreturn)) #else #define PRINTF(i, j) From 430419c28100960c554cf753a5309231c03ec780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 9 Oct 2019 14:20:23 +0400 Subject: [PATCH 0850/1198] tests: fix some python warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: ResourceWarning: unclosed file <_io.BufferedReader name='test_tree1.dtb'> Signed-off-by: Marc-André Lureau Message-Id: <20191009102025.10179-9-marcandre.lureau@redhat.com> Signed-off-by: David Gibson --- tests/pylibfdt_tests.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 42f31ba..509cf14 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -64,7 +64,8 @@ def _ReadFdt(fname): Returns: Fdt bytearray suitable for passing to libfdt functions """ - return libfdt.Fdt(open(fname, mode='rb').read()) + with open(fname, mode='rb') as f: + return libfdt.Fdt(f.read()) class PyLibfdtBasicTests(unittest.TestCase): """Test class for basic pylibfdt access functions @@ -573,7 +574,8 @@ class PyLibfdtRoTests(unittest.TestCase): def setUp(self): """Read in the device tree we use for testing""" - self.fdt = libfdt.FdtRo(open('test_tree1.dtb', mode='rb').read()) + with open('test_tree1.dtb', mode='rb') as f: + self.fdt = libfdt.FdtRo(f.read()) def testAccess(self): """Basic sanity check for the FdtRo class""" From fdf3f6d897ab8759fb7d7277ba5224beb4727d1d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 24 Oct 2019 19:02:26 -0600 Subject: [PATCH 0851/1198] pylibfdt: Correct the type for fdt_property_stub() This function should use a void * type, not char *. This causes an error: TypeError: in method 'fdt_property_stub', argument 3 of type 'char const *' Fix it and update the tests. Signed-off-by: Simon Glass Message-Id: <20191025010226.34378-1-sjg@chromium.org> Signed-off-by: David Gibson --- pylibfdt/libfdt.i | 6 +++--- tests/pylibfdt_tests.py | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index feb8c9c..3e09d3a 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -18,7 +18,7 @@ * a struct called fdt_property. That struct causes swig to create a class in * libfdt.py called fdt_property(), which confuses things. */ -static int fdt_property_stub(void *fdt, const char *name, const char *val, +static int fdt_property_stub(void *fdt, const char *name, const void *val, int len) { return fdt_property(fdt, name, val, len); @@ -930,7 +930,7 @@ class FdtSw(FdtRo): Args: name: Name of property to add - val: Value of property + val: Value of property (bytes) quiet: Errors to ignore (empty to raise on all errors) Raises: @@ -1113,6 +1113,6 @@ int fdt_property_cell(void *fdt, const char *name, uint32_t val); * This function has a stub since the name fdt_property is used for both a * function and a struct, which confuses SWIG. */ -int fdt_property_stub(void *fdt, const char *name, const char *val, int len); +int fdt_property_stub(void *fdt, const char *name, const void *val, int len); %include diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 509cf14..021a5a8 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -522,8 +522,9 @@ class PyLibfdtSwTests(unittest.TestCase): sw.property_string('compatible', 'subnode1') sw.property_u32('reg', 1) sw.property_cell('prop-int', TEST_VALUE_1) + sw.property('data', b'\x00data\x01') sw.begin_node('subsubnode') - sw.property('compatible', 'subsubnode1\0subsubnode') + sw.property('compatible', b'subsubnode1\0subsubnode') sw.property_cell('prop-int', TEST_VALUE_1) sw.end_node() sw.begin_node('ss1') @@ -540,7 +541,7 @@ class PyLibfdtSwTests(unittest.TestCase): with sw.add_node('subsubnode@0'): sw.property_u32('reg', 0) sw.property_cell('phandle', PHANDLE_2) - sw.property('compatible', 'subsubnode2\0subsubnode') + sw.property('compatible', b'subsubnode2\0subsubnode') sw.property_cell('prop-int', TEST_VALUE_2) with sw.add_node('ss2'): pass From 7150286225476345bd6e7312331e3baf4d621c32 Mon Sep 17 00:00:00 2001 From: Ethan Sommer Date: Tue, 29 Oct 2019 12:26:19 -0400 Subject: [PATCH 0852/1198] support byacc in addition to bison Use -b to explicitly set file prefix, so that byacc generates files with the same names as bison. Add %locations to dtc-parser.y to explicitly enable location tracking for byacc, and define YYERROR_CALL to prevent byacc from defining it to call yyerror with 2 parameters because of the locations directive, because dtc-parser.y defines yyerror to accept one parameter. Signed-off-by: Ethan Sommer Message-Id: <20191029162619.32561-1-e5ten.arch@gmail.com> Signed-off-by: David Gibson --- Makefile | 2 +- dtc-parser.y | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e955242..4d88157 100644 --- a/Makefile +++ b/Makefile @@ -368,6 +368,6 @@ clean: libfdt_clean pylibfdt_clean tests_clean %.tab.c %.tab.h %.output: %.y @$(VECHO) BISON $@ - $(BISON) -d $< + $(BISON) -b $(basename $(basename $@)) -d $< FORCE: diff --git a/dtc-parser.y b/dtc-parser.y index 2ed4dc1..40dcf4f 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -2,6 +2,8 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. */ +%locations + %{ #include #include @@ -17,6 +19,8 @@ extern void yyerror(char const *s); treesource_error = true; \ } while (0) +#define YYERROR_CALL(msg) yyerror(msg) + extern struct dt_info *parser_output; extern bool treesource_error; %} From 6ce585ac153b1bcf4d9110d1cf589bdbeab301cf Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 7 Nov 2019 17:46:43 +0100 Subject: [PATCH 0853/1198] Use correct inttypes.h format specifier The type here is uint32_t which should use PRIx32, not plain %x which is for an int, we've just gotten away with it so far. Signed-off-by: David Gibson --- util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util.c b/util.c index 48af961..40274fb 100644 --- a/util.c +++ b/util.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -393,7 +394,7 @@ void utilfdt_print_data(const char *data, int len) printf(" = <"); for (i = 0, len /= 4; i < len; i++) - printf("0x%08x%s", fdt32_to_cpu(cell[i]), + printf("0x%08" PRIx32 "%s", fdt32_to_cpu(cell[i]), i < (len - 1) ? " " : ""); printf(">"); } else { From af57d440d887c03d305cc6b18d53daf06766cd5b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 8 Nov 2019 14:42:53 +0000 Subject: [PATCH 0854/1198] libfdt: Correct prototype for fdt_ro_probe_() This function returns an int32_t, however the prototype in libfdt_internal.h shows it returning an int. We haven't caught this before because they're the same type on nearly all platforms this gets built on. Apparently it's not the case on FreeRTOS, so someone hit this mismatch building for that platform. Reported-by: dharani kumar Signed-off-by: David Gibson --- libfdt/libfdt_internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 741eeb3..058c735 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -10,10 +10,10 @@ #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) -int fdt_ro_probe_(const void *fdt); +int32_t fdt_ro_probe_(const void *fdt); #define FDT_RO_PROBE(fdt) \ { \ - int totalsize_; \ + int32_t totalsize_; \ if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \ return totalsize_; \ } From dbe80d577ee2670a132ab5b7458bf4d3ca94c4f4 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Thu, 14 Nov 2019 20:36:15 +0000 Subject: [PATCH 0855/1198] tests: add extension to sed -i for GNU/BSD sed compatibility BSD sed requires that an extension is provided to the -i (in-place edit) flag, which may immediately follow the -i or may be separated by a space - sed -i .bak and sed -i.bak are equivalent. The extension is optional with GNU sed, but if provided must immediately follow the -i. Thus, sed -i.bak behaves identically with both GNU and BSD sed. Signed-off-by: Ed Maste Message-Id: <20191114203615.2866-1-emaste@freefall.freebsd.org> 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 081f1ee..a0a5245 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -730,7 +730,7 @@ dtc_tests () { # Dependencies run_dtc_test -I dts -O dtb -o dependencies.test.dtb -d dependencies.test.d "$SRCDIR/dependencies.dts" - sed -i "s,$SRCDIR/,,g" dependencies.test.d + sed -i.bak "s,$SRCDIR/,,g" dependencies.test.d run_wrap_test cmp dependencies.test.d "$SRCDIR/dependencies.cmp" # Search paths From 7a22132c79ecbefc6dccfc14ee5d4aae5ef2f452 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 12 Nov 2019 18:24:10 -0700 Subject: [PATCH 0856/1198] pylibfdt: Adjust for deprecated test methods Python recently deprecated some test methods in favour of others. Adjust the code to avoid warnings. Signed-off-by: Simon Glass Message-Id: <20191113012410.62550-1-sjg@chromium.org> Signed-off-by: David Gibson --- tests/pylibfdt_tests.py | 198 ++++++++++++++++++++-------------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 021a5a8..64b5bd1 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -118,34 +118,34 @@ class PyLibfdtBasicTests(unittest.TestCase): def testImport(self): """Check that we can import the library correctly""" - self.assertEquals(type(libfdt), types.ModuleType) + self.assertEqual(type(libfdt), types.ModuleType) def testBadFdt(self): """Check that a filename provided accidentally is not accepted""" with self.assertRaises(FdtException) as e: fdt = libfdt.Fdt(b'a string') - self.assertEquals(e.exception.err, -libfdt.BADMAGIC) + self.assertEqual(e.exception.err, -libfdt.BADMAGIC) def testSubnodeOffset(self): """check that we can locate a subnode by name""" node1 = self.fdt.path_offset('/subnode@1') - self.assertEquals(self.fdt.subnode_offset(0, 'subnode@1'), node1) + self.assertEqual(self.fdt.subnode_offset(0, 'subnode@1'), node1) with self.assertRaises(FdtException) as e: self.fdt.subnode_offset(0, 'missing') - self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + self.assertEqual(e.exception.err, -libfdt.NOTFOUND) node2 = self.fdt.path_offset('/subnode@1/subsubnode') - self.assertEquals(self.fdt.subnode_offset(node1, 'subsubnode'), node2) + self.assertEqual(self.fdt.subnode_offset(node1, 'subsubnode'), node2) def testPathOffset(self): """Check that we can find the offset of a node""" - self.assertEquals(self.fdt.path_offset('/'), 0) + self.assertEqual(self.fdt.path_offset('/'), 0) self.assertTrue(self.fdt.path_offset('/subnode@1') > 0) with self.assertRaises(FdtException) as e: self.fdt.path_offset('/wibble') - self.assertEquals(e.exception.err, -libfdt.NOTFOUND) - self.assertEquals(self.fdt.path_offset('/wibble', QUIET_NOTFOUND), + self.assertEqual(e.exception.err, -libfdt.NOTFOUND) + self.assertEqual(self.fdt.path_offset('/wibble', QUIET_NOTFOUND), -libfdt.NOTFOUND) def testPropertyOffset(self): @@ -156,54 +156,54 @@ class PyLibfdtBasicTests(unittest.TestCase): next_offset = self.fdt.next_property_offset(offset) self.assertTrue(next_offset > offset) offset = next_offset - self.assertEquals(self.fdt.next_property_offset(offset, QUIET_NOTFOUND), + self.assertEqual(self.fdt.next_property_offset(offset, QUIET_NOTFOUND), -libfdt.NOTFOUND) def testPropertyOffsetExceptions(self): """Check that exceptions are raised as expected""" with self.assertRaises(FdtException) as e: self.fdt.first_property_offset(107) - self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + self.assertEqual(e.exception.err, -libfdt.BADOFFSET) # Quieten the NOTFOUND exception and check that a BADOFFSET # exception is still raised. with self.assertRaises(FdtException) as e: self.fdt.first_property_offset(107, QUIET_NOTFOUND) - self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + self.assertEqual(e.exception.err, -libfdt.BADOFFSET) with self.assertRaises(FdtException) as e: self.fdt.next_property_offset(107, QUIET_NOTFOUND) - self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + self.assertEqual(e.exception.err, -libfdt.BADOFFSET) # Check that NOTFOUND can be quietened. node = self.fdt.path_offset('/subnode@1/ss1') - self.assertEquals(self.fdt.first_property_offset(node, QUIET_NOTFOUND), + self.assertEqual(self.fdt.first_property_offset(node, QUIET_NOTFOUND), -libfdt.NOTFOUND) with self.assertRaises(FdtException) as e: self.fdt.first_property_offset(node) - self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + self.assertEqual(e.exception.err, -libfdt.NOTFOUND) def testGetName(self): """Check that we can get the name of a node""" - self.assertEquals(self.fdt.get_name(0), '') + self.assertEqual(self.fdt.get_name(0), '') node = self.fdt.path_offset('/subnode@1/subsubnode') - self.assertEquals(self.fdt.get_name(node), 'subsubnode') + self.assertEqual(self.fdt.get_name(node), 'subsubnode') with self.assertRaises(FdtException) as e: self.fdt.get_name(-2) - self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + self.assertEqual(e.exception.err, -libfdt.BADOFFSET) def testGetPropertyByOffset(self): """Check that we can read the name and contents of a property""" root = 0 poffset = self.fdt.first_property_offset(root) prop = self.fdt.get_property_by_offset(poffset) - self.assertEquals(prop.name, 'compatible') - self.assertEquals(prop, b'test_tree1\0') + self.assertEqual(prop.name, 'compatible') + self.assertEqual(prop, b'test_tree1\0') with self.assertRaises(FdtException) as e: self.fdt.get_property_by_offset(-2) - self.assertEquals(e.exception.err, -libfdt.BADOFFSET) - self.assertEquals( + self.assertEqual(e.exception.err, -libfdt.BADOFFSET) + self.assertEqual( -libfdt.BADOFFSET, self.fdt.get_property_by_offset(-2, [libfdt.BADOFFSET])) @@ -211,21 +211,21 @@ class PyLibfdtBasicTests(unittest.TestCase): """Check that we can read the contents of a property by name""" root = self.fdt.path_offset('/') value = self.fdt.getprop(root, "compatible") - self.assertEquals(value, b'test_tree1\0') - self.assertEquals(-libfdt.NOTFOUND, self.fdt.getprop(root, 'missing', + self.assertEqual(value, b'test_tree1\0') + self.assertEqual(-libfdt.NOTFOUND, self.fdt.getprop(root, 'missing', QUIET_NOTFOUND)) with self.assertRaises(FdtException) as e: self.fdt.getprop(root, 'missing') - self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + self.assertEqual(e.exception.err, -libfdt.NOTFOUND) node = self.fdt.path_offset('/subnode@1/subsubnode') value = self.fdt.getprop(node, "compatible") - self.assertEquals(value, b'subsubnode1\0subsubnode\0') + self.assertEqual(value, b'subsubnode1\0subsubnode\0') def testStrError(self): """Check that we can get an error string""" - self.assertEquals(libfdt.strerror(-libfdt.NOTFOUND), + self.assertEqual(libfdt.strerror(-libfdt.NOTFOUND), 'FDT_ERR_NOTFOUND') def testNextNodeOffset(self): @@ -236,7 +236,7 @@ class PyLibfdtBasicTests(unittest.TestCase): while depth >= 0: node_list.append([depth, self.fdt.get_name(node)]) node, depth = self.fdt.next_node(node, depth, (libfdt.BADOFFSET,)) - self.assertEquals(node_list, [ + self.assertEqual(node_list, [ [0, ''], [1, 'subnode@1'], [2, 'subsubnode'], @@ -253,155 +253,155 @@ class PyLibfdtBasicTests(unittest.TestCase): while node >= 0: node_list.append(self.fdt.get_name(node)) node = self.fdt.next_subnode(node, QUIET_NOTFOUND) - self.assertEquals(node_list, ['subnode@1', 'subnode@2']) + self.assertEqual(node_list, ['subnode@1', 'subnode@2']) def testFirstNextSubnodeOffsetExceptions(self): """Check except handling for first/next subnode functions""" node = self.fdt.path_offset('/subnode@1/subsubnode', QUIET_NOTFOUND) - self.assertEquals(self.fdt.first_subnode(node, QUIET_NOTFOUND), + self.assertEqual(self.fdt.first_subnode(node, QUIET_NOTFOUND), -libfdt.NOTFOUND) with self.assertRaises(FdtException) as e: self.fdt.first_subnode(node) - self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + self.assertEqual(e.exception.err, -libfdt.NOTFOUND) node = self.fdt.path_offset('/subnode@1/ss1', QUIET_NOTFOUND) - self.assertEquals(self.fdt.next_subnode(node, QUIET_NOTFOUND), + self.assertEqual(self.fdt.next_subnode(node, QUIET_NOTFOUND), -libfdt.NOTFOUND) with self.assertRaises(FdtException) as e: self.fdt.next_subnode(node) - self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + self.assertEqual(e.exception.err, -libfdt.NOTFOUND) def testDeleteProperty(self): """Test that we can delete a property""" node_name = '/subnode@1' - self.assertEquals(self.GetPropList(node_name), + self.assertEqual(self.GetPropList(node_name), ['compatible', 'reg', 'prop-int']) node = self.fdt.path_offset('/%s' % node_name) - self.assertEquals(self.fdt.delprop(node, 'reg'), 0) - self.assertEquals(self.GetPropList(node_name), + self.assertEqual(self.fdt.delprop(node, 'reg'), 0) + self.assertEqual(self.GetPropList(node_name), ['compatible', 'prop-int']) def testHeader(self): """Test that we can access the header values""" - self.assertEquals(self.fdt.magic(), 0xd00dfeed) - self.assertEquals(self.fdt.totalsize(), len(self.fdt._fdt)) - self.assertEquals(self.fdt.off_dt_struct(), 88) - self.assertEquals(self.fdt.off_dt_strings(), 652) - self.assertEquals(self.fdt.off_mem_rsvmap(), 40) - self.assertEquals(self.fdt.version(), 17) - self.assertEquals(self.fdt.last_comp_version(), 16) - self.assertEquals(self.fdt.boot_cpuid_phys(), 0) - self.assertEquals(self.fdt.size_dt_strings(), 105) - self.assertEquals(self.fdt.size_dt_struct(), 564) + self.assertEqual(self.fdt.magic(), 0xd00dfeed) + self.assertEqual(self.fdt.totalsize(), len(self.fdt._fdt)) + self.assertEqual(self.fdt.off_dt_struct(), 88) + self.assertEqual(self.fdt.off_dt_strings(), 652) + self.assertEqual(self.fdt.off_mem_rsvmap(), 40) + self.assertEqual(self.fdt.version(), 17) + self.assertEqual(self.fdt.last_comp_version(), 16) + self.assertEqual(self.fdt.boot_cpuid_phys(), 0) + self.assertEqual(self.fdt.size_dt_strings(), 105) + self.assertEqual(self.fdt.size_dt_struct(), 564) def testPack(self): """Test that we can pack the tree after deleting something""" orig_size = self.fdt.totalsize() node = self.fdt.path_offset('/subnode@2', QUIET_NOTFOUND) - self.assertEquals(self.fdt.delprop(node, 'prop-int'), 0) - self.assertEquals(orig_size, self.fdt.totalsize()) - self.assertEquals(self.fdt.pack(), 0) + self.assertEqual(self.fdt.delprop(node, 'prop-int'), 0) + self.assertEqual(orig_size, self.fdt.totalsize()) + self.assertEqual(self.fdt.pack(), 0) self.assertTrue(self.fdt.totalsize() < orig_size) - self.assertEquals(self.fdt.totalsize(), len(self.fdt.as_bytearray())) + self.assertEqual(self.fdt.totalsize(), len(self.fdt.as_bytearray())) def testBadPropertyOffset(self): """Test that bad property offsets are detected""" with self.assertRaises(FdtException) as e: self.fdt.get_property_by_offset(13) - self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + self.assertEqual(e.exception.err, -libfdt.BADOFFSET) with self.assertRaises(FdtException) as e: self.fdt.first_property_offset(3) - self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + self.assertEqual(e.exception.err, -libfdt.BADOFFSET) with self.assertRaises(FdtException) as e: self.fdt.next_property_offset(3) - self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + self.assertEqual(e.exception.err, -libfdt.BADOFFSET) def testBadPathOffset(self): """Test that bad path names are detected""" - with self.assertRaisesRegexp(FdtException, get_err(libfdt.BADPATH)): + with self.assertRaisesRegex(FdtException, get_err(libfdt.BADPATH)): self.fdt.path_offset('not-present') def testQuietAll(self): """Check that exceptions can be masked by QUIET_ALL""" - self.assertEquals(-libfdt.NOTFOUND, + self.assertEqual(-libfdt.NOTFOUND, self.fdt.path_offset('/missing', QUIET_ALL)) - self.assertEquals(-libfdt.BADOFFSET, + self.assertEqual(-libfdt.BADOFFSET, self.fdt.get_property_by_offset(13, QUIET_ALL)) - self.assertEquals(-libfdt.BADPATH, + self.assertEqual(-libfdt.BADPATH, self.fdt.path_offset('missing', QUIET_ALL)) def testIntegers(self): """Check that integers can be passed and returned""" - self.assertEquals(0, libfdt.fdt_get_phandle(self.fdt._fdt, 0)) + self.assertEqual(0, libfdt.fdt_get_phandle(self.fdt._fdt, 0)) node2 = self.fdt.path_offset('/subnode@2') - self.assertEquals(0x2000, libfdt.fdt_get_phandle(self.fdt._fdt, node2)) + self.assertEqual(0x2000, libfdt.fdt_get_phandle(self.fdt._fdt, node2)) def testGetPhandle(self): """Test for the get_phandle() method""" - self.assertEquals(0, self.fdt.get_phandle(0)) + self.assertEqual(0, self.fdt.get_phandle(0)) node2 = self.fdt.path_offset('/subnode@2') - self.assertEquals(0x2000, self.fdt.get_phandle(node2)) + self.assertEqual(0x2000, self.fdt.get_phandle(node2)) def testGetAlias(self): """Test for the get_alias() method""" - self.assertEquals("/subnode@1", self.fdt3.get_alias('s1')) - self.assertEquals("/subnode@1/subsubnode", self.fdt3.get_alias('ss1')) - self.assertEquals("/subnode@1/subsubnode/subsubsubnode", self.fdt3.get_alias('sss1')) + self.assertEqual("/subnode@1", self.fdt3.get_alias('s1')) + self.assertEqual("/subnode@1/subsubnode", self.fdt3.get_alias('ss1')) + self.assertEqual("/subnode@1/subsubnode/subsubsubnode", self.fdt3.get_alias('sss1')) def testParentOffset(self): """Test for the parent_offset() method""" - self.assertEquals(-libfdt.NOTFOUND, + self.assertEqual(-libfdt.NOTFOUND, self.fdt.parent_offset(0, QUIET_NOTFOUND)) with self.assertRaises(FdtException) as e: self.fdt.parent_offset(0) - self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + self.assertEqual(e.exception.err, -libfdt.NOTFOUND) node1 = self.fdt.path_offset('/subnode@2') - self.assertEquals(0, self.fdt.parent_offset(node1)) + self.assertEqual(0, self.fdt.parent_offset(node1)) node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') - self.assertEquals(node1, self.fdt.parent_offset(node2)) + self.assertEqual(node1, self.fdt.parent_offset(node2)) def testNodeOffsetByPhandle(self): """Test for the node_offset_by_phandle() method""" - self.assertEquals(-libfdt.NOTFOUND, + self.assertEqual(-libfdt.NOTFOUND, self.fdt.node_offset_by_phandle(1, QUIET_NOTFOUND)) node1 = self.fdt.path_offset('/subnode@2') - self.assertEquals(node1, self.fdt.node_offset_by_phandle(0x2000)) + self.assertEqual(node1, self.fdt.node_offset_by_phandle(0x2000)) node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') - self.assertEquals(node2, self.fdt.node_offset_by_phandle(0x2001)) + self.assertEqual(node2, self.fdt.node_offset_by_phandle(0x2001)) def get_prop(self, name): return self.fdt2.getprop(0, name) def testGetIntProperties(self): """Test that we can access properties as integers""" - self.assertEquals(0xdeadbeef, self.get_prop("prop-hex32").as_uint32()) - self.assertEquals(123, self.get_prop("prop-uint32").as_uint32()) - self.assertEquals(-2, self.get_prop("prop-int32").as_int32()) - self.assertEquals(9223372036854775807, + self.assertEqual(0xdeadbeef, self.get_prop("prop-hex32").as_uint32()) + self.assertEqual(123, self.get_prop("prop-uint32").as_uint32()) + self.assertEqual(-2, self.get_prop("prop-int32").as_int32()) + self.assertEqual(9223372036854775807, self.get_prop("prop-uint64").as_uint64()) - self.assertEquals(-2, self.get_prop("prop-int64").as_int64()) + self.assertEqual(-2, self.get_prop("prop-int64").as_int64()) def testReserveMap(self): """Test that we can access the memory reserve map""" - self.assertEquals(2, self.fdt.num_mem_rsv()) - self.assertEquals([ 0xdeadbeef00000000, 0x100000], + self.assertEqual(2, self.fdt.num_mem_rsv()) + self.assertEqual([ 0xdeadbeef00000000, 0x100000], self.fdt.get_mem_rsv(0)) - self.assertEquals([123456789, 0o10000], self.fdt.get_mem_rsv(1)) + self.assertEqual([123456789, 0o10000], self.fdt.get_mem_rsv(1)) def testEmpty(self): """Test that we can create an empty tree""" - self.assertEquals(-libfdt.NOSPACE, + self.assertEqual(-libfdt.NOSPACE, Fdt.create_empty_tree(1, (libfdt.NOSPACE,))) fdt = Fdt.create_empty_tree(128) - self.assertEquals(128, fdt.totalsize()) + self.assertEqual(128, fdt.totalsize()) def testOpenInto(self): """Test that we can resize a tree""" fdt = Fdt.create_empty_tree(128) - self.assertEquals(128, fdt.totalsize()) + self.assertEqual(128, fdt.totalsize()) fdt.resize(256) - self.assertEquals(256, fdt.totalsize()) + self.assertEqual(256, fdt.totalsize()) fdt.pack() self.assertTrue(fdt.totalsize() < 128) @@ -409,27 +409,27 @@ class PyLibfdtBasicTests(unittest.TestCase): """Test that we can update and create properties""" node = self.fdt.path_offset('/subnode@1') self.fdt.setprop(node, 'compatible', TEST_BYTES_1) - self.assertEquals(TEST_BYTES_1, self.fdt.getprop(node, 'compatible')) + self.assertEqual(TEST_BYTES_1, self.fdt.getprop(node, 'compatible')) # Check that this property is missing, and that we don't have space to # add it - self.assertEquals(-libfdt.NOTFOUND, + self.assertEqual(-libfdt.NOTFOUND, self.fdt.getprop(node, 'missing', QUIET_NOTFOUND)) - self.assertEquals(-libfdt.NOSPACE, + self.assertEqual(-libfdt.NOSPACE, self.fdt.setprop(node, 'missing', TEST_BYTES_1, quiet=(libfdt.NOSPACE,))) # Expand the device tree so we now have room self.fdt.resize(self.fdt.totalsize() + 50) self.fdt.setprop(node, 'missing', TEST_BYTES_1) - self.assertEquals(TEST_BYTES_1, self.fdt.getprop(node, 'missing')) + self.assertEqual(TEST_BYTES_1, self.fdt.getprop(node, 'missing')) def testSetPropU32(self): """Test that we can update and create integer properties""" node = 0 prop = 'prop-int' self.fdt.setprop_u32(node, prop, TEST_VALUE_1) - self.assertEquals(struct.pack('>I', TEST_VALUE_1), + self.assertEqual(struct.pack('>I', TEST_VALUE_1), self.fdt.getprop(node, prop)) def testSetPropU64(self): @@ -437,16 +437,16 @@ class PyLibfdtBasicTests(unittest.TestCase): node = 0 prop = 'prop-int64' self.fdt.setprop_u64(node, prop, TEST_VALUE64_1) - self.assertEquals(struct.pack('>Q', TEST_VALUE64_1), + self.assertEqual(struct.pack('>Q', TEST_VALUE64_1), self.fdt.getprop(node, prop)) def testSetPropStr(self): """Test that we can set a property to a particular string""" node = 0 prop = 'prop-str' - self.assertEquals(TEST_STRING_1, self.fdt.getprop(node, prop).as_str()) + self.assertEqual(TEST_STRING_1, self.fdt.getprop(node, prop).as_str()) self.fdt.setprop_str(node, prop, TEST_STRING_2) - self.assertEquals(TEST_STRING_2, self.fdt.getprop(node, prop).as_str()) + self.assertEqual(TEST_STRING_2, self.fdt.getprop(node, prop).as_str()) with self.assertRaises(ValueError) as e: self.fdt.getprop(node, 'prop-int').as_str() self.assertIn('lacks nul termination', str(e.exception)) @@ -460,7 +460,7 @@ class PyLibfdtBasicTests(unittest.TestCase): self.fdt.resize(self.fdt.totalsize() + 50) prop = 'prop-unicode' self.fdt.setprop_str(node, prop, TEST_STRING_3) - self.assertEquals(TEST_STRING_3, + self.assertEqual(TEST_STRING_3, self.fdt.getprop(node, prop).as_str()) def testSetName(self): @@ -468,7 +468,7 @@ class PyLibfdtBasicTests(unittest.TestCase): node = self.fdt.path_offset('/subnode@1') old_val = self.fdt.get_name(node) self.fdt.set_name(node, 'test') - self.assertEquals('test', self.fdt.get_name(node)) + self.assertEqual('test', self.fdt.get_name(node)) with self.assertRaises(ValueError) as e: self.fdt.set_name(node, 'some\0name') @@ -481,27 +481,27 @@ class PyLibfdtBasicTests(unittest.TestCase): def testAddDeleteNodes(self): """Test that we can add and delete nodes""" node_name = '/subnode@1' - self.assertEquals(self.GetSubnodes(node_name), ['subsubnode', 'ss1']) + self.assertEqual(self.GetSubnodes(node_name), ['subsubnode', 'ss1']) node = self.fdt.path_offset('%s/subsubnode' % node_name) - self.assertEquals(self.fdt.del_node(node, 'subsubnode'), 0) - self.assertEquals(self.GetSubnodes(node_name), ['ss1']) + self.assertEqual(self.fdt.del_node(node, 'subsubnode'), 0) + self.assertEqual(self.GetSubnodes(node_name), ['ss1']) node = self.fdt.path_offset(node_name) offset = self.fdt.add_subnode(node, 'more') self.assertTrue(offset > 0) - self.assertEquals(self.GetSubnodes(node_name), ['more', 'ss1']) + self.assertEqual(self.GetSubnodes(node_name), ['more', 'ss1']) class PyLibfdtSwTests(unittest.TestCase): """Test class for pylibfdt sequential-write DT creation """ def assertOk(self, err_code): - self.assertEquals(0, err_code) + self.assertEqual(0, err_code) def testCreate(self): # First check the minimum size and also the FdtSw() constructor - with self.assertRaisesRegexp(FdtException, get_err(libfdt.NOSPACE)): - self.assertEquals(-libfdt.NOSPACE, FdtSw(3)) + with self.assertRaisesRegex(FdtException, get_err(libfdt.NOSPACE)): + self.assertEqual(-libfdt.NOSPACE, FdtSw(3)) sw = FdtSw() sw.add_reservemap_entry(TEST_ADDR_1, TEST_SIZE_1) From d9c55f855b65872e9cc74799499416414441c217 Mon Sep 17 00:00:00 2001 From: Stefan Mavrodiev Date: Mon, 11 Nov 2019 10:04:43 +0200 Subject: [PATCH 0857/1198] Remove trailing zero from the overlay path The overlay path ends with trailing zero. When adding this path as property value, this character should be removed. This is the case when the overlay adds a node with an alias. Signed-off-by: Stefan Mavrodiev Message-Id: <20191111080444.9819-2-stefan@olimex.com> Signed-off-by: David Gibson --- libfdt/fdt_overlay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index be71873..b310e49 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -752,7 +752,7 @@ static int overlay_symbol_update(void *fdt, void *fdto) if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) { /* //__overlay__/ */ rel_path = s + len; - rel_path_len = e - rel_path; + rel_path_len = e - rel_path - 1; } else if ((e - s) == len && (memcmp(s, "/__overlay__", len - 1) == 0)) { /* //__overlay__ */ From adcd676491ccbefc17da551cf911b2f4d7d330f6 Mon Sep 17 00:00:00 2001 From: Stefan Mavrodiev Date: Mon, 11 Nov 2019 10:04:44 +0200 Subject: [PATCH 0858/1198] Add test-case for trailing zero If there is trailing zero, fdtget adds extra chacarter to the property value. Thus comparing the expected with the actual value, an error is emitted. Signed-off-by: Stefan Mavrodiev Message-Id: <20191111080444.9819-3-stefan@olimex.com> Signed-off-by: David Gibson --- tests/run_tests.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index a0a5245..06bbccb 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -944,6 +944,10 @@ fdtoverlay_tests() { # test that baz correctly inserted the property run_fdtoverlay_test baz "/foonode/barnode/baznode" "baz-property" "-ts" ${stacked_basedtb} ${stacked_targetdtb} ${stacked_bardtb} ${stacked_bazdtb} + # test that bar and baz are correctly appended to __symbols__ + run_fdtoverlay_test "/foonode/barnode" "/__symbols__" "bar" "-ts" ${stacked_basedtb} ${stacked_targetdtb} ${stacked_bardtb} + run_fdtoverlay_test "/foonode/barnode/baznode" "/__symbols__" "baz" "-ts" ${stacked_basedtb} ${stacked_targetdtb} ${stacked_bardtb} ${stacked_bazdtb} + overlay_long_path="$SRCDIR/overlay_overlay_long_path.dts" overlay_long_pathdtb=overlay_overlay_long_path.fdoverlay.test.dtb target_long_pathdtb=overlay_overlay_long_path_target.fdoverlay.test.dtb From 743000931bc975810e13da2965ac2ef07166b4f3 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Fri, 15 Nov 2019 15:51:08 +0000 Subject: [PATCH 0859/1198] tests: default to 'cc' if CC not set By default FreeBSD does not have 'gcc' in the PATH (on common platforms). As on Linux 'cc' is available as a link to the default compiler (Clang or GCC), so just use 'cc'. Signed-off-by: Ed Maste Message-Id: <20191115155108.39488-1-emaste@freefall.freebsd.org> 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 06bbccb..e37ae59 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -4,7 +4,7 @@ SRCDIR=`dirname "$0"` . "$SRCDIR/testutils.sh" if [ -z "$CC" ]; then - CC=gcc + CC=cc fi # stat differs between platforms From 34c82275bae6a1ff1350af036bfb5127f6bc1407 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Wed, 20 Nov 2019 21:04:22 +0000 Subject: [PATCH 0860/1198] Avoid gnu_printf attribute when using Clang Clang does not support gnu_printf, so just use printf when using it to compile. Signed-off-by: Ed Maste Message-Id: <20191120210422.61327-1-emaste@freefall.freebsd.org> Signed-off-by: David Gibson --- util.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/util.h b/util.h index 347b305..5a4172d 100644 --- a/util.h +++ b/util.h @@ -12,7 +12,11 @@ */ #ifdef __GNUC__ +#ifdef __clang__ +#define PRINTF(i, j) __attribute__((format (printf, i, j))) +#else #define PRINTF(i, j) __attribute__((format (gnu_printf, i, j))) +#endif #define NORETURN __attribute__((noreturn)) #else #define PRINTF(i, j) From 9f86aff444f4df9d5b12a8013ffb136562009631 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Wed, 20 Nov 2019 21:11:33 +0000 Subject: [PATCH 0861/1198] Add .cirrus.yml for FreeBSD build Right now this is just a build test for FreeBSD, along with a Linux build and "make check." A later change will add "gmake check" for FreeBSD. Signed-off-by: Ed Maste Message-Id: <20191120211133.69281-1-emaste@freefall.freebsd.org> Signed-off-by: David Gibson --- .cirrus.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .cirrus.yml diff --git a/.cirrus.yml b/.cirrus.yml new file mode 100644 index 0000000..de4a318 --- /dev/null +++ b/.cirrus.yml @@ -0,0 +1,21 @@ +env: + CIRRUS_CLONE_DEPTH: 1 + +freebsd_12_task: + freebsd_instance: + image: freebsd-12-1-release-amd64 + install_script: + pkg install -y bison gmake pkgconf + build_script: + gmake + +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 From c40aeb60b47a56e3d4d3aebb6fffff2117f8c9eb Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 3 Dec 2019 13:20:20 +0100 Subject: [PATCH 0862/1198] travis.yml: Run tests on the non-x86 builders, too Travis recently added the possibility to compile on aarch64, ppc64le and s390x hosts, so let's add this possibility to the dtc CI, too. Unfortunately, there are some weird valgrind errors when running on ppc64le (which rather look like a problem on the valgrind side to me, and not in dtc), so we can not use "checkm" on ppc64le yet. Signed-off-by: Thomas Huth Message-Id: <20191203122020.14442-1-thuth@redhat.com> Signed-off-by: David Gibson --- .travis.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.travis.yml b/.travis.yml index 114932a..a5163de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,3 +31,35 @@ matrix: - 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 0eb1cb0b531eeaf79b572baec978d40eefe06ca8 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Tue, 10 Dec 2019 16:30:33 +0000 Subject: [PATCH 0863/1198] Makefile: pass $(CFLAGS) also during dependency generation When Valgrind is not available NO_VALGRIND is set in CFLAGS, and this is needed during dependency generation as well as compilation. Message-Id: <20191210163033.9888-1-emaste@freefall.freebsd.org> Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4d88157..da6cf92 100644 --- a/Makefile +++ b/Makefile @@ -344,7 +344,7 @@ clean: libfdt_clean pylibfdt_clean tests_clean %.d: %.c @$(VECHO) DEP $< - $(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -MM -MG -MT "$*.o $@" $< > $@ %.d: %.S @$(VECHO) DEP $< From cab09eedd644cebdb4390b8b269012350d291cba Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 19 Dec 2019 13:14:45 +1100 Subject: [PATCH 0864/1198] Move -DNO_VALGRIND into CPPFLAGS Since -D sets preprocessor directives, it applies for the preprocessor not just the C compiler proper and so belongs in CPPFLAGS rather than CFLAGS. Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index da6cf92..e73576a 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?) ifeq ($(NO_VALGRIND),1) - CFLAGS += -DNO_VALGRIND + CPPFLAGS += -DNO_VALGRIND else CFLAGS += $(shell $(PKG_CONFIG) --cflags valgrind) endif From 0e9225eb0dfec51def612b928d2f1836b092bc7e Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Tue, 14 Jan 2020 18:53:41 +0100 Subject: [PATCH 0865/1198] Remove redundant YYLOC global declaration gcc 10 will default to -fno-common, which causes this error at link time: (.text+0x0): multiple definition of `yylloc'; dtc-lexer.lex.o (symbol from plugin):(.text+0x0): first defined here This is because both dtc-lexer as well as dtc-parser define the same global symbol yyloc. Before with -fcommon those were merged into one defintion. The proper solution would be to to mark this as "extern", however that leads to: dtc-lexer.l:26:16: error: redundant redeclaration of 'yylloc' [-Werror=redundant-decls] 26 | extern YYLTYPE yylloc; | ^~~~~~ In file included from dtc-lexer.l:24: dtc-parser.tab.h:127:16: note: previous declaration of 'yylloc' was here 127 | extern YYLTYPE yylloc; | ^~~~~~ cc1: all warnings being treated as errors which means the declaration is completely redundant and can just be dropped. Signed-off-by: Dirk Mueller Message-Id: <20200114175341.2994-1-dmueller@suse.com> Signed-off-by: David Gibson --- dtc-lexer.l | 1 - 1 file changed, 1 deletion(-) diff --git a/dtc-lexer.l b/dtc-lexer.l index 5c6c3fd..b3b7270 100644 --- a/dtc-lexer.l +++ b/dtc-lexer.l @@ -23,7 +23,6 @@ LINECOMMENT "//".*\n #include "srcpos.h" #include "dtc-parser.tab.h" -YYLTYPE yylloc; extern bool treesource_error; /* CAUTION: this will stop working if we ever use yyless() or yyunput() */ From cc6a5a07150427b7b527fc753cd09f8bf518cd9c Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 24 Jan 2020 08:46:57 -0600 Subject: [PATCH 0866/1198] Revert "yamltree: Ensure consistent bracketing of properties with phandles" This reverts commit 18d7b2f4ee45fec422b7d82bab0b3c762ee907e4. This doesn't work for properties such as 'interrupt-map' that has phandle in the middle of an entry. It would also not work for a 0 or -1 phandle value that acts as a NULL. Signed-off-by: Rob Herring Message-Id: <20200124144657.29749-1-robh@kernel.org> Signed-off-by: David Gibson --- yamltree.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/yamltree.c b/yamltree.c index 43ca869..5b6ea8e 100644 --- a/yamltree.c +++ b/yamltree.c @@ -138,27 +138,6 @@ static void yaml_propval(yaml_emitter_t *emitter, struct property *prop) (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE); yaml_emitter_emit_or_die(emitter, &event); - /* Ensure we have a type marker before any phandle */ - for_each_marker(m) { - int last_offset = 0; - struct marker *type_m; - - if (m->type >= TYPE_UINT8) - last_offset = m->offset; - - if (!(m->next && m->next->type == REF_PHANDLE && - last_offset < m->next->offset)) - continue; - - type_m = xmalloc(sizeof(*type_m)); - type_m->offset = m->next->offset; - type_m->type = TYPE_UINT32; - type_m->ref = NULL; - type_m->next = m->next; - m->next = type_m; - } - - m = prop->val.markers; for_each_marker(m) { int chunk_len; char *data = &prop->val.val[m->offset]; From 0c5326cb2845922ad809190dae783940e1df2f0c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 20 Feb 2020 14:45:50 -0700 Subject: [PATCH 0867/1198] libfdt: De-inline fdt_header_size() There does not seem to be a strong reason to inline this function. Also we are about to add some extra code to it which will increase its size. Move it into fdt.c and use a simple declaration in libfdt.h Signed-off-by: Simon Glass Message-Id: <20200220214557.176528-2-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/fdt.c | 5 +++++ libfdt/libfdt.h | 9 +++++---- libfdt/version.lds | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index d6ce7c0..3e37a4b 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -70,6 +70,11 @@ size_t fdt_header_size_(uint32_t version) return FDT_V17_SIZE; } +size_t fdt_header_size(const void *fdt) +{ + return fdt_header_size_(fdt_version(fdt)); +} + int fdt_check_header(const void *fdt) { size_t hdrsize; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index fc4c496..48f375c 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -266,11 +266,12 @@ fdt_set_hdr_(size_dt_struct); * fdt_header_size - return the size of the tree's header * @fdt: pointer to a flattened device tree */ +size_t fdt_header_size(const void *fdt); + +/** + * fdt_header_size_ - internal function which takes a version number + */ size_t fdt_header_size_(uint32_t version); -static inline size_t fdt_header_size(const void *fdt) -{ - return fdt_header_size_(fdt_version(fdt)); -} /** * fdt_check_header - sanity check a device tree header diff --git a/libfdt/version.lds b/libfdt/version.lds index ae32924..7ab85f1 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -20,6 +20,7 @@ LIBFDT_1.2 { fdt_get_alias_namelen; fdt_get_alias; fdt_get_path; + fdt_header_size; fdt_supernode_atdepth_offset; fdt_node_depth; fdt_parent_offset; From 464962489dcc563e354ff64c9e58856185f32728 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 20 Feb 2020 14:45:51 -0700 Subject: [PATCH 0868/1198] Add a way to control the level of checks in the code Add a new ASSUME_MASK option, which allows for some control over the checks used in libfdt. With all assumptions enabled, libfdt assumes that the input data and parameters are all correct and that internal errors cannot happen. By default no assumptions are made and all checks are enabled. Signed-off-by: Simon Glass Message-Id: <20200220214557.176528-3-sjg@chromium.org> Signed-off-by: David Gibson --- Makefile | 6 ++- libfdt/libfdt_internal.h | 104 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e73576a..0dff03f 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,11 @@ EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = -CPPFLAGS = -I libfdt -I . +# Control the assumptions made (e.g. risking security issues) in the code. +# See libfdt_internal.h for details +ASSUME_MASK ?= 0 + +CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK) WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \ -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS) diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 058c735..e9913cd 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -48,4 +48,108 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) #define FDT_SW_MAGIC (~FDT_MAGIC) +/**********************************************************************/ +/* Checking controls */ +/**********************************************************************/ + +#ifndef FDT_ASSUME_MASK +#define FDT_ASSUME_MASK 0 +#endif + +/* + * Defines assumptions which can be enabled. Each of these can be enabled + * individually. For maximum saftey, don't enable any assumptions! + * + * For minimal code size and no safety, use ASSUME_PERFECT at your own risk. + * You should have another method of validating the device tree, such as a + * signature or hash check before using libfdt. + * + * For situations where security is not a concern it may be safe to enable + * ASSUME_SANE. + */ +enum { + /* + * This does essentially no checks. Only the latest device-tree + * version is correctly handled. Inconsistencies or errors in the device + * tree may cause undefined behaviour or crashes. Invalid parameters + * passed to libfdt may do the same. + * + * If an error occurs when modifying the tree it may leave the tree in + * an intermediate (but valid) state. As an example, adding a property + * where there is insufficient space may result in the property name + * being added to the string table even though the property itself is + * not added to the struct section. + * + * Only use this if you have a fully validated device tree with + * the latest supported version and wish to minimise code size. + */ + ASSUME_PERFECT = 0xff, + + /* + * This assumes that the device tree is sane. i.e. header metadata + * and basic hierarchy are correct. + * + * With this assumption enabled, normal device trees produced by libfdt + * and the compiler should be handled safely. Malicious device trees and + * complete garbage may cause libfdt to behave badly or crash. + * + * Note: Only checks that relate exclusively to the device tree itself + * (not the parameters passed to libfdt) are disabled by this + * assumption. This includes checking headers, tags and the like. + */ + ASSUME_VALID_DTB = 1 << 0, + + /* + * This builds on ASSUME_VALID_DTB and further assumes that libfdt + * functions are called with valid parameters, i.e. not trigger + * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any + * extensive checking of parameters and the device tree, making various + * assumptions about correctness. + * + * It doesn't make sense to enable this assumption unless + * ASSUME_VALID_DTB is also enabled. + */ + ASSUME_VALID_INPUT = 1 << 1, + + /* + * This disables checks for device-tree version and removes all code + * which handles older versions. + * + * Only enable this if you know you have a device tree with the latest + * version. + */ + ASSUME_LATEST = 1 << 2, + + /* + * This assume that it is OK for a failed additional to the device tree + * due to lack of space or some other problem can skip any rollback + * steps (such as dropping the property name from the string table). + * This is safe to enable in most circumstances, even though it may + * leave the tree in a sub-optimal state. + */ + ASSUME_NO_ROLLBACK = 1 << 3, + + /* + * This assumes that the device tree components appear in the correct + * order. As such it disables a check in fdt_open_into() and removes the + * ability to fix the problem there. This is safe if you know that the + * device tree is correctly ordered. See fdt_blocks_misordered_(). + */ + ASSUME_LIBFDT_ORDER = 1 << 4, +}; + +/** + * can_assume_() - check if a particular assumption is enabled + * + * @mask: Mask to check (ASSUME_...) + * @return true if that assumption is enabled, else false + */ +static inline bool can_assume_(int mask) +{ + return FDT_ASSUME_MASK & mask; +} + +/** helper macros for checking assumptions */ +#define can_assume(_assume) can_assume_(ASSUME_ ## _assume) + #endif /* LIBFDT_INTERNAL_H */ From 57bc6327b80bc95bee9fc5f07d4fc83186a8f167 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 20 Feb 2020 14:45:52 -0700 Subject: [PATCH 0869/1198] libfdt: Add support for disabling dtb checks Support ASSUME_VALID_DTB to disable some sanity checks If we assume that the DTB itself is valid then we can skip some checks and save code space. Add various conditions to handle this. Signed-off-by: Simon Glass Message-Id: <20200220214557.176528-4-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/fdt.c | 57 ++++++++++++++++++++++++++++--------------------- libfdt/fdt_ro.c | 3 ++- libfdt/fdt_rw.c | 2 ++ libfdt/fdt_sw.c | 16 ++++++++------ 4 files changed, 47 insertions(+), 31 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 3e37a4b..d4daf60 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -19,6 +19,9 @@ int32_t fdt_ro_probe_(const void *fdt) { uint32_t totalsize = fdt_totalsize(fdt); + if (can_assume(VALID_DTB)) + return totalsize; + if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) @@ -81,37 +84,43 @@ int fdt_check_header(const void *fdt) if (fdt_magic(fdt) != FDT_MAGIC) return -FDT_ERR_BADMAGIC; - hdrsize = fdt_header_size(fdt); if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) || (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)) return -FDT_ERR_BADVERSION; if (fdt_version(fdt) < fdt_last_comp_version(fdt)) return -FDT_ERR_BADVERSION; + hdrsize = fdt_header_size(fdt); + if (!can_assume(VALID_DTB)) { - if ((fdt_totalsize(fdt) < hdrsize) - || (fdt_totalsize(fdt) > INT_MAX)) - return -FDT_ERR_TRUNCATED; - - /* Bounds check memrsv block */ - if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt))) - return -FDT_ERR_TRUNCATED; - - /* Bounds check structure block */ - if (fdt_version(fdt) < 17) { - if (!check_off_(hdrsize, fdt_totalsize(fdt), - fdt_off_dt_struct(fdt))) + if ((fdt_totalsize(fdt) < hdrsize) + || (fdt_totalsize(fdt) > INT_MAX)) return -FDT_ERR_TRUNCATED; - } else { - if (!check_block_(hdrsize, fdt_totalsize(fdt), - fdt_off_dt_struct(fdt), - fdt_size_dt_struct(fdt))) + + /* Bounds check memrsv block */ + if (!check_off_(hdrsize, fdt_totalsize(fdt), + fdt_off_mem_rsvmap(fdt))) return -FDT_ERR_TRUNCATED; } - /* Bounds check strings block */ - if (!check_block_(hdrsize, fdt_totalsize(fdt), - fdt_off_dt_strings(fdt), fdt_size_dt_strings(fdt))) - return -FDT_ERR_TRUNCATED; + if (!can_assume(VALID_DTB)) { + /* Bounds check structure block */ + if (fdt_version(fdt) < 17) { + if (!check_off_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } else { + if (!check_block_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt), + fdt_size_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } + + /* Bounds check strings block */ + if (!check_block_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_strings(fdt), + fdt_size_dt_strings(fdt))) + return -FDT_ERR_TRUNCATED; + } return 0; } @@ -142,7 +151,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) *nextoffset = -FDT_ERR_TRUNCATED; tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); - if (!tagp) + if (!can_assume(VALID_DTB) && !tagp) return FDT_END; /* premature end */ tag = fdt32_to_cpu(*tagp); offset += FDT_TAGSIZE; @@ -154,13 +163,13 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) do { p = fdt_offset_ptr(fdt, offset++, 1); } while (p && (*p != '\0')); - if (!p) + if (!can_assume(VALID_DTB) && !p) return FDT_END; /* premature end */ break; case FDT_PROP: lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); - if (!lenp) + if (!can_assume(VALID_DTB) && !lenp) return FDT_END; /* premature end */ /* skip-name offset, length and value */ offset += sizeof(struct fdt_property) - FDT_TAGSIZE diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index a5c2797..4c26fbe 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -388,7 +388,8 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, (offset = fdt_next_property_offset(fdt, offset))) { const struct fdt_property *prop; - if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) { + prop = fdt_get_property_by_offset_(fdt, offset, lenp); + if (!can_assume(VALID_DTB) && !prop) { offset = -FDT_ERR_INTERNAL; break; } diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 8795947..707c00a 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -24,6 +24,8 @@ static int fdt_blocks_misordered_(const void *fdt, static int fdt_rw_probe_(void *fdt) { + if (can_assume(VALID_DTB)) + return 0; FDT_RO_PROBE(fdt); if (fdt_version(fdt) < 17) diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 76bea22..352193c 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -12,10 +12,13 @@ static int fdt_sw_probe_(void *fdt) { - if (fdt_magic(fdt) == FDT_MAGIC) - return -FDT_ERR_BADSTATE; - else if (fdt_magic(fdt) != FDT_SW_MAGIC) - return -FDT_ERR_BADMAGIC; + if (!can_assume(VALID_DTB)) { + if (fdt_magic(fdt) == FDT_MAGIC) + return -FDT_ERR_BADSTATE; + else if (fdt_magic(fdt) != FDT_SW_MAGIC) + return -FDT_ERR_BADMAGIC; + } + return 0; } @@ -38,7 +41,7 @@ static int fdt_sw_probe_memrsv_(void *fdt) if (err) return err; - if (fdt_off_dt_strings(fdt) != 0) + if (!can_assume(VALID_DTB) && fdt_off_dt_strings(fdt) != 0) return -FDT_ERR_BADSTATE; return 0; } @@ -151,7 +154,8 @@ int fdt_resize(void *fdt, void *buf, int bufsize) headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); tailsize = fdt_size_dt_strings(fdt); - if ((headsize + tailsize) > fdt_totalsize(fdt)) + if (!can_assume(VALID_DTB) && + headsize + tailsize > fdt_totalsize(fdt)) return -FDT_ERR_INTERNAL; if ((headsize + tailsize) > bufsize) From 77563ae72b7c3349008e712669253f6c54b752a7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 20 Feb 2020 14:45:53 -0700 Subject: [PATCH 0870/1198] libfdt: Add support for disabling sanity checks Allow enabling ASSUME_VALID_INPUT to disable sanity checks on the device tree and the parameters to libfdt. This assumption covers that cases where the problem could be with either. Signed-off-by: Simon Glass Message-Id: <20200220214557.176528-5-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/fdt.c | 11 +++++---- libfdt/fdt_ro.c | 61 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index d4daf60..0dabb92 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -129,10 +129,11 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { unsigned absoffset = offset + fdt_off_dt_struct(fdt); - if ((absoffset < offset) - || ((absoffset + len) < absoffset) - || (absoffset + len) > fdt_totalsize(fdt)) - return NULL; + if (!can_assume(VALID_INPUT)) + if ((absoffset < offset) + || ((absoffset + len) < absoffset) + || (absoffset + len) > fdt_totalsize(fdt)) + return NULL; if (fdt_version(fdt) >= 0x11) if (((offset + len) < offset) @@ -197,6 +198,8 @@ 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)) return -FDT_ERR_BADOFFSET; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 4c26fbe..9c32559 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -33,17 +33,26 @@ static int fdt_nodename_eq_(const void *fdt, int offset, const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) { - int32_t totalsize = fdt_ro_probe_(fdt); - uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt); + int32_t totalsize; + uint32_t absoffset; size_t len; int err; const char *s, *n; + if (can_assume(VALID_INPUT)) { + s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; + + if (lenp) + *lenp = strlen(s); + return s; + } + totalsize = fdt_ro_probe_(fdt); err = totalsize; if (totalsize < 0) goto fail; err = -FDT_ERR_BADOFFSET; + absoffset = stroffset + fdt_off_dt_strings(fdt); if (absoffset >= totalsize) goto fail; len = totalsize - absoffset; @@ -151,10 +160,13 @@ 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; - if (absoffset < fdt_off_mem_rsvmap(fdt)) - return NULL; - if (absoffset > fdt_totalsize(fdt) - sizeof(struct fdt_reserve_entry)) - return NULL; + if (!can_assume(VALID_INPUT)) { + if (absoffset < fdt_off_mem_rsvmap(fdt)) + return NULL; + if (absoffset > fdt_totalsize(fdt) - + sizeof(struct fdt_reserve_entry)) + return NULL; + } return fdt_mem_rsv_(fdt, n); } @@ -164,7 +176,7 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) FDT_RO_PROBE(fdt); re = fdt_mem_rsv(fdt, n); - if (!re) + if (!can_assume(VALID_INPUT) && !re) return -FDT_ERR_BADOFFSET; *address = fdt64_ld(&re->address); @@ -346,7 +358,8 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, int err; const struct fdt_property *prop; - if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) { + if (!can_assume(VALID_INPUT) && + (err = fdt_check_prop_offset_(fdt, offset)) < 0) { if (lenp) *lenp = err; return NULL; @@ -462,14 +475,19 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, if (namep) { const char *name; int namelen; - name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), - &namelen); - if (!name) { - if (lenp) - *lenp = namelen; - return NULL; + + if (!can_assume(VALID_INPUT)) { + name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), + &namelen); + if (!name) { + if (lenp) + *lenp = namelen; + return NULL; + } + *namep = name; + } else { + *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff)); } - *namep = name; } /* Handle realignment */ @@ -599,10 +617,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, } } - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) - return -FDT_ERR_BADOFFSET; - else if (offset == -FDT_ERR_BADOFFSET) - return -FDT_ERR_BADSTRUCTURE; + if (!can_assume(VALID_INPUT)) { + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + } return offset; /* error from fdt_next_node() */ } @@ -614,7 +634,8 @@ int fdt_node_depth(const void *fdt, int nodeoffset) err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); if (err) - return (err < 0) ? err : -FDT_ERR_INTERNAL; + return (can_assume(VALID_INPUT) || err < 0) ? err : + -FDT_ERR_INTERNAL; return nodedepth; } From fc03c4a2e04ef76f54582bfcd3ad17d0b0507e9a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 20 Feb 2020 14:45:54 -0700 Subject: [PATCH 0871/1198] libfdt: Add support for disabling rollback handling Allow enabling FDT_ASSUME_NO_ROLLBACK to disable rolling back after a failed operation. Signed-off-by: Simon Glass Reviewed-by: David Gibson Message-Id: <20200220214557.176528-6-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 707c00a..4a95ce2 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -114,6 +114,15 @@ static int fdt_splice_string_(void *fdt, int newlen) return 0; } +/** + * fdt_find_add_string_() - Find or allocate a string + * + * @fdt: pointer to the device tree to check/adjust + * @s: string to find/add + * @allocated: Set to 0 if the string was found, 1 if not found and so + * 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) { char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); @@ -122,7 +131,8 @@ static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) int len = strlen(s) + 1; int err; - *allocated = 0; + if (!can_assume(NO_ROLLBACK)) + *allocated = 0; p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); if (p) @@ -134,7 +144,8 @@ static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) if (err) return err; - *allocated = 1; + if (!can_assume(NO_ROLLBACK)) + *allocated = 1; memcpy(new, s, len); return (new - strtab); @@ -208,7 +219,8 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, err = fdt_splice_struct_(fdt, *prop, 0, proplen); if (err) { - if (allocated) + /* Delete the string if we failed to add it */ + if (!can_assume(NO_ROLLBACK) && allocated) fdt_del_last_string_(fdt, name); return err; } From c18bae9a4c96a9258fdcee30fe4b0c4fc3730036 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 20 Feb 2020 14:45:55 -0700 Subject: [PATCH 0872/1198] libfdt: Add support for disabling version checks Allow enabling FDT_ASSUME_LATEST to disable version checks. Signed-off-by: Simon Glass Reviewed-by: David Gibson Message-Id: <20200220214557.176528-7-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/fdt.c | 34 +++++++++++++++++++++------------- libfdt/fdt_ro.c | 16 ++++++++-------- libfdt/fdt_rw.c | 6 +++--- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 0dabb92..4419204 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -24,10 +24,13 @@ int32_t fdt_ro_probe_(const void *fdt) if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ - if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; - if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; + if (!can_assume(LATEST)) { + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + if (fdt_last_comp_version(fdt) > + FDT_LAST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + } } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { /* Unfinished sequential-write blob */ if (fdt_size_dt_struct(fdt) == 0) @@ -75,7 +78,8 @@ size_t fdt_header_size_(uint32_t version) size_t fdt_header_size(const void *fdt) { - return fdt_header_size_(fdt_version(fdt)); + return can_assume(LATEST) ? FDT_V17_SIZE : + fdt_header_size_(fdt_version(fdt)); } int fdt_check_header(const void *fdt) @@ -84,11 +88,14 @@ int fdt_check_header(const void *fdt) if (fdt_magic(fdt) != FDT_MAGIC) return -FDT_ERR_BADMAGIC; - if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) - || (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)) - return -FDT_ERR_BADVERSION; - if (fdt_version(fdt) < fdt_last_comp_version(fdt)) - return -FDT_ERR_BADVERSION; + if (!can_assume(LATEST)) { + if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + || (fdt_last_comp_version(fdt) > + FDT_LAST_SUPPORTED_VERSION)) + return -FDT_ERR_BADVERSION; + if (fdt_version(fdt) < fdt_last_comp_version(fdt)) + return -FDT_ERR_BADVERSION; + } hdrsize = fdt_header_size(fdt); if (!can_assume(VALID_DTB)) { @@ -104,7 +111,7 @@ int fdt_check_header(const void *fdt) if (!can_assume(VALID_DTB)) { /* Bounds check structure block */ - if (fdt_version(fdt) < 17) { + if (!can_assume(LATEST) && fdt_version(fdt) < 17) { if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_dt_struct(fdt))) return -FDT_ERR_TRUNCATED; @@ -135,7 +142,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) || (absoffset + len) > fdt_totalsize(fdt)) return NULL; - if (fdt_version(fdt) >= 0x11) + if (can_assume(LATEST) || fdt_version(fdt) >= 0x11) if (((offset + len) < offset) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; @@ -175,7 +182,8 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) /* skip-name offset, length and value */ offset += sizeof(struct fdt_property) - FDT_TAGSIZE + fdt32_to_cpu(*lenp); - if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && + if (!can_assume(LATEST) && + fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) offset += 4; break; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 9c32559..2fa768e 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -60,7 +60,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) if (fdt_magic(fdt) == FDT_MAGIC) { if (stroffset < 0) goto fail; - if (fdt_version(fdt) >= 17) { + if (can_assume(LATEST) || fdt_version(fdt) >= 17) { if (stroffset >= fdt_size_dt_strings(fdt)) goto fail; if ((fdt_size_dt_strings(fdt) - stroffset) < len) @@ -307,7 +307,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) nameptr = nh->name; - if (fdt_version(fdt) < 0x10) { + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { /* * For old FDT versions, match the naming conventions of V16: * give only the leaf name (after all /). The actual tree @@ -380,7 +380,7 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, /* Prior to version 16, properties may need realignment * and this API does not work. fdt_getprop_*() will, however. */ - if (fdt_version(fdt) < 0x10) { + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { if (lenp) *lenp = -FDT_ERR_BADVERSION; return NULL; @@ -427,7 +427,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt, { /* Prior to version 16, properties may need realignment * and this API does not work. fdt_getprop_*() will, however. */ - if (fdt_version(fdt) < 0x10) { + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { if (lenp) *lenp = -FDT_ERR_BADVERSION; return NULL; @@ -458,8 +458,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, return NULL; /* Handle realignment */ - if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 && - fdt32_ld(&prop->len) >= 8) + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && + (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) return prop->data + 4; return prop->data; } @@ -491,8 +491,8 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, } /* Handle realignment */ - if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 && - fdt32_ld(&prop->len) >= 8) + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && + (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) return prop->data + 4; return prop->data; } diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 4a95ce2..fe13671 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -28,12 +28,12 @@ static int fdt_rw_probe_(void *fdt) return 0; FDT_RO_PROBE(fdt); - if (fdt_version(fdt) < 17) + if (!can_assume(LATEST) && fdt_version(fdt) < 17) return -FDT_ERR_BADVERSION; if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), fdt_size_dt_struct(fdt))) return -FDT_ERR_BADLAYOUT; - if (fdt_version(fdt) > 17) + if (!can_assume(LATEST) && fdt_version(fdt) > 17) fdt_set_version(fdt, 17); return 0; @@ -425,7 +425,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); - if (fdt_version(fdt) >= 17) { + if (can_assume(LATEST) || fdt_version(fdt) >= 17) { struct_size = fdt_size_dt_struct(fdt); } else { struct_size = 0; From f270f45fd5d2baac37d559f0063110cb646b2332 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 20 Feb 2020 14:45:56 -0700 Subject: [PATCH 0873/1198] libfdt: Add support for disabling ordering check/fixup Add a way to remove this check and the reordering code, which is unnecessary if the dtb is known to be correctly ordered. Signed-off-by: Simon Glass Reviewed-by: David Gibson Message-Id: <20200220214557.176528-8-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/fdt_rw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index fe13671..1385425 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -435,7 +435,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) return struct_size; } - if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { + if (can_assume(LIBFDT_ORDER) | + !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { /* no further work necessary */ err = fdt_move(fdt, buf, bufsize); if (err) From 0f61c72dedc4bf11cd19a78fc36a7bde99d653e0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 20 Feb 2020 14:45:57 -0700 Subject: [PATCH 0874/1198] libfdt: Allow exclusion of fdt_check_full() This function is used to perform a full check of the device tree. Allow it to be excluded if all assumptions are enabled. Signed-off-by: Simon Glass Reviewed-by: David Gibson Message-Id: <20200220214557.176528-9-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/Makefile.libfdt | 2 +- libfdt/fdt_check.c | 74 ++++++++++++++++++++++++++++++++++++++++++ libfdt/fdt_ro.c | 63 ----------------------------------- 3 files changed, 75 insertions(+), 64 deletions(-) create mode 100644 libfdt/fdt_check.c diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index e546397..b6d8fc0 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -8,7 +8,7 @@ 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_addresses.c fdt_overlay.c fdt_check.c LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) diff --git a/libfdt/fdt_check.c b/libfdt/fdt_check.c new file mode 100644 index 0000000..7f6a96c --- /dev/null +++ b/libfdt/fdt_check.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +int fdt_check_full(const void *fdt, size_t bufsize) +{ + int err; + int num_memrsv; + int offset, nextoffset = 0; + uint32_t tag; + unsigned int depth = 0; + const void *prop; + const char *propname; + + if (bufsize < FDT_V1_SIZE) + return -FDT_ERR_TRUNCATED; + err = fdt_check_header(fdt); + if (err != 0) + return err; + if (bufsize < fdt_totalsize(fdt)) + return -FDT_ERR_TRUNCATED; + + num_memrsv = fdt_num_mem_rsv(fdt); + if (num_memrsv < 0) + return num_memrsv; + + while (1) { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + + if (nextoffset < 0) + return nextoffset; + + switch (tag) { + case FDT_NOP: + break; + + case FDT_END: + if (depth != 0) + return -FDT_ERR_BADSTRUCTURE; + return 0; + + case FDT_BEGIN_NODE: + depth++; + if (depth > INT_MAX) + return -FDT_ERR_BADSTRUCTURE; + break; + + case FDT_END_NODE: + if (depth == 0) + return -FDT_ERR_BADSTRUCTURE; + depth--; + break; + + case FDT_PROP: + prop = fdt_getprop_by_offset(fdt, offset, &propname, + &err); + if (!prop) + return err; + break; + + default: + return -FDT_ERR_INTERNAL; + } + } +} diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 2fa768e..1945503 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -855,66 +855,3 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, return offset; /* error from fdt_next_node() */ } - -int fdt_check_full(const void *fdt, size_t bufsize) -{ - int err; - int num_memrsv; - int offset, nextoffset = 0; - uint32_t tag; - unsigned depth = 0; - const void *prop; - const char *propname; - - if (bufsize < FDT_V1_SIZE) - return -FDT_ERR_TRUNCATED; - err = fdt_check_header(fdt); - if (err != 0) - return err; - if (bufsize < fdt_totalsize(fdt)) - return -FDT_ERR_TRUNCATED; - - num_memrsv = fdt_num_mem_rsv(fdt); - if (num_memrsv < 0) - return num_memrsv; - - while (1) { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - - if (nextoffset < 0) - return nextoffset; - - switch (tag) { - case FDT_NOP: - break; - - case FDT_END: - if (depth != 0) - return -FDT_ERR_BADSTRUCTURE; - return 0; - - case FDT_BEGIN_NODE: - depth++; - if (depth > INT_MAX) - return -FDT_ERR_BADSTRUCTURE; - break; - - case FDT_END_NODE: - if (depth == 0) - return -FDT_ERR_BADSTRUCTURE; - depth--; - break; - - case FDT_PROP: - prop = fdt_getprop_by_offset(fdt, offset, &propname, - &err); - if (!prop) - return err; - break; - - default: - return -FDT_ERR_INTERNAL; - } - } -} From fc207c32341bb58ee2a43d105540674d44ba0f7b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 2 Mar 2020 12:02:52 -0700 Subject: [PATCH 0875/1198] libfdt: Fix a few typos Fix 'saftey' and 'additional' typos noticed in the assumption series. Reword the ASSUME_NO_ROLLBACK slightly to improve clarity. Signed-off-by: Simon Glass Suggested-by: David Gibson Message-Id: <20200302190255.51426-1-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/libfdt_internal.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index e9913cd..3201678 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -58,7 +58,7 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) /* * Defines assumptions which can be enabled. Each of these can be enabled - * individually. For maximum saftey, don't enable any assumptions! + * individually. For maximum safety, don't enable any assumptions! * * For minimal code size and no safety, use ASSUME_PERFECT at your own risk. * You should have another method of validating the device tree, such as a @@ -121,8 +121,8 @@ enum { ASSUME_LATEST = 1 << 2, /* - * This assume that it is OK for a failed additional to the device tree - * due to lack of space or some other problem can skip any rollback + * This assumes that it is OK for a failed addition to the device tree, + * due to lack of space or some other problem, to skip any rollback * steps (such as dropping the property name from the string table). * This is safe to enable in most circumstances, even though it may * leave the tree in a sub-optimal state. From 28fd7590aad2ab4c0aae6b6674b15f103c492d64 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 2 Mar 2020 12:02:53 -0700 Subject: [PATCH 0876/1198] libfdt: Improve comments in some of the assumptions Add a little more detail in a few of these comments. Signed-off-by: Simon Glass Suggested-by: David Gibson Message-Id: <20200302190255.51426-2-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/libfdt_internal.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 3201678..7999f6a 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -91,7 +91,9 @@ enum { * * With this assumption enabled, normal device trees produced by libfdt * and the compiler should be handled safely. Malicious device trees and - * complete garbage may cause libfdt to behave badly or crash. + * complete garbage may cause libfdt to behave badly or crash. Truncated + * device trees (e.g. those only partially loaded) can also cause + * problems. * * Note: Only checks that relate exclusively to the device tree itself * (not the parameters passed to libfdt) are disabled by this @@ -130,8 +132,15 @@ enum { ASSUME_NO_ROLLBACK = 1 << 3, /* - * This assumes that the device tree components appear in the correct - * order. As such it disables a check in fdt_open_into() and removes the + * This assumes that the device tree components appear in a 'convenient' + * order, i.e. the memory reservation block first, then the structure + * block and finally the string block. + * + * This order is not specified by the device-tree specification, + * but is expected by libfdt. The device-tree compiler always created + * device trees with this order. + * + * This assumption disables a check in fdt_open_into() and removes the * ability to fix the problem there. This is safe if you know that the * device tree is correctly ordered. See fdt_blocks_misordered_(). */ From e5cc26b68bc094c9260caaf330e03bb71129082e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 2 Mar 2020 12:02:54 -0700 Subject: [PATCH 0877/1198] libfdt: Add support for disabling internal checks If libfdt returns -FDT_ERR_INTERNAL that generally indicates a bug in the library. Add a new assumption for these cases since it should be save to disable these checks regardless of the input. Signed-off-by: Simon Glass Suggested-by: David Gibson Message-Id: <20200302190255.51426-3-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 4 ++-- libfdt/libfdt_internal.h | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 1945503..e03570a 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -402,7 +402,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, const struct fdt_property *prop; prop = fdt_get_property_by_offset_(fdt, offset, lenp); - if (!can_assume(VALID_DTB) && !prop) { + if (!can_assume(LIBFDT_FLAWLESS) && !prop) { offset = -FDT_ERR_INTERNAL; break; } @@ -634,7 +634,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset) err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); if (err) - return (can_assume(VALID_INPUT) || err < 0) ? err : + return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err : -FDT_ERR_INTERNAL; return nodedepth; } diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 7999f6a..d4e0bd4 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -145,6 +145,15 @@ enum { * device tree is correctly ordered. See fdt_blocks_misordered_(). */ ASSUME_LIBFDT_ORDER = 1 << 4, + + /* + * This assumes that libfdt itself does not have any internal bugs. It + * drops certain checks that should never be needed unless libfdt has an + * undiscovered bug. + * + * This can generally be considered safe to enable. + */ + ASSUME_LIBFDT_FLAWLESS = 1 << 5, }; /** From e5c92a4780c636fcfa6a84080d365f74393071aa Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 2 Mar 2020 12:02:55 -0700 Subject: [PATCH 0878/1198] libfdt: Use VALID_INPUT for FDT_ERR_BADSTATE checks This error indicates a logic bug in the code calling libfdt, so VALID_DTB is not really the right check. Update it to use VALID_INPUT instead. Signed-off-by: Simon Glass Suggested-by: David Gibson Message-Id: <20200302190255.51426-4-sjg@chromium.org> Signed-off-by: David Gibson --- libfdt/fdt.c | 2 +- libfdt/fdt_sw.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 4419204..c28fcc1 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -33,7 +33,7 @@ int32_t fdt_ro_probe_(const void *fdt) } } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { /* Unfinished sequential-write blob */ - if (fdt_size_dt_struct(fdt) == 0) + if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0) return -FDT_ERR_BADSTATE; } else { return -FDT_ERR_BADMAGIC; diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 352193c..26759d5 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -12,7 +12,7 @@ static int fdt_sw_probe_(void *fdt) { - if (!can_assume(VALID_DTB)) { + if (!can_assume(VALID_INPUT)) { if (fdt_magic(fdt) == FDT_MAGIC) return -FDT_ERR_BADSTATE; else if (fdt_magic(fdt) != FDT_SW_MAGIC) @@ -41,7 +41,7 @@ static int fdt_sw_probe_memrsv_(void *fdt) if (err) return err; - if (!can_assume(VALID_DTB) && fdt_off_dt_strings(fdt) != 0) + if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0) return -FDT_ERR_BADSTATE; return 0; } @@ -67,7 +67,8 @@ static int fdt_sw_probe_struct_(void *fdt) if (err) return err; - if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) + if (!can_assume(VALID_INPUT) && + fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) return -FDT_ERR_BADSTATE; return 0; } From 76b43dcbd18a67fa366d6383093621dfa4f7f28c Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 3 Mar 2020 13:39:31 -0600 Subject: [PATCH 0879/1198] checks: Add 'dma-ranges' check Generalize the existing 'ranges' check to also work for 'dma-ranges' which has the same parsing requirements. Signed-off-by: Rob Herring Message-Id: <20200303193931.1653-1-robh@kernel.org> Signed-off-by: David Gibson --- checks.c | 23 +++++++++++++---------- tests/bad-dma-ranges.dts | 12 ++++++++++++ tests/run_tests.sh | 1 + 3 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 tests/bad-dma-ranges.dts diff --git a/checks.c b/checks.c index 756f0fa..8acbc05 100644 --- a/checks.c +++ b/checks.c @@ -765,13 +765,15 @@ static void check_ranges_format(struct check *c, struct dt_info *dti, { struct property *prop; int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen; + const char *ranges = c->data; - prop = get_property(node, "ranges"); + prop = get_property(node, ranges); if (!prop) return; if (!node->parent) { - FAIL_PROP(c, dti, node, prop, "Root node has a \"ranges\" property"); + FAIL_PROP(c, dti, node, prop, "Root node has a \"%s\" property", + ranges); return; } @@ -783,23 +785,24 @@ static void check_ranges_format(struct check *c, struct dt_info *dti, if (prop->val.len == 0) { if (p_addr_cells != c_addr_cells) - FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its " + FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its " "#address-cells (%d) differs from %s (%d)", - c_addr_cells, node->parent->fullpath, + ranges, c_addr_cells, node->parent->fullpath, p_addr_cells); if (p_size_cells != c_size_cells) - FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its " + FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its " "#size-cells (%d) differs from %s (%d)", - c_size_cells, node->parent->fullpath, + ranges, c_size_cells, node->parent->fullpath, p_size_cells); } else if ((prop->val.len % entrylen) != 0) { - FAIL_PROP(c, dti, node, prop, "\"ranges\" property has invalid length (%d bytes) " + FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) " "(parent #address-cells == %d, child #address-cells == %d, " - "#size-cells == %d)", prop->val.len, + "#size-cells == %d)", ranges, prop->val.len, p_addr_cells, c_addr_cells, c_size_cells); } } -WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells); +WARNING(ranges_format, check_ranges_format, "ranges", &addr_size_cells); +WARNING(dma_ranges_format, check_ranges_format, "dma-ranges", &addr_size_cells); static const struct bus_type pci_bus = { .name = "PCI", @@ -1780,7 +1783,7 @@ static struct check *check_table[] = { &property_name_chars_strict, &node_name_chars_strict, - &addr_size_cells, ®_format, &ranges_format, + &addr_size_cells, ®_format, &ranges_format, &dma_ranges_format, &unit_address_vs_reg, &unit_address_format, diff --git a/tests/bad-dma-ranges.dts b/tests/bad-dma-ranges.dts new file mode 100644 index 0000000..fbe7ab8 --- /dev/null +++ b/tests/bad-dma-ranges.dts @@ -0,0 +1,12 @@ +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; + node { + #address-cells = <1>; + #size-cells = <1>; + ranges; + dma-ranges = <0 0 0 0 0>; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index e37ae59..ac0ffc2 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -664,6 +664,7 @@ dtc_tests () { check_tests "$SRCDIR/bad-reg-ranges.dts" reg_format ranges_format check_tests "$SRCDIR/bad-empty-ranges.dts" ranges_format check_tests "$SRCDIR/reg-ranges-root.dts" reg_format ranges_format + check_tests "$SRCDIR/bad-dma-ranges.dts" dma_ranges_format check_tests "$SRCDIR/default-addr-size.dts" avoid_default_addr_size check_tests "$SRCDIR/obsolete-chosen-interrupt-controller.dts" obsolete_chosen_interrupt_controller check_tests "$SRCDIR/reg-without-unit-addr.dts" unit_address_vs_reg From 2b5f62d109a24fd7032ed790dbf74f8dc7962313 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 4 Mar 2020 15:32:47 +1100 Subject: [PATCH 0880/1198] tests: Let run_tests.sh run Python tests without Makefile assistance Currently run_tests.sh needs the $PYTHON environment variable set to correctly run pylibfdt tests. The Makefile does this for make check, but it breaks if the script is run manually. Add a fallback to handle that case. Signed-off-by: David Gibson --- tests/run_tests.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index ac0ffc2..6fed97a 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -7,6 +7,10 @@ if [ -z "$CC" ]; then CC=cc fi +if [ -z "$PYTHON" ]; then + PYTHON=python3 +fi + # stat differs between platforms if [ -z "$STATSZ" ]; then stat --version 2>/dev/null | grep -q 'GNU' From 95ec8ef706bd776f3154f6a4dfa11b07433a2a80 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 4 Mar 2020 15:38:48 +1100 Subject: [PATCH 0881/1198] tests: No need to explicitly pass $PYTHON from Make to run_tests.sh Make automatically passes its variables through the environment, so we don't need to explicitly copy this one into the test script. Signed-off-by: David Gibson --- tests/Makefile.tests | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 51259f0..f3997e2 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -82,18 +82,18 @@ tests_clean: rm -rf $(TESTS_CLEANDIRS) check: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) - cd $(TESTS_PREFIX); PYTHON=$(PYTHON) ./run_tests.sh + cd $(TESTS_PREFIX); ./run_tests.sh ifeq ($(NO_VALGRIND),1) checkm: @echo "make checkm requires valgrind, but NO_VALGRIND=1" else checkm: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) - cd $(TESTS_PREFIX); PYTHON=$(PYTHON) ./run_tests.sh -m + cd $(TESTS_PREFIX); ./run_tests.sh -m endif checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) - cd $(TESTS_PREFIX); PYTHON=$(PYTHON) ./run_tests.sh -v + cd $(TESTS_PREFIX); ./run_tests.sh -v ifneq ($(DEPTARGETS),) -include $(TESTS_DEPFILES) From 6c253afd07d4722aaa7f72d33ca7cbeba973ccfb Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 4 Mar 2020 15:44:00 +1100 Subject: [PATCH 0882/1198] Encode $(NO_PYTHON) consistently with other variables We have several $(NO_*) variables used to disable optional features. $(NO_PYTHON) is encoded as empty for "include Python support" and anything else for "disable Python support". However the other variables - $(NO_YAML) and $(NO_VALGRIND) - use 0 for "include" and 1 for "disable". Change $(NO_PYTHON) to work consistently with the others. Signed-off-by: David Gibson --- Makefile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 0dff03f..5f4aa91 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,8 @@ 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 @@ -168,7 +170,7 @@ check_python_deps = \ maybe_pylibfdt: FORCE target=pylibfdt; $(check_python_deps) -ifeq ($(NO_PYTHON),) +ifeq ($(NO_PYTHON),0) all: maybe_pylibfdt endif @@ -240,7 +242,7 @@ install: install-bin install-lib install-includes maybe_install_pylibfdt: FORCE target=install_pylibfdt; $(check_python_deps) -ifeq ($(NO_PYTHON),) +ifeq ($(NO_PYTHON),0) install: maybe_install_pylibfdt endif @@ -312,7 +314,7 @@ TESTS_BIN += fdtput TESTS_BIN += fdtget TESTS_BIN += fdtdump TESTS_BIN += fdtoverlay -ifeq ($(NO_PYTHON),) +ifeq ($(NO_PYTHON),0) TESTS_PYLIBFDT += maybe_pylibfdt endif From 9b75292c335ca4d4f93ba91db92d4de1f0269e93 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 4 Mar 2020 15:45:47 +1100 Subject: [PATCH 0883/1198] tests: Honour $(NO_PYTHON) flag from Makefile in run_tests.sh Currently the test script bases whether to run the Python tests on whether it can see a built Python module. That can easily be fooled if there is a stale module there. Instead, have it actually look at the NO_PYTHON variable exported from the Makefile. If the variable doesn't exist (such as if we're running the script manually) fall back on the old logic. Signed-off-by: David Gibson --- tests/run_tests.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 6fed97a..7abcb03 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -11,6 +11,20 @@ if [ -z "$PYTHON" ]; then PYTHON=python3 fi +if [ -n "$NO_PYTHON" ]; then + if [ "$NO_PYTHON" != "0" ]; then + no_python=true + else + no_python=false + fi +else + if [ -f ../pylibfdt/_libfdt.so ] || [ -f ../pylibfdt/_libfdt.cpython-3*.so ]; then + no_python=false + else + no_python=true + fi +fi + # stat differs between platforms if [ -z "$STATSZ" ]; then stat --version 2>/dev/null | grep -q 'GNU' @@ -1016,7 +1030,7 @@ if [ -z "$TESTSETS" ]; then TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget fdtput fdtdump fdtoverlay" # Test pylibfdt if the libfdt Python module is available. - if [ -f ../pylibfdt/_libfdt.so ] || [ -f ../pylibfdt/_libfdt.cpython-3*.so ]; then + if ! $no_python; then TESTSETS="$TESTSETS pylibfdt" fi fi From e4ce227e89d7334c44e0018ae837e0a2a824a812 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 4 Mar 2020 16:05:31 +1100 Subject: [PATCH 0884/1198] tests: Properly clean up .bak file from tests One of our testcases creates a .bak file from invoking sed. Fix that to be removed by make clean, and also ignore it in git to avoid clutter. Signed-off-by: David Gibson --- .gitignore | 1 + tests/Makefile.tests | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ee4e489..1f2a0f2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.patch *.so *~ +*.bak *.tab.[ch] lex.yy.c *.lex.c diff --git a/tests/Makefile.tests b/tests/Makefile.tests index f3997e2..cb66c9f 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -49,7 +49,7 @@ TESTS_DEPFILES = $(TESTS:%=%.d) \ $(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d) TESTS_CLEANFILES_L = $(STD_CLEANFILES) \ - *.dtb *.test.dts *.test.dt.yaml *.dtsv1 tmp.* \ + *.dtb *.test.dts *.test.dt.yaml *.dtsv1 tmp.* *.bak \ dumptrees TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) TESTS_CLEANDIRS_L = fs From c5995ddf4c20345886120048bf0cd8e8d7cc597f Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 4 Mar 2020 16:10:06 +1100 Subject: [PATCH 0885/1198] tests: Honour NO_YAML make variable Support for YAML output in dtc is optional (to cover systems that don't have libyaml). Currently the tests for yaml output test if the libyaml package is locally installed. That duplicates similar logic in the Makefile, and worse it will cause failed tests if the user explicitly disables YAML support, rather than simply not having libyaml installed. Fix this by having the test script use the NO_YAML variable exported by make. Fall back to the current test if the variable isn't set, such as when running the script manually. Signed-off-by: David Gibson --- tests/run_tests.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 7abcb03..b0a1fc3 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -25,6 +25,20 @@ else fi fi +if [ -n "$NO_YAML" ]; then + if [ "$NO_YAML" != "0" ]; then + no_yaml=true + else + no_yaml=false + fi +else + if pkg-config --exists yaml-0.1; then + no_yaml=false + else + no_yaml=true + fi +fi + # stat differs between platforms if [ -z "$STATSZ" ]; then stat --version 2>/dev/null | grep -q 'GNU' @@ -615,7 +629,7 @@ dtc_tests () { done # Check -Oyaml output - if pkg-config --exists yaml-0.1; then + if ! $no_yaml; then for tree in type-preservation; do run_dtc_test -I dts -O yaml -o $tree.test.dt.yaml "$SRCDIR/$tree.dts" run_wrap_test cmp "$SRCDIR/$tree.dt.yaml" $tree.test.dt.yaml From 1f9a417508837fca4dd0e3bf0e3c0e5c9fb93edf Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 4 Mar 2020 16:26:33 +1100 Subject: [PATCH 0886/1198] tests: Allow running the testsuite on already installed binary / libraries Currently the test runner script always expects to be run from within the tests/ subdirectory of a dtc source tree: it looks for dtc and other binaries in the parent of the current directory and for the libfdt shared library in ../libfdt. That works great with make check and for testing a build you've just made. However, sometimes it's useful to test a dtc & libfdt which have already been installed on the system, or which for whatever reason are located somewhere else. This patch allows the test runner script to do this when TEST_BINDIR and/or TEST_LIBDIR environment variables are set. Signed-off-by: David Gibson --- tests/run_tests.sh | 5 ++++- tests/testutils.sh | 14 +++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index b0a1fc3..eccb85d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -52,7 +52,10 @@ if [ -z "$STATSZ" ]; then fi # Help things find the libfdt shared object -export LD_LIBRARY_PATH=../libfdt +if [ -z "$TEST_LIBDIR" ]; then + TEST_LIBDIR=../libfdt +fi +export LD_LIBRARY_PATH="$TEST_LIBDIR" export QUIET_TEST=1 STOP_ON_FAIL=0 diff --git a/tests/testutils.sh b/tests/testutils.sh index 8dda6e1..6b2f0d1 100644 --- a/tests/testutils.sh +++ b/tests/testutils.sh @@ -18,11 +18,15 @@ FAIL_IF_SIGNAL () { fi } -DTC=../dtc -DTGET=../fdtget -DTPUT=../fdtput -FDTDUMP=../fdtdump -FDTOVERLAY=../fdtoverlay +if [ -z "$TEST_BINDIR" ]; then + TEST_BINDIR=.. +fi + +DTC=${TEST_BINDIR}/dtc +DTGET=${TEST_BINDIR}/fdtget +DTPUT=${TEST_BINDIR}/fdtput +FDTDUMP=${TEST_BINDIR}/fdtdump +FDTOVERLAY=${TEST_BINDIR}/fdtoverlay verbose_run () { if [ -z "$QUIET_TEST" ]; then From 62cb4ad286ff82648232f769f78401bf6b00deda Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 4 Mar 2020 16:40:00 +1100 Subject: [PATCH 0887/1198] Execute tests on FreeBSD with Cirrus CI Signed-off-by: David Gibson --- .cirrus.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.cirrus.yml b/.cirrus.yml index de4a318..c270a09 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -8,6 +8,8 @@ freebsd_12_task: pkg install -y bison gmake pkgconf build_script: gmake + test_script: + gmake check linux_gcc_task: container: From 2525da3dba9beceb96651dc2986581871dbeca30 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 4 Mar 2020 17:14:58 +1100 Subject: [PATCH 0888/1198] Bump version to v1.6.0 We've accumulated some new features and a bunch of fixes. Also the versioning on v1.5.1 was messed up :(. Prepare for another release. Signed-off-by: David Gibson --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5f4aa91..f02aa19 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ # CONFIG_LOCALVERSION from some future config system. # VERSION = 1 -PATCHLEVEL = 5 +PATCHLEVEL = 6 SUBLEVEL = 0 EXTRAVERSION = LOCAL_VERSION = From 73d6e9ecb4179b510408bc526240f829262df361 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 5 Mar 2020 15:04:45 +0100 Subject: [PATCH 0889/1198] 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 0890/1198] 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 0891/1198] 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 0892/1198] 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 0893/1198] 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 0894/1198] 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 0895/1198] 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 0896/1198] 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 0897/1198] 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 0898/1198] 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 0899/1198] 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 0900/1198] 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 0901/1198] 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 0902/1198] 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 0903/1198] 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 0904/1198] 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 0905/1198] 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 0906/1198] 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 0907/1198] 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 0908/1198] 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 0909/1198] 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 0910/1198] 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 0911/1198] 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 0912/1198] 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 0913/1198] 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 0914/1198] 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 0915/1198] 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 0916/1198] 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 0917/1198] 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 0918/1198] 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 0919/1198] 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 0920/1198] 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 0921/1198] 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 0922/1198] 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 0923/1198] 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 0924/1198] 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 0925/1198] 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 0926/1198] 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 0927/1198] 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 0928/1198] 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 0929/1198] 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 0930/1198] 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 0931/1198] 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 0932/1198] 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 0933/1198] 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 0934/1198] 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 0935/1198] 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 0936/1198] 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 0937/1198] 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 0938/1198] 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 0939/1198] 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 0940/1198] 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 0941/1198] 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 0942/1198] 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 0943/1198] 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 0944/1198] 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 0945/1198] 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 0946/1198] 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 0947/1198] 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 0948/1198] 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 0949/1198] 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 0950/1198] 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 0951/1198] 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 0952/1198] 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 0953/1198] 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 0954/1198] 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 0955/1198] 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 0956/1198] 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 0957/1198] 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 0958/1198] 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 0959/1198] 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 0960/1198] 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 0961/1198] 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 0962/1198] 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 0963/1198] 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 0964/1198] 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 0965/1198] 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 0966/1198] 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 0967/1198] 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 0968/1198] 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 0969/1198] 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 0970/1198] 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 0971/1198] 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 0972/1198] 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 0973/1198] 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 0974/1198] 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 0975/1198] 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 0976/1198] 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 0977/1198] 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 0978/1198] 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 0979/1198] 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 0980/1198] 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 0981/1198] 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 0982/1198] 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 0983/1198] 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 0984/1198] 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 0985/1198] 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 0986/1198] 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 0987/1198] 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 0988/1198] 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 0989/1198] 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 0990/1198] 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 0991/1198] 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 0992/1198] 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 0993/1198] 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 0994/1198] 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 0995/1198] 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 0996/1198] 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 0997/1198] 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 0998/1198] 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 0999/1198] 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 1000/1198] 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 1001/1198] 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 1002/1198] 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 1003/1198] 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 1004/1198] 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 1005/1198] 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 1006/1198] 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 1007/1198] 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 1008/1198] 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 1009/1198] 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 1010/1198] 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 1011/1198] 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 1012/1198] 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 1013/1198] 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 1014/1198] 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 1015/1198] 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 1016/1198] 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 1017/1198] 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 1018/1198] 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 1019/1198] 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 1020/1198] 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 1021/1198] 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 1022/1198] 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 1023/1198] 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 1024/1198] 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 1025/1198] 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 1026/1198] 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 1027/1198] 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 1028/1198] 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 1029/1198] 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 1030/1198] 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 1031/1198] 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 1032/1198] 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 1033/1198] 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 1034/1198] 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 1035/1198] 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 1036/1198] 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 1037/1198] 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 1038/1198] 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 1039/1198] 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 1040/1198] 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 1041/1198] 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 1042/1198] 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 1043/1198] 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 1044/1198] 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 1045/1198] 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 1046/1198] 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 1047/1198] 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 1048/1198] 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 1049/1198] 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 1050/1198] 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 1051/1198] 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 1052/1198] 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 1053/1198] 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 1054/1198] 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 1055/1198] 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 1056/1198] 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 1057/1198] 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 1058/1198] 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 1059/1198] 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 1060/1198] 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 1061/1198] 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 1062/1198] 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 1063/1198] 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 1064/1198] 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 1065/1198] 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 1066/1198] 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 1067/1198] 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 1068/1198] 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 1069/1198] 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 1070/1198] 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 1071/1198] 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 1072/1198] 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 1073/1198] 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 1074/1198] 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 1075/1198] 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 1076/1198] 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 1077/1198] 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 1078/1198] 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 1079/1198] 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 1080/1198] 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 1081/1198] 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 1082/1198] 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 1083/1198] 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 1084/1198] 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 1085/1198] 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 1086/1198] 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 1087/1198] 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 1088/1198] 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 1089/1198] 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 1090/1198] 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 1091/1198] 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 1092/1198] 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 1093/1198] 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 1094/1198] 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 1095/1198] 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 1096/1198] 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 1097/1198] 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 1098/1198] 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 1099/1198] 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 1100/1198] 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 1101/1198] 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 1102/1198] 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 1103/1198] 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 1104/1198] 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 1105/1198] 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 1106/1198] 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 1107/1198] 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 1108/1198] 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 1109/1198] 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 1110/1198] 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 1111/1198] 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 1112/1198] 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 1113/1198] 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 1114/1198] 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 1115/1198] 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 1116/1198] 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 1117/1198] 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 1118/1198] 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 1119/1198] 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 1120/1198] 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 1121/1198] 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 1122/1198] 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 1123/1198] 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 1124/1198] 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 1125/1198] 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 1126/1198] 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 1127/1198] 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 1128/1198] 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 1129/1198] 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 1130/1198] 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 1131/1198] 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 1132/1198] 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 1133/1198] 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 1134/1198] 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 1135/1198] 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 1136/1198] 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 1137/1198] 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 1138/1198] 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 1139/1198] 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 1140/1198] 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 1141/1198] .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 1142/1198] 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 1143/1198] 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 1144/1198] 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 1145/1198] 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 1146/1198] 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 1147/1198] 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 1148/1198] 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 1149/1198] 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 1150/1198] 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 1151/1198] 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 1152/1198] 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 1153/1198] 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 1154/1198] 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 1155/1198] 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 1156/1198] 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 1157/1198] 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 1158/1198] 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 1159/1198] 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 1160/1198] 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 1161/1198] 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 1162/1198] 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 1163/1198] 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 1164/1198] 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 1165/1198] 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 1166/1198] 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 1167/1198] 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 1168/1198] 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 1169/1198] 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 1170/1198] 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 1171/1198] 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 1172/1198] 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 1173/1198] 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 1174/1198] 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 1175/1198] 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 1176/1198] 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 1177/1198] 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 1178/1198] 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 1179/1198] 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 1180/1198] 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 1181/1198] 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 1182/1198] 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 1183/1198] 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 1184/1198] 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 1185/1198] 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 1186/1198] 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 */ From b126924732983f60ddc6bdcf6157083982ef32f0 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 9 Dec 2025 15:50:51 -0600 Subject: [PATCH 1187/1198] libfdt: libfdt_internal.h correct final comment in ASSUME block The value "ASSUME_SANE" was never used in the project here, only ASSUME_PERFECT was used. Update the comment to reflect the correct name. Fixes: 464962489dcc ("Add a way to control the level of checks in the code") Signed-off-by: Tom Rini Message-ID: <20251210022002.3004223-2-trini@konsulko.com> Signed-off-by: David Gibson --- libfdt/libfdt_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index b60b545..9eb3239 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -92,7 +92,7 @@ static inline uint64_t fdt64_ld_(const fdt64_t *p) * signature or hash check before using libfdt. * * For situations where security is not a concern it may be safe to enable - * ASSUME_SANE. + * ASSUME_PERFECT. */ enum { /* From 39cae0bd0031e31a7b027cefbfb0bf7ff1201b52 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 9 Dec 2025 15:50:52 -0600 Subject: [PATCH 1188/1198] libfdt: Improve size savings in FDT_RO_PROBE slightly In the case where we have set FDT_ASSUME_MASK to disable ASSUME_VALID_DTB checks, we can improve the FDT_RO_PROBE macro slightly. The first thing that fdt_ro_probe_() does when we can_assume(VALID_DTB) is true is to return whatever the contents of the totalsize field of the DTB is. Since the FDT_RO_PROBE macro only cares about a negative value there, we can optimize this check such that we are to assume it's a valid DTB, we don't need to do anything here. Signed-off-by: Tom Rini Message-ID: <20251210022002.3004223-3-trini@konsulko.com> Signed-off-by: David Gibson --- libfdt/libfdt_internal.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 9eb3239..0e103ca 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -11,11 +11,13 @@ #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) int32_t fdt_ro_probe_(const void *fdt); -#define FDT_RO_PROBE(fdt) \ - { \ - int32_t totalsize_; \ - if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \ - return totalsize_; \ +#define FDT_RO_PROBE(fdt) \ + { \ + if (!can_assume(VALID_DTB)) { \ + int32_t totalsize_; \ + if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \ + return totalsize_; \ + } \ } int fdt_check_node_offset_(const void *fdt, int offset); From 194ac9422ac956e7b1f0dd43649a169bbbf86c58 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 9 Dec 2025 15:50:53 -0600 Subject: [PATCH 1189/1198] libfdt: fdt_get_name: Add can_assume(VALID_DTB) check In this function from fdt_ro.c we have (reasonably) some checks of the DTB before we begin work. However, we do this in a way that we cannot make use of the normal FDT_RO_PROBE macro and instead have a direct call to fdt_ro_probe_(). Add a test for !can_assume(VALID_DTB) here first so that in cases where we are assuming a valid DTB we can omit the checks. Signed-off-by: Tom Rini Message-ID: <20251210022002.3004223-4-trini@konsulko.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 b78c4e4..63494fb 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -306,8 +306,8 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) const char *nameptr; int err; - if (((err = fdt_ro_probe_(fdt)) < 0) - || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) + if (!can_assume(VALID_DTB) && (((err = fdt_ro_probe_(fdt)) < 0) + || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))) goto fail; nameptr = nh->name; From 9a1c801a1a3c102bf95c5339c9e985b26b823a21 Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Tue, 6 Jan 2026 14:19:30 -0500 Subject: [PATCH 1190/1198] Fix discarded const qualifiers It's unsafe to implicitly discard the const qualifier on a pointer. In overlay_fixup_phandle(), this was probably just an oversight, and making the "sep" variable a const char * is sufficient to fix it. In create_node(), however, the "p" variable is directly modifying the buffer pointed to by "const char* node_name". To fix this, we need to actually make a duplicate of the buffer and operate on that instead. This introduces a malloc()/free() and an unbounded strdup() into the operation, but fdtput isn't a long-running service and the node_name argument comes directly from argv, so this shouldn't introduce a significant performance impact. Signed-off-by: Stephen Gallagher Signed-off-by: David Gibson --- fdtput.c | 8 +++++--- libfdt/fdt_overlay.c | 3 ++- meson.build | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/fdtput.c b/fdtput.c index 05f2b93..fdb581a 100644 --- a/fdtput.c +++ b/fdtput.c @@ -254,19 +254,21 @@ static int create_paths(char **blob, const char *in_path) static int create_node(char **blob, const char *node_name) { int node = 0; - char *p; + const char *p; + char *path = NULL; p = strrchr(node_name, '/'); if (!p) { report_error(node_name, -1, -FDT_ERR_BADPATH); return -1; } - *p = '\0'; *blob = realloc_node(*blob, p + 1); if (p > node_name) { - node = fdt_path_offset(*blob, node_name); + path = xstrndup(node_name, (size_t)(p - node_name)); + node = fdt_path_offset(*blob, path); + free(path); if (node < 0) { report_error(node_name, -1, node); return -1; diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c index e6b9eb6..51a3859 100644 --- a/libfdt/fdt_overlay.c +++ b/libfdt/fdt_overlay.c @@ -407,7 +407,8 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, const char *fixup_str = value; uint32_t path_len, name_len; uint32_t fixup_len; - char *sep, *endptr; + const char *sep; + char *endptr; int poffset, ret; fixup_end = memchr(value, '\0', len); diff --git a/meson.build b/meson.build index 66b44e8..501b706 100644 --- a/meson.build +++ b/meson.build @@ -18,6 +18,7 @@ add_project_arguments( '-Wshadow', '-Wsuggest-attribute=format', '-Wwrite-strings', + '-Wdiscarded-qualifiers', ]), language: 'c' ) From 14dd76b96732ee7ffd1c42b1ff5922ccca902503 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Mon, 12 Jan 2026 15:18:55 +0100 Subject: [PATCH 1191/1198] fdtdump: Change FDT_PROP prob handling to ease future addition In order to ease future tags addition, perform operation related to FDT_PROP when the tag is explicitly FDT_PROP instead of relying to a kind of default value case. Handle the FDT_PROP tag exactly in the same way as it is done for other tags. No functional modification. Signed-off-by: Herve Codina Message-ID: <20260112142009.1006236-6-herve.codina@bootlin.com> Reviewed-by: Ayush Singh Signed-off-by: David Gibson --- fdtdump.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/fdtdump.c b/fdtdump.c index d424869..0260609 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -129,23 +129,25 @@ static void dump_blob(void *blob, bool debug) continue; } - if (tag != FDT_PROP) { - fprintf(stderr, "%*s ** Unknown tag 0x%08"PRIx32"\n", depth * shift, "", tag); - break; + if (tag == FDT_PROP) { + sz = fdt32_to_cpu(GET_CELL(p)); + s = p_strings + fdt32_to_cpu(GET_CELL(p)); + if (version < 16 && sz >= 8) + p = PALIGN(p, 8); + t = p; + + p = PALIGN(p + sz, 4); + + dumpf("%04"PRIxPTR": string: %s\n", (uintptr_t)s - blob_off, s); + dumpf("%04"PRIxPTR": value\n", (uintptr_t)t - blob_off); + printf("%*s%s", depth * shift, "", s); + utilfdt_print_data(t, sz); + printf(";\n"); + continue; } - sz = fdt32_to_cpu(GET_CELL(p)); - s = p_strings + fdt32_to_cpu(GET_CELL(p)); - if (version < 16 && sz >= 8) - p = PALIGN(p, 8); - t = p; - p = PALIGN(p + sz, 4); - - dumpf("%04"PRIxPTR": string: %s\n", (uintptr_t)s - blob_off, s); - dumpf("%04"PRIxPTR": value\n", (uintptr_t)t - blob_off); - printf("%*s%s", depth * shift, "", s); - utilfdt_print_data(t, sz); - printf(";\n"); + fprintf(stderr, "%*s ** Unknown tag 0x%08"PRIx32"\n", depth * shift, "", tag); + break; } } From 7c78c8542d73eefafff9f9eccb38c986af82394c Mon Sep 17 00:00:00 2001 From: Maldus512 Date: Wed, 14 Jan 2026 14:24:05 +0100 Subject: [PATCH 1192/1198] Added empty node name check The Devicetree specification states that a node name shall be of form `node-name@unit-address` and that the `node-name` component cannot be empty. However, the `dtc` parser considers a node name as a non-empty sequences of the allowed characters plus the @ character, and unit-address extraction is processed after parsing. This has the side effect of considering an empty name plus an address as a valid node name (e.g. `@0`). I've added the node_name_not_empty check, verifying that the `node->basenamelen` is not zero (unless it's the root node). Signed-off-by: Mattia Maldini [dwg: Re-wrap commit message] Signed-off-by: David Gibson --- checks.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/checks.c b/checks.c index 5d09216..45d0213 100644 --- a/checks.c +++ b/checks.c @@ -340,6 +340,14 @@ 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_not_empty(struct check *c, struct dt_info *dti, + struct node *node) +{ + if (node->basenamelen == 0 && node->parent != NULL) + FAIL(c, dti, node, "Empty node name"); +} +ERROR(node_name_not_empty, check_node_name_not_empty, NULL, &node_name_chars); + static void check_node_name_vs_property_name(struct check *c, struct dt_info *dti, struct node *node) @@ -1899,7 +1907,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, + &node_name_chars, &node_name_format, &node_name_not_empty, &property_name_chars, &name_is_string, &name_properties, &node_name_vs_property_name, &duplicate_label, From ef3b1baf63707ee6775857c86100ae4e90fbb3d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 19 Sep 2025 11:29:14 +0200 Subject: [PATCH 1193/1198] Emit /plugin/ when compiling to .dts with DTSF_PLUGIN set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes `dtc -I dts -O dts` to make the file a plugin if the source file is one. Reviewed-by: David Gibson Signed-off-by: Uwe Kleine-König Message-ID: <20250919092912.663304-9-u.kleine-koenig@baylibre.com> Signed-off-by: David Gibson --- treesource.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/treesource.c b/treesource.c index d25f01f..72d1cb5 100644 --- a/treesource.c +++ b/treesource.c @@ -369,7 +369,10 @@ void dt_to_source(FILE *f, struct dt_info *dti) { struct reserve_info *re; - fprintf(f, "/dts-v1/;\n\n"); + fprintf(f, "/dts-v1/;\n"); + if (dti->dtsflags & DTSF_PLUGIN) + fprintf(f, "/plugin/;\n"); + fprintf(f, "\n"); for (re = dti->reservelist; re; re = re->next) { struct label *l; From cbb48690c697fe927a1b1c421f78ecfd3f32e54d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 19 Sep 2025 11:29:15 +0200 Subject: [PATCH 1194/1198] Set DTSF_PLUGIN if needed when compiling from dtb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The need for the plugin flag is determined by the existence of __fixups__ or __local_fixups__. This is a bit simplifying because if __fixups__ or __local_fixups__ exist but don't have properties, the plugin flag isn't needed. But in practise the test should be good enough such that this corner case doesn't matter. Reviewed-by: David Gibson Signed-off-by: Uwe Kleine-König Message-ID: <20250919092912.663304-10-u.kleine-koenig@baylibre.com> Signed-off-by: David Gibson --- flattree.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/flattree.c b/flattree.c index 30e6de2..f3b698c 100644 --- a/flattree.c +++ b/flattree.c @@ -807,6 +807,7 @@ struct dt_info *dt_from_blob(const char *fname) struct node *tree; uint32_t val; int flags = 0; + unsigned int dtsflags = DTSF_V1; f = srcfile_relative_open(fname, NULL); @@ -919,5 +920,8 @@ struct dt_info *dt_from_blob(const char *fname) fclose(f); - return build_dt_info(DTSF_V1, reservelist, tree, boot_cpuid_phys); + if (get_subnode(tree, "__fixups__") || get_subnode(tree, "__local_fixups__")) + dtsflags |= DTSF_PLUGIN; + + return build_dt_info(dtsflags, reservelist, tree, boot_cpuid_phys); } From 64330c682cac532ae3eba2e5902e5bbaffa65ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 19 Sep 2025 11:29:16 +0200 Subject: [PATCH 1195/1198] Improve type guessing when compiling to dts format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the presence of (non-type) markers guess the type of each chunk between markers individually instead of only once for the whole property. Note that this only gets relevant with the next few commits that restore labels and phandles. Note further that this rework is necessary with these further changes, because phandle markers are currently not considered for type guessing and so a phandle at an offset that isn't a multiple of 4 triggers an assertion if the property was guessed to have type TYPE_UINT32. Now that guess_value_type() is only called for data chunks without markers, the function can be simplified a bit. Reviewed-by: David Gibson Signed-off-by: Uwe Kleine-König Message-ID: <20250919092912.663304-11-u.kleine-koenig@baylibre.com> Signed-off-by: David Gibson --- treesource.c | 70 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/treesource.c b/treesource.c index 72d1cb5..5764959 100644 --- a/treesource.c +++ b/treesource.c @@ -173,23 +173,20 @@ static struct marker **add_marker(struct marker **mi, return &nm->next; } -static void add_string_markers(struct property *prop) +static void add_string_markers(struct property *prop, unsigned int offset, int len) { - int l, len = prop->val.len; - const char *p = prop->val.val; + int l; + const char *p = prop->val.val + offset; struct marker **mi = &prop->val.markers; for (l = strlen(p) + 1; l < len; l += strlen(p + l) + 1) - mi = add_marker(mi, TYPE_STRING, l, NULL); + mi = add_marker(mi, TYPE_STRING, offset + l, NULL); } -static enum markertype guess_value_type(struct property *prop) +static enum markertype guess_value_type(struct property *prop, unsigned int offset, int len) { - int len = prop->val.len; - const char *p = prop->val.val; - struct marker *m = prop->val.markers; + const char *p = prop->val.val + offset; int nnotstring = 0, nnul = 0; - int nnotstringlbl = 0, nnotcelllbl = 0; int i; for (i = 0; i < len; i++) { @@ -199,30 +196,49 @@ static enum markertype guess_value_type(struct property *prop) nnul++; } - for_each_marker_of_type(m, LABEL) { - if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0')) - nnotstringlbl++; - if ((m->offset % sizeof(cell_t)) != 0) - nnotcelllbl++; - } - - if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul)) - && (nnotstringlbl == 0)) { + if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= len - nnul)) { if (nnul > 1) - add_string_markers(prop); + add_string_markers(prop, offset, len); return TYPE_STRING; - } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { + } else if ((len % sizeof(cell_t)) == 0) { return TYPE_UINT32; } return TYPE_UINT8; } +static void guess_type_markers(struct property *prop) +{ + struct marker **m = &prop->val.markers; + unsigned int offset = 0; + + for (m = &prop->val.markers; *m; m = &((*m)->next)) { + if (is_type_marker((*m)->type)) + /* assume the whole property is already marked */ + return; + + if ((*m)->offset > offset) { + m = add_marker(m, guess_value_type(prop, offset, (*m)->offset - offset), + offset, NULL); + + offset = (*m)->offset; + } + + if ((*m)->type == REF_PHANDLE) { + m = add_marker(m, TYPE_UINT32, offset, NULL); + offset += 4; + } + } + + if (offset < prop->val.len) + add_marker(m, guess_value_type(prop, offset, prop->val.len - offset), + offset, NULL); +} + static void write_propval(FILE *f, struct property *prop) { size_t len = prop->val.len; - struct marker *m = prop->val.markers; - struct marker dummy_marker; + struct marker *m; enum markertype emit_type = TYPE_NONE; char *srcstr; @@ -241,14 +257,8 @@ static void write_propval(FILE *f, struct property *prop) fprintf(f, " ="); - if (!next_type_marker(m)) { - /* data type information missing, need to guess */ - dummy_marker.type = guess_value_type(prop); - dummy_marker.next = prop->val.markers; - dummy_marker.offset = 0; - dummy_marker.ref = NULL; - m = &dummy_marker; - } + guess_type_markers(prop); + m = prop->val.markers; for_each_marker(m) { size_t chunk_len = (m->next ? m->next->offset : len) - m->offset; From db65a3a3f4f0cc301acff39de33347991da6ef1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 19 Sep 2025 11:29:17 +0200 Subject: [PATCH 1196/1198] Restore labels from __symbols__ node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the input has a __symbols__ node, restore the named labels for the respective nodes. Reviewed-by: David Gibson Signed-off-by: Uwe Kleine-König Message-ID: <20250919092912.663304-12-u.kleine-koenig@baylibre.com> Signed-off-by: David Gibson --- dtc.c | 2 ++ dtc.h | 1 + livetree.c | 21 +++++++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/dtc.c b/dtc.c index b3445b7..63a6c85 100644 --- a/dtc.c +++ b/dtc.c @@ -338,6 +338,8 @@ int main(int argc, char *argv[]) if (auto_label_aliases) generate_label_tree(dti, "aliases", false); + generate_labels_from_tree(dti, "__symbols__"); + if (generate_symbols) generate_label_tree(dti, "__symbols__", true); diff --git a/dtc.h b/dtc.h index 3a220b9..f97f3c2 100644 --- a/dtc.h +++ b/dtc.h @@ -339,6 +339,7 @@ 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_labels_from_tree(struct dt_info *dti, const 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); diff --git a/livetree.c b/livetree.c index f328824..8aafc9a 100644 --- a/livetree.c +++ b/livetree.c @@ -1112,6 +1112,27 @@ static int generate_local_fixups_tree_internal(struct dt_info *dti, return ret; } +void generate_labels_from_tree(struct dt_info *dti, const char *name) +{ + struct node *an; + struct property *p; + + an = get_subnode(dti->dt, name); + if (!an) + return; + + for_each_property(an, p) { + struct node *labeled_node; + + labeled_node = get_node_by_path(dti->dt, p->val.val); + if (labeled_node) + add_label(&labeled_node->labels, p->name); + else if (quiet < 1) + fprintf(stderr, "Warning: Path %s referenced in property %s/%s missing", + p->val.val, name, p->name); + } +} + void generate_label_tree(struct dt_info *dti, const char *name, bool allocph) { if (!any_label_tree(dti, dti->dt)) From 05c524db44ff5412c6b954c6122a18c45216e950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 19 Sep 2025 11:29:18 +0200 Subject: [PATCH 1197/1198] Restore phandle references from __local_fixups__ node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The __local_fixups__ node contains information about phandles. Parse it to improve the result when decompiling a device tree blob. Signed-off-by: Uwe Kleine-König Message-ID: <20250919092912.663304-13-u.kleine-koenig@baylibre.com> Signed-off-by: David Gibson --- dtc.c | 2 ++ dtc.h | 2 ++ livetree.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ treesource.c | 33 ++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) diff --git a/dtc.c b/dtc.c index 63a6c85..9f90b37 100644 --- a/dtc.c +++ b/dtc.c @@ -343,6 +343,8 @@ int main(int argc, char *argv[]) if (generate_symbols) generate_label_tree(dti, "__symbols__", true); + local_fixup_phandles(dti, "__local_fixups__"); + if (generate_fixups) { generate_fixups_tree(dti, "__fixups__"); generate_local_fixups_tree(dti, "__local_fixups__"); diff --git a/dtc.h b/dtc.h index f97f3c2..d07a583 100644 --- a/dtc.h +++ b/dtc.h @@ -343,6 +343,7 @@ void generate_labels_from_tree(struct dt_info *dti, const 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); +void local_fixup_phandles(struct dt_info *dti, const char *name); /* Checks */ @@ -358,6 +359,7 @@ struct dt_info *dt_from_blob(const char *fname); /* Tree source */ +void add_phandle_marker(struct dt_info *dti, struct property *prop, unsigned int offset); void dt_to_source(FILE *f, struct dt_info *dti); struct dt_info *dt_from_source(const char *f); diff --git a/livetree.c b/livetree.c index 8aafc9a..3dbef90 100644 --- a/livetree.c +++ b/livetree.c @@ -1160,3 +1160,60 @@ void generate_local_fixups_tree(struct dt_info *dti, const char *name) "Warning: Preexisting data in %s malformed, some content could not be added.\n", name); } + +static void local_fixup_phandles_node(struct dt_info *dti, struct node *lf, struct node *n) +{ + struct property *lfp; + struct node *lfsubnode; + + for_each_property(lf, lfp) { + struct property *p = get_property(n, lfp->name); + fdt32_t *offsets = (fdt32_t *)lfp->val.val; + size_t i; + + if (!p) { + if (quiet < 1) + fprintf(stderr, "Warning: Property %s in %s referenced in __local_fixups__ missing\n", + lfp->name, n->fullpath); + continue; + } + + /* + * Each property in the __local_fixups__ tree is a concatenation + * of offsets, so it must be a multiple of sizeof(fdt32_t). + */ + if (lfp->val.len % sizeof(fdt32_t)) { + if (quiet < 1) + fprintf(stderr, "Warning: property %s in /__local_fixups__%s malformed\n", + lfp->name, n->fullpath); + continue; + } + + for (i = 0; i < lfp->val.len / sizeof(fdt32_t); i++) + add_phandle_marker(dti, p, dtb_ld32(offsets + i)); + } + + for_each_child(lf, lfsubnode) { + struct node *subnode = get_subnode(n, lfsubnode->name); + + if (!subnode) { + if (quiet < 1) + fprintf(stderr, "Warning: node %s/%s referenced in __local_fixups__ missing\n", + lfsubnode->name, n->fullpath); + continue; + } + + local_fixup_phandles_node(dti, lfsubnode, subnode); + } +} + +void local_fixup_phandles(struct dt_info *dti, const char *name) +{ + struct node *an; + + an = get_subnode(dti->dt, name); + if (!an) + return; + + local_fixup_phandles_node(dti, an, dti->dt); +} diff --git a/treesource.c b/treesource.c index 5764959..e2eca63 100644 --- a/treesource.c +++ b/treesource.c @@ -183,6 +183,39 @@ static void add_string_markers(struct property *prop, unsigned int offset, int l mi = add_marker(mi, TYPE_STRING, offset + l, NULL); } +void add_phandle_marker(struct dt_info *dti, struct property *prop, unsigned int offset) +{ + cell_t phandle; + struct node *refn; + char *ref; + + if (prop->val.len < offset + 4) { + if (quiet < 1) + fprintf(stderr, + "Warning: property %s too short to contain a phandle at offset %u\n", + prop->name, offset); + return; + } + + phandle = dtb_ld32(prop->val.val + offset); + refn = get_node_by_phandle(dti->dt, phandle); + + if (!refn) { + if (quiet < 1) + fprintf(stderr, + "Warning: node referenced by phandle 0x%x in property %s not found\n", + phandle, prop->name); + return; + } + + if (refn->labels) + ref = refn->labels->label; + else + ref = refn->fullpath; + + add_marker(&prop->val.markers, REF_PHANDLE, offset, ref); +} + static enum markertype guess_value_type(struct property *prop, unsigned int offset, int len) { const char *p = prop->val.val + offset; From a26ef6400bd845beb6e7f369809ca1c42d856904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 19 Sep 2025 11:29:19 +0200 Subject: [PATCH 1198/1198] Restore phandle references from __fixups__ node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The __fixups__ node contains information about labels. Parse its properties to create phandle markers which improve the resulting dts when decompiling a device tree blob. Reviewed-by: David Gibson Signed-off-by: Uwe Kleine-König Message-ID: <20250919092912.663304-14-u.kleine-koenig@baylibre.com> Signed-off-by: David Gibson --- dtc.c | 1 + dtc.h | 3 ++ livetree.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++ treesource.c | 6 ++++ 4 files changed, 106 insertions(+) diff --git a/dtc.c b/dtc.c index 9f90b37..6dae60d 100644 --- a/dtc.c +++ b/dtc.c @@ -343,6 +343,7 @@ int main(int argc, char *argv[]) if (generate_symbols) generate_label_tree(dti, "__symbols__", true); + fixup_phandles(dti, "__fixups__"); local_fixup_phandles(dti, "__local_fixups__"); if (generate_fixups) { diff --git a/dtc.h b/dtc.h index d07a583..7231200 100644 --- a/dtc.h +++ b/dtc.h @@ -342,6 +342,7 @@ void sort_tree(struct dt_info *dti); void generate_labels_from_tree(struct dt_info *dti, const 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 fixup_phandles(struct dt_info *dti, const char *name); void generate_local_fixups_tree(struct dt_info *dti, const char *name); void local_fixup_phandles(struct dt_info *dti, const char *name); @@ -359,6 +360,8 @@ struct dt_info *dt_from_blob(const char *fname); /* Tree source */ +void property_add_marker(struct property *prop, + enum markertype type, unsigned int offset, char *ref); void add_phandle_marker(struct dt_info *dti, struct property *prop, unsigned int offset); void dt_to_source(FILE *f, struct dt_info *dti); struct dt_info *dt_from_source(const char *f); diff --git a/livetree.c b/livetree.c index 3dbef90..5d72abc 100644 --- a/livetree.c +++ b/livetree.c @@ -1151,6 +1151,102 @@ void generate_fixups_tree(struct dt_info *dti, const char *name) name); } +void fixup_phandles(struct dt_info *dti, const char *name) +{ + struct node *an; + struct property *fp; + + an = get_subnode(dti->dt, name); + if (!an) + return; + + for_each_property(an, fp) { + char *fnext = fp->val.val; + char *fv; + unsigned int fl; + + while ((fl = fp->val.len - (fnext - fp->val.val))) { + char *propname, *soffset; + struct node *n; + struct property *p; + long offset; + + fv = fnext; + fnext = memchr(fv, 0, fl); + + if (!fnext) { + if (quiet < 1) + fprintf(stderr, "Warning: Malformed fixup entry for label %s\n", + fp->name); + break; + } + fnext += 1; + + propname = memchr(fv, ':', fnext - 1 - fv); + if (!propname) { + if (quiet < 1) + fprintf(stderr, "Warning: Malformed fixup entry for label %s\n", + fp->name); + continue; + } + propname++; + + soffset = memchr(propname, ':', fnext - 1 - propname); + if (!soffset) { + if (quiet < 1) + fprintf(stderr, "Warning: Malformed fixup entry for label %s\n", + fp->name); + continue; + } + soffset++; + + /* + * temporarily modify the property to not have to create + * a copy for the node path. + */ + *(propname - 1) = '\0'; + + n = get_node_by_path(dti->dt, fv); + if (!n && quiet < 1) + fprintf(stderr, "Warning: Label %s references non-existing node %s\n", + fp->name, fv); + + *(propname - 1) = ':'; + + if (!n) + continue; + + /* + * temporarily modify the property to not have to create + * a copy for the property name. + */ + *(soffset - 1) = '\0'; + + p = get_property(n, propname); + + if (!p && quiet < 1) + fprintf(stderr, "Warning: Label %s references non-existing property %s in node %s\n", + fp->name, n->fullpath, propname); + + *(soffset - 1) = ':'; + + if (!p) + continue; + + offset = strtol(soffset, NULL, 0); + if (offset < 0 || offset + 4 > p->val.len) { + if (quiet < 1) + fprintf(stderr, + "Warning: Label %s contains invalid offset for property %s in node %s\n", + fp->name, p->name, n->fullpath); + continue; + } + + property_add_marker(p, REF_PHANDLE, offset, fp->name); + } + } +} + void generate_local_fixups_tree(struct dt_info *dti, const char *name) { if (!any_local_fixup_tree(dti, dti->dt)) diff --git a/treesource.c b/treesource.c index e2eca63..bf648bf 100644 --- a/treesource.c +++ b/treesource.c @@ -173,6 +173,12 @@ static struct marker **add_marker(struct marker **mi, return &nm->next; } +void property_add_marker(struct property *prop, + enum markertype type, unsigned int offset, char *ref) +{ + add_marker(&prop->val.markers, type, offset, ref); +} + static void add_string_markers(struct property *prop, unsigned int offset, int len) { int l;