mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-22 14:51:41 +00:00
3046 lines
90 KiB
Diff
3046 lines
90 KiB
Diff
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
|
|
index 3d18e453..5adfc8f5 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 @@ static bool run_check(struct check *c, struct dt_info *dti)
|
|
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, ®_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, ®_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, ®_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, ®_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 8cae2374..aa37a16c 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 c6006030..fd825ebb 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 2c862bc8..6b016dba 100644
|
|
--- a/scripts/dtc/dtc-lexer.lex.c_shipped
|
|
+++ b/scripts/dtc/dtc-lexer.lex.c_shipped
|
|
@@ -9,7 +9,7 @@
|
|
#define FLEX_SCANNER
|
|
#define YY_FLEX_MAJOR_VERSION 2
|
|
#define YY_FLEX_MINOR_VERSION 6
|
|
-#define YY_FLEX_SUBMINOR_VERSION 1
|
|
+#define YY_FLEX_SUBMINOR_VERSION 0
|
|
#if YY_FLEX_SUBMINOR_VERSION > 0
|
|
#define FLEX_BETA
|
|
#endif
|
|
@@ -88,13 +88,25 @@ typedef unsigned int flex_uint32_t;
|
|
|
|
#endif /* ! FLEXINT_H */
|
|
|
|
-/* TODO: this is always defined, so inline it */
|
|
-#define yyconst const
|
|
+#ifdef __cplusplus
|
|
|
|
-#if defined(__GNUC__) && __GNUC__ >= 3
|
|
-#define yynoreturn __attribute__((__noreturn__))
|
|
+/* The "const" storage-class-modifier is valid. */
|
|
+#define YY_USE_CONST
|
|
+
|
|
+#else /* ! __cplusplus */
|
|
+
|
|
+/* C99 requires __STDC__ to be defined as 1. */
|
|
+#if defined (__STDC__)
|
|
+
|
|
+#define YY_USE_CONST
|
|
+
|
|
+#endif /* defined (__STDC__) */
|
|
+#endif /* ! __cplusplus */
|
|
+
|
|
+#ifdef YY_USE_CONST
|
|
+#define yyconst const
|
|
#else
|
|
-#define yynoreturn
|
|
+#define yyconst
|
|
#endif
|
|
|
|
/* Returned upon end-of-file. */
|
|
@@ -155,7 +167,7 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
|
typedef size_t yy_size_t;
|
|
#endif
|
|
|
|
-extern int yyleng;
|
|
+extern yy_size_t yyleng;
|
|
|
|
extern FILE *yyin, *yyout;
|
|
|
|
@@ -194,7 +206,7 @@ struct yy_buffer_state
|
|
/* Size of input buffer in bytes, not including room for EOB
|
|
* characters.
|
|
*/
|
|
- int yy_buf_size;
|
|
+ yy_size_t yy_buf_size;
|
|
|
|
/* Number of characters read into yy_ch_buf, not including EOB
|
|
* characters.
|
|
@@ -222,7 +234,7 @@ struct yy_buffer_state
|
|
|
|
int yy_bs_lineno; /**< The line count. */
|
|
int yy_bs_column; /**< The column count. */
|
|
-
|
|
+
|
|
/* Whether to try to fill the input buffer when we reach the
|
|
* end of it.
|
|
*/
|
|
@@ -250,7 +262,7 @@ struct yy_buffer_state
|
|
/* Stack of input buffers. */
|
|
static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
|
|
static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
|
|
-static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */
|
|
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
|
|
|
|
/* We provide macros for accessing buffer states in case in the
|
|
* future we want to put the buffer states in a more general
|
|
@@ -270,10 +282,10 @@ static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */
|
|
/* yy_hold_char holds the character lost when yytext is formed. */
|
|
static char yy_hold_char;
|
|
static int yy_n_chars; /* number of characters read into yy_ch_buf */
|
|
-int yyleng;
|
|
+yy_size_t yyleng;
|
|
|
|
/* Points to current character in buffer. */
|
|
-static char *yy_c_buf_p = NULL;
|
|
+static char *yy_c_buf_p = (char *) 0;
|
|
static int yy_init = 0; /* whether we need to initialize */
|
|
static int yy_start = 0; /* start state number */
|
|
|
|
@@ -298,7 +310,7 @@ static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
|
|
|
|
YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
|
|
YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
|
|
-YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len );
|
|
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len );
|
|
|
|
void *yyalloc (yy_size_t );
|
|
void *yyrealloc (void *,yy_size_t );
|
|
@@ -335,7 +347,7 @@ void yyfree (void * );
|
|
|
|
typedef unsigned char YY_CHAR;
|
|
|
|
-FILE *yyin = NULL, *yyout = NULL;
|
|
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
|
|
|
|
typedef int yy_state_type;
|
|
|
|
@@ -352,14 +364,17 @@ extern char *yytext;
|
|
static yy_state_type yy_get_previous_state (void );
|
|
static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
|
|
static int yy_get_next_buffer (void );
|
|
-static void yynoreturn yy_fatal_error (yyconst char* msg );
|
|
+#if defined(__GNUC__) && __GNUC__ >= 3
|
|
+__attribute__((__noreturn__))
|
|
+#endif
|
|
+static void yy_fatal_error (yyconst char msg[] );
|
|
|
|
/* Done after the current pattern has been matched and before the
|
|
* corresponding action - sets up yytext.
|
|
*/
|
|
#define YY_DO_BEFORE_ACTION \
|
|
(yytext_ptr) = yy_bp; \
|
|
- yyleng = (int) (yy_cp - yy_bp); \
|
|
+ yyleng = (size_t) (yy_cp - yy_bp); \
|
|
(yy_hold_char) = *yy_cp; \
|
|
*yy_cp = '\0'; \
|
|
(yy_c_buf_p) = yy_cp;
|
|
@@ -655,8 +670,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 676 "dtc-lexer.lex.c"
|
|
|
|
#define INITIAL 0
|
|
#define BYTESTRING 1
|
|
@@ -698,7 +714,7 @@ FILE *yyget_out (void );
|
|
|
|
void yyset_out (FILE * _out_str );
|
|
|
|
- int yyget_leng (void );
|
|
+yy_size_t yyget_leng (void );
|
|
|
|
char *yyget_text (void );
|
|
|
|
@@ -755,7 +771,7 @@ static int input (void );
|
|
/* This used to be an fputs(), but since the string might contain NUL's,
|
|
* we now use fwrite().
|
|
*/
|
|
-#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
|
|
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
|
|
#endif
|
|
|
|
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
|
|
@@ -779,7 +795,7 @@ static int input (void );
|
|
else \
|
|
{ \
|
|
errno=0; \
|
|
- while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
|
|
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
|
|
{ \
|
|
if( errno != EINTR) \
|
|
{ \
|
|
@@ -878,9 +894,9 @@ YY_DECL
|
|
}
|
|
|
|
{
|
|
-#line 68 "dtc-lexer.l"
|
|
+#line 69 "dtc-lexer.l"
|
|
|
|
-#line 884 "dtc-lexer.lex.c"
|
|
+#line 900 "dtc-lexer.lex.c"
|
|
|
|
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
|
|
{
|
|
@@ -911,7 +927,7 @@ yy_match:
|
|
if ( yy_current_state >= 166 )
|
|
yy_c = yy_meta[(unsigned int) yy_c];
|
|
}
|
|
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
|
|
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
|
|
++yy_cp;
|
|
}
|
|
while ( yy_current_state != 165 );
|
|
@@ -937,7 +953,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 +963,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 +997,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 +1007,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 +1017,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 +1027,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 +1035,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 +1044,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 +1053,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 +1063,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 +1073,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 +1083,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 +1109,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 +1133,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 +1142,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 +1152,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 +1161,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 +1170,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 +1181,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 +1190,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"
|
|
+#line 251 "dtc-lexer.l"
|
|
{ return DT_GE; };
|
|
YY_BREAK
|
|
case 26:
|
|
YY_RULE_SETUP
|
|
-#line 251 "dtc-lexer.l"
|
|
+#line 252 "dtc-lexer.l"
|
|
{ return DT_EQ; };
|
|
YY_BREAK
|
|
case 27:
|
|
YY_RULE_SETUP
|
|
-#line 252 "dtc-lexer.l"
|
|
+#line 253 "dtc-lexer.l"
|
|
{ return DT_NE; };
|
|
YY_BREAK
|
|
case 28:
|
|
YY_RULE_SETUP
|
|
-#line 253 "dtc-lexer.l"
|
|
+#line 254 "dtc-lexer.l"
|
|
{ return DT_AND; };
|
|
YY_BREAK
|
|
case 29:
|
|
YY_RULE_SETUP
|
|
-#line 254 "dtc-lexer.l"
|
|
+#line 255 "dtc-lexer.l"
|
|
{ return DT_OR; };
|
|
YY_BREAK
|
|
case 30:
|
|
YY_RULE_SETUP
|
|
-#line 256 "dtc-lexer.l"
|
|
+#line 257 "dtc-lexer.l"
|
|
{
|
|
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
|
|
(unsigned)yytext[0]);
|
|
@@ -1249,10 +1265,10 @@ YY_RULE_SETUP
|
|
YY_BREAK
|
|
case 31:
|
|
YY_RULE_SETUP
|
|
-#line 271 "dtc-lexer.l"
|
|
+#line 272 "dtc-lexer.l"
|
|
ECHO;
|
|
YY_BREAK
|
|
-#line 1256 "dtc-lexer.lex.c"
|
|
+#line 1272 "dtc-lexer.lex.c"
|
|
|
|
case YY_END_OF_BUFFER:
|
|
{
|
|
@@ -1438,7 +1454,7 @@ static int yy_get_next_buffer (void)
|
|
|
|
else
|
|
{
|
|
- int num_to_read =
|
|
+ yy_size_t num_to_read =
|
|
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
|
|
|
|
while ( num_to_read <= 0 )
|
|
@@ -1452,7 +1468,7 @@ static int yy_get_next_buffer (void)
|
|
|
|
if ( b->yy_is_our_buffer )
|
|
{
|
|
- int new_size = b->yy_buf_size * 2;
|
|
+ yy_size_t new_size = b->yy_buf_size * 2;
|
|
|
|
if ( new_size <= 0 )
|
|
b->yy_buf_size += b->yy_buf_size / 8;
|
|
@@ -1465,7 +1481,7 @@ static int yy_get_next_buffer (void)
|
|
}
|
|
else
|
|
/* Can't grow it, we don't own it. */
|
|
- b->yy_ch_buf = NULL;
|
|
+ b->yy_ch_buf = 0;
|
|
|
|
if ( ! b->yy_ch_buf )
|
|
YY_FATAL_ERROR(
|
|
@@ -1548,7 +1564,7 @@ static int yy_get_next_buffer (void)
|
|
if ( yy_current_state >= 166 )
|
|
yy_c = yy_meta[(unsigned int) yy_c];
|
|
}
|
|
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
|
|
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
|
|
}
|
|
|
|
return yy_current_state;
|
|
@@ -1576,7 +1592,7 @@ static int yy_get_next_buffer (void)
|
|
if ( yy_current_state >= 166 )
|
|
yy_c = yy_meta[(unsigned int) yy_c];
|
|
}
|
|
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
|
|
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
|
|
yy_is_jam = (yy_current_state == 165);
|
|
|
|
return yy_is_jam ? 0 : yy_current_state;
|
|
@@ -1610,7 +1626,7 @@ static int yy_get_next_buffer (void)
|
|
|
|
else
|
|
{ /* need more input */
|
|
- int offset = (yy_c_buf_p) - (yytext_ptr);
|
|
+ yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
|
|
++(yy_c_buf_p);
|
|
|
|
switch ( yy_get_next_buffer( ) )
|
|
@@ -1634,7 +1650,7 @@ static int yy_get_next_buffer (void)
|
|
case EOB_ACT_END_OF_FILE:
|
|
{
|
|
if ( yywrap( ) )
|
|
- return 0;
|
|
+ return EOF;
|
|
|
|
if ( ! (yy_did_buffer_switch_on_eof) )
|
|
YY_NEW_FILE;
|
|
@@ -1884,7 +1900,7 @@ void yypop_buffer_state (void)
|
|
*/
|
|
static void yyensure_buffer_stack (void)
|
|
{
|
|
- int num_to_alloc;
|
|
+ yy_size_t num_to_alloc;
|
|
|
|
if (!(yy_buffer_stack)) {
|
|
|
|
@@ -1892,15 +1908,15 @@ static void yyensure_buffer_stack (void)
|
|
* scanner will even need a stack. We use 2 instead of 1 to avoid an
|
|
* immediate realloc on the next call.
|
|
*/
|
|
- num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
|
|
+ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
|
|
(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
|
|
(num_to_alloc * sizeof(struct yy_buffer_state*)
|
|
);
|
|
if ( ! (yy_buffer_stack) )
|
|
YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
|
|
-
|
|
+
|
|
memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
|
|
-
|
|
+
|
|
(yy_buffer_stack_max) = num_to_alloc;
|
|
(yy_buffer_stack_top) = 0;
|
|
return;
|
|
@@ -1929,7 +1945,7 @@ static void yyensure_buffer_stack (void)
|
|
* @param base the character buffer
|
|
* @param size the size in bytes of the character buffer
|
|
*
|
|
- * @return the newly allocated buffer state object.
|
|
+ * @return the newly allocated buffer state object.
|
|
*/
|
|
YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
|
|
{
|
|
@@ -1939,7 +1955,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
|
|
base[size-2] != YY_END_OF_BUFFER_CHAR ||
|
|
base[size-1] != YY_END_OF_BUFFER_CHAR )
|
|
/* They forgot to leave room for the EOB's. */
|
|
- return NULL;
|
|
+ return 0;
|
|
|
|
b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
|
|
if ( ! b )
|
|
@@ -1948,7 +1964,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
|
|
b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
|
|
b->yy_buf_pos = b->yy_ch_buf = base;
|
|
b->yy_is_our_buffer = 0;
|
|
- b->yy_input_file = NULL;
|
|
+ b->yy_input_file = 0;
|
|
b->yy_n_chars = b->yy_buf_size;
|
|
b->yy_is_interactive = 0;
|
|
b->yy_at_bol = 1;
|
|
@@ -1971,7 +1987,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
|
|
YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
|
|
{
|
|
|
|
- return yy_scan_bytes(yystr,(int) strlen(yystr) );
|
|
+ return yy_scan_bytes(yystr,strlen(yystr) );
|
|
}
|
|
|
|
/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
|
|
@@ -1981,7 +1997,7 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
|
|
*
|
|
* @return the newly allocated buffer state object.
|
|
*/
|
|
-YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
|
|
+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len )
|
|
{
|
|
YY_BUFFER_STATE b;
|
|
char *buf;
|
|
@@ -1989,7 +2005,7 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
|
|
yy_size_t i;
|
|
|
|
/* Get memory for full buffer, including space for trailing EOB's. */
|
|
- n = (yy_size_t) _yybytes_len + 2;
|
|
+ n = _yybytes_len + 2;
|
|
buf = (char *) yyalloc(n );
|
|
if ( ! buf )
|
|
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
|
|
@@ -2015,7 +2031,7 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
|
|
#define YY_EXIT_FAILURE 2
|
|
#endif
|
|
|
|
-static void yynoreturn yy_fatal_error (yyconst char* msg )
|
|
+static void yy_fatal_error (yyconst char* msg )
|
|
{
|
|
(void) fprintf( stderr, "%s\n", msg );
|
|
exit( YY_EXIT_FAILURE );
|
|
@@ -2045,7 +2061,7 @@ static void yynoreturn yy_fatal_error (yyconst char* msg )
|
|
*/
|
|
int yyget_lineno (void)
|
|
{
|
|
-
|
|
+
|
|
return yylineno;
|
|
}
|
|
|
|
@@ -2068,7 +2084,7 @@ FILE *yyget_out (void)
|
|
/** Get the length of the current token.
|
|
*
|
|
*/
|
|
-int yyget_leng (void)
|
|
+yy_size_t yyget_leng (void)
|
|
{
|
|
return yyleng;
|
|
}
|
|
@@ -2124,10 +2140,10 @@ static int yy_init_globals (void)
|
|
* This function is called from yylex_destroy(), so don't allocate here.
|
|
*/
|
|
|
|
- (yy_buffer_stack) = NULL;
|
|
+ (yy_buffer_stack) = 0;
|
|
(yy_buffer_stack_top) = 0;
|
|
(yy_buffer_stack_max) = 0;
|
|
- (yy_c_buf_p) = NULL;
|
|
+ (yy_c_buf_p) = (char *) 0;
|
|
(yy_init) = 0;
|
|
(yy_start) = 0;
|
|
|
|
@@ -2136,8 +2152,8 @@ static int yy_init_globals (void)
|
|
yyin = stdin;
|
|
yyout = stdout;
|
|
#else
|
|
- yyin = NULL;
|
|
- yyout = NULL;
|
|
+ yyin = (FILE *) 0;
|
|
+ yyout = (FILE *) 0;
|
|
#endif
|
|
|
|
/* For future reference: Set errno on error, since we are called by
|
|
@@ -2195,7 +2211,7 @@ static int yy_flex_strlen (yyconst char * s )
|
|
|
|
void *yyalloc (yy_size_t size )
|
|
{
|
|
- return malloc(size);
|
|
+ return (void *) malloc( size );
|
|
}
|
|
|
|
void *yyrealloc (void * ptr, yy_size_t size )
|
|
@@ -2208,7 +2224,7 @@ void *yyrealloc (void * ptr, yy_size_t size )
|
|
* any pointer type to void*, and deal with argument conversions
|
|
* as though doing an assignment.
|
|
*/
|
|
- return realloc(ptr, size);
|
|
+ return (void *) realloc( (char *) ptr, size );
|
|
}
|
|
|
|
void yyfree (void * ptr )
|
|
@@ -2218,7 +2234,7 @@ void yyfree (void * ptr )
|
|
|
|
#define YYTABLES_NAME "yytables"
|
|
|
|
-#line 271 "dtc-lexer.l"
|
|
+#line 272 "dtc-lexer.l"
|
|
|
|
|
|
|
|
diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
|
|
index 2965227a..0a7a5ed8 100644
|
|
--- a/scripts/dtc/dtc-parser.tab.c_shipped
|
|
+++ b/scripts/dtc/dtc-parser.tab.c_shipped
|
|
@@ -1557,10 +1557,10 @@ yyreduce:
|
|
{
|
|
struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref));
|
|
|
|
- add_label(&target->labels, (yyvsp[-2].labelref));
|
|
- if (target)
|
|
+ if (target) {
|
|
+ add_label(&target->labels, (yyvsp[-2].labelref));
|
|
merge_nodes(target, (yyvsp[0].node));
|
|
- else
|
|
+ } else
|
|
ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref));
|
|
(yyval.node) = (yyvsp[-3].node);
|
|
}
|
|
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
|
|
index b2fd4d15..ca3f5003 100644
|
|
--- a/scripts/dtc/dtc-parser.y
|
|
+++ b/scripts/dtc/dtc-parser.y
|
|
@@ -171,10 +171,10 @@ devicetree:
|
|
{
|
|
struct node *target = get_node_by_ref($1, $3);
|
|
|
|
- add_label(&target->labels, $2);
|
|
- if (target)
|
|
+ if (target) {
|
|
+ add_label(&target->labels, $2);
|
|
merge_nodes(target, $4);
|
|
- else
|
|
+ } else
|
|
ERROR(&@3, "Label or path %s not found", $3);
|
|
$$ = $1;
|
|
}
|
|
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
|
|
index a4edf4c7..f5eed9d7 100644
|
|
--- a/scripts/dtc/dtc.c
|
|
+++ b/scripts/dtc/dtc.c
|
|
@@ -138,7 +138,7 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
|
|
static const char *guess_input_format(const char *fname, const char *fallback)
|
|
{
|
|
struct stat statbuf;
|
|
- uint32_t magic;
|
|
+ fdt32_t magic;
|
|
FILE *f;
|
|
|
|
if (stat(fname, &statbuf) != 0)
|
|
@@ -159,8 +159,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)
|
|
}
|
|
fclose(f);
|
|
|
|
- magic = fdt32_to_cpu(magic);
|
|
- if (magic == FDT_MAGIC)
|
|
+ if (fdt32_to_cpu(magic) == FDT_MAGIC)
|
|
return "dtb";
|
|
|
|
return guess_type_by_name(fname, fallback);
|
|
@@ -216,7 +215,7 @@ int main(int argc, char *argv[])
|
|
alignsize = strtol(optarg, NULL, 0);
|
|
if (!is_power_of_2(alignsize))
|
|
die("Invalid argument \"%d\" to -a option\n",
|
|
- optarg);
|
|
+ alignsize);
|
|
break;
|
|
case 'f':
|
|
force = true;
|
|
@@ -309,6 +308,8 @@ int main(int argc, char *argv[])
|
|
else
|
|
die("Unknown input format \"%s\"\n", inform);
|
|
|
|
+ dti->outname = outname;
|
|
+
|
|
if (depfile) {
|
|
fputc('\n', depfile);
|
|
fclose(depfile);
|
|
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
|
|
index c6f125c6..fc24e175 100644
|
|
--- a/scripts/dtc/dtc.h
|
|
+++ b/scripts/dtc/dtc.h
|
|
@@ -43,7 +43,6 @@
|
|
#define debug(...)
|
|
#endif
|
|
|
|
-
|
|
#define DEFAULT_FDT_VERSION 17
|
|
|
|
/*
|
|
@@ -114,7 +113,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_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_re(struct data d, uint64_t address, uint64_t size);
|
|
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);
|
|
@@ -136,6 +135,10 @@ struct label {
|
|
struct label *next;
|
|
};
|
|
|
|
+struct bus_type {
|
|
+ const char *name;
|
|
+};
|
|
+
|
|
struct property {
|
|
bool deleted;
|
|
char *name;
|
|
@@ -162,6 +165,7 @@ struct node {
|
|
int addr_cells, size_cells;
|
|
|
|
struct label *labels;
|
|
+ const struct bus_type *bus;
|
|
};
|
|
|
|
#define for_each_label_withdel(l0, l) \
|
|
@@ -227,7 +231,7 @@ uint32_t guess_boot_cpuid(struct node *tree);
|
|
/* Boot info (tree plus memreserve information */
|
|
|
|
struct reserve_info {
|
|
- struct fdt_reserve_entry re;
|
|
+ uint64_t address, size;
|
|
|
|
struct reserve_info *next;
|
|
|
|
@@ -246,6 +250,7 @@ struct dt_info {
|
|
struct reserve_info *reservelist;
|
|
uint32_t boot_cpuid_phys;
|
|
struct node *dt; /* the device tree */
|
|
+ const char *outname; /* filename being written to, "-" for stdout */
|
|
};
|
|
|
|
/* DTS version flags definitions */
|
|
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
|
|
index ebac548b..fcf71541 100644
|
|
--- a/scripts/dtc/flattree.c
|
|
+++ b/scripts/dtc/flattree.c
|
|
@@ -49,7 +49,7 @@ static struct version_info {
|
|
|
|
struct emitter {
|
|
void (*cell)(void *, cell_t);
|
|
- void (*string)(void *, char *, int);
|
|
+ void (*string)(void *, const char *, int);
|
|
void (*align)(void *, int);
|
|
void (*data)(void *, struct data);
|
|
void (*beginnode)(void *, struct label *labels);
|
|
@@ -64,7 +64,7 @@ static void bin_emit_cell(void *e, cell_t val)
|
|
*dtbuf = data_append_cell(*dtbuf, val);
|
|
}
|
|
|
|
-static void bin_emit_string(void *e, char *str, int len)
|
|
+static void bin_emit_string(void *e, const char *str, int len)
|
|
{
|
|
struct data *dtbuf = e;
|
|
|
|
@@ -144,22 +144,14 @@ static void asm_emit_cell(void *e, cell_t val)
|
|
(val >> 8) & 0xff, val & 0xff);
|
|
}
|
|
|
|
-static void asm_emit_string(void *e, char *str, int len)
|
|
+static void asm_emit_string(void *e, const char *str, int len)
|
|
{
|
|
FILE *f = e;
|
|
- char c = 0;
|
|
|
|
- if (len != 0) {
|
|
- /* XXX: ewww */
|
|
- c = str[len];
|
|
- str[len] = '\0';
|
|
- }
|
|
-
|
|
- fprintf(f, "\t.string\t\"%s\"\n", str);
|
|
-
|
|
- if (len != 0) {
|
|
- str[len] = c;
|
|
- }
|
|
+ if (len != 0)
|
|
+ fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
|
|
+ else
|
|
+ fprintf(f, "\t.string\t\"%s\"\n", str);
|
|
}
|
|
|
|
static void asm_emit_align(void *e, int a)
|
|
@@ -179,7 +171,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(*((uint32_t *)(d.val+off))));
|
|
+ asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));
|
|
off += sizeof(uint32_t);
|
|
}
|
|
|
|
@@ -318,17 +310,16 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
|
|
{
|
|
struct reserve_info *re;
|
|
struct data d = empty_data;
|
|
- static struct fdt_reserve_entry null_re = {0,0};
|
|
int j;
|
|
|
|
for (re = reservelist; re; re = re->next) {
|
|
- d = data_append_re(d, &re->re);
|
|
+ d = data_append_re(d, re->address, re->size);
|
|
}
|
|
/*
|
|
* Add additional reserved slots if the user asked for them.
|
|
*/
|
|
for (j = 0; j < reservenum; j++) {
|
|
- d = data_append_re(d, &null_re);
|
|
+ d = data_append_re(d, 0, 0);
|
|
}
|
|
|
|
return d;
|
|
@@ -544,11 +535,11 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
|
|
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", (unsigned int)(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));
|
|
+ (unsigned int)(re->address & 0xffffffff));
|
|
+ ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32));
|
|
+ ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff));
|
|
}
|
|
for (i = 0; i < reservenum; i++) {
|
|
fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
|
|
@@ -609,7 +600,7 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len)
|
|
|
|
static uint32_t flat_read_word(struct inbuf *inb)
|
|
{
|
|
- uint32_t val;
|
|
+ fdt32_t val;
|
|
|
|
assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
|
|
|
|
@@ -718,13 +709,15 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
|
|
* First pass, count entries.
|
|
*/
|
|
while (1) {
|
|
+ uint64_t address, size;
|
|
+
|
|
flat_read_chunk(inb, &re, sizeof(re));
|
|
- re.address = fdt64_to_cpu(re.address);
|
|
- re.size = fdt64_to_cpu(re.size);
|
|
- if (re.size == 0)
|
|
+ address = fdt64_to_cpu(re.address);
|
|
+ size = fdt64_to_cpu(re.size);
|
|
+ if (size == 0)
|
|
break;
|
|
|
|
- new = build_reserve_entry(re.address, re.size);
|
|
+ new = build_reserve_entry(address, size);
|
|
reservelist = add_reserve_entry(reservelist, new);
|
|
}
|
|
|
|
@@ -817,6 +810,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
|
|
struct dt_info *dt_from_blob(const char *fname)
|
|
{
|
|
FILE *f;
|
|
+ fdt32_t magic_buf, totalsize_buf;
|
|
uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
|
|
uint32_t off_dt, off_str, off_mem_rsvmap;
|
|
int rc;
|
|
@@ -833,7 +827,7 @@ struct dt_info *dt_from_blob(const char *fname)
|
|
|
|
f = srcfile_relative_open(fname, NULL);
|
|
|
|
- rc = fread(&magic, sizeof(magic), 1, f);
|
|
+ rc = fread(&magic_buf, sizeof(magic_buf), 1, f);
|
|
if (ferror(f))
|
|
die("Error reading DT blob magic number: %s\n",
|
|
strerror(errno));
|
|
@@ -844,11 +838,11 @@ struct dt_info *dt_from_blob(const char *fname)
|
|
die("Mysterious short read reading magic number\n");
|
|
}
|
|
|
|
- magic = fdt32_to_cpu(magic);
|
|
+ magic = fdt32_to_cpu(magic_buf);
|
|
if (magic != FDT_MAGIC)
|
|
die("Blob has incorrect magic number\n");
|
|
|
|
- rc = fread(&totalsize, sizeof(totalsize), 1, f);
|
|
+ rc = fread(&totalsize_buf, sizeof(totalsize_buf), 1, f);
|
|
if (ferror(f))
|
|
die("Error reading DT blob size: %s\n", strerror(errno));
|
|
if (rc < 1) {
|
|
@@ -858,7 +852,7 @@ struct dt_info *dt_from_blob(const char *fname)
|
|
die("Mysterious short read reading blob size\n");
|
|
}
|
|
|
|
- totalsize = fdt32_to_cpu(totalsize);
|
|
+ totalsize = fdt32_to_cpu(totalsize_buf);
|
|
if (totalsize < FDT_V1_SIZE)
|
|
die("DT blob size (%d) is too small\n", totalsize);
|
|
|
|
diff --git a/scripts/dtc/libfdt/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c
|
|
new file mode 100644
|
|
index 00000000..eff4dbcc
|
|
--- /dev/null
|
|
+++ b/scripts/dtc/libfdt/fdt_addresses.c
|
|
@@ -0,0 +1,96 @@
|
|
+/*
|
|
+ * libfdt - Flat Device Tree manipulation
|
|
+ * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
|
|
+ *
|
|
+ * 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 <fdt.h>
|
|
+#include <libfdt.h>
|
|
+
|
|
+#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/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c
|
|
index f72d13b1..f2ae9b77 100644
|
|
--- a/scripts/dtc/libfdt/fdt_empty_tree.c
|
|
+++ b/scripts/dtc/libfdt/fdt_empty_tree.c
|
|
@@ -81,4 +81,3 @@ int fdt_create_empty_tree(void *buf, int bufsize)
|
|
|
|
return fdt_open_into(buf, buf, bufsize);
|
|
}
|
|
-
|
|
diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c
|
|
new file mode 100644
|
|
index 00000000..ceb96878
|
|
--- /dev/null
|
|
+++ b/scripts/dtc/libfdt/fdt_overlay.c
|
|
@@ -0,0 +1,677 @@
|
|
+#include "libfdt_env.h"
|
|
+
|
|
+#include <fdt.h>
|
|
+#include <libfdt.h>
|
|
+
|
|
+#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 fdt32_t *val;
|
|
+ int len;
|
|
+
|
|
+ val = fdt_getprop(fdto, fragment, "target", &len);
|
|
+ if (!val)
|
|
+ return 0;
|
|
+
|
|
+ if ((len != sizeof(*val)) || (fdt32_to_cpu(*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 fdt32_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 fdt32_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++) {
|
|
+ fdt32_t adj_val;
|
|
+ uint32_t poffset;
|
|
+
|
|
+ poffset = 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 + 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;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ 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_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
|
|
+ * @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
|
|
+ * 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 poffset, const char *label)
|
|
+{
|
|
+ const char *symbol_path;
|
|
+ uint32_t phandle;
|
|
+ fdt32_t phandle_prop;
|
|
+ int symbol_off, fixup_off;
|
|
+ int prop_len;
|
|
+
|
|
+ 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;
|
|
+ if (fixup_off < 0)
|
|
+ return fixup_off;
|
|
+
|
|
+ phandle_prop = cpu_to_fdt32(phandle);
|
|
+ return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
|
|
+ name, name_len, poffset,
|
|
+ &phandle_prop,
|
|
+ sizeof(phandle_prop));
|
|
+};
|
|
+
|
|
+/**
|
|
+ * 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 poffset, 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;
|
|
+
|
|
+ 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,
|
|
+ poffset, 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; /* nothing to do */
|
|
+ if (fixups_off < 0)
|
|
+ return fixups_off;
|
|
+
|
|
+ /* And base DTs without symbols */
|
|
+ symbols_off = fdt_path_offset(fdt, "/__symbols__");
|
|
+ if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND)))
|
|
+ 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/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
|
|
index 3d00d2ee..08de2cce 100644
|
|
--- a/scripts/dtc/libfdt/fdt_ro.c
|
|
+++ b/scripts/dtc/libfdt/fdt_ro.c
|
|
@@ -60,7 +60,7 @@ static int _fdt_nodename_eq(const void *fdt, int offset,
|
|
{
|
|
const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
|
|
|
|
- if (! p)
|
|
+ if (!p)
|
|
/* short match */
|
|
return 0;
|
|
|
|
@@ -327,7 +327,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
|
const struct fdt_property *prop;
|
|
|
|
prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
|
|
- if (! prop)
|
|
+ if (!prop)
|
|
return NULL;
|
|
|
|
return prop->data;
|
|
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
|
|
index 2eed4f58..8b487f6c 100644
|
|
--- a/scripts/dtc/libfdt/fdt_rw.c
|
|
+++ b/scripts/dtc/libfdt/fdt_rw.c
|
|
@@ -207,7 +207,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
|
|
int err;
|
|
|
|
*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
|
|
- if (! (*prop))
|
|
+ if (!*prop)
|
|
return oldlen;
|
|
|
|
if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
|
|
@@ -283,7 +283,8 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
|
if (err)
|
|
return err;
|
|
|
|
- memcpy(prop->data, val, len);
|
|
+ if (len)
|
|
+ memcpy(prop->data, val, len);
|
|
return 0;
|
|
}
|
|
|
|
@@ -322,7 +323,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
|
|
FDT_RW_CHECK_HEADER(fdt);
|
|
|
|
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
|
|
- if (! prop)
|
|
+ if (!prop)
|
|
return len;
|
|
|
|
proplen = sizeof(*prop) + FDT_TAGALIGN(len);
|
|
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
|
|
index 6a804859..2bd15e7a 100644
|
|
--- a/scripts/dtc/libfdt/fdt_sw.c
|
|
+++ b/scripts/dtc/libfdt/fdt_sw.c
|
|
@@ -220,7 +220,7 @@ static int _fdt_find_add_string(void *fdt, const char *s)
|
|
return offset;
|
|
}
|
|
|
|
-int fdt_property(void *fdt, const char *name, const void *val, int len)
|
|
+int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
|
|
{
|
|
struct fdt_property *prop;
|
|
int nameoff;
|
|
@@ -238,7 +238,19 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
|
|
prop->tag = cpu_to_fdt32(FDT_PROP);
|
|
prop->nameoff = cpu_to_fdt32(nameoff);
|
|
prop->len = cpu_to_fdt32(len);
|
|
- memcpy(prop->data, val, len);
|
|
+ *valp = prop->data;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int fdt_property(void *fdt, const char *name, const void *val, int len)
|
|
+{
|
|
+ void *ptr;
|
|
+ int ret;
|
|
+
|
|
+ ret = fdt_property_placeholder(fdt, name, len, &ptr);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ memcpy(ptr, val, len);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
|
|
index 6aaab399..5e859198 100644
|
|
--- a/scripts/dtc/libfdt/fdt_wip.c
|
|
+++ b/scripts/dtc/libfdt/fdt_wip.c
|
|
@@ -82,7 +82,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
|
|
int proplen;
|
|
|
|
propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
|
|
- if (! propval)
|
|
+ if (!propval)
|
|
return proplen;
|
|
|
|
if (proplen != len)
|
|
@@ -107,7 +107,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
|
|
int len;
|
|
|
|
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
|
|
- if (! prop)
|
|
+ if (!prop)
|
|
return len;
|
|
|
|
_fdt_nop_region(prop, len + sizeof(*prop));
|
|
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
|
|
index b842b156..707b5069 100644
|
|
--- a/scripts/dtc/libfdt/libfdt.h
|
|
+++ b/scripts/dtc/libfdt/libfdt.h
|
|
@@ -143,7 +143,9 @@
|
|
/* Low-level functions (you probably don't need these) */
|
|
/**********************************************************************/
|
|
|
|
+#ifndef SWIG /* This function is not useful in Python */
|
|
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
|
|
+#endif
|
|
static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
|
|
{
|
|
return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
|
|
@@ -210,7 +212,6 @@ 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))
|
|
#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
|
|
@@ -354,8 +355,10 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
|
|
* useful for finding subnodes based on a portion of a larger string,
|
|
* such as a full path.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
|
|
const char *name, int namelen);
|
|
+#endif
|
|
/**
|
|
* fdt_subnode_offset - find a subnode of a given node
|
|
* @fdt: pointer to the device tree blob
|
|
@@ -391,7 +394,9 @@ 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.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_path_offset - find a tree node by its full path
|
|
@@ -550,10 +555,12 @@ 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.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
|
int nodeoffset,
|
|
const char *name,
|
|
int namelen, int *lenp);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_get_property - find a given property in a given node
|
|
@@ -624,8 +631,10 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
|
|
* -FDT_ERR_BADSTRUCTURE,
|
|
* -FDT_ERR_TRUNCATED, standard meanings
|
|
*/
|
|
+#ifndef SWIG /* This function is not useful in Python */
|
|
const void *fdt_getprop_by_offset(const void *fdt, int offset,
|
|
const char **namep, int *lenp);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_getprop_namelen - get property value based on substring
|
|
@@ -638,6 +647,7 @@ 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.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
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,
|
|
@@ -647,6 +657,7 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
|
|
return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
|
|
namelen, lenp);
|
|
}
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_getprop - retrieve the value of a given property
|
|
@@ -707,8 +718,10 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
|
|
* Identical to fdt_get_alias(), but only examine the first namelen
|
|
* characters of name for matching the alias name.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
const char *fdt_get_alias_namelen(const void *fdt,
|
|
const char *name, int namelen);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_get_alias - retrieve the path referenced by a given alias
|
|
@@ -1106,10 +1119,12 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
|
|
* 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.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
|
|
const char *name, int namelen,
|
|
uint32_t idx, const void *val,
|
|
int len);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_setprop_inplace - change a property's value, but not its size
|
|
@@ -1139,8 +1154,10 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
|
|
* -FDT_ERR_BADSTRUCTURE,
|
|
* -FDT_ERR_TRUNCATED, standard meanings
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
|
|
const void *val, int len);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
|
|
@@ -1297,6 +1314,22 @@ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
|
|
{
|
|
return fdt_property_u32(fdt, name, val);
|
|
}
|
|
+
|
|
+/**
|
|
+ * fdt_property_placeholder - add a new property and return a ptr to its value
|
|
+ *
|
|
+ * @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
|
|
+ *
|
|
+ * returns:
|
|
+ * 0, on success
|
|
+ * -FDT_ERR_BADMAGIC,
|
|
+ * -FDT_ERR_NOSPACE, standard meanings
|
|
+ */
|
|
+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)
|
|
int fdt_end_node(void *fdt);
|
|
@@ -1527,6 +1560,36 @@ 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_empty - set a property to an empty value
|
|
+ * @fdt: pointer to the device tree blob
|
|
+ * @nodeoffset: offset of the node whose property to change
|
|
+ * @name: name of the property to change
|
|
+ *
|
|
+ * fdt_setprop_empty() sets the value of the named property in the
|
|
+ * given node to an empty (zero length) value, or creates a new empty
|
|
+ * 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
|
|
+ */
|
|
+#define fdt_setprop_empty(fdt, nodeoffset, name) \
|
|
+ fdt_setprop((fdt), (nodeoffset), (name), NULL, 0)
|
|
+
|
|
/**
|
|
* fdt_appendprop - append to or create a property
|
|
* @fdt: pointer to the device tree blob
|
|
@@ -1704,8 +1767,10 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
|
|
* creating subnodes based on a portion of a larger string, such as a
|
|
* full path.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
|
const char *name, int namelen);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_add_subnode - creates a new node
|
|
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
|
|
index 99f936da..952056cd 100644
|
|
--- a/scripts/dtc/libfdt/libfdt_env.h
|
|
+++ b/scripts/dtc/libfdt/libfdt_env.h
|
|
@@ -58,16 +58,16 @@
|
|
#include <string.h>
|
|
|
|
#ifdef __CHECKER__
|
|
-#define __force __attribute__((force))
|
|
-#define __bitwise __attribute__((bitwise))
|
|
+#define FDT_FORCE __attribute__((force))
|
|
+#define FDT_BITWISE __attribute__((bitwise))
|
|
#else
|
|
-#define __force
|
|
-#define __bitwise
|
|
+#define FDT_FORCE
|
|
+#define FDT_BITWISE
|
|
#endif
|
|
|
|
-typedef uint16_t __bitwise fdt16_t;
|
|
-typedef uint32_t __bitwise fdt32_t;
|
|
-typedef uint64_t __bitwise fdt64_t;
|
|
+typedef uint16_t FDT_BITWISE fdt16_t;
|
|
+typedef uint32_t FDT_BITWISE fdt32_t;
|
|
+typedef uint64_t FDT_BITWISE fdt64_t;
|
|
|
|
#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))
|
|
@@ -80,29 +80,29 @@ typedef uint64_t __bitwise fdt64_t;
|
|
|
|
static inline uint16_t fdt16_to_cpu(fdt16_t x)
|
|
{
|
|
- return (__force uint16_t)CPU_TO_FDT16(x);
|
|
+ return (FDT_FORCE uint16_t)CPU_TO_FDT16(x);
|
|
}
|
|
static inline fdt16_t cpu_to_fdt16(uint16_t x)
|
|
{
|
|
- return (__force fdt16_t)CPU_TO_FDT16(x);
|
|
+ return (FDT_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);
|
|
+ return (FDT_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);
|
|
+ return (FDT_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);
|
|
+ return (FDT_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);
|
|
+ return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x);
|
|
}
|
|
#undef CPU_TO_FDT64
|
|
#undef CPU_TO_FDT32
|
|
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
|
|
index afa2f67b..aecd2787 100644
|
|
--- a/scripts/dtc/livetree.c
|
|
+++ b/scripts/dtc/livetree.c
|
|
@@ -242,7 +242,7 @@ void delete_property_by_name(struct node *node, char *name)
|
|
struct property *prop = node->proplist;
|
|
|
|
while (prop) {
|
|
- if (!strcmp(prop->name, name)) {
|
|
+ if (streq(prop->name, name)) {
|
|
delete_property(prop);
|
|
return;
|
|
}
|
|
@@ -275,7 +275,7 @@ void delete_node_by_name(struct node *parent, char *name)
|
|
struct node *node = parent->children;
|
|
|
|
while (node) {
|
|
- if (!strcmp(node->name, name)) {
|
|
+ if (streq(node->name, name)) {
|
|
delete_node(node);
|
|
return;
|
|
}
|
|
@@ -319,8 +319,8 @@ struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
|
|
|
|
memset(new, 0, sizeof(*new));
|
|
|
|
- new->re.address = address;
|
|
- new->re.size = size;
|
|
+ new->address = address;
|
|
+ new->size = size;
|
|
|
|
return new;
|
|
}
|
|
@@ -393,7 +393,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 fdt32_to_cpu(*((cell_t *)prop->val.val));
|
|
+ return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
|
|
}
|
|
|
|
struct property *get_property_by_label(struct node *tree, const char *label,
|
|
@@ -478,7 +478,8 @@ struct node *get_node_by_path(struct node *tree, const char *path)
|
|
p = strchr(path, '/');
|
|
|
|
for_each_child(tree, child) {
|
|
- if (p && strneq(path, child->name, p-path))
|
|
+ if (p && (strlen(child->name) == p-path) &&
|
|
+ strneq(path, child->name, p-path))
|
|
return get_node_by_path(child, p+1);
|
|
else if (!p && streq(path, child->name))
|
|
return child;
|
|
@@ -599,13 +600,13 @@ static int cmp_reserve_info(const void *ax, const void *bx)
|
|
a = *((const struct reserve_info * const *)ax);
|
|
b = *((const struct reserve_info * const *)bx);
|
|
|
|
- if (a->re.address < b->re.address)
|
|
+ if (a->address < b->address)
|
|
return -1;
|
|
- else if (a->re.address > b->re.address)
|
|
+ else if (a->address > b->address)
|
|
return 1;
|
|
- else if (a->re.size < b->re.size)
|
|
+ else if (a->size < b->size)
|
|
return -1;
|
|
- else if (a->re.size > b->re.size)
|
|
+ else if (a->size > b->size)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
@@ -847,6 +848,8 @@ 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);
|
|
+
|
|
+ free(entry);
|
|
}
|
|
|
|
static void generate_fixups_tree_internal(struct dt_info *dti,
|
|
@@ -900,7 +903,7 @@ static void add_local_fixup_entry(struct dt_info *dti,
|
|
struct node *refnode)
|
|
{
|
|
struct node *wn, *nwn; /* local fixup node, walk node, new */
|
|
- uint32_t value_32;
|
|
+ fdt32_t value_32;
|
|
char **compp;
|
|
int i, depth;
|
|
|
|
diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
|
|
index aa3aad04..9d384599 100644
|
|
--- a/scripts/dtc/srcpos.c
|
|
+++ b/scripts/dtc/srcpos.c
|
|
@@ -252,7 +252,7 @@ srcpos_string(struct srcpos *pos)
|
|
const char *fname = "<no-file>";
|
|
char *pos_str;
|
|
|
|
- if (pos)
|
|
+ if (pos->file && pos->file->name)
|
|
fname = pos->file->name;
|
|
|
|
|
|
diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h
|
|
index 2cdfcd82..7caca825 100644
|
|
--- a/scripts/dtc/srcpos.h
|
|
+++ b/scripts/dtc/srcpos.h
|
|
@@ -22,6 +22,7 @@
|
|
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
+#include "util.h"
|
|
|
|
struct srcfile_state {
|
|
FILE *f;
|
|
@@ -106,12 +107,10 @@ 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_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 PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix,
|
|
+ const char *fmt, va_list va);
|
|
+extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix,
|
|
+ const char *fmt, ...);
|
|
|
|
extern void srcpos_set_line(char *f, int l);
|
|
|
|
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
|
|
index c9d89679..2461a3d0 100644
|
|
--- a/scripts/dtc/treesource.c
|
|
+++ b/scripts/dtc/treesource.c
|
|
@@ -137,7 +137,7 @@ static void write_propval_string(FILE *f, struct data val)
|
|
static void write_propval_cells(FILE *f, struct data val)
|
|
{
|
|
void *propend = val.val + val.len;
|
|
- cell_t *cp = (cell_t *)val.val;
|
|
+ fdt32_t *cp = (fdt32_t *)val.val;
|
|
struct marker *m = val.markers;
|
|
|
|
fprintf(f, "<");
|
|
@@ -275,8 +275,8 @@ void dt_to_source(FILE *f, struct dt_info *dti)
|
|
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);
|
|
+ (unsigned long long)re->address,
|
|
+ (unsigned long long)re->size);
|
|
}
|
|
|
|
write_tree_source_node(f, dti->dt, 0);
|
|
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
|
|
index 3550f86b..9953c32a 100644
|
|
--- a/scripts/dtc/util.c
|
|
+++ b/scripts/dtc/util.c
|
|
@@ -396,7 +396,7 @@ void utilfdt_print_data(const char *data, int len)
|
|
} while (s < data + len);
|
|
|
|
} else if ((len % 4) == 0) {
|
|
- const uint32_t *cell = (const uint32_t *)data;
|
|
+ const fdt32_t *cell = (const fdt32_t *)data;
|
|
|
|
printf(" = <");
|
|
for (i = 0, len /= 4; i < len; i++)
|
|
@@ -412,15 +412,16 @@ void utilfdt_print_data(const char *data, int len)
|
|
}
|
|
}
|
|
|
|
-void util_version(void)
|
|
+void NORETURN util_version(void)
|
|
{
|
|
printf("Version: %s\n", DTC_VERSION);
|
|
exit(0);
|
|
}
|
|
|
|
-void util_usage(const char *errmsg, const char *synopsis,
|
|
- const char *short_opts, struct option const long_opts[],
|
|
- const char * const opts_help[])
|
|
+void NORETURN 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[] = "<arg>";
|
|
diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
|
|
index f5c4f1b5..ad5f4119 100644
|
|
--- a/scripts/dtc/util.h
|
|
+++ b/scripts/dtc/util.h
|
|
@@ -25,9 +25,17 @@
|
|
* USA
|
|
*/
|
|
|
|
+#ifdef __GNUC__
|
|
+#define PRINTF(i, j) __attribute__((format (printf, i, j)))
|
|
+#define NORETURN __attribute__((noreturn))
|
|
+#else
|
|
+#define PRINTF(i, j)
|
|
+#define NORETURN
|
|
+#endif
|
|
+
|
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
|
|
|
-static inline void __attribute__((noreturn)) die(const char *str, ...)
|
|
+static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
@@ -53,13 +61,14 @@ static inline void *xrealloc(void *p, size_t len)
|
|
void *new = realloc(p, len);
|
|
|
|
if (!new)
|
|
- die("realloc() failed (len=%d)\n", len);
|
|
+ die("realloc() failed (len=%zd)\n", len);
|
|
|
|
return new;
|
|
}
|
|
|
|
extern char *xstrdup(const char *s);
|
|
-extern int xasprintf(char **strp, const char *fmt, ...);
|
|
+
|
|
+extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
|
|
extern char *join_path(const char *path, const char *name);
|
|
|
|
/**
|
|
@@ -188,7 +197,7 @@ void utilfdt_print_data(const char *data, int len);
|
|
/**
|
|
* Show source version and exit
|
|
*/
|
|
-void util_version(void) __attribute__((noreturn));
|
|
+void NORETURN util_version(void);
|
|
|
|
/**
|
|
* Show usage and exit
|
|
@@ -202,9 +211,10 @@ 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_usage(const char *errmsg, const char *synopsis,
|
|
- const char *short_opts, struct option const long_opts[],
|
|
- const char * const opts_help[]) __attribute__((noreturn));
|
|
+void NORETURN util_usage(const char *errmsg, const char *synopsis,
|
|
+ const char *short_opts,
|
|
+ struct option const long_opts[],
|
|
+ const char * const opts_help[]);
|
|
|
|
/**
|
|
* Show usage and exit
|