summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/dtc/checks.c222
-rw-r--r--scripts/dtc/dtc-lexer.l2
-rw-r--r--scripts/dtc/dtc.c6
-rw-r--r--scripts/dtc/dtc.h40
-rw-r--r--scripts/dtc/flattree.c11
-rw-r--r--scripts/dtc/libfdt/fdt.c4
-rw-r--r--scripts/dtc/libfdt/fdt_rw.c18
-rw-r--r--scripts/dtc/libfdt/fdt_strerror.c1
-rw-r--r--scripts/dtc/libfdt/libfdt.h7
-rw-r--r--scripts/dtc/livetree.c6
-rw-r--r--scripts/dtc/treesource.c48
-rw-r--r--scripts/dtc/util.h6
-rw-r--r--scripts/dtc/version_gen.h2
-rw-r--r--scripts/dtc/yamltree.c16
14 files changed, 275 insertions, 114 deletions
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
index 17cb6890d45a..781ba1129a8e 100644
--- a/scripts/dtc/checks.c
+++ b/scripts/dtc/checks.c
@@ -143,6 +143,14 @@ static void check_nodes_props(struct check *c, struct dt_info *dti, struct node
check_nodes_props(c, dti, child);
}
+static bool is_multiple_of(int multiple, int divisor)
+{
+ if (divisor == 0)
+ return multiple == 0;
+ else
+ return (multiple % divisor) == 0;
+}
+
static bool run_check(struct check *c, struct dt_info *dti)
{
struct node *dt = dti->dt;
@@ -297,19 +305,20 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define DIGITS "0123456789"
-#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
+#define NODECHARS LOWERCASE UPPERCASE DIGITS ",._+-@"
+#define PROPCHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
static void check_node_name_chars(struct check *c, struct dt_info *dti,
struct node *node)
{
- int n = strspn(node->name, c->data);
+ size_t n = strspn(node->name, c->data);
if (n < strlen(node->name))
FAIL(c, dti, node, "Bad character '%c' in node name",
node->name[n]);
}
-ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
+ERROR(node_name_chars, check_node_name_chars, NODECHARS);
static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
struct node *node)
@@ -330,6 +339,20 @@ static void check_node_name_format(struct check *c, struct dt_info *dti,
}
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
+static void check_node_name_vs_property_name(struct check *c,
+ struct dt_info *dti,
+ struct node *node)
+{
+ if (!node->parent)
+ return;
+
+ if (get_property(node->parent, node->name)) {
+ FAIL(c, dti, node, "node name and property name conflict");
+ }
+}
+WARNING(node_name_vs_property_name, check_node_name_vs_property_name,
+ NULL, &node_name_chars);
+
static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
struct node *node)
{
@@ -363,14 +386,14 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
struct property *prop;
for_each_property(node, prop) {
- int n = strspn(prop->name, c->data);
+ size_t n = strspn(prop->name, c->data);
if (n < strlen(prop->name))
FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
prop->name[n]);
}
}
-ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
+ERROR(property_name_chars, check_property_name_chars, PROPCHARS);
static void check_property_name_chars_strict(struct check *c,
struct dt_info *dti,
@@ -380,7 +403,7 @@ static void check_property_name_chars_strict(struct check *c,
for_each_property(node, prop) {
const char *name = prop->name;
- int n = strspn(name, c->data);
+ size_t n = strspn(name, c->data);
if (n == strlen(prop->name))
continue;
@@ -497,7 +520,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop);
- if ((phandle == 0) || (phandle == -1)) {
+ if (!phandle_is_valid(phandle)) {
FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
phandle, prop->name);
return 0;
@@ -556,7 +579,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
if (!prop)
return; /* No name property, that's fine */
- if ((prop->val.len != node->basenamelen+1)
+ if ((prop->val.len != node->basenamelen + 1U)
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
" of base node name)", prop->val.val);
@@ -657,7 +680,6 @@ ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &pa
*/
WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
-WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
WARNING_IF_NOT_STRING(model_is_string, "model");
@@ -672,8 +694,7 @@ static void check_names_is_string_list(struct check *c, struct dt_info *dti,
struct property *prop;
for_each_property(node, prop) {
- const char *s = strrchr(prop->name, '-');
- if (!s || !streq(s, "-names"))
+ if (!strends(prop->name, "-names"))
continue;
c->data = prop->name;
@@ -753,7 +774,7 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
size_cells = node_size_cells(node->parent);
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
- if (!entrylen || (prop->val.len % entrylen) != 0)
+ if (!is_multiple_of(prop->val.len, entrylen))
FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) "
"(#address-cells == %d, #size-cells == %d)",
prop->val.len, addr_cells, size_cells);
@@ -794,7 +815,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
"#size-cells (%d) differs from %s (%d)",
ranges, c_size_cells, node->parent->fullpath,
p_size_cells);
- } else if ((prop->val.len % entrylen) != 0) {
+ } else if (!is_multiple_of(prop->val.len, entrylen)) {
FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) "
"(parent #address-cells == %d, child #address-cells == %d, "
"#size-cells == %d)", ranges, prop->val.len,
@@ -871,7 +892,7 @@ static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struc
} else {
cells = (cell_t *)prop->val.val;
min_bus = fdt32_to_cpu(cells[0]);
- max_bus = fdt32_to_cpu(cells[0]);
+ max_bus = fdt32_to_cpu(cells[1]);
}
if ((bus_num < min_bus) || (bus_num > max_bus))
FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
@@ -1367,9 +1388,9 @@ static void check_property_phandle_args(struct check *c,
const struct provider *provider)
{
struct node *root = dti->dt;
- int cell, cellsize = 0;
+ unsigned int cell, cellsize = 0;
- if (prop->val.len % sizeof(cell_t)) {
+ if (!is_multiple_of(prop->val.len, sizeof(cell_t))) {
FAIL_PROP(c, dti, node, prop,
"property size (%d) is invalid, expected multiple of %zu",
prop->val.len, sizeof(cell_t));
@@ -1379,14 +1400,14 @@ static void check_property_phandle_args(struct check *c,
for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
struct node *provider_node;
struct property *cellprop;
- int phandle;
+ cell_t phandle;
phandle = propval_cell_n(prop, cell);
/*
* Some bindings use a cell value 0 or -1 to skip over optional
* entries when each index position has a specific definition.
*/
- if (phandle == 0 || phandle == -1) {
+ if (!phandle_is_valid(phandle)) {
/* Give up if this is an overlay with external references */
if (dti->dtsflags & DTSF_PLUGIN)
break;
@@ -1452,7 +1473,8 @@ static void check_provider_cells_property(struct check *c,
}
#define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \
static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \
- WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references);
+ WARNING_IF_NOT_CELL(nm##_is_cell, cells_name); \
+ WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &nm##_is_cell, &phandle_references);
WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
@@ -1473,24 +1495,17 @@ WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sen
static bool prop_is_gpio(struct property *prop)
{
- char *str;
-
/*
* *-gpios and *-gpio can appear in property names,
* so skip over any false matches (only one known ATM)
*/
- if (strstr(prop->name, "nr-gpio"))
+ if (strends(prop->name, ",nr-gpios"))
return false;
- str = strrchr(prop->name, '-');
- if (str)
- str++;
- else
- str = prop->name;
- if (!(streq(str, "gpios") || streq(str, "gpio")))
- return false;
-
- return true;
+ return strends(prop->name, "-gpios") ||
+ streq(prop->name, "gpios") ||
+ strends(prop->name, "-gpio") ||
+ streq(prop->name, "gpio");
}
static void check_gpios_property(struct check *c,
@@ -1525,13 +1540,10 @@ static void check_deprecated_gpio_property(struct check *c,
struct property *prop;
for_each_property(node, prop) {
- char *str;
-
if (!prop_is_gpio(prop))
continue;
- str = strstr(prop->name, "gpio");
- if (!streq(str, "gpio"))
+ if (!strends(prop->name, "gpio"))
continue;
FAIL_PROP(c, dti, node, prop,
@@ -1561,21 +1573,106 @@ static void check_interrupt_provider(struct check *c,
struct node *node)
{
struct property *prop;
+ bool irq_provider = node_is_interrupt_provider(node);
- if (!node_is_interrupt_provider(node))
+ prop = get_property(node, "#interrupt-cells");
+ if (irq_provider && !prop) {
+ FAIL(c, dti, node,
+ "Missing '#interrupt-cells' in interrupt provider");
return;
+ }
- prop = get_property(node, "#interrupt-cells");
- if (!prop)
+ if (!irq_provider && prop) {
FAIL(c, dti, node,
- "Missing #interrupt-cells in interrupt provider");
+ "'#interrupt-cells' found, but node is not an interrupt provider");
+ return;
+ }
+}
+WARNING(interrupt_provider, check_interrupt_provider, NULL, &interrupts_extended_is_cell);
- prop = get_property(node, "#address-cells");
- if (!prop)
+static void check_interrupt_map(struct check *c,
+ struct dt_info *dti,
+ struct node *node)
+{
+ struct node *root = dti->dt;
+ struct property *prop, *irq_map_prop;
+ size_t cellsize, cell, map_cells;
+
+ irq_map_prop = get_property(node, "interrupt-map");
+ if (!irq_map_prop)
+ return;
+
+ if (node->addr_cells < 0) {
FAIL(c, dti, node,
- "Missing #address-cells in interrupt provider");
+ "Missing '#address-cells' in interrupt-map provider");
+ return;
+ }
+ cellsize = node_addr_cells(node);
+ cellsize += propval_cell(get_property(node, "#interrupt-cells"));
+
+ prop = get_property(node, "interrupt-map-mask");
+ if (prop && (prop->val.len != (cellsize * sizeof(cell_t))))
+ FAIL_PROP(c, dti, node, prop,
+ "property size (%d) is invalid, expected %zu",
+ prop->val.len, cellsize * sizeof(cell_t));
+
+ if (!is_multiple_of(irq_map_prop->val.len, sizeof(cell_t))) {
+ FAIL_PROP(c, dti, node, irq_map_prop,
+ "property size (%d) is invalid, expected multiple of %zu",
+ irq_map_prop->val.len, sizeof(cell_t));
+ return;
+ }
+
+ map_cells = irq_map_prop->val.len / sizeof(cell_t);
+ for (cell = 0; cell < map_cells; ) {
+ struct node *provider_node;
+ struct property *cellprop;
+ int phandle;
+ size_t parent_cellsize;
+
+ if ((cell + cellsize) >= map_cells) {
+ FAIL_PROP(c, dti, node, irq_map_prop,
+ "property size (%d) too small, expected > %zu",
+ irq_map_prop->val.len, (cell + cellsize) * sizeof(cell_t));
+ break;
+ }
+ cell += cellsize;
+
+ phandle = propval_cell_n(irq_map_prop, cell);
+ if (!phandle_is_valid(phandle)) {
+ /* Give up if this is an overlay with external references */
+ if (!(dti->dtsflags & DTSF_PLUGIN))
+ FAIL_PROP(c, dti, node, irq_map_prop,
+ "Cell %zu is not a phandle(%d)",
+ cell, phandle);
+ break;
+ }
+
+ provider_node = get_node_by_phandle(root, phandle);
+ if (!provider_node) {
+ FAIL_PROP(c, dti, node, irq_map_prop,
+ "Could not get phandle(%d) node for (cell %zu)",
+ phandle, cell);
+ break;
+ }
+
+ cellprop = get_property(provider_node, "#interrupt-cells");
+ if (cellprop) {
+ parent_cellsize = propval_cell(cellprop);
+ } else {
+ FAIL(c, dti, node, "Missing property '#interrupt-cells' in node %s or bad phandle (referred from interrupt-map[%zu])",
+ provider_node->fullpath, cell);
+ break;
+ }
+
+ cellprop = get_property(provider_node, "#address-cells");
+ if (cellprop)
+ parent_cellsize += propval_cell(cellprop);
+
+ cell += 1 + parent_cellsize;
+ }
}
-WARNING(interrupt_provider, check_interrupt_provider, NULL);
+WARNING(interrupt_map, check_interrupt_map, NULL, &phandle_references, &addr_size_cells, &interrupt_provider);
static void check_interrupts_property(struct check *c,
struct dt_info *dti,
@@ -1584,13 +1681,13 @@ static void check_interrupts_property(struct check *c,
struct node *root = dti->dt;
struct node *irq_node = NULL, *parent = node;
struct property *irq_prop, *prop = NULL;
- int irq_cells, phandle;
+ cell_t irq_cells, phandle;
irq_prop = get_property(node, "interrupts");
if (!irq_prop)
return;
- if (irq_prop->val.len % sizeof(cell_t))
+ if (!is_multiple_of(irq_prop->val.len, sizeof(cell_t)))
FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu",
irq_prop->val.len, sizeof(cell_t));
@@ -1603,7 +1700,7 @@ static void check_interrupts_property(struct check *c,
prop = get_property(parent, "interrupt-parent");
if (prop) {
phandle = propval_cell(prop);
- if ((phandle == 0) || (phandle == -1)) {
+ if (!phandle_is_valid(phandle)) {
/* Give up if this is an overlay with
* external references */
if (dti->dtsflags & DTSF_PLUGIN)
@@ -1639,7 +1736,7 @@ static void check_interrupts_property(struct check *c,
}
irq_cells = propval_cell(prop);
- if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) {
+ if (!is_multiple_of(irq_prop->val.len, irq_cells * sizeof(cell_t))) {
FAIL_PROP(c, dti, node, prop,
"size is (%d), expected multiple of %d",
irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
@@ -1750,7 +1847,7 @@ WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
struct node *endpoint)
{
- int phandle;
+ cell_t phandle;
struct node *node;
struct property *prop;
@@ -1760,7 +1857,7 @@ static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop);
/* Give up if this is an overlay with external references */
- if (phandle == 0 || phandle == -1)
+ if (!phandle_is_valid(phandle))
return NULL;
node = get_node_by_phandle(dti->dt, phandle);
@@ -1796,7 +1893,7 @@ WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
&node_name_chars, &node_name_format, &property_name_chars,
- &name_is_string, &name_properties,
+ &name_is_string, &name_properties, &node_name_vs_property_name,
&duplicate_label,
@@ -1804,7 +1901,7 @@ static struct check *check_table[] = {
&phandle_references, &path_references,
&omit_unused_nodes,
- &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
+ &address_cells_is_cell, &size_cells_is_cell,
&device_type_is_string, &model_is_string, &status_is_string,
&label_is_string,
@@ -1839,26 +1936,43 @@ static struct check *check_table[] = {
&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
&clocks_property,
+ &clocks_is_cell,
&cooling_device_property,
+ &cooling_device_is_cell,
&dmas_property,
+ &dmas_is_cell,
&hwlocks_property,
+ &hwlocks_is_cell,
&interrupts_extended_property,
+ &interrupts_extended_is_cell,
&io_channels_property,
+ &io_channels_is_cell,
&iommus_property,
+ &iommus_is_cell,
&mboxes_property,
+ &mboxes_is_cell,
&msi_parent_property,
+ &msi_parent_is_cell,
&mux_controls_property,
+ &mux_controls_is_cell,
&phys_property,
+ &phys_is_cell,
&power_domains_property,
+ &power_domains_is_cell,
&pwms_property,
+ &pwms_is_cell,
&resets_property,
+ &resets_is_cell,
&sound_dai_property,
+ &sound_dai_is_cell,
&thermal_sensors_property,
+ &thermal_sensors_is_cell,
&deprecated_gpio_property,
&gpios_property,
&interrupts_property,
&interrupt_provider,
+ &interrupt_map,
&alias_paths,
@@ -1882,7 +1996,7 @@ static void enable_warning_error(struct check *c, bool warn, bool error)
static void disable_warning_error(struct check *c, bool warn, bool error)
{
- int i;
+ unsigned int i;
/* Lowering level, also lower it for things this is the prereq
* for */
@@ -1903,7 +2017,7 @@ static void disable_warning_error(struct check *c, bool warn, bool error)
void parse_checks_option(bool warn, bool error, const char *arg)
{
- int i;
+ unsigned int i;
const char *name = arg;
bool enable = true;
@@ -1930,7 +2044,7 @@ void parse_checks_option(bool warn, bool error, const char *arg)
void process_checks(bool force, struct dt_info *dti)
{
- int i;
+ unsigned int i;
int error = 0;
for (i = 0; i < ARRAY_SIZE(check_table); i++) {
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
index b3b7270300de..5568b4ae84cf 100644
--- a/scripts/dtc/dtc-lexer.l
+++ b/scripts/dtc/dtc-lexer.l
@@ -57,7 +57,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
push_input_file(name);
}
-<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
+<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)* {
char *line, *fnstart, *fnend;
struct data fn;
/* skip text before line # */
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index 838c5df96c00..bc786c543b7e 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -12,7 +12,7 @@
* Command line options
*/
int quiet; /* Level of quietness */
-int reservenum; /* Number of memory reservation slots */
+unsigned int reservenum;/* Number of memory reservation slots */
int minsize; /* Minimum blob size */
int padsize; /* Additional padding to blob */
int alignsize; /* Additional padding to blob accroding to the alignsize */
@@ -197,7 +197,7 @@ int main(int argc, char *argv[])
depname = optarg;
break;
case 'R':
- reservenum = strtol(optarg, NULL, 0);
+ reservenum = strtoul(optarg, NULL, 0);
break;
case 'S':
minsize = strtol(optarg, NULL, 0);
@@ -359,8 +359,6 @@ int main(int argc, char *argv[])
#endif
} else if (streq(outform, "dtb")) {
dt_to_blob(outf, dti, outversion);
- } else if (streq(outform, "dtbo")) {
- dt_to_blob(outf, dti, outversion);
} else if (streq(outform, "asm")) {
dt_to_asm(outf, dti, outversion);
} else if (streq(outform, "null")) {
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index d3e82fb8e3db..0a1f54991026 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -35,7 +35,7 @@
* Command line options
*/
extern int quiet; /* Level of quietness */
-extern int reservenum; /* Number of memory reservation slots */
+extern unsigned int reservenum; /* Number of memory reservation slots */
extern int minsize; /* Minimum blob size */
extern int padsize; /* Additional padding to blob */
extern int alignsize; /* Additional padding to blob accroding to the alignsize */
@@ -51,6 +51,11 @@ extern int annotate; /* annotate .dts with input source location */
typedef uint32_t cell_t;
+static inline bool phandle_is_valid(cell_t phandle)
+{
+ return phandle != 0 && phandle != ~0U;
+}
+
static inline uint16_t dtb_ld16(const void *p)
{
const uint8_t *bp = (const uint8_t *)p;
@@ -86,6 +91,16 @@ static inline uint64_t dtb_ld64(const void *p)
#define streq(a, b) (strcmp((a), (b)) == 0)
#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
+static inline bool strends(const char *str, const char *suffix)
+{
+ unsigned int len, suffix_len;
+
+ len = strlen(str);
+ suffix_len = strlen(suffix);
+ if (len < suffix_len)
+ return false;
+ return streq(str + len - suffix_len, suffix);
+}
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
@@ -101,6 +116,12 @@ enum markertype {
TYPE_UINT64,
TYPE_STRING,
};
+
+static inline bool is_type_marker(enum markertype type)
+{
+ return type >= TYPE_UINT8;
+}
+
extern const char *markername(enum markertype markertype);
struct marker {
@@ -125,7 +146,22 @@ struct data {
for_each_marker(m) \
if ((m)->type == (t))
-size_t type_marker_length(struct marker *m);
+static inline struct marker *next_type_marker(struct marker *m)
+{
+ for_each_marker(m)
+ if (is_type_marker(m->type))
+ break;
+ return m;
+}
+
+static inline size_t type_marker_length(struct marker *m)
+{
+ struct marker *next = next_type_marker(m->next);
+
+ if (next)
+ return next->offset - m->offset;
+ return 0;
+}
void data_free(struct data d);
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
index 4659afbfcbab..95e43d32c3e6 100644
--- a/scripts/dtc/flattree.c
+++ b/scripts/dtc/flattree.c
@@ -124,7 +124,8 @@ static void asm_emit_cell(void *e, cell_t val)
{
FILE *f = e;
- fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n",
+ fprintf(f, "\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n"
+ "\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n",
(val >> 24) & 0xff, (val >> 16) & 0xff,
(val >> 8) & 0xff, val & 0xff);
}
@@ -134,9 +135,9 @@ static void asm_emit_string(void *e, const char *str, int len)
FILE *f = e;
if (len != 0)
- fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
+ fprintf(f, "\t.asciz\t\"%.*s\"\n", len, str);
else
- fprintf(f, "\t.string\t\"%s\"\n", str);
+ fprintf(f, "\t.asciz\t\"%s\"\n", str);
}
static void asm_emit_align(void *e, int a)
@@ -295,7 +296,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
{
struct reserve_info *re;
struct data d = empty_data;
- int j;
+ unsigned int j;
for (re = reservelist; re; re = re->next) {
d = data_append_re(d, re->address, re->size);
@@ -438,7 +439,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
while (p < (strbuf.val + strbuf.len)) {
len = strlen(p);
- fprintf(f, "\t.string \"%s\"\n", p);
+ fprintf(f, "\t.asciz \"%s\"\n", p);
p += len+1;
}
}
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 3e893073da05..9fe7cf4b747d 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -90,6 +90,10 @@ int fdt_check_header(const void *fdt)
{
size_t hdrsize;
+ /* The device tree must be at an 8-byte aligned address */
+ if ((uintptr_t)fdt & 7)
+ return -FDT_ERR_ALIGNMENT;
+
if (fdt_magic(fdt) != FDT_MAGIC)
return -FDT_ERR_BADMAGIC;
if (!can_assume(LATEST)) {
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index f13458d165d4..3621d3651d3f 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -349,7 +349,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
return offset;
/* Try to place the new node after the parent's properties */
- fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
+ tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
+ /* the fdt_subnode_offset_namelen() should ensure this never hits */
+ if (!can_assume(LIBFDT_FLAWLESS) && (tag != FDT_BEGIN_NODE))
+ return -FDT_ERR_INTERNAL;
do {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);
@@ -391,7 +394,9 @@ int fdt_del_node(void *fdt, int nodeoffset)
}
static void fdt_packblocks_(const char *old, char *new,
- int mem_rsv_size, int struct_size)
+ int mem_rsv_size,
+ int struct_size,
+ int strings_size)
{
int mem_rsv_off, struct_off, strings_off;
@@ -406,8 +411,7 @@ static void fdt_packblocks_(const char *old, char *new,
fdt_set_off_dt_struct(new, struct_off);
fdt_set_size_dt_struct(new, struct_size);
- memmove(new + strings_off, old + fdt_off_dt_strings(old),
- fdt_size_dt_strings(old));
+ memmove(new + strings_off, old + fdt_off_dt_strings(old), strings_size);
fdt_set_off_dt_strings(new, strings_off);
fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
}
@@ -467,7 +471,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
return -FDT_ERR_NOSPACE;
}
- fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size);
+ fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size,
+ fdt_size_dt_strings(fdt));
memmove(buf, tmp, newsize);
fdt_set_magic(buf, FDT_MAGIC);
@@ -487,7 +492,8 @@ int fdt_pack(void *fdt)
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);
- fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
+ fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt),
+ fdt_size_dt_strings(fdt));
fdt_set_totalsize(fdt, fdt_data_size_(fdt));
return 0;
diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c
index b4356931b06d..d852b77e81e7 100644
--- a/scripts/dtc/libfdt/fdt_strerror.c
+++ b/scripts/dtc/libfdt/fdt_strerror.c
@@ -39,6 +39,7 @@ static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
FDT_ERRTABENT(FDT_ERR_BADFLAGS),
+ FDT_ERRTABENT(FDT_ERR_ALIGNMENT),
};
#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0])))
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index c42807a7663e..ce31e844856a 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -131,6 +131,13 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
* to work even with unaligned pointers on platforms (such as ARMv5) that don't
* like unaligned loads and stores.
*/
+static inline uint16_t fdt16_ld(const fdt16_t *p)
+{
+ const uint8_t *bp = (const uint8_t *)p;
+
+ return ((uint16_t)bp[0] << 8) | bp[1];
+}
+
static inline uint32_t fdt32_ld(const fdt32_t *p)
{
const uint8_t *bp = (const uint8_t *)p;
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index 7eacd0248641..cc612370ec61 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -526,7 +526,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
p = strchr(path, '/');
for_each_child(tree, child) {
- if (p && strprefixeq(path, p - path, child->name))
+ if (p && strprefixeq(path, (size_t)(p - path), child->name))
return get_node_by_path(child, p+1);
else if (!p && streq(path, child->name))
return child;
@@ -559,7 +559,7 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
{
struct node *child, *node;
- if ((phandle == 0) || (phandle == -1)) {
+ if (!phandle_is_valid(phandle)) {
assert(generate_fixups);
return NULL;
}
@@ -594,7 +594,7 @@ cell_t get_node_phandle(struct node *root, struct node *node)
static cell_t phandle = 1; /* FIXME: ick, static local */
struct data d = empty_data;
- if ((node->phandle != 0) && (node->phandle != -1))
+ if (phandle_is_valid(node->phandle))
return node->phandle;
while (get_node_by_phandle(root, phandle))
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
index 061ba8c9c5e8..33fedee82d58 100644
--- a/scripts/dtc/treesource.c
+++ b/scripts/dtc/treesource.c
@@ -124,27 +124,6 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
}
}
-static bool has_data_type_information(struct marker *m)
-{
- return m->type >= TYPE_UINT8;
-}
-
-static struct marker *next_type_marker(struct marker *m)
-{
- while (m && !has_data_type_information(m))
- m = m->next;
- return m;
-}
-
-size_t type_marker_length(struct marker *m)
-{
- struct marker *next = next_type_marker(m->next);
-
- if (next)
- return next->offset - m->offset;
- return 0;
-}
-
static const char *delim_start[] = {
[TYPE_UINT8] = "[",
[TYPE_UINT16] = "/bits/ 16 <",
@@ -229,26 +208,39 @@ static void write_propval(FILE *f, struct property *prop)
size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
size_t data_len = type_marker_length(m) ? : len - m->offset;
const char *p = &prop->val.val[m->offset];
+ struct marker *m_phandle;
- if (has_data_type_information(m)) {
+ if (is_type_marker(m->type)) {
emit_type = m->type;
fprintf(f, " %s", delim_start[emit_type]);
} else if (m->type == LABEL)
fprintf(f, " %s:", m->ref);
- else if (m->offset)
- fputc(' ', f);
- if (emit_type == TYPE_NONE) {
- assert(chunk_len == 0);
+ if (emit_type == TYPE_NONE || chunk_len == 0)
continue;
- }
switch(emit_type) {
case TYPE_UINT16:
write_propval_int(f, p, chunk_len, 2);
break;
case TYPE_UINT32:
- write_propval_int(f, p, chunk_len, 4);
+ m_phandle = prop->val.markers;
+ for_each_marker_of_type(m_phandle, REF_PHANDLE)
+ if (m->offset == m_phandle->offset)
+ break;
+
+ if (m_phandle) {
+ if (m_phandle->ref[0] == '/')
+ fprintf(f, "&{%s}", m_phandle->ref);
+ else
+ fprintf(f, "&%s", m_phandle->ref);
+ if (chunk_len > 4) {
+ fputc(' ', f);
+ write_propval_int(f, p + 4, chunk_len - 4, 4);
+ }
+ } else {
+ write_propval_int(f, p, chunk_len, 4);
+ }
break;
case TYPE_UINT64:
write_propval_int(f, p, chunk_len, 8);
diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
index a771b4654c76..c45b2c295aa5 100644
--- a/scripts/dtc/util.h
+++ b/scripts/dtc/util.h
@@ -13,10 +13,10 @@
*/
#ifdef __GNUC__
-#ifdef __clang__
-#define PRINTF(i, j) __attribute__((format (printf, i, j)))
-#else
+#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
#define PRINTF(i, j) __attribute__((format (gnu_printf, i, j)))
+#else
+#define PRINTF(i, j) __attribute__((format (printf, i, j)))
#endif
#define NORETURN __attribute__((noreturn))
#else
diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h
index 73a7839603f1..785cc4c57326 100644
--- a/scripts/dtc/version_gen.h
+++ b/scripts/dtc/version_gen.h
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.6.0-g183df9e9"
+#define DTC_VERSION "DTC 1.6.1-g0a3a9d34"
diff --git a/scripts/dtc/yamltree.c b/scripts/dtc/yamltree.c
index e63d32fe142a..55908c829c98 100644
--- a/scripts/dtc/yamltree.c
+++ b/scripts/dtc/yamltree.c
@@ -29,11 +29,12 @@ char *yaml_error_name[] = {
(emitter)->problem, __func__, __LINE__); \
})
-static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, unsigned int len, int width)
+static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers,
+ char *data, unsigned int seq_offset, unsigned int len, int width)
{
yaml_event_t event;
void *tag;
- unsigned int off, start_offset = markers->offset;
+ unsigned int off;
switch(width) {
case 1: tag = "!u8"; break;
@@ -66,7 +67,7 @@ static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, ch
m = markers;
is_phandle = false;
for_each_marker_of_type(m, REF_PHANDLE) {
- if (m->offset == (start_offset + off)) {
+ if (m->offset == (seq_offset + off)) {
is_phandle = true;
break;
}
@@ -114,6 +115,7 @@ static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
yaml_event_t event;
unsigned int len = prop->val.len;
struct marker *m = prop->val.markers;
+ struct marker *markers = prop->val.markers;
/* Emit the property name */
yaml_scalar_event_initialize(&event, NULL,
@@ -151,19 +153,19 @@ static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
switch(m->type) {
case TYPE_UINT16:
- yaml_propval_int(emitter, m, data, chunk_len, 2);
+ yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 2);
break;
case TYPE_UINT32:
- yaml_propval_int(emitter, m, data, chunk_len, 4);
+ yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 4);
break;
case TYPE_UINT64:
- yaml_propval_int(emitter, m, data, chunk_len, 8);
+ yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 8);
break;
case TYPE_STRING:
yaml_propval_string(emitter, data, chunk_len);
break;
default:
- yaml_propval_int(emitter, m, data, chunk_len, 1);
+ yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 1);
break;
}
}