summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Herring <robh@kernel.org>2017-03-21 09:01:08 -0500
committerRob Herring <robh@kernel.org>2017-03-22 14:56:14 -0500
commit89d123106a97bf412a4c10482044c822f4b069f7 (patch)
tree35603f528aedddff67a643b957f2803601a03f95
parent86cef6144d273404d8cb5c0b215ada8d23e5dbeb (diff)
scripts/dtc: Update to upstream version v1.4.4-8-g756ffc4f52f6
This adds the following commits from upstream: 756ffc4f52f6 Build pylibfdt as part of the normal build process 8cb3896358e9 Adjust libfdt.h to work with swig b40aa8359aff Mention pylibfdt in the documentation 12cfb740cc76 Add tests for pylibfdt 50f250701631 Add an initial Python library for libfdt cdbb2b6c7a3a checks: Warn on node name unit-addresses with '0x' or leading 0s 4c15d5da17cc checks: Add bus checks for simple-bus buses 33c3985226d3 checks: Add bus checks for PCI buses 558cd81bdd43 dtc: Bump version to v1.4.4 c17a811c62eb fdtput: Remove star from value_len documentation 194d5caaefcb fdtget: Use @return to document the return value d922ecdd017b tests: Make realloc_fdt() really allocate *fdt 921cc17fec29 libfdt: overlay: Check the value of the right variable 9ffdf60bf463 dtc: Simplify asm_emit_string() implementation 881012e44386 libfdt: Change names of sparse helper macros bad5b28049e5 Fix assorted sparse warnings 672ac09ea04d Clean up gcc attributes 49300f2ade6a dtc: Don't abuse struct fdt_reserve_entry fa8bc7f928ac dtc: Bump version to v1.4.3 34a9886a177f Add printf format attributes f72508e2b6ca Correct some broken printf() like format mismatches 397d5ef0203c libfdt: Add fdt_setprop_empty() 69a1bd6ad3f9 libfdt: Remove undefined behaviour setting empty properties acd1b534a592 Print output filename as part of warning messages 120775eb1cf3 dtc: Use streq() in preference to strcmp() 852e9ecbe197 checks: Add Warning for stricter node name character checking ef0e8f061534 checks: Add Warning for stricter property name character checking 00d7bb1f4b0e dtc: pos parameter to srcpos_string() can't be NULL 95d57726bca4 livetree.c: Fix memory leak 3b9c97093d6e dtc: Fix NULL pointer use in dtlabel + dtref case 43eb551426ea manual: Fix typo it -> in 4baf15f7f13f Makefile: Add tags rule Signed-off-by: Rob Herring <robh@kernel.org>
-rw-r--r--scripts/dtc/checks.c361
-rw-r--r--scripts/dtc/data.c16
-rw-r--r--scripts/dtc/dtc-lexer.l3
-rw-r--r--scripts/dtc/dtc-lexer.lex.c_shipped77
-rw-r--r--scripts/dtc/dtc-parser.tab.c_shipped6
-rw-r--r--scripts/dtc/dtc-parser.y6
-rw-r--r--scripts/dtc/dtc.c9
-rw-r--r--scripts/dtc/dtc.h11
-rw-r--r--scripts/dtc/flattree.c58
-rw-r--r--scripts/dtc/libfdt/fdt_rw.c3
-rw-r--r--scripts/dtc/libfdt/libfdt.h51
-rw-r--r--scripts/dtc/libfdt/libfdt_env.h26
-rw-r--r--scripts/dtc/livetree.c22
-rw-r--r--scripts/dtc/srcpos.c2
-rw-r--r--scripts/dtc/srcpos.h11
-rw-r--r--scripts/dtc/treesource.c6
-rw-r--r--scripts/dtc/util.c11
-rw-r--r--scripts/dtc/util.h24
-rw-r--r--scripts/dtc/version_gen.h2
19 files changed, 523 insertions, 182 deletions
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
index 3d18e45374c8..5adfc8f52b4f 100644
--- a/scripts/dtc/checks.c
+++ b/scripts/dtc/checks.c
@@ -72,17 +72,16 @@ struct check {
#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)));
-#endif
-static inline void check_msg(struct check *c, const char *fmt, ...)
+static inline void PRINTF(3, 4) 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): ",
+ fprintf(stderr, "%s: %s (%s): ",
+ strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
(c->error) ? "ERROR" : "Warning", c->name);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
@@ -90,11 +89,11 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
va_end(ap);
}
-#define FAIL(c, ...) \
- do { \
- TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
- (c)->status = FAILED; \
- check_msg((c), __VA_ARGS__); \
+#define FAIL(c, dti, ...) \
+ do { \
+ TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
+ (c)->status = FAILED; \
+ check_msg((c), dti, __VA_ARGS__); \
} while (0)
static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node)
@@ -127,7 +126,7 @@ static bool run_check(struct check *c, struct dt_info *dti)
error = error || run_check(prq, dti);
if (prq->status != PASSED) {
c->status = PREREQ;
- check_msg(c, "Failed prerequisite '%s'",
+ check_msg(c, dti, "Failed prerequisite '%s'",
c->prereq[i]->name);
}
}
@@ -157,7 +156,7 @@ out:
static inline void check_always_fail(struct check *c, struct dt_info *dti,
struct node *node)
{
- FAIL(c, "always_fail check");
+ FAIL(c, dti, "always_fail check");
}
CHECK(always_fail, check_always_fail, NULL);
@@ -172,7 +171,7 @@ static void check_is_string(struct check *c, struct dt_info *dti,
return; /* Not present, assumed ok */
if (!data_is_one_string(prop->val))
- FAIL(c, "\"%s\" property in %s is not a string",
+ FAIL(c, dti, "\"%s\" property in %s is not a string",
propname, node->fullpath);
}
#define WARNING_IF_NOT_STRING(nm, propname) \
@@ -191,7 +190,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti,
return; /* Not present, assumed ok */
if (prop->val.len != sizeof(cell_t))
- FAIL(c, "\"%s\" property in %s is not a single cell",
+ FAIL(c, dti, "\"%s\" property in %s is not a single cell",
propname, node->fullpath);
}
#define WARNING_IF_NOT_CELL(nm, propname) \
@@ -213,7 +212,7 @@ static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
child2;
child2 = child2->next_sibling)
if (streq(child->name, child2->name))
- FAIL(c, "Duplicate node name %s",
+ FAIL(c, dti, "Duplicate node name %s",
child->fullpath);
}
ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
@@ -228,7 +227,7 @@ static void check_duplicate_property_names(struct check *c, struct dt_info *dti,
if (prop2->deleted)
continue;
if (streq(prop->name, prop2->name))
- FAIL(c, "Duplicate property name %s in %s",
+ FAIL(c, dti, "Duplicate property name %s in %s",
prop->name, node->fullpath);
}
}
@@ -239,6 +238,7 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define DIGITS "0123456789"
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
+#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
static void check_node_name_chars(struct check *c, struct dt_info *dti,
struct node *node)
@@ -246,16 +246,27 @@ static void check_node_name_chars(struct check *c, struct dt_info *dti,
int n = strspn(node->name, c->data);
if (n < strlen(node->name))
- FAIL(c, "Bad character '%c' in node %s",
+ FAIL(c, dti, "Bad character '%c' in node %s",
node->name[n], node->fullpath);
}
ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
+static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ int n = strspn(node->name, c->data);
+
+ if (n < node->basenamelen)
+ FAIL(c, dti, "Character '%c' not recommended in node %s",
+ node->name[n], node->fullpath);
+}
+CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT);
+
static void check_node_name_format(struct check *c, struct dt_info *dti,
struct node *node)
{
if (strchr(get_unitname(node), '@'))
- FAIL(c, "Node %s has multiple '@' characters in name",
+ FAIL(c, dti, "Node %s has multiple '@' characters in name",
node->fullpath);
}
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
@@ -274,11 +285,11 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
if (prop) {
if (!unitname[0])
- FAIL(c, "Node %s has a reg or ranges property, but no unit name",
+ FAIL(c, dti, "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",
+ FAIL(c, dti, "Node %s has a unit name, but no reg property",
node->fullpath);
}
}
@@ -293,12 +304,44 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
int n = strspn(prop->name, c->data);
if (n < strlen(prop->name))
- FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
+ FAIL(c, dti, "Bad character '%c' in property name \"%s\", node %s",
prop->name[n], prop->name, node->fullpath);
}
}
ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
+static void check_property_name_chars_strict(struct check *c,
+ struct dt_info *dti,
+ struct node *node)
+{
+ struct property *prop;
+
+ for_each_property(node, prop) {
+ const char *name = prop->name;
+ int n = strspn(name, c->data);
+
+ if (n == strlen(prop->name))
+ continue;
+
+ /* Certain names are whitelisted */
+ if (streq(name, "device_type"))
+ continue;
+
+ /*
+ * # is only allowed at the beginning of property names not counting
+ * the vendor prefix.
+ */
+ if (name[n] == '#' && ((n == 0) || (name[n-1] == ','))) {
+ name += n + 1;
+ n = strspn(name, c->data);
+ }
+ if (n < strlen(name))
+ FAIL(c, dti, "Character '%c' not recommended in property name \"%s\", node %s",
+ name[n], prop->name, node->fullpath);
+ }
+}
+CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT);
+
#define DESCLABEL_FMT "%s%s%s%s%s"
#define DESCLABEL_ARGS(node,prop,mark) \
((mark) ? "value of " : ""), \
@@ -327,7 +370,7 @@ static void check_duplicate_label(struct check *c, struct dt_info *dti,
return;
if ((othernode != node) || (otherprop != prop) || (othermark != mark))
- FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT
+ FAIL(c, dti, "Duplicate label '%s' on " DESCLABEL_FMT
" and " DESCLABEL_FMT,
label, DESCLABEL_ARGS(node, prop, mark),
DESCLABEL_ARGS(othernode, otherprop, othermark));
@@ -367,7 +410,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
return 0;
if (prop->val.len != sizeof(cell_t)) {
- FAIL(c, "%s has bad length (%d) %s property",
+ FAIL(c, dti, "%s has bad length (%d) %s property",
node->fullpath, prop->val.len, prop->name);
return 0;
}
@@ -379,7 +422,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
/* "Set this node's phandle equal to some
* other node's phandle". That's nonsensical
* by construction. */ {
- FAIL(c, "%s in %s is a reference to another node",
+ FAIL(c, dti, "%s in %s is a reference to another node",
prop->name, node->fullpath);
}
/* But setting this node's phandle equal to its own
@@ -393,7 +436,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop);
if ((phandle == 0) || (phandle == -1)) {
- FAIL(c, "%s has bad value (0x%x) in %s property",
+ FAIL(c, dti, "%s has bad value (0x%x) in %s property",
node->fullpath, phandle, prop->name);
return 0;
}
@@ -420,7 +463,7 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,
return;
if (linux_phandle && phandle && (phandle != linux_phandle))
- FAIL(c, "%s has mismatching 'phandle' and 'linux,phandle'"
+ FAIL(c, dti, "%s has mismatching 'phandle' and 'linux,phandle'"
" properties", node->fullpath);
if (linux_phandle && !phandle)
@@ -428,7 +471,7 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,
other = get_node_by_phandle(root, phandle);
if (other && (other != node)) {
- FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
+ FAIL(c, dti, "%s has duplicated phandle 0x%x (seen before at %s)",
node->fullpath, phandle, other->fullpath);
return;
}
@@ -453,7 +496,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
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"
+ FAIL(c, dti, "\"name\" property in %s is incorrect (\"%s\" instead"
" of base node name)", node->fullpath, prop->val.val);
} else {
/* The name property is correct, and therefore redundant.
@@ -488,16 +531,16 @@ static void fixup_phandle_references(struct check *c, struct dt_info *dti,
refnode = get_node_by_ref(dt, m->ref);
if (! refnode) {
if (!(dti->dtsflags & DTSF_PLUGIN))
- FAIL(c, "Reference to non-existent node or "
+ FAIL(c, dti, "Reference to non-existent node or "
"label \"%s\"\n", m->ref);
else /* mark the entry as unresolved */
- *((cell_t *)(prop->val.val + m->offset)) =
+ *((fdt32_t *)(prop->val.val + m->offset)) =
cpu_to_fdt32(0xffffffff);
continue;
}
phandle = get_node_phandle(dt, refnode);
- *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
+ *((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
}
}
}
@@ -520,7 +563,7 @@ static void fixup_path_references(struct check *c, struct dt_info *dti,
refnode = get_node_by_ref(dt, m->ref);
if (!refnode) {
- FAIL(c, "Reference to non-existent node or label \"%s\"\n",
+ FAIL(c, dti, "Reference to non-existent node or label \"%s\"\n",
m->ref);
continue;
}
@@ -579,19 +622,19 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
return; /* No "reg", that's fine */
if (!node->parent) {
- FAIL(c, "Root node has a \"reg\" property");
+ FAIL(c, dti, "Root node has a \"reg\" property");
return;
}
if (prop->val.len == 0)
- FAIL(c, "\"reg\" property in %s is empty", node->fullpath);
+ FAIL(c, dti, "\"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 (!entrylen || (prop->val.len % entrylen) != 0)
- FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
+ FAIL(c, dti, "\"reg\" property in %s has invalid length (%d bytes) "
"(#address-cells == %d, #size-cells == %d)",
node->fullpath, prop->val.len, addr_cells, size_cells);
}
@@ -608,7 +651,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
return;
if (!node->parent) {
- FAIL(c, "Root node has a \"ranges\" property");
+ FAIL(c, dti, "Root node has a \"ranges\" property");
return;
}
@@ -620,17 +663,17 @@ 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(c, "%s has empty \"ranges\" property but its "
+ FAIL(c, dti, "%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 "
+ FAIL(c, dti, "%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) "
+ FAIL(c, dti, "\"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);
@@ -638,6 +681,229 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
}
WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
+static const struct bus_type pci_bus = {
+ .name = "PCI",
+};
+
+static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *node)
+{
+ struct property *prop;
+ cell_t *cells;
+
+ prop = get_property(node, "device_type");
+ if (!prop || !streq(prop->val.val, "pci"))
+ return;
+
+ node->bus = &pci_bus;
+
+ if (!strneq(node->name, "pci", node->basenamelen) &&
+ !strneq(node->name, "pcie", node->basenamelen))
+ FAIL(c, dti, "Node %s node name is not \"pci\" or \"pcie\"",
+ node->fullpath);
+
+ prop = get_property(node, "ranges");
+ if (!prop)
+ FAIL(c, dti, "Node %s missing ranges for PCI bridge (or not a bridge)",
+ node->fullpath);
+
+ if (node_addr_cells(node) != 3)
+ FAIL(c, dti, "Node %s incorrect #address-cells for PCI bridge",
+ node->fullpath);
+ if (node_size_cells(node) != 2)
+ FAIL(c, dti, "Node %s incorrect #size-cells for PCI bridge",
+ node->fullpath);
+
+ prop = get_property(node, "bus-range");
+ if (!prop) {
+ FAIL(c, dti, "Node %s missing bus-range for PCI bridge",
+ node->fullpath);
+ return;
+ }
+ if (prop->val.len != (sizeof(cell_t) * 2)) {
+ FAIL(c, dti, "Node %s bus-range must be 2 cells",
+ node->fullpath);
+ return;
+ }
+ cells = (cell_t *)prop->val.val;
+ if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1]))
+ FAIL(c, dti, "Node %s bus-range 1st cell must be less than or equal to 2nd cell",
+ node->fullpath);
+ if (fdt32_to_cpu(cells[1]) > 0xff)
+ FAIL(c, dti, "Node %s bus-range maximum bus number must be less than 256",
+ node->fullpath);
+}
+WARNING(pci_bridge, check_pci_bridge, NULL,
+ &device_type_is_string, &addr_size_cells);
+
+static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struct node *node)
+{
+ struct property *prop;
+ unsigned int bus_num, min_bus, max_bus;
+ cell_t *cells;
+
+ if (!node->parent || (node->parent->bus != &pci_bus))
+ return;
+
+ prop = get_property(node, "reg");
+ if (!prop)
+ return;
+
+ cells = (cell_t *)prop->val.val;
+ bus_num = (fdt32_to_cpu(cells[0]) & 0x00ff0000) >> 16;
+
+ prop = get_property(node->parent, "bus-range");
+ if (!prop) {
+ min_bus = max_bus = 0;
+ } else {
+ cells = (cell_t *)prop->val.val;
+ min_bus = fdt32_to_cpu(cells[0]);
+ max_bus = fdt32_to_cpu(cells[0]);
+ }
+ if ((bus_num < min_bus) || (bus_num > max_bus))
+ FAIL(c, dti, "Node %s PCI bus number %d out of range, expected (%d - %d)",
+ node->fullpath, bus_num, min_bus, max_bus);
+}
+WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, &reg_format, &pci_bridge);
+
+static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct node *node)
+{
+ struct property *prop;
+ const char *unitname = get_unitname(node);
+ char unit_addr[5];
+ unsigned int dev, func, reg;
+ cell_t *cells;
+
+ if (!node->parent || (node->parent->bus != &pci_bus))
+ return;
+
+ prop = get_property(node, "reg");
+ if (!prop) {
+ FAIL(c, dti, "Node %s missing PCI reg property", node->fullpath);
+ return;
+ }
+
+ cells = (cell_t *)prop->val.val;
+ if (cells[1] || cells[2])
+ FAIL(c, dti, "Node %s PCI reg config space address cells 2 and 3 must be 0",
+ node->fullpath);
+
+ reg = fdt32_to_cpu(cells[0]);
+ dev = (reg & 0xf800) >> 11;
+ func = (reg & 0x700) >> 8;
+
+ if (reg & 0xff000000)
+ FAIL(c, dti, "Node %s PCI reg address is not configuration space",
+ node->fullpath);
+ if (reg & 0x000000ff)
+ FAIL(c, dti, "Node %s PCI reg config space address register number must be 0",
+ node->fullpath);
+
+ if (func == 0) {
+ snprintf(unit_addr, sizeof(unit_addr), "%x", dev);
+ if (streq(unitname, unit_addr))
+ return;
+ }
+
+ snprintf(unit_addr, sizeof(unit_addr), "%x,%x", dev, func);
+ if (streq(unitname, unit_addr))
+ return;
+
+ FAIL(c, dti, "Node %s PCI unit address format error, expected \"%s\"",
+ node->fullpath, unit_addr);
+}
+WARNING(pci_device_reg, check_pci_device_reg, NULL, &reg_format, &pci_bridge);
+
+static const struct bus_type simple_bus = {
+ .name = "simple-bus",
+};
+
+static bool node_is_compatible(struct node *node, const char *compat)
+{
+ struct property *prop;
+ const char *str, *end;
+
+ prop = get_property(node, "compatible");
+ if (!prop)
+ return false;
+
+ for (str = prop->val.val, end = str + prop->val.len; str < end;
+ str += strnlen(str, end - str) + 1) {
+ if (strneq(str, compat, end - str))
+ return true;
+ }
+ return false;
+}
+
+static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
+{
+ if (node_is_compatible(node, "simple-bus"))
+ node->bus = &simple_bus;
+}
+WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells);
+
+static void check_simple_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];
+ unsigned int size;
+ uint64_t reg = 0;
+ cell_t *cells = NULL;
+
+ if (!node->parent || (node->parent->bus != &simple_bus))
+ return;
+
+ prop = get_property(node, "reg");
+ if (prop)
+ cells = (cell_t *)prop->val.val;
+ else {
+ prop = get_property(node, "ranges");
+ if (prop && prop->val.len)
+ /* skip of child address */
+ cells = ((cell_t *)prop->val.val) + node_addr_cells(node);
+ }
+
+ if (!cells) {
+ if (node->parent->parent && !(node->bus == &simple_bus))
+ FAIL(c, dti, "Node %s missing or empty reg/ranges property", node->fullpath);
+ return;
+ }
+
+ size = node_addr_cells(node->parent);
+ while (size--)
+ reg = (reg << 32) | fdt32_to_cpu(*(cells++));
+
+ snprintf(unit_addr, sizeof(unit_addr), "%lx", reg);
+ if (!streq(unitname, unit_addr))
+ FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"",
+ node->fullpath, unit_addr);
+}
+WARNING(simple_bus_reg, check_simple_bus_reg, NULL, &reg_format, &simple_bus_bridge);
+
+static void check_unit_address_format(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ const char *unitname = get_unitname(node);
+
+ if (node->parent && node->parent->bus)
+ return;
+
+ if (!unitname[0])
+ return;
+
+ if (!strncmp(unitname, "0x", 2)) {
+ FAIL(c, dti, "Node %s unit name should not have leading \"0x\"",
+ node->fullpath);
+ /* skip over 0x for next test */
+ unitname += 2;
+ }
+ if (unitname[0] == '0' && isxdigit(unitname[1]))
+ FAIL(c, dti, "Node %s unit name should not have leading 0s",
+ node->fullpath);
+}
+WARNING(unit_address_format, check_unit_address_format, NULL,
+ &node_name_format, &pci_bridge, &simple_bus_bridge);
+
/*
* Style checks
*/
@@ -656,11 +922,11 @@ static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti,
return;
if (node->parent->addr_cells == -1)
- FAIL(c, "Relying on default #address-cells value for %s",
+ FAIL(c, dti, "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",
+ FAIL(c, dti, "Relying on default #size-cells value for %s",
node->fullpath);
}
WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
@@ -684,7 +950,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
prop = get_property(chosen, "interrupt-controller");
if (prop)
- FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
+ FAIL(c, dti, "/chosen has obsolete \"interrupt-controller\" "
"property");
}
WARNING(obsolete_chosen_interrupt_controller,
@@ -703,9 +969,20 @@ 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,
+ &property_name_chars_strict,
+ &node_name_chars_strict,
+
&addr_size_cells, &reg_format, &ranges_format,
&unit_address_vs_reg,
+ &unit_address_format,
+
+ &pci_bridge,
+ &pci_device_reg,
+ &pci_device_bus_num,
+
+ &simple_bus_bridge,
+ &simple_bus_reg,
&avoid_default_addr_size,
&obsolete_chosen_interrupt_controller,
diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
index 8cae23746882..aa37a16c8891 100644
--- a/scripts/dtc/data.c
+++ b/scripts/dtc/data.c
@@ -171,9 +171,9 @@ struct data data_merge(struct data d1, struct data d2)
struct data data_append_integer(struct data d, uint64_t value, int bits)
{
uint8_t value_8;
- uint16_t value_16;
- uint32_t value_32;
- uint64_t value_64;
+ fdt16_t value_16;
+ fdt32_t value_32;
+ fdt64_t value_64;
switch (bits) {
case 8:
@@ -197,14 +197,14 @@ struct data data_append_integer(struct data d, uint64_t value, int bits)
}
}
-struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
+struct data data_append_re(struct data d, uint64_t address, uint64_t size)
{
- struct fdt_reserve_entry bere;
+ struct fdt_reserve_entry re;
- bere.address = cpu_to_fdt64(re->address);
- bere.size = cpu_to_fdt64(re->size);
+ re.address = cpu_to_fdt64(address);
+ re.size = cpu_to_fdt64(size);
- return data_append_data(d, &bere, sizeof(bere));
+ return data_append_data(d, &re, sizeof(re));
}
struct data data_append_cell(struct data d, cell_t word)
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
index c600603044f3..fd825ebba69c 100644
--- a/scripts/dtc/dtc-lexer.l
+++ b/scripts/dtc/dtc-lexer.l
@@ -62,7 +62,8 @@ 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, ...);
+static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
+
%}
%%
diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
index 2c862bc86ad0..64c243772398 100644
--- a/scripts/dtc/dtc-lexer.lex.c_shipped
+++ b/scripts/dtc/dtc-lexer.lex.c_shipped
@@ -655,8 +655,9 @@ 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, ...);
-#line 660 "dtc-lexer.lex.c"
+static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
+
+#line 661 "dtc-lexer.lex.c"
#define INITIAL 0
#define BYTESTRING 1
@@ -878,9 +879,9 @@ YY_DECL
}
{
-#line 68 "dtc-lexer.l"
+#line 69 "dtc-lexer.l"
-#line 884 "dtc-lexer.lex.c"
+#line 885 "dtc-lexer.lex.c"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
@@ -937,7 +938,7 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
/* rule 1 can match eol */
YY_RULE_SETUP
-#line 69 "dtc-lexer.l"
+#line 70 "dtc-lexer.l"
{
char *name = strchr(yytext, '\"') + 1;
yytext[yyleng-1] = '\0';
@@ -947,7 +948,7 @@ YY_RULE_SETUP
case 2:
/* rule 2 can match eol */
YY_RULE_SETUP
-#line 75 "dtc-lexer.l"
+#line 76 "dtc-lexer.l"
{
char *line, *fnstart, *fnend;
struct data fn;
@@ -981,7 +982,7 @@ case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(BYTESTRING):
case YY_STATE_EOF(PROPNODENAME):
case YY_STATE_EOF(V1):
-#line 104 "dtc-lexer.l"
+#line 105 "dtc-lexer.l"
{
if (!pop_input_file()) {
yyterminate();
@@ -991,7 +992,7 @@ case YY_STATE_EOF(V1):
case 3:
/* rule 3 can match eol */
YY_RULE_SETUP
-#line 110 "dtc-lexer.l"
+#line 111 "dtc-lexer.l"
{
DPRINT("String: %s\n", yytext);
yylval.data = data_copy_escape_string(yytext+1,
@@ -1001,7 +1002,7 @@ YY_RULE_SETUP
YY_BREAK
case 4:
YY_RULE_SETUP
-#line 117 "dtc-lexer.l"
+#line 118 "dtc-lexer.l"
{
DPRINT("Keyword: /dts-v1/\n");
dts_version = 1;
@@ -1011,7 +1012,7 @@ YY_RULE_SETUP
YY_BREAK
case 5:
YY_RULE_SETUP
-#line 124 "dtc-lexer.l"
+#line 125 "dtc-lexer.l"
{
DPRINT("Keyword: /plugin/\n");
return DT_PLUGIN;
@@ -1019,7 +1020,7 @@ YY_RULE_SETUP
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 129 "dtc-lexer.l"
+#line 130 "dtc-lexer.l"
{
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
@@ -1028,7 +1029,7 @@ YY_RULE_SETUP
YY_BREAK
case 7:
YY_RULE_SETUP
-#line 135 "dtc-lexer.l"
+#line 136 "dtc-lexer.l"
{
DPRINT("Keyword: /bits/\n");
BEGIN_DEFAULT();
@@ -1037,7 +1038,7 @@ YY_RULE_SETUP
YY_BREAK
case 8:
YY_RULE_SETUP
-#line 141 "dtc-lexer.l"
+#line 142 "dtc-lexer.l"
{
DPRINT("Keyword: /delete-property/\n");
DPRINT("<PROPNODENAME>\n");
@@ -1047,7 +1048,7 @@ YY_RULE_SETUP
YY_BREAK
case 9:
YY_RULE_SETUP
-#line 148 "dtc-lexer.l"
+#line 149 "dtc-lexer.l"
{
DPRINT("Keyword: /delete-node/\n");
DPRINT("<PROPNODENAME>\n");
@@ -1057,7 +1058,7 @@ YY_RULE_SETUP
YY_BREAK
case 10:
YY_RULE_SETUP
-#line 155 "dtc-lexer.l"
+#line 156 "dtc-lexer.l"
{
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
@@ -1067,7 +1068,7 @@ YY_RULE_SETUP
YY_BREAK
case 11:
YY_RULE_SETUP
-#line 162 "dtc-lexer.l"
+#line 163 "dtc-lexer.l"
{
char *e;
DPRINT("Integer Literal: '%s'\n", yytext);
@@ -1093,7 +1094,7 @@ YY_RULE_SETUP
case 12:
/* rule 12 can match eol */
YY_RULE_SETUP
-#line 184 "dtc-lexer.l"
+#line 185 "dtc-lexer.l"
{
struct data d;
DPRINT("Character literal: %s\n", yytext);
@@ -1117,7 +1118,7 @@ YY_RULE_SETUP
YY_BREAK
case 13:
YY_RULE_SETUP
-#line 205 "dtc-lexer.l"
+#line 206 "dtc-lexer.l"
{ /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
@@ -1126,7 +1127,7 @@ YY_RULE_SETUP
YY_BREAK
case 14:
YY_RULE_SETUP
-#line 211 "dtc-lexer.l"
+#line 212 "dtc-lexer.l"
{ /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
@@ -1136,7 +1137,7 @@ YY_RULE_SETUP
YY_BREAK
case 15:
YY_RULE_SETUP
-#line 218 "dtc-lexer.l"
+#line 219 "dtc-lexer.l"
{
yylval.byte = strtol(yytext, NULL, 16);
DPRINT("Byte: %02x\n", (int)yylval.byte);
@@ -1145,7 +1146,7 @@ YY_RULE_SETUP
YY_BREAK
case 16:
YY_RULE_SETUP
-#line 224 "dtc-lexer.l"
+#line 225 "dtc-lexer.l"
{
DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT();
@@ -1154,7 +1155,7 @@ YY_RULE_SETUP
YY_BREAK
case 17:
YY_RULE_SETUP
-#line 230 "dtc-lexer.l"
+#line 231 "dtc-lexer.l"
{
DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = xstrdup((yytext[0] == '\\') ?
@@ -1165,7 +1166,7 @@ YY_RULE_SETUP
YY_BREAK
case 18:
YY_RULE_SETUP
-#line 238 "dtc-lexer.l"
+#line 239 "dtc-lexer.l"
{
DPRINT("Binary Include\n");
return DT_INCBIN;
@@ -1174,64 +1175,64 @@ YY_RULE_SETUP
case 19:
/* rule 19 can match eol */
YY_RULE_SETUP
-#line 243 "dtc-lexer.l"
+#line 244 "dtc-lexer.l"
/* eat whitespace */
YY_BREAK
case 20:
/* rule 20 can match eol */
YY_RULE_SETUP
-#line 244 "dtc-lexer.l"
+#line 245 "dtc-lexer.l"
/* eat C-style comments */
YY_BREAK
case 21:
/* rule 21 can match eol */
YY_RULE_SETUP
-#line 245 "dtc-lexer.l"
+#line 246 "dtc-lexer.l"
/* eat C++-style comments */
YY_BREAK
case 22:
YY_RULE_SETUP
-#line 247 "dtc-lexer.l"
+#line 248 "dtc-lexer.l"
{ return DT_LSHIFT; };
YY_BREAK
case 23:
YY_RULE_SETUP
-#line 248 "dtc-lexer.l"
+#line 249 "dtc-lexer.l"
{ return DT_RSHIFT; };
YY_BREAK
case 24:
YY_RULE_SETUP
-#line 249 "dtc-lexer.l"
+#line 250 "dtc-lexer.l"
{ return DT_LE; };
YY_BREAK
case 25:
YY_RULE_SETUP
-#line 250 "dtc-lexer.l"