From c2e7075ca83036317cee4a564729eb82a5433169 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 28 Nov 2018 18:37:35 -0600 Subject: scripts/dtc: Update to upstream version v1.4.7-57-gf267e674d145 This adds the following commits from upstream: f267e674d145 checks: Fix crash with multiple source annotations 3616b9a811b6 checks: Use source position information for check failures 2bdbd07a1223 checks: Make each message output atomic a1eff70c02cf util: Add xa{v}sprintf_append functions 82a52ce4573b libfdt: Add a test for fdt_getprop_by_offset() 607b8586b383 PEP8 / Flake8 cleanups for setup.py f9c0a425b648 Remove broken objdir / srcdir support 5182b5e6f28c pylibfdt: Use common PREFIX variable d45bf1f5f2a6 Refine make tests_clean target 99284c4db9cb Refine pylibfdt_clean target a4629cfaedfb Refine libfdt_clean target 08380fc43aa2 tests: Use modern octal literals for Python 8113c00b99d3 pylibfdt: Allow switch to Python 3 via environment variable PYTHON 11738cf01f15 libfdt: Don't use memcpy to handle unaligned reads on ARM 86a288a73670 checks: Restructure check_msg to decrease indentation 5667e7ef9a9a annotations: add the annotation functionality 8e20ccf52f90 annotations: add positions ca930e20bb54 tests: Don't lose errors from make checkm 43366bb4eeee tests: Property count valgrind errors in wrapped tests 5062516fb8cb srcpos: Remove srcpos_empty a3143fafbf83 Revert "annotations: add positions" 403cc79f06a1 checks: Update SPI bus check for 'spi-slave' baa1d2cf7894 annotations: add positions ff2ad38f6a5a Merge remote-tracking branch 'origin/pr/18' aa7254d9cb17 libfdt: return correct value if #size-cells property is not present 49903aed7783 use ptrdiff_t modifier for printing pointer differences da2b691ccf68 treesource: Fix dts output for phandles in middle of a sequence of ints 8f8b77a0d62d tests: Wrap check_align() calls with base_run_test() 522d81d572f2 Fix dts output with a REF_PATH marker e45198c98359 Added test cases for target references 0fcffda15e9f Merge nodes with local target label references 1e4a0928f3b3 pylibfdt: Don't have setup.py depend on where it's invoked from ca399b14956f pylibfdt: Eliminate run_setup make function 98972f1b3e33 pylibfdt: Improved version extraction 7ba2be6cda5f pylibfdt: Don't silence setup.py when V=1 7691f9d39301 pylibfdt: Make SETUP make variable 855b9963def9 pylibfdt: Simpler CFLAGS handling 47cafbeeb977 pylibfdt: Link extension module with libfdt rather than rebuilding dd695d6afb19 pylibfdt: Correctly set build output directory 59327523d0d8 pylibfdt: We don't need include files from the base directory e84742aa7b93 checks: fix simple-bus compatible matching 8c59a97ce096 Fix missing labels when emitting dts format d448f9a5fd94 Revert dts output formatting changes of spaces around brackets Signed-off-by: Rob Herring --- scripts/dtc/checks.c | 73 ++++++++++++++---- scripts/dtc/dtc-lexer.l | 4 +- scripts/dtc/dtc-parser.y | 52 +++++++++---- scripts/dtc/dtc.c | 11 ++- scripts/dtc/dtc.h | 11 ++- scripts/dtc/flattree.c | 4 +- scripts/dtc/fstree.c | 5 +- scripts/dtc/libfdt/Makefile.libfdt | 4 + scripts/dtc/libfdt/fdt_addresses.c | 16 +++- scripts/dtc/libfdt/libfdt.h | 24 ++++-- scripts/dtc/livetree.c | 33 +++++--- scripts/dtc/srcpos.c | 153 +++++++++++++++++++++++++++++++++---- scripts/dtc/srcpos.h | 14 ++-- scripts/dtc/treesource.c | 115 ++++++++++++++++++---------- scripts/dtc/util.c | 60 ++++++++++----- scripts/dtc/util.h | 2 + scripts/dtc/version_gen.h | 2 +- 17 files changed, 436 insertions(+), 147 deletions(-) (limited to 'scripts/dtc') diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index 9c9b0c328af6..4834e44b37b2 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -19,6 +19,7 @@ */ #include "dtc.h" +#include "srcpos.h" #ifdef TRACE_CHECKS #define TRACE(c, ...) \ @@ -78,23 +79,56 @@ 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); + char *str = NULL; + struct srcpos *pos = NULL; + char *file_str; + + if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2))) + return; + + 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); + } - if ((c->warn && (quiet < 1)) - || (c->error && (quiet < 2))) { - fprintf(stderr, "%s: %s (%s): ", - strcmp(dti->outname, "-") ? dti->outname : "", + xasprintf_append(&str, ": %s (%s): ", (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 (node) { + if (prop) + xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name); + else + xasprintf_append(&str, "%s: ", node->fullpath); } + + va_start(ap, fmt); + xavsprintf_append(&str, fmt, ap); va_end(ap); + + xasprintf_append(&str, "\n"); + + if (!prop && pos) { + pos = node->srcpos; + while (pos->next) { + pos = pos->next; + + file_str = srcpos_string(pos); + xasprintf_append(&str, " also defined at %s\n", file_str); + free(file_str); + } + } + + fputs(str, stderr); } #define FAIL(c, dti, node, ...) \ @@ -910,7 +944,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 +955,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) { @@ -1035,6 +1070,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; @@ -1063,7 +1099,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"); @@ -1082,6 +1120,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; diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l index 615b7ec6588f..06c040902444 100644 --- a/scripts/dtc/dtc-lexer.l +++ b/scripts/dtc/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/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index dd70ebf386f4..2ec981e86111 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/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: @@ -176,9 +180,12 @@ 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 + | devicetree DT_LABEL dt_ref nodedef { struct node *target = get_node_by_ref($1, $3); @@ -189,7 +196,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 +215,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 +246,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); @@ -237,7 +263,7 @@ devicetree: nodedef: '{' proplist subnodes '}' ';' { - $$ = build_node($2, $3); + $$ = build_node($2, $3, &@$); } ; @@ -255,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 ';' { @@ -285,7 +311,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 +409,7 @@ arrayprefix: $$.data = data_append_integer($1.data, $2, $1.bits); } - | arrayprefix DT_REF + | arrayprefix dt_ref { uint64_t val = ~0ULL >> (64 - $1.bits); @@ -540,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/scripts/dtc/dtc.c b/scripts/dtc/dtc.c index 64134aadb997..695e1f789fc7 100644 --- a/scripts/dtc/dtc.c +++ b/scripts/dtc/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/scripts/dtc/dtc.h b/scripts/dtc/dtc.h index cbe541525c2c..789e0b1bc057 100644 --- a/scripts/dtc/dtc.h +++ b/scripts/dtc/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 @@ -158,6 +159,7 @@ struct property { struct property *next; struct label *labels; + struct srcpos *srcpos; }; struct node { @@ -177,6 +179,7 @@ struct node { struct label *labels; const struct bus_type *bus; + struct srcpos *srcpos; bool omit_if_unused, is_referenced; }; @@ -205,13 +208,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/scripts/dtc/flattree.c b/scripts/dtc/flattree.c index 851ea87dbc0f..acf04c30669f 100644 --- a/scripts/dtc/flattree.c +++ b/scripts/dtc/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/scripts/dtc/fstree.c b/scripts/dtc/fstree.c index ae7d06c3c492..1e7eeba47ff6 100644 --- a/scripts/dtc/fstree.c +++ b/scripts/dtc/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/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt index 098b3f36e668..3af3656df801 100644 --- a/scripts/dtc/libfdt/Makefile.libfdt +++ b/scripts/dtc/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_dir)/%) diff --git a/scripts/dtc/libfdt/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c index 49537b578d03..f13a87dfa068 100644 --- a/scripts/dtc/libfdt/fdt_addresses.c +++ b/scripts/dtc/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/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index 2bd151dd355f..627da2e079c9 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/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; - - memcpy(&v, p, sizeof(v)); - return fdt64_to_cpu(v); + 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]; } /**********************************************************************/ @@ -1145,7 +1153,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/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index 4ff0679e0062..7a2e6446a17b 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/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/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c index cb6ed0e3e5e4..41f83700ee91 100644 --- a/scripts/dtc/srcpos.c +++ b/scripts/dtc/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) @@ -197,18 +243,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; @@ -234,13 +268,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) { @@ -266,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) { @@ -294,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/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h index 9ded12a3830a..6326a952c40e 100644 --- a/scripts/dtc/srcpos.h +++ b/scripts/dtc/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,19 +94,18 @@ struct srcpos { YYRHSLOC(Rhs, 0).last_column; \ (Current).file = YYRHSLOC (Rhs, 0).file; \ } \ + (Current).next = NULL; \ } 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 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/scripts/dtc/treesource.c b/scripts/dtc/treesource.c index f2874f1d1465..1af36628b75f 100644 --- a/scripts/dtc/treesource.c +++ b/scripts/dtc/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, "\""); @@ -118,18 +122,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 +168,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] = "", }; @@ -208,13 +214,22 @@ 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; } - fprintf(f, " = "); + fprintf(f, " ="); if (!next_type_marker(m)) { /* data type information missing, need to guess */ @@ -225,32 +240,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); - } - - fprintf(f, "%s", delim_start[emit_type]); + if (has_data_type_information(m)) { + 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 (chunk_len <= 0) + if (emit_type == TYPE_NONE) { + assert(chunk_len == 0); continue; + } switch(emit_type) { case TYPE_UINT16: @@ -268,15 +274,23 @@ 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, ";"); + 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) @@ -284,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); @@ -305,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; diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c index a69b7a13463d..9c6fb5f286ae 100644 --- a/scripts/dtc/util.c +++ b/scripts/dtc/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/scripts/dtc/util.h b/scripts/dtc/util.h index f6cea8274174..7658781a6200 100644 --- a/scripts/dtc/util.h +++ b/scripts/dtc/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); /** diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index 6d23fd095f16..75f383c0b9d3 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.4.7-gc86da84d" +#define DTC_VERSION "DTC 1.4.7-gf267e674" -- cgit v1.2.3-59-g8ed1b From 4f0e3a57d6eb727c54249542c509e0b7aa122465 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 6 Sep 2018 13:26:07 -0500 Subject: kbuild: Add support for DT binding schema checks This adds the build infrastructure for checking DT binding schema documents and validating dts files using the binding schema. Check DT binding schema documents: make dt_binding_check Build dts files and check using DT binding schema: make dtbs_check Optionally, DT_SCHEMA_FILES can be passed in with a schema file(s) to use for validation. This makes it easier to find and fix errors generated by a specific schema. Currently, the validation targets are separate from a normal build to avoid a hard dependency on the external DT schema project and because there are lots of warnings generated. Cc: Jonathan Corbet Cc: Mark Rutland Acked-by: Masahiro Yamada Cc: Michal Marek Cc: linux-doc@vger.kernel.org Cc: devicetree@vger.kernel.org Cc: linux-kbuild@vger.kernel.org Signed-off-by: Rob Herring --- .gitignore | 1 + Documentation/Makefile | 2 +- Documentation/devicetree/bindings/.gitignore | 2 ++ Documentation/devicetree/bindings/Makefile | 27 +++++++++++++++++++++++++++ Makefile | 13 ++++++++++--- scripts/Makefile.lib | 24 ++++++++++++++++++++++-- scripts/dtc/Makefile | 4 ++++ 7 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 Documentation/devicetree/bindings/.gitignore create mode 100644 Documentation/devicetree/bindings/Makefile (limited to 'scripts/dtc') diff --git a/.gitignore b/.gitignore index 97ba6b79834c..a20ac26aa2f5 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ *.bin *.bz2 *.c.[012]*.* +*.dt.yaml *.dtb *.dtb.S *.dwo diff --git a/Documentation/Makefile b/Documentation/Makefile index 2ca77ad0f238..9786957c6a35 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -2,7 +2,7 @@ # Makefile for Sphinx documentation # -subdir-y := +subdir-y := devicetree/bindings/ # You can set these variables from the command line. SPHINXBUILD = sphinx-build diff --git a/Documentation/devicetree/bindings/.gitignore b/Documentation/devicetree/bindings/.gitignore new file mode 100644 index 000000000000..ef82fcfcccab --- /dev/null +++ b/Documentation/devicetree/bindings/.gitignore @@ -0,0 +1,2 @@ +*.example.dts +processed-schema.yaml diff --git a/Documentation/devicetree/bindings/Makefile b/Documentation/devicetree/bindings/Makefile new file mode 100644 index 000000000000..6e5cef0ed6fb --- /dev/null +++ b/Documentation/devicetree/bindings/Makefile @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +DT_DOC_CHECKER ?= dt-doc-validate +DT_EXTRACT_EX ?= dt-extract-example +DT_MK_SCHEMA ?= dt-mk-schema +DT_MK_SCHEMA_FLAGS := $(if $(DT_SCHEMA_FILES), -u) + +quiet_cmd_chk_binding = CHKDT $(patsubst $(srctree)/%,%,$<) + cmd_chk_binding = $(DT_DOC_CHECKER) $< ; \ + $(DT_EXTRACT_EX) $< > $@ + +$(obj)/%.example.dts: $(src)/%.yaml FORCE + $(call if_changed,chk_binding) + +DT_TMP_SCHEMA := processed-schema.yaml +extra-y += $(DT_TMP_SCHEMA) + +quiet_cmd_mk_schema = SCHEMA $@ + cmd_mk_schema = $(DT_MK_SCHEMA) $(DT_MK_SCHEMA_FLAGS) -o $@ $(filter-out FORCE, $^) + +DT_DOCS = $(shell cd $(srctree)/$(src) && find * -name '*.yaml') +DT_SCHEMA_FILES ?= $(addprefix $(src)/,$(DT_DOCS)) + +extra-y += $(patsubst $(src)/%.yaml,%.example.dts, $(DT_SCHEMA_FILES)) +extra-y += $(patsubst $(src)/%.yaml,%.example.dtb, $(DT_SCHEMA_FILES)) + +$(obj)/$(DT_TMP_SCHEMA): $(DT_SCHEMA_FILES) FORCE + $(call if_changed,mk_schema) diff --git a/Makefile b/Makefile index 2f36db897895..a3e2db2a3119 100644 --- a/Makefile +++ b/Makefile @@ -1232,10 +1232,13 @@ ifneq ($(dtstree),) %.dtb: prepare3 scripts_dtc $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@ -PHONY += dtbs dtbs_install -dtbs: prepare3 scripts_dtc +PHONY += dtbs dtbs_install dt_binding_check +dtbs dtbs_check: prepare3 scripts_dtc $(Q)$(MAKE) $(build)=$(dtstree) +dtbs_check: export CHECK_DTBS=1 +dtbs_check: dt_binding_check + dtbs_install: $(Q)$(MAKE) $(dtbinst)=$(dtstree) @@ -1249,6 +1252,9 @@ PHONY += scripts_dtc scripts_dtc: scripts_basic $(Q)$(MAKE) $(build)=scripts/dtc +dt_binding_check: scripts_dtc + $(Q)$(MAKE) $(build)=Documentation/devicetree/bindings + # --------------------------------------------------------------------------- # Modules @@ -1611,7 +1617,8 @@ clean: $(clean-dirs) $(call cmd,rmfiles) @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ \( -name '*.[aios]' -o -name '*.ko' -o -name '.*.cmd' \ - -o -name '*.ko.*' -o -name '*.dtb' -o -name '*.dtb.S' \ + -o -name '*.ko.*' \ + -o -name '*.dtb' -o -name '*.dtb.S' -o -name '*.dt.yaml' \ -o -name '*.dwo' -o -name '*.lst' \ -o -name '*.su' \ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 8fe4468f9bda..723b33c942df 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -61,6 +61,11 @@ real-obj-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) extra-y += $(dtb-y) extra-$(CONFIG_OF_ALL_DTBS) += $(dtb-) +ifneq ($(CHECK_DTBS),) +extra-y += $(patsubst %.dtb,%.dt.yaml, $(dtb-y)) +extra-$(CONFIG_OF_ALL_DTBS) += $(patsubst %.dtb,%.dt.yaml, $(dtb-)) +endif + # Add subdir path extra-y := $(addprefix $(obj)/,$(extra-y)) @@ -284,13 +289,28 @@ $(obj)/%.dtb.S: $(obj)/%.dtb FORCE quiet_cmd_dtc = DTC $@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \ $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ - $(DTC) -O dtb -o $@ -b 0 \ + $(DTC) -O $(2) -o $@ -b 0 \ $(addprefix -i,$(dir $<) $(DTC_INCLUDE)) $(DTC_FLAGS) \ -d $(depfile).dtc.tmp $(dtc-tmp) ; \ cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) $(obj)/%.dtb: $(src)/%.dts $(DTC) FORCE - $(call if_changed_dep,dtc) + $(call if_changed_dep,dtc,dtb) + +DT_CHECKER ?= dt-validate +DT_BINDING_DIR := Documentation/devicetree/bindings +DT_TMP_SCHEMA := $(objtree)/$(DT_BINDING_DIR)/processed-schema.yaml + +quiet_cmd_dtb_check = CHECK $@ + cmd_dtb_check = $(DT_CHECKER) -p $(DT_TMP_SCHEMA) $@ ; + +define rule_dtc_dt_yaml + $(call cmd_and_fixdep,dtc,yaml) \ + $(call echo-cmd,dtb_check) $(cmd_dtb_check) +endef + +$(obj)/%.dt.yaml: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE + $(call if_changed_rule,dtc_dt_yaml) dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile index 056d5da6c477..5f227d8d39d8 100644 --- a/scripts/dtc/Makefile +++ b/scripts/dtc/Makefile @@ -12,6 +12,10 @@ dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o HOST_EXTRACFLAGS := -I$(src)/libfdt ifeq ($(wildcard /usr/include/yaml.h),) +ifneq ($(CHECK_DTBS),) +$(error dtc needs libyaml for DT schema validation support. \ + Install the necessary libyaml development package.) +endif HOST_EXTRACFLAGS += -DNO_YAML else dtc-objs += yamltree.o -- cgit v1.2.3-59-g8ed1b