summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scripts/dtc/Makefile7
-rw-r--r--scripts/dtc/Makefile.dtc4
-rw-r--r--scripts/dtc/checks.c143
-rw-r--r--scripts/dtc/data.c4
-rw-r--r--scripts/dtc/dtc-parser.y16
-rw-r--r--scripts/dtc/dtc.c11
-rw-r--r--scripts/dtc/dtc.h13
-rw-r--r--scripts/dtc/flattree.c2
-rw-r--r--scripts/dtc/libfdt/fdt.c81
-rw-r--r--scripts/dtc/libfdt/fdt_addresses.c35
-rw-r--r--scripts/dtc/libfdt/fdt_overlay.c6
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c199
-rw-r--r--scripts/dtc/libfdt/fdt_rw.c28
-rw-r--r--scripts/dtc/libfdt/fdt_sw.c109
-rw-r--r--scripts/dtc/libfdt/libfdt.h76
-rw-r--r--scripts/dtc/libfdt/libfdt_env.h1
-rw-r--r--scripts/dtc/libfdt/libfdt_internal.h5
-rw-r--r--scripts/dtc/livetree.c12
-rw-r--r--scripts/dtc/treesource.c225
-rw-r--r--scripts/dtc/util.c23
-rw-r--r--scripts/dtc/util.h20
-rw-r--r--scripts/dtc/version_gen.h2
-rw-r--r--scripts/dtc/yamltree.c247
23 files changed, 1033 insertions, 236 deletions
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
index 1c943e03eaf2..81c6f5132f12 100644
--- a/scripts/dtc/Makefile
+++ b/scripts/dtc/Makefile
@@ -11,6 +11,13 @@ dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
11# Source files need to get at the userspace version of libfdt_env.h to compile 11# Source files need to get at the userspace version of libfdt_env.h to compile
12HOST_EXTRACFLAGS := -I$(src)/libfdt 12HOST_EXTRACFLAGS := -I$(src)/libfdt
13 13
14ifeq ($(wildcard /usr/include/yaml.h),)
15HOST_EXTRACFLAGS += -DNO_YAML
16else
17dtc-objs += yamltree.o
18HOSTLDLIBS_dtc := -lyaml
19endif
20
14# Generated files need one more search path to include headers in source tree 21# Generated files need one more search path to include headers in source tree
15HOSTCFLAGS_dtc-lexer.lex.o := -I$(src) 22HOSTCFLAGS_dtc-lexer.lex.o := -I$(src)
16HOSTCFLAGS_dtc-parser.tab.o := -I$(src) 23HOSTCFLAGS_dtc-parser.tab.o := -I$(src)
diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc
index bece49b35535..d4375630a7f7 100644
--- a/scripts/dtc/Makefile.dtc
+++ b/scripts/dtc/Makefile.dtc
@@ -14,5 +14,9 @@ DTC_SRCS = \
14 treesource.c \ 14 treesource.c \
15 util.c 15 util.c
16 16
17ifneq ($(NO_YAML),1)
18DTC_SRCS += yamltree.c
19endif
20
17DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c 21DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
18DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o) 22DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
index a2cc1036c915..9c9b0c328af6 100644
--- a/scripts/dtc/checks.c
+++ b/scripts/dtc/checks.c
@@ -962,6 +962,143 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
962} 962}
963WARNING(simple_bus_reg, check_simple_bus_reg, NULL, &reg_format, &simple_bus_bridge); 963WARNING(simple_bus_reg, check_simple_bus_reg, NULL, &reg_format, &simple_bus_bridge);
964 964
965static const struct bus_type i2c_bus = {
966 .name = "i2c-bus",
967};
968
969static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
970{
971 if (strprefixeq(node->name, node->basenamelen, "i2c-bus") ||
972 strprefixeq(node->name, node->basenamelen, "i2c-arb")) {
973 node->bus = &i2c_bus;
974 } else if (strprefixeq(node->name, node->basenamelen, "i2c")) {
975 struct node *child;
976 for_each_child(node, child) {
977 if (strprefixeq(child->name, node->basenamelen, "i2c-bus"))
978 return;
979 }
980 node->bus = &i2c_bus;
981 } else
982 return;
983
984 if (!node->children)
985 return;
986
987 if (node_addr_cells(node) != 1)
988 FAIL(c, dti, node, "incorrect #address-cells for I2C bus");
989 if (node_size_cells(node) != 0)
990 FAIL(c, dti, node, "incorrect #size-cells for I2C bus");
991
992}
993WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells);
994
995static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
996{
997 struct property *prop;
998 const char *unitname = get_unitname(node);
999 char unit_addr[17];
1000 uint32_t reg = 0;
1001 int len;
1002 cell_t *cells = NULL;
1003
1004 if (!node->parent || (node->parent->bus != &i2c_bus))
1005 return;
1006
1007 prop = get_property(node, "reg");
1008 if (prop)
1009 cells = (cell_t *)prop->val.val;
1010
1011 if (!cells) {
1012 FAIL(c, dti, node, "missing or empty reg property");
1013 return;
1014 }
1015
1016 reg = fdt32_to_cpu(*cells);
1017 snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
1018 if (!streq(unitname, unit_addr))
1019 FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"",
1020 unit_addr);
1021
1022 for (len = prop->val.len; len > 0; len -= 4) {
1023 reg = fdt32_to_cpu(*(cells++));
1024 if (reg > 0x3ff)
1025 FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",
1026 reg);
1027
1028 }
1029}
1030WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, &reg_format, &i2c_bus_bridge);
1031
1032static const struct bus_type spi_bus = {
1033 .name = "spi-bus",
1034};
1035
1036static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
1037{
1038
1039 if (strprefixeq(node->name, node->basenamelen, "spi")) {
1040 node->bus = &spi_bus;
1041 } else {
1042 /* Try to detect SPI buses which don't have proper node name */
1043 struct node *child;
1044
1045 if (node_addr_cells(node) != 1 || node_size_cells(node) != 0)
1046 return;
1047
1048 for_each_child(node, child) {
1049 struct property *prop;
1050 for_each_property(child, prop) {
1051 if (strprefixeq(prop->name, 4, "spi-")) {
1052 node->bus = &spi_bus;
1053 break;
1054 }
1055 }
1056 if (node->bus == &spi_bus)
1057 break;
1058 }
1059
1060 if (node->bus == &spi_bus && get_property(node, "reg"))
1061 FAIL(c, dti, node, "node name for SPI buses should be 'spi'");
1062 }
1063 if (node->bus != &spi_bus || !node->children)
1064 return;
1065
1066 if (node_addr_cells(node) != 1)
1067 FAIL(c, dti, node, "incorrect #address-cells for SPI bus");
1068 if (node_size_cells(node) != 0)
1069 FAIL(c, dti, node, "incorrect #size-cells for SPI bus");
1070
1071}
1072WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells);
1073
1074static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
1075{
1076 struct property *prop;
1077 const char *unitname = get_unitname(node);
1078 char unit_addr[9];
1079 uint32_t reg = 0;
1080 cell_t *cells = NULL;
1081
1082 if (!node->parent || (node->parent->bus != &spi_bus))
1083 return;
1084
1085 prop = get_property(node, "reg");
1086 if (prop)
1087 cells = (cell_t *)prop->val.val;
1088
1089 if (!cells) {
1090 FAIL(c, dti, node, "missing or empty reg property");
1091 return;
1092 }
1093
1094 reg = fdt32_to_cpu(*cells);
1095 snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
1096 if (!streq(unitname, unit_addr))
1097 FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"",
1098 unit_addr);
1099}
1100WARNING(spi_bus_reg, check_spi_bus_reg, NULL, &reg_format, &spi_bus_bridge);
1101
965static void check_unit_address_format(struct check *c, struct dt_info *dti, 1102static void check_unit_address_format(struct check *c, struct dt_info *dti,
966 struct node *node) 1103 struct node *node)
967{ 1104{
@@ -1582,6 +1719,12 @@ static struct check *check_table[] = {
1582 &simple_bus_bridge, 1719 &simple_bus_bridge,
1583 &simple_bus_reg, 1720 &simple_bus_reg,
1584 1721
1722 &i2c_bus_bridge,
1723 &i2c_bus_reg,
1724
1725 &spi_bus_bridge,
1726 &spi_bus_reg,
1727
1585 &avoid_default_addr_size, 1728 &avoid_default_addr_size,
1586 &avoid_unnecessary_addr_size, 1729 &avoid_unnecessary_addr_size,
1587 &unique_unit_address, 1730 &unique_unit_address,
diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
index aa37a16c8891..4a204145cc7b 100644
--- a/scripts/dtc/data.c
+++ b/scripts/dtc/data.c
@@ -74,7 +74,8 @@ struct data data_copy_escape_string(const char *s, int len)
74 struct data d; 74 struct data d;
75 char *q; 75 char *q;
76 76
77 d = data_grow_for(empty_data, len + 1); 77 d = data_add_marker(empty_data, TYPE_STRING, NULL);
78 d = data_grow_for(d, len + 1);
78 79
79 q = d.val; 80 q = d.val;
80 while (i < len) { 81 while (i < len) {
@@ -94,6 +95,7 @@ struct data data_copy_file(FILE *f, size_t maxlen)
94{ 95{
95 struct data d = empty_data; 96 struct data d = empty_data;
96 97
98 d = data_add_marker(d, TYPE_NONE, NULL);
97 while (!feof(f) && (d.len < maxlen)) { 99 while (!feof(f) && (d.len < maxlen)) {
98 size_t chunksize, ret; 100 size_t chunksize, ret;
99 101
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
index 011a5b25539a..dd70ebf386f4 100644
--- a/scripts/dtc/dtc-parser.y
+++ b/scripts/dtc/dtc-parser.y
@@ -287,6 +287,7 @@ propdata:
287 } 287 }
288 | propdataprefix DT_REF 288 | propdataprefix DT_REF
289 { 289 {
290 $1 = data_add_marker($1, TYPE_STRING, $2);
290 $$ = data_add_marker($1, REF_PATH, $2); 291 $$ = data_add_marker($1, REF_PATH, $2);
291 } 292 }
292 | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' 293 | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
@@ -340,22 +341,27 @@ arrayprefix:
340 DT_BITS DT_LITERAL '<' 341 DT_BITS DT_LITERAL '<'
341 { 342 {
342 unsigned long long bits; 343 unsigned long long bits;
344 enum markertype type = TYPE_UINT32;
343 345
344 bits = $2; 346 bits = $2;
345 347
346 if ((bits != 8) && (bits != 16) && 348 switch (bits) {
347 (bits != 32) && (bits != 64)) { 349 case 8: type = TYPE_UINT8; break;
350 case 16: type = TYPE_UINT16; break;
351 case 32: type = TYPE_UINT32; break;
352 case 64: type = TYPE_UINT64; break;
353 default:
348 ERROR(&@2, "Array elements must be" 354 ERROR(&@2, "Array elements must be"
349 " 8, 16, 32 or 64-bits"); 355 " 8, 16, 32 or 64-bits");
350 bits = 32; 356 bits = 32;
351 } 357 }
352 358
353 $$.data = empty_data; 359 $$.data = data_add_marker(empty_data, type, NULL);
354 $$.bits = bits; 360 $$.bits = bits;
355 } 361 }
356 | '<' 362 | '<'
357 { 363 {
358 $$.data = empty_data; 364 $$.data = data_add_marker(empty_data, TYPE_UINT32, NULL);
359 $$.bits = 32; 365 $$.bits = 32;
360 } 366 }
361 | arrayprefix integer_prim 367 | arrayprefix integer_prim
@@ -499,7 +505,7 @@ integer_unary:
499bytestring: 505bytestring:
500 /* empty */ 506 /* empty */
501 { 507 {
502 $$ = empty_data; 508 $$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
503 } 509 }
504 | bytestring DT_BYTE 510 | bytestring DT_BYTE
505 { 511 {
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index c36994e6eac5..64134aadb997 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -95,6 +95,9 @@ static const char * const usage_opts_help[] = {
95 "\n\tOutput formats are:\n" 95 "\n\tOutput formats are:\n"
96 "\t\tdts - device tree source text\n" 96 "\t\tdts - device tree source text\n"
97 "\t\tdtb - device tree blob\n" 97 "\t\tdtb - device tree blob\n"
98#ifndef NO_YAML
99 "\t\tyaml - device tree encoded as YAML\n"
100#endif
98 "\t\tasm - assembler source", 101 "\t\tasm - assembler source",
99 "\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)", 102 "\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
100 "\n\tOutput dependency file", 103 "\n\tOutput dependency file",
@@ -128,6 +131,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
128 return fallback; 131 return fallback;
129 if (!strcasecmp(s, ".dts")) 132 if (!strcasecmp(s, ".dts"))
130 return "dts"; 133 return "dts";
134 if (!strcasecmp(s, ".yaml"))
135 return "yaml";
131 if (!strcasecmp(s, ".dtb")) 136 if (!strcasecmp(s, ".dtb"))
132 return "dtb"; 137 return "dtb";
133 return fallback; 138 return fallback;
@@ -350,6 +355,12 @@ int main(int argc, char *argv[])
350 355
351 if (streq(outform, "dts")) { 356 if (streq(outform, "dts")) {
352 dt_to_source(outf, dti); 357 dt_to_source(outf, dti);
358#ifndef NO_YAML
359 } else if (streq(outform, "yaml")) {
360 if (!streq(inform, "dts"))
361 die("YAML output format requires dts input format\n");
362 dt_to_yaml(outf, dti);
363#endif
353 } else if (streq(outform, "dtb")) { 364 } else if (streq(outform, "dtb")) {
354 dt_to_blob(outf, dti, outversion); 365 dt_to_blob(outf, dti, outversion);
355 } else if (streq(outform, "asm")) { 366 } else if (streq(outform, "asm")) {
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index 6d667701ab6a..cbe541525c2c 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -74,10 +74,17 @@ typedef uint32_t cell_t;
74 74
75/* Data blobs */ 75/* Data blobs */
76enum markertype { 76enum markertype {
77 TYPE_NONE,
77 REF_PHANDLE, 78 REF_PHANDLE,
78 REF_PATH, 79 REF_PATH,
79 LABEL, 80 LABEL,
81 TYPE_UINT8,
82 TYPE_UINT16,
83 TYPE_UINT32,
84 TYPE_UINT64,
85 TYPE_STRING,
80}; 86};
87extern const char *markername(enum markertype markertype);
81 88
82struct marker { 89struct marker {
83 enum markertype type; 90 enum markertype type;
@@ -101,6 +108,8 @@ struct data {
101 for_each_marker(m) \ 108 for_each_marker(m) \
102 if ((m)->type == (t)) 109 if ((m)->type == (t))
103 110
111size_t type_marker_length(struct marker *m);
112
104void data_free(struct data d); 113void data_free(struct data d);
105 114
106struct data data_grow_for(struct data d, int xlen); 115struct data data_grow_for(struct data d, int xlen);
@@ -290,6 +299,10 @@ struct dt_info *dt_from_blob(const char *fname);
290void dt_to_source(FILE *f, struct dt_info *dti); 299void dt_to_source(FILE *f, struct dt_info *dti);
291struct dt_info *dt_from_source(const char *f); 300struct dt_info *dt_from_source(const char *f);
292 301
302/* YAML source */
303
304void dt_to_yaml(FILE *f, struct dt_info *dti);
305
293/* FS trees */ 306/* FS trees */
294 307
295struct dt_info *dt_from_fs(const char *dirname); 308struct dt_info *dt_from_fs(const char *dirname);
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
index 8d268fb785db..851ea87dbc0f 100644
--- a/scripts/dtc/flattree.c
+++ b/scripts/dtc/flattree.c
@@ -393,7 +393,7 @@ void dt_to_blob(FILE *f, struct dt_info *dti, int version)
393 padlen = 0; 393 padlen = 0;
394 if (quiet < 1) 394 if (quiet < 1)
395 fprintf(stderr, 395 fprintf(stderr,
396 "Warning: blob size %d >= minimum size %d\n", 396 "Warning: blob size %"PRIu32" >= minimum size %d\n",
397 fdt32_to_cpu(fdt.totalsize), minsize); 397 fdt32_to_cpu(fdt.totalsize), minsize);
398 } 398 }
399 } 399 }
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 7855a1787763..ae03b1112961 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -55,7 +55,12 @@
55 55
56#include "libfdt_internal.h" 56#include "libfdt_internal.h"
57 57
58int fdt_check_header(const void *fdt) 58/*
59 * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
60 * that the given buffer contains what appears to be a flattened
61 * device tree with sane information in its header.
62 */
63int fdt_ro_probe_(const void *fdt)
59{ 64{
60 if (fdt_magic(fdt) == FDT_MAGIC) { 65 if (fdt_magic(fdt) == FDT_MAGIC) {
61 /* Complete tree */ 66 /* Complete tree */
@@ -74,6 +79,78 @@ int fdt_check_header(const void *fdt)
74 return 0; 79 return 0;
75} 80}
76 81
82static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
83{
84 return (off >= hdrsize) && (off <= totalsize);
85}
86
87static int check_block_(uint32_t hdrsize, uint32_t totalsize,
88 uint32_t base, uint32_t size)
89{
90 if (!check_off_(hdrsize, totalsize, base))
91 return 0; /* block start out of bounds */
92 if ((base + size) < base)
93 return 0; /* overflow */
94 if (!check_off_(hdrsize, totalsize, base + size))
95 return 0; /* block end out of bounds */
96 return 1;
97}
98
99size_t fdt_header_size_(uint32_t version)
100{
101 if (version <= 1)
102 return FDT_V1_SIZE;
103 else if (version <= 2)
104 return FDT_V2_SIZE;
105 else if (version <= 3)
106 return FDT_V3_SIZE;
107 else if (version <= 16)
108 return FDT_V16_SIZE;
109 else
110 return FDT_V17_SIZE;
111}
112
113int fdt_check_header(const void *fdt)
114{
115 size_t hdrsize;
116
117 if (fdt_magic(fdt) != FDT_MAGIC)
118 return -FDT_ERR_BADMAGIC;
119 hdrsize = fdt_header_size(fdt);
120 if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
121 || (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION))
122 return -FDT_ERR_BADVERSION;
123 if (fdt_version(fdt) < fdt_last_comp_version(fdt))
124 return -FDT_ERR_BADVERSION;
125
126 if ((fdt_totalsize(fdt) < hdrsize)
127 || (fdt_totalsize(fdt) > INT_MAX))
128 return -FDT_ERR_TRUNCATED;
129
130 /* Bounds check memrsv block */
131 if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt)))
132 return -FDT_ERR_TRUNCATED;
133
134 /* Bounds check structure block */
135 if (fdt_version(fdt) < 17) {
136 if (!check_off_(hdrsize, fdt_totalsize(fdt),
137 fdt_off_dt_struct(fdt)))
138 return -FDT_ERR_TRUNCATED;
139 } else {
140 if (!check_block_(hdrsize, fdt_totalsize(fdt),
141 fdt_off_dt_struct(fdt),
142 fdt_size_dt_struct(fdt)))
143 return -FDT_ERR_TRUNCATED;
144 }
145
146 /* Bounds check strings block */
147 if (!check_block_(hdrsize, fdt_totalsize(fdt),
148 fdt_off_dt_strings(fdt), fdt_size_dt_strings(fdt)))
149 return -FDT_ERR_TRUNCATED;
150
151 return 0;
152}
153
77const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) 154const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
78{ 155{
79 unsigned absoffset = offset + fdt_off_dt_struct(fdt); 156 unsigned absoffset = offset + fdt_off_dt_struct(fdt);
@@ -244,7 +321,7 @@ const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
244 321
245int fdt_move(const void *fdt, void *buf, int bufsize) 322int fdt_move(const void *fdt, void *buf, int bufsize)
246{ 323{
247 FDT_CHECK_HEADER(fdt); 324 FDT_RO_PROBE(fdt);
248 325
249 if (fdt_totalsize(fdt) > bufsize) 326 if (fdt_totalsize(fdt) > bufsize)
250 return -FDT_ERR_NOSPACE; 327 return -FDT_ERR_NOSPACE;
diff --git a/scripts/dtc/libfdt/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c
index eff4dbcc729d..49537b578d03 100644
--- a/scripts/dtc/libfdt/fdt_addresses.c
+++ b/scripts/dtc/libfdt/fdt_addresses.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * libfdt - Flat Device Tree manipulation 2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au> 3 * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
4 * Copyright (C) 2018 embedded brains GmbH
4 * 5 *
5 * libfdt is dual licensed: you can use it either under the terms of 6 * libfdt is dual licensed: you can use it either under the terms of
6 * the GPL, or the BSD license, at your option. 7 * the GPL, or the BSD license, at your option.
@@ -55,42 +56,32 @@
55 56
56#include "libfdt_internal.h" 57#include "libfdt_internal.h"
57 58
58int fdt_address_cells(const void *fdt, int nodeoffset) 59static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
59{ 60{
60 const fdt32_t *ac; 61 const fdt32_t *c;
61 int val; 62 int val;
62 int len; 63 int len;
63 64
64 ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len); 65 c = fdt_getprop(fdt, nodeoffset, name, &len);
65 if (!ac) 66 if (!c)
66 return 2; 67 return 2;
67 68
68 if (len != sizeof(*ac)) 69 if (len != sizeof(*c))
69 return -FDT_ERR_BADNCELLS; 70 return -FDT_ERR_BADNCELLS;
70 71
71 val = fdt32_to_cpu(*ac); 72 val = fdt32_to_cpu(*c);
72 if ((val <= 0) || (val > FDT_MAX_NCELLS)) 73 if ((val <= 0) || (val > FDT_MAX_NCELLS))
73 return -FDT_ERR_BADNCELLS; 74 return -FDT_ERR_BADNCELLS;
74 75
75 return val; 76 return val;
76} 77}
77 78
78int fdt_size_cells(const void *fdt, int nodeoffset) 79int fdt_address_cells(const void *fdt, int nodeoffset)
79{ 80{
80 const fdt32_t *sc; 81 return fdt_cells(fdt, nodeoffset, "#address-cells");
81 int val; 82}
82 int len;
83
84 sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
85 if (!sc)
86 return 2;
87
88 if (len != sizeof(*sc))
89 return -FDT_ERR_BADNCELLS;
90
91 val = fdt32_to_cpu(*sc);
92 if ((val < 0) || (val > FDT_MAX_NCELLS))
93 return -FDT_ERR_BADNCELLS;
94 83
95 return val; 84int fdt_size_cells(const void *fdt, int nodeoffset)
85{
86 return fdt_cells(fdt, nodeoffset, "#size-cells");
96} 87}
diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c
index bf75388ec9a2..5fdab6c6371d 100644
--- a/scripts/dtc/libfdt/fdt_overlay.c
+++ b/scripts/dtc/libfdt/fdt_overlay.c
@@ -697,7 +697,7 @@ static int get_path_len(const void *fdt, int nodeoffset)
697 int len = 0, namelen; 697 int len = 0, namelen;
698 const char *name; 698 const char *name;
699 699
700 FDT_CHECK_HEADER(fdt); 700 FDT_RO_PROBE(fdt);
701 701
702 for (;;) { 702 for (;;) {
703 name = fdt_get_name(fdt, nodeoffset, &namelen); 703 name = fdt_get_name(fdt, nodeoffset, &namelen);
@@ -866,8 +866,8 @@ int fdt_overlay_apply(void *fdt, void *fdto)
866 uint32_t delta = fdt_get_max_phandle(fdt); 866 uint32_t delta = fdt_get_max_phandle(fdt);
867 int ret; 867 int ret;
868 868
869 FDT_CHECK_HEADER(fdt); 869 FDT_RO_PROBE(fdt);
870 FDT_CHECK_HEADER(fdto); 870 FDT_RO_PROBE(fdto);
871 871
872 ret = overlay_adjust_local_phandles(fdto, delta); 872 ret = overlay_adjust_local_phandles(fdto, delta);
873 if (ret) 873 if (ret)
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index dfb3236da388..eafc14282892 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -76,17 +76,72 @@ static int fdt_nodename_eq_(const void *fdt, int offset,
76 return 0; 76 return 0;
77} 77}
78 78
79const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
80{
81 uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt);
82 size_t len;
83 int err;
84 const char *s, *n;
85
86 err = fdt_ro_probe_(fdt);
87 if (err != 0)
88 goto fail;
89
90 err = -FDT_ERR_BADOFFSET;
91 if (absoffset >= fdt_totalsize(fdt))
92 goto fail;
93 len = fdt_totalsize(fdt) - absoffset;
94
95 if (fdt_magic(fdt) == FDT_MAGIC) {
96 if (stroffset < 0)
97 goto fail;
98 if (fdt_version(fdt) >= 17) {
99 if (stroffset >= fdt_size_dt_strings(fdt))
100 goto fail;
101 if ((fdt_size_dt_strings(fdt) - stroffset) < len)
102 len = fdt_size_dt_strings(fdt) - stroffset;
103 }
104 } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
105 if ((stroffset >= 0)
106 || (stroffset < -fdt_size_dt_strings(fdt)))
107 goto fail;
108 if ((-stroffset) < len)
109 len = -stroffset;
110 } else {
111 err = -FDT_ERR_INTERNAL;
112 goto fail;
113 }
114
115 s = (const char *)fdt + absoffset;
116 n = memchr(s, '\0', len);
117 if (!n) {
118 /* missing terminating NULL */
119 err = -FDT_ERR_TRUNCATED;
120 goto fail;
121 }
122
123 if (lenp)
124 *lenp = n - s;
125 return s;
126
127fail:
128 if (lenp)
129 *lenp = err;
130 return NULL;
131}
132
79const char *fdt_string(const void *fdt, int stroffset) 133const char *fdt_string(const void *fdt, int stroffset)
80{ 134{
81 return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; 135 return fdt_get_string(fdt, stroffset, NULL);
82} 136}
83 137
84static int fdt_string_eq_(const void *fdt, int stroffset, 138static int fdt_string_eq_(const void *fdt, int stroffset,
85 const char *s, int len) 139 const char *s, int len)
86{ 140{
87 const char *p = fdt_string(fdt, stroffset); 141 int slen;
142 const char *p = fdt_get_string(fdt, stroffset, &slen);
88 143
89 return (strlen(p) == len) && (memcmp(p, s, len) == 0); 144 return p && (slen == len) && (memcmp(p, s, len) == 0);
90} 145}
91 146
92uint32_t fdt_get_max_phandle(const void *fdt) 147uint32_t fdt_get_max_phandle(const void *fdt)
@@ -115,21 +170,42 @@ uint32_t fdt_get_max_phandle(const void *fdt)
115 return 0; 170 return 0;
116} 171}
117 172
173static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
174{
175 int offset = n * sizeof(struct fdt_reserve_entry);
176 int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
177
178 if (absoffset < fdt_off_mem_rsvmap(fdt))
179 return NULL;
180 if (absoffset > fdt_totalsize(fdt) - sizeof(struct fdt_reserve_entry))
181 return NULL;
182 return fdt_mem_rsv_(fdt, n);
183}
184
118int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) 185int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
119{ 186{
120 FDT_CHECK_HEADER(fdt); 187 const struct fdt_reserve_entry *re;
121 *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address); 188
122 *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size); 189 FDT_RO_PROBE(fdt);
190 re = fdt_mem_rsv(fdt, n);
191 if (!re)
192 return -FDT_ERR_BADOFFSET;
193
194 *address = fdt64_ld(&re->address);
195 *size = fdt64_ld(&re->size);
123 return 0; 196 return 0;
124} 197}
125 198
126int fdt_num_mem_rsv(const void *fdt) 199int fdt_num_mem_rsv(const void *fdt)
127{ 200{
128 int i = 0; 201 int i;
202 const struct fdt_reserve_entry *re;
129 203
130 while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0) 204 for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
131 i++; 205 if (fdt64_ld(&re->size) == 0)
132 return i; 206 return i;
207 }
208 return -FDT_ERR_TRUNCATED;
133} 209}
134 210
135static int nextprop_(const void *fdt, int offset) 211static int nextprop_(const void *fdt, int offset)
@@ -161,7 +237,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
161{ 237{
162 int depth; 238 int depth;
163 239
164 FDT_CHECK_HEADER(fdt); 240 FDT_RO_PROBE(fdt);
165 241
166 for (depth = 0; 242 for (depth = 0;
167 (offset >= 0) && (depth >= 0); 243 (offset >= 0) && (depth >= 0);
@@ -187,7 +263,7 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
187 const char *p = path; 263 const char *p = path;
188 int offset = 0; 264 int offset = 0;
189 265
190 FDT_CHECK_HEADER(fdt); 266 FDT_RO_PROBE(fdt);
191 267
192 /* see if we have an alias */ 268 /* see if we have an alias */
193 if (*path != '/') { 269 if (*path != '/') {
@@ -237,7 +313,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
237 const char *nameptr; 313 const char *nameptr;
238 int err; 314 int err;
239 315
240 if (((err = fdt_check_header(fdt)) != 0) 316 if (((err = fdt_ro_probe_(fdt)) != 0)
241 || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) 317 || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
242 goto fail; 318 goto fail;
243 319
@@ -303,7 +379,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
303 prop = fdt_offset_ptr_(fdt, offset); 379 prop = fdt_offset_ptr_(fdt, offset);
304 380
305 if (lenp) 381 if (lenp)
306 *lenp = fdt32_to_cpu(prop->len); 382 *lenp = fdt32_ld(&prop->len);
307 383
308 return prop; 384 return prop;
309} 385}
@@ -340,7 +416,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
340 offset = -FDT_ERR_INTERNAL; 416 offset = -FDT_ERR_INTERNAL;
341 break; 417 break;
342 } 418 }
343 if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff), 419 if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
344 name, namelen)) { 420 name, namelen)) {
345 if (poffset) 421 if (poffset)
346 *poffset = offset; 422 *poffset = offset;
@@ -393,7 +469,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
393 469
394 /* Handle realignment */ 470 /* Handle realignment */
395 if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 && 471 if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
396 fdt32_to_cpu(prop->len) >= 8) 472 fdt32_ld(&prop->len) >= 8)
397 return prop->data + 4; 473 return prop->data + 4;
398 return prop->data; 474 return prop->data;
399} 475}
@@ -406,12 +482,22 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
406 prop = fdt_get_property_by_offset_(fdt, offset, lenp); 482 prop = fdt_get_property_by_offset_(fdt, offset, lenp);
407 if (!prop) 483 if (!prop)
408 return NULL; 484 return NULL;
409 if (namep) 485 if (namep) {
410 *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); 486 const char *name;
487 int namelen;
488 name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
489 &namelen);
490 if (!name) {
491 if (lenp)
492 *lenp = namelen;
493 return NULL;
494 }
495 *namep = name;
496 }
411 497
412 /* Handle realignment */ 498 /* Handle realignment */
413 if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 && 499 if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
414 fdt32_to_cpu(prop->len) >= 8) 500 fdt32_ld(&prop->len) >= 8)
415 return prop->data + 4; 501 return prop->data + 4;
416 return prop->data; 502 return prop->data;
417} 503}
@@ -436,7 +522,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
436 return 0; 522 return 0;
437 } 523 }
438 524
439 return fdt32_to_cpu(*php); 525 return fdt32_ld(php);
440} 526}
441 527
442const char *fdt_get_alias_namelen(const void *fdt, 528const char *fdt_get_alias_namelen(const void *fdt,
@@ -462,7 +548,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
462 int offset, depth, namelen; 548 int offset, depth, namelen;
463 const char *name; 549 const char *name;
464 550
465 FDT_CHECK_HEADER(fdt); 551 FDT_RO_PROBE(fdt);
466 552
467 if (buflen < 2) 553 if (buflen < 2)
468 return -FDT_ERR_NOSPACE; 554 return -FDT_ERR_NOSPACE;
@@ -514,7 +600,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
514 int offset, depth; 600 int offset, depth;
515 int supernodeoffset = -FDT_ERR_INTERNAL; 601 int supernodeoffset = -FDT_ERR_INTERNAL;
516 602
517 FDT_CHECK_HEADER(fdt); 603 FDT_RO_PROBE(fdt);
518 604
519 if (supernodedepth < 0) 605 if (supernodedepth < 0)
520 return -FDT_ERR_NOTFOUND; 606 return -FDT_ERR_NOTFOUND;
@@ -573,7 +659,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
573 const void *val; 659 const void *val;
574 int len; 660 int len;
575 661
576 FDT_CHECK_HEADER(fdt); 662 FDT_RO_PROBE(fdt);
577 663
578 /* FIXME: The algorithm here is pretty horrible: we scan each 664 /* FIXME: The algorithm here is pretty horrible: we scan each
579 * property of a node in fdt_getprop(), then if that didn't 665 * property of a node in fdt_getprop(), then if that didn't
@@ -599,7 +685,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
599 if ((phandle == 0) || (phandle == -1)) 685 if ((phandle == 0) || (phandle == -1))
600 return -FDT_ERR_BADPHANDLE; 686 return -FDT_ERR_BADPHANDLE;
601 687
602 FDT_CHECK_HEADER(fdt); 688 FDT_RO_PROBE(fdt);
603 689
604 /* FIXME: The algorithm here is pretty horrible: we 690 /* FIXME: The algorithm here is pretty horrible: we
605 * potentially scan each property of a node in 691 * potentially scan each property of a node in
@@ -752,7 +838,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
752{ 838{
753 int offset, err; 839 int offset, err;
754 840
755 FDT_CHECK_HEADER(fdt); 841 FDT_RO_PROBE(fdt);
756 842
757 /* FIXME: The algorithm here is pretty horrible: we scan each 843 /* FIXME: The algorithm here is pretty horrible: we scan each
758 * property of a node in fdt_node_check_compatible(), then if 844 * property of a node in fdt_node_check_compatible(), then if
@@ -771,3 +857,66 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
771 857
772 return offset; /* error from fdt_next_node() */ 858 return offset; /* error from fdt_next_node() */
773} 859}
860
861int fdt_check_full(const void *fdt, size_t bufsize)
862{
863 int err;
864 int num_memrsv;
865 int offset, nextoffset = 0;
866 uint32_t tag;
867 unsigned depth = 0;
868 const void *prop;
869 const char *propname;
870
871 if (bufsize < FDT_V1_SIZE)
872 return -FDT_ERR_TRUNCATED;
873 err = fdt_check_header(fdt);
874 if (err != 0)
875 return err;
876 if (bufsize < fdt_totalsize(fdt))
877 return -FDT_ERR_TRUNCATED;
878
879 num_memrsv = fdt_num_mem_rsv(fdt);
880 if (num_memrsv < 0)
881 return num_memrsv;
882
883 while (1) {
884 offset = nextoffset;
885 tag = fdt_next_tag(fdt, offset, &nextoffset);
886
887 if (nextoffset < 0)
888 return nextoffset;
889
890 switch (tag) {
891 case FDT_NOP:
892 break;
893
894 case FDT_END:
895 if (depth != 0)
896 return -FDT_ERR_BADSTRUCTURE;
897 return 0;
898
899 case FDT_BEGIN_NODE:
900 depth++;
901 if (depth > INT_MAX)
902 return -FDT_ERR_BADSTRUCTURE;
903 break;
904
905 case FDT_END_NODE:
906 if (depth == 0)
907 return -FDT_ERR_BADSTRUCTURE;
908 depth--;
909 break;
910
911 case FDT_PROP:
912 prop = fdt_getprop_by_offset(fdt, offset, &propname,
913 &err);
914 if (!prop)
915 return err;
916 break;
917
918 default:
919 return -FDT_ERR_INTERNAL;
920 }
921 }
922}
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 9b829051e444..2e49855d7cf8 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -67,9 +67,9 @@ static int fdt_blocks_misordered_(const void *fdt,
67 (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); 67 (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
68} 68}
69 69
70static int fdt_rw_check_header_(void *fdt) 70static int fdt_rw_probe_(void *fdt)
71{ 71{
72 FDT_CHECK_HEADER(fdt); 72 FDT_RO_PROBE(fdt);
73 73
74 if (fdt_version(fdt) < 17) 74 if (fdt_version(fdt) < 17)
75 return -FDT_ERR_BADVERSION; 75 return -FDT_ERR_BADVERSION;
@@ -82,10 +82,10 @@ static int fdt_rw_check_header_(void *fdt)
82 return 0; 82 return 0;
83} 83}
84 84
85#define FDT_RW_CHECK_HEADER(fdt) \ 85#define FDT_RW_PROBE(fdt) \
86 { \ 86 { \
87 int err_; \ 87 int err_; \
88 if ((err_ = fdt_rw_check_header_(fdt)) != 0) \ 88 if ((err_ = fdt_rw_probe_(fdt)) != 0) \
89 return err_; \ 89 return err_; \
90 } 90 }
91 91
@@ -176,7 +176,7 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
176 struct fdt_reserve_entry *re; 176 struct fdt_reserve_entry *re;
177 int err; 177 int err;
178 178
179 FDT_RW_CHECK_HEADER(fdt); 179 FDT_RW_PROBE(fdt);
180 180
181 re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt)); 181 re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
182 err = fdt_splice_mem_rsv_(fdt, re, 0, 1); 182 err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
@@ -192,7 +192,7 @@ int fdt_del_mem_rsv(void *fdt, int n)
192{ 192{
193 struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n); 193 struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
194 194
195 FDT_RW_CHECK_HEADER(fdt); 195 FDT_RW_PROBE(fdt);
196 196
197 if (n >= fdt_num_mem_rsv(fdt)) 197 if (n >= fdt_num_mem_rsv(fdt))
198 return -FDT_ERR_NOTFOUND; 198 return -FDT_ERR_NOTFOUND;
@@ -252,7 +252,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
252 int oldlen, newlen; 252 int oldlen, newlen;
253 int err; 253 int err;
254 254
255 FDT_RW_CHECK_HEADER(fdt); 255 FDT_RW_PROBE(fdt);
256 256
257 namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); 257 namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
258 if (!namep) 258 if (!namep)
@@ -275,7 +275,7 @@ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
275 struct fdt_property *prop; 275 struct fdt_property *prop;
276 int err; 276 int err;
277 277
278 FDT_RW_CHECK_HEADER(fdt); 278 FDT_RW_PROBE(fdt);
279 279
280 err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop); 280 err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
281 if (err == -FDT_ERR_NOTFOUND) 281 if (err == -FDT_ERR_NOTFOUND)
@@ -308,7 +308,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
308 struct fdt_property *prop; 308 struct fdt_property *prop;
309 int err, oldlen, newlen; 309 int err, oldlen, newlen;
310 310
311 FDT_RW_CHECK_HEADER(fdt); 311 FDT_RW_PROBE(fdt);
312 312
313 prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); 313 prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
314 if (prop) { 314 if (prop) {
@@ -334,7 +334,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
334 struct fdt_property *prop; 334 struct fdt_property *prop;
335 int len, proplen; 335 int len, proplen;
336 336
337 FDT_RW_CHECK_HEADER(fdt); 337 FDT_RW_PROBE(fdt);
338 338
339 prop = fdt_get_property_w(fdt, nodeoffset, name, &len); 339 prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
340 if (!prop) 340 if (!prop)
@@ -354,7 +354,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
354 uint32_t tag; 354 uint32_t tag;
355 fdt32_t *endtag; 355 fdt32_t *endtag;
356 356
357 FDT_RW_CHECK_HEADER(fdt); 357 FDT_RW_PROBE(fdt);
358 358
359 offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); 359 offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
360 if (offset >= 0) 360 if (offset >= 0)
@@ -394,7 +394,7 @@ int fdt_del_node(void *fdt, int nodeoffset)
394{ 394{
395 int endoffset; 395 int endoffset;
396 396
397 FDT_RW_CHECK_HEADER(fdt); 397 FDT_RW_PROBE(fdt);
398 398
399 endoffset = fdt_node_end_offset_(fdt, nodeoffset); 399 endoffset = fdt_node_end_offset_(fdt, nodeoffset);
400 if (endoffset < 0) 400 if (endoffset < 0)
@@ -435,7 +435,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
435 const char *fdtend = fdtstart + fdt_totalsize(fdt); 435 const char *fdtend = fdtstart + fdt_totalsize(fdt);
436 char *tmp; 436 char *tmp;
437 437
438 FDT_CHECK_HEADER(fdt); 438 FDT_RO_PROBE(fdt);
439 439
440 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) 440 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
441 * sizeof(struct fdt_reserve_entry); 441 * sizeof(struct fdt_reserve_entry);
@@ -494,7 +494,7 @@ int fdt_pack(void *fdt)
494{ 494{
495 int mem_rsv_size; 495 int mem_rsv_size;
496 496
497 FDT_RW_CHECK_HEADER(fdt); 497 FDT_RW_PROBE(fdt);
498 498
499 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) 499 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
500 * sizeof(struct fdt_reserve_entry); 500 * sizeof(struct fdt_reserve_entry);
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
index 6d33cc29d022..9fa4a94d83c3 100644
--- a/scripts/dtc/libfdt/fdt_sw.c
+++ b/scripts/dtc/libfdt/fdt_sw.c
@@ -55,21 +55,77 @@
55 55
56#include "libfdt_internal.h" 56#include "libfdt_internal.h"
57 57
58static int fdt_sw_check_header_(void *fdt) 58static int fdt_sw_probe_(void *fdt)
59{ 59{
60 if (fdt_magic(fdt) != FDT_SW_MAGIC) 60 if (fdt_magic(fdt) == FDT_MAGIC)
61 return -FDT_ERR_BADSTATE;
62 else if (fdt_magic(fdt) != FDT_SW_MAGIC)
61 return -FDT_ERR_BADMAGIC; 63 return -FDT_ERR_BADMAGIC;
62 /* FIXME: should check more details about the header state */
63 return 0; 64 return 0;
64} 65}
65 66
66#define FDT_SW_CHECK_HEADER(fdt) \ 67#define FDT_SW_PROBE(fdt) \
68 { \
69 int err; \
70 if ((err = fdt_sw_probe_(fdt)) != 0) \
71 return err; \
72 }
73
74/* 'memrsv' state: Initial state after fdt_create()
75 *
76 * Allowed functions:
77 * fdt_add_reservmap_entry()
78 * fdt_finish_reservemap() [moves to 'struct' state]
79 */
80static int fdt_sw_probe_memrsv_(void *fdt)
81{
82 int err = fdt_sw_probe_(fdt);
83 if (err)
84 return err;
85
86 if (fdt_off_dt_strings(fdt) != 0)
87 return -FDT_ERR_BADSTATE;
88 return 0;
89}
90
91#define FDT_SW_PROBE_MEMRSV(fdt) \
92 { \
93 int err; \
94 if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
95 return err; \
96 }
97
98/* 'struct' state: Enter this state after fdt_finish_reservemap()
99 *
100 * Allowed functions:
101 * fdt_begin_node()
102 * fdt_end_node()
103 * fdt_property*()
104 * fdt_finish() [moves to 'complete' state]
105 */
106static int fdt_sw_probe_struct_(void *fdt)
107{
108 int err = fdt_sw_probe_(fdt);
109 if (err)
110 return err;
111
112 if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
113 return -FDT_ERR_BADSTATE;
114 return 0;
115}
116
117#define FDT_SW_PROBE_STRUCT(fdt) \
67 { \ 118 { \
68 int err; \ 119 int err; \
69 if ((err = fdt_sw_check_header_(fdt)) != 0) \ 120 if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
70 return err; \ 121 return err; \
71 } 122 }
72 123
124/* 'complete' state: Enter this state after fdt_finish()
125 *
126 * Allowed functions: none
127 */
128
73static void *fdt_grab_space_(void *fdt, size_t len) 129static void *fdt_grab_space_(void *fdt, size_t len)
74{ 130{
75 int offset = fdt_size_dt_struct(fdt); 131 int offset = fdt_size_dt_struct(fdt);
@@ -87,9 +143,11 @@ static void *fdt_grab_space_(void *fdt, size_t len)
87 143
88int fdt_create(void *buf, int bufsize) 144int fdt_create(void *buf, int bufsize)
89{ 145{
146 const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
147 sizeof(struct fdt_reserve_entry));
90 void *fdt = buf; 148 void *fdt = buf;
91 149
92 if (bufsize < sizeof(struct fdt_header)) 150 if (bufsize < hdrsize)
93 return -FDT_ERR_NOSPACE; 151 return -FDT_ERR_NOSPACE;
94 152
95 memset(buf, 0, bufsize); 153 memset(buf, 0, bufsize);
@@ -99,10 +157,9 @@ int fdt_create(void *buf, int bufsize)
99 fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); 157 fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
100 fdt_set_totalsize(fdt, bufsize); 158 fdt_set_totalsize(fdt, bufsize);
101 159
102 fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), 160 fdt_set_off_mem_rsvmap(fdt, hdrsize);
103 sizeof(struct fdt_reserve_entry)));
104 fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); 161 fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
105 fdt_set_off_dt_strings(fdt, bufsize); 162 fdt_set_off_dt_strings(fdt, 0);
106 163
107 return 0; 164 return 0;
108} 165}
@@ -112,11 +169,14 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
112 size_t headsize, tailsize; 169 size_t headsize, tailsize;
113 char *oldtail, *newtail; 170 char *oldtail, *newtail;
114 171
115 FDT_SW_CHECK_HEADER(fdt); 172 FDT_SW_PROBE(fdt);
116 173
117 headsize = fdt_off_dt_struct(fdt); 174 headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
118 tailsize = fdt_size_dt_strings(fdt); 175 tailsize = fdt_size_dt_strings(fdt);
119 176
177 if ((headsize + tailsize) > fdt_totalsize(fdt))
178 return -FDT_ERR_INTERNAL;
179
120 if ((headsize + tailsize) > bufsize) 180 if ((headsize + tailsize) > bufsize)
121 return -FDT_ERR_NOSPACE; 181 return -FDT_ERR_NOSPACE;
122 182
@@ -133,8 +193,9 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
133 memmove(buf, fdt, headsize); 193 memmove(buf, fdt, headsize);
134 } 194 }
135 195
136 fdt_set_off_dt_strings(buf, bufsize);
137 fdt_set_totalsize(buf, bufsize); 196 fdt_set_totalsize(buf, bufsize);
197 if (fdt_off_dt_strings(buf))
198 fdt_set_off_dt_strings(buf, bufsize);
138 199
139 return 0; 200 return 0;
140} 201}
@@ -144,10 +205,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
144 struct fdt_reserve_entry *re; 205 struct fdt_reserve_entry *re;
145 int offset; 206 int offset;
146 207
147 FDT_SW_CHECK_HEADER(fdt); 208 FDT_SW_PROBE_MEMRSV(fdt);
148
149 if (fdt_size_dt_struct(fdt))
150 return -FDT_ERR_BADSTATE;
151 209
152 offset = fdt_off_dt_struct(fdt); 210 offset = fdt_off_dt_struct(fdt);
153 if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) 211 if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
@@ -164,16 +222,23 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
164 222
165int fdt_finish_reservemap(void *fdt) 223int fdt_finish_reservemap(void *fdt)
166{ 224{
167 return fdt_add_reservemap_entry(fdt, 0, 0); 225 int err = fdt_add_reservemap_entry(fdt, 0, 0);
226
227 if (err)
228 return err;
229
230 fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
231 return 0;
168} 232}
169 233
170int fdt_begin_node(void *fdt, const char *name) 234int fdt_begin_node(void *fdt, const char *name)
171{ 235{
172 struct fdt_node_header *nh; 236 struct fdt_node_header *nh;
173 int namelen = strlen(name) + 1; 237 int namelen;
174 238
175 FDT_SW_CHECK_HEADER(fdt); 239 FDT_SW_PROBE_STRUCT(fdt);
176 240
241 namelen = strlen(name) + 1;
177 nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); 242 nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
178 if (! nh) 243 if (! nh)
179 return -FDT_ERR_NOSPACE; 244 return -FDT_ERR_NOSPACE;
@@ -187,7 +252,7 @@ int fdt_end_node(void *fdt)
187{ 252{
188 fdt32_t *en; 253 fdt32_t *en;
189 254
190 FDT_SW_CHECK_HEADER(fdt); 255 FDT_SW_PROBE_STRUCT(fdt);
191 256
192 en = fdt_grab_space_(fdt, FDT_TAGSIZE); 257 en = fdt_grab_space_(fdt, FDT_TAGSIZE);
193 if (! en) 258 if (! en)
@@ -225,7 +290,7 @@ int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
225 struct fdt_property *prop; 290 struct fdt_property *prop;
226 int nameoff; 291 int nameoff;
227 292
228 FDT_SW_CHECK_HEADER(fdt); 293 FDT_SW_PROBE_STRUCT(fdt);
229 294
230 nameoff = fdt_find_add_string_(fdt, name); 295 nameoff = fdt_find_add_string_(fdt, name);
231 if (nameoff == 0) 296 if (nameoff == 0)
@@ -262,7 +327,7 @@ int fdt_finish(void *fdt)
262 uint32_t tag; 327 uint32_t tag;
263 int offset, nextoffset; 328 int offset, nextoffset;
264 329
265 FDT_SW_CHECK_HEADER(fdt); 330 FDT_SW_PROBE_STRUCT(fdt);
266 331
267 /* Add terminator */ 332 /* Add terminator */
268 end = fdt_grab_space_(fdt, sizeof(*end)); 333 end = fdt_grab_space_(fdt, sizeof(*end));
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index 1e27780e1185..2bd151dd355f 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -90,8 +90,9 @@
90 90
91/* Error codes: codes for bad device tree blobs */ 91/* Error codes: codes for bad device tree blobs */
92#define FDT_ERR_TRUNCATED 8 92#define FDT_ERR_TRUNCATED 8
93 /* FDT_ERR_TRUNCATED: Structure block of the given device tree 93 /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
94 * ends without an FDT_END tag. */ 94 * terminated (overflows, goes outside allowed bounds, or
95 * isn't properly terminated). */
95#define FDT_ERR_BADMAGIC 9 96#define FDT_ERR_BADMAGIC 9
96 /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a 97 /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
97 * device tree at all - it is missing the flattened device 98 * device tree at all - it is missing the flattened device
@@ -153,6 +154,29 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
153 154
154uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); 155uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
155 156
157/*
158 * Alignment helpers:
159 * These helpers access words from a device tree blob. They're
160 * built to work even with unaligned pointers on platforms (ike
161 * ARM) that don't like unaligned loads and stores
162 */
163
164static inline uint32_t fdt32_ld(const fdt32_t *p)
165{
166 fdt32_t v;
167
168 memcpy(&v, p, sizeof(v));
169 return fdt32_to_cpu(v);
170}
171
172static inline uint64_t fdt64_ld(const fdt64_t *p)
173{
174 fdt64_t v;
175
176 memcpy(&v, p, sizeof(v));
177 return fdt64_to_cpu(v);
178}
179
156/**********************************************************************/ 180/**********************************************************************/
157/* Traversal functions */ 181/* Traversal functions */
158/**********************************************************************/ 182/**********************************************************************/
@@ -213,7 +237,7 @@ int fdt_next_subnode(const void *fdt, int offset);
213/* General functions */ 237/* General functions */
214/**********************************************************************/ 238/**********************************************************************/
215#define fdt_get_header(fdt, field) \ 239#define fdt_get_header(fdt, field) \
216 (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) 240 (fdt32_ld(&((const struct fdt_header *)(fdt))->field))
217#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) 241#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
218#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) 242#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
219#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) 243#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
@@ -244,18 +268,31 @@ fdt_set_hdr_(size_dt_struct);
244#undef fdt_set_hdr_ 268#undef fdt_set_hdr_
245 269
246/** 270/**
247 * fdt_check_header - sanity check a device tree or possible device tree 271 * fdt_header_size - return the size of the tree's header
272 * @fdt: pointer to a flattened device tree
273 */
274size_t fdt_header_size_(uint32_t version);
275static inline size_t fdt_header_size(const void *fdt)
276{
277 return fdt_header_size_(fdt_version(fdt));
278}
279
280/**
281 * fdt_check_header - sanity check a device tree header
282
248 * @fdt: pointer to data which might be a flattened device tree 283 * @fdt: pointer to data which might be a flattened device tree
249 * 284 *
250 * fdt_check_header() checks that the given buffer contains what 285 * fdt_check_header() checks that the given buffer contains what
251 * appears to be a flattened device tree with sane information in its 286 * appears to be a flattened device tree, and that the header contains
252 * header. 287 * valid information (to the extent that can be determined from the
288 * header alone).
253 * 289 *
254 * returns: 290 * returns:
255 * 0, if the buffer appears to contain a valid device tree 291 * 0, if the buffer appears to contain a valid device tree
256 * -FDT_ERR_BADMAGIC, 292 * -FDT_ERR_BADMAGIC,
257 * -FDT_ERR_BADVERSION, 293 * -FDT_ERR_BADVERSION,
258 * -FDT_ERR_BADSTATE, standard meanings, as above 294 * -FDT_ERR_BADSTATE,
295 * -FDT_ERR_TRUNCATED, standard meanings, as above
259 */ 296 */
260int fdt_check_header(const void *fdt); 297int fdt_check_header(const void *fdt);
261 298
@@ -284,6 +321,24 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
284/* Read-only functions */ 321/* Read-only functions */
285/**********************************************************************/ 322/**********************************************************************/
286 323
324int fdt_check_full(const void *fdt, size_t bufsize);
325
326/**
327 * fdt_get_string - retrieve a string from the strings block of a device tree
328 * @fdt: pointer to the device tree blob
329 * @stroffset: offset of the string within the strings block (native endian)
330 * @lenp: optional pointer to return the string's length
331 *
332 * fdt_get_string() retrieves a pointer to a single string from the
333 * strings block of the device tree blob at fdt, and optionally also
334 * returns the string's length in *lenp.
335 *
336 * returns:
337 * a pointer to the string, on success
338 * NULL, if stroffset is out of bounds, or doesn't point to a valid string
339 */
340const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
341
287/** 342/**
288 * fdt_string - retrieve a string from the strings block of a device tree 343 * fdt_string - retrieve a string from the strings block of a device tree
289 * @fdt: pointer to the device tree blob 344 * @fdt: pointer to the device tree blob
@@ -294,7 +349,7 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
294 * 349 *
295 * returns: 350 * returns:
296 * a pointer to the string, on success 351 * a pointer to the string, on success
297 * NULL, if stroffset is out of bounds 352 * NULL, if stroffset is out of bounds, or doesn't point to a valid string
298 */ 353 */
299const char *fdt_string(const void *fdt, int stroffset); 354const char *fdt_string(const void *fdt, int stroffset);
300 355
@@ -1090,7 +1145,7 @@ int fdt_address_cells(const void *fdt, int nodeoffset);
1090 * 1145 *
1091 * returns: 1146 * returns:
1092 * 0 <= n < FDT_MAX_NCELLS, on success 1147 * 0 <= n < FDT_MAX_NCELLS, on success
1093 * 2, if the node has no #address-cells property 1148 * 2, if the node has no #size-cells property
1094 * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid 1149 * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
1095 * #size-cells property 1150 * #size-cells property
1096 * -FDT_ERR_BADMAGIC, 1151 * -FDT_ERR_BADMAGIC,
@@ -1313,10 +1368,13 @@ static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
1313 fdt64_t tmp = cpu_to_fdt64(val); 1368 fdt64_t tmp = cpu_to_fdt64(val);
1314 return fdt_property(fdt, name, &tmp, sizeof(tmp)); 1369 return fdt_property(fdt, name, &tmp, sizeof(tmp));
1315} 1370}
1371
1372#ifndef SWIG /* Not available in Python */
1316static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) 1373static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
1317{ 1374{
1318 return fdt_property_u32(fdt, name, val); 1375 return fdt_property_u32(fdt, name, val);
1319} 1376}
1377#endif
1320 1378
1321/** 1379/**
1322 * fdt_property_placeholder - add a new property and return a ptr to its value 1380 * fdt_property_placeholder - add a new property and return a ptr to its value
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
index bd2474628775..eb2053845c9c 100644
--- a/scripts/dtc/libfdt/libfdt_env.h
+++ b/scripts/dtc/libfdt/libfdt_env.h
@@ -56,6 +56,7 @@
56#include <stdint.h> 56#include <stdint.h>
57#include <stdlib.h> 57#include <stdlib.h>
58#include <string.h> 58#include <string.h>
59#include <limits.h>
59 60
60#ifdef __CHECKER__ 61#ifdef __CHECKER__
61#define FDT_FORCE __attribute__((force)) 62#define FDT_FORCE __attribute__((force))
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
index 7681e192295b..4109f890ae60 100644
--- a/scripts/dtc/libfdt/libfdt_internal.h
+++ b/scripts/dtc/libfdt/libfdt_internal.h
@@ -55,10 +55,11 @@
55#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) 55#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
56#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) 56#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
57 57
58#define FDT_CHECK_HEADER(fdt) \ 58int fdt_ro_probe_(const void *fdt);
59#define FDT_RO_PROBE(fdt) \
59 { \ 60 { \
60 int err_; \ 61 int err_; \
61 if ((err_ = fdt_check_header(fdt)) != 0) \ 62 if ((err_ = fdt_ro_probe_(fdt)) != 0) \
62 return err_; \ 63 return err_; \
63 } 64 }
64 65
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index 6e4c367f54b3..4ff0679e0062 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -594,6 +594,7 @@ struct node *get_node_by_ref(struct node *tree, const char *ref)
594cell_t get_node_phandle(struct node *root, struct node *node) 594cell_t get_node_phandle(struct node *root, struct node *node)
595{ 595{
596 static cell_t phandle = 1; /* FIXME: ick, static local */ 596 static cell_t phandle = 1; /* FIXME: ick, static local */
597 struct data d = empty_data;
597 598
598 if ((node->phandle != 0) && (node->phandle != -1)) 599 if ((node->phandle != 0) && (node->phandle != -1))
599 return node->phandle; 600 return node->phandle;
@@ -603,17 +604,16 @@ cell_t get_node_phandle(struct node *root, struct node *node)
603 604
604 node->phandle = phandle; 605 node->phandle = phandle;
605 606
607 d = data_add_marker(d, TYPE_UINT32, NULL);
608 d = data_append_cell(d, phandle);
609
606 if (!get_property(node, "linux,phandle") 610 if (!get_property(node, "linux,phandle")
607 && (phandle_format & PHANDLE_LEGACY)) 611 && (phandle_format & PHANDLE_LEGACY))
608 add_property(node, 612 add_property(node, build_property("linux,phandle", d));
609 build_property("linux,phandle",
610 data_append_cell(empty_data, phandle)));
611 613
612 if (!get_property(node, "phandle") 614 if (!get_property(node, "phandle")
613 && (phandle_format & PHANDLE_EPAPR)) 615 && (phandle_format & PHANDLE_EPAPR))
614 add_property(node, 616 add_property(node, build_property("phandle", d));
615 build_property("phandle",
616 data_append_cell(empty_data, phandle)));
617 617
618 /* If the node *does* have a phandle property, we must 618 /* If the node *does* have a phandle property, we must
619 * be dealing with a self-referencing phandle, which will be 619 * be dealing with a self-referencing phandle, which will be
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
index 2461a3d068a0..f2874f1d1465 100644
--- a/scripts/dtc/treesource.c
+++ b/scripts/dtc/treesource.c
@@ -61,24 +61,14 @@ static bool isstring(char c)
61 || strchr("\a\b\t\n\v\f\r", c)); 61 || strchr("\a\b\t\n\v\f\r", c));
62} 62}
63 63
64static void write_propval_string(FILE *f, struct data val) 64static void write_propval_string(FILE *f, const char *s, size_t len)
65{ 65{
66 const char *str = val.val; 66 const char *end = s + len - 1;
67 int i; 67 assert(*end == '\0');
68 struct marker *m = val.markers;
69
70 assert(str[val.len-1] == '\0');
71 68
72 while (m && (m->offset == 0)) {
73 if (m->type == LABEL)
74 fprintf(f, "%s: ", m->ref);
75 m = m->next;
76 }
77 fprintf(f, "\""); 69 fprintf(f, "\"");
78 70 while (s < end) {
79 for (i = 0; i < (val.len-1); i++) { 71 char c = *s++;
80 char c = str[i];
81
82 switch (c) { 72 switch (c) {
83 case '\a': 73 case '\a':
84 fprintf(f, "\\a"); 74 fprintf(f, "\\a");
@@ -108,91 +98,78 @@ static void write_propval_string(FILE *f, struct data val)
108 fprintf(f, "\\\""); 98 fprintf(f, "\\\"");
109 break; 99 break;
110 case '\0': 100 case '\0':
111 fprintf(f, "\", "); 101 fprintf(f, "\\0");
112 while (m && (m->offset <= (i + 1))) {
113 if (m->type == LABEL) {
114 assert(m->offset == (i+1));
115 fprintf(f, "%s: ", m->ref);
116 }
117 m = m->next;
118 }
119 fprintf(f, "\"");
120 break; 102 break;
121 default: 103 default:
122 if (isprint((unsigned char)c)) 104 if (isprint((unsigned char)c))
123 fprintf(f, "%c", c); 105 fprintf(f, "%c", c);
124 else 106 else
125 fprintf(f, "\\x%02hhx", c); 107 fprintf(f, "\\x%02"PRIx8, c);
126 } 108 }
127 } 109 }
128 fprintf(f, "\""); 110 fprintf(f, "\"");
129
130 /* Wrap up any labels at the end of the value */
131 for_each_marker_of_type(m, LABEL) {
132 assert (m->offset == val.len);
133 fprintf(f, " %s:", m->ref);
134 }
135} 111}
136 112
137static void write_propval_cells(FILE *f, struct data val) 113static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
138{ 114{
139 void *propend = val.val + val.len; 115 const char *end = p + len;
140 fdt32_t *cp = (fdt32_t *)val.val; 116 assert(len % width == 0);
141 struct marker *m = val.markers;
142
143 fprintf(f, "<");
144 for (;;) {
145 while (m && (m->offset <= ((char *)cp - val.val))) {
146 if (m->type == LABEL) {
147 assert(m->offset == ((char *)cp - val.val));
148 fprintf(f, "%s: ", m->ref);
149 }
150 m = m->next;
151 }
152 117
153 fprintf(f, "0x%x", fdt32_to_cpu(*cp++)); 118 for (; p < end; p += width) {
154 if ((void *)cp >= propend) 119 switch (width) {
120 case 1:
121 fprintf(f, " %02"PRIx8, *(const uint8_t*)p);
122 break;
123 case 2:
124 fprintf(f, " 0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p));
125 break;
126 case 4:
127 fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p));
128 break;
129 case 8:
130 fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p));
155 break; 131 break;
156 fprintf(f, " "); 132 }
157 } 133 }
134}
158 135
159 /* Wrap up any labels at the end of the value */ 136static bool has_data_type_information(struct marker *m)
160 for_each_marker_of_type(m, LABEL) { 137{
161 assert (m->offset == val.len); 138 return m->type >= TYPE_UINT8;
162 fprintf(f, " %s:", m->ref);
163 }
164 fprintf(f, ">");
165} 139}
166 140
167static void write_propval_bytes(FILE *f, struct data val) 141static struct marker *next_type_marker(struct marker *m)
168{ 142{
169 void *propend = val.val + val.len; 143 while (m && !has_data_type_information(m))
170 const char *bp = val.val; 144 m = m->next;
171 struct marker *m = val.markers; 145 return m;
172 146}
173 fprintf(f, "[");
174 for (;;) {
175 while (m && (m->offset == (bp-val.val))) {
176 if (m->type == LABEL)
177 fprintf(f, "%s: ", m->ref);
178 m = m->next;
179 }
180 147
181 fprintf(f, "%02hhx", (unsigned char)(*bp++)); 148size_t type_marker_length(struct marker *m)
182 if ((const void *)bp >= propend) 149{
183 break; 150 struct marker *next = next_type_marker(m->next);
184 fprintf(f, " ");
185 }
186 151
187 /* Wrap up any labels at the end of the value */ 152 if (next)
188 for_each_marker_of_type(m, LABEL) { 153 return next->offset - m->offset;
189 assert (m->offset == val.len); 154 return 0;
190 fprintf(f, " %s:", m->ref);
191 }
192 fprintf(f, "]");
193} 155}
194 156
195static void write_propval(FILE *f, struct property *prop) 157static const char *delim_start[] = {
158 [TYPE_UINT8] = "[",
159 [TYPE_UINT16] = "/bits/ 16 <",
160 [TYPE_UINT32] = "<",
161 [TYPE_UINT64] = "/bits/ 64 <",
162 [TYPE_STRING] = "",
163};
164static const char *delim_end[] = {
165 [TYPE_UINT8] = " ]",
166 [TYPE_UINT16] = " >",
167 [TYPE_UINT32] = " >",
168 [TYPE_UINT64] = " >",
169 [TYPE_STRING] = "",
170};
171
172static enum markertype guess_value_type(struct property *prop)
196{ 173{
197 int len = prop->val.len; 174 int len = prop->val.len;
198 const char *p = prop->val.val; 175 const char *p = prop->val.val;
@@ -201,11 +178,6 @@ static void write_propval(FILE *f, struct property *prop)
201 int nnotstringlbl = 0, nnotcelllbl = 0; 178 int nnotstringlbl = 0, nnotcelllbl = 0;
202 int i; 179 int i;
203 180
204 if (len == 0) {
205 fprintf(f, ";\n");
206 return;
207 }
208
209 for (i = 0; i < len; i++) { 181 for (i = 0; i < len; i++) {
210 if (! isstring(p[i])) 182 if (! isstring(p[i]))
211 nnotstring++; 183 nnotstring++;
@@ -220,17 +192,91 @@ static void write_propval(FILE *f, struct property *prop)
220 nnotcelllbl++; 192 nnotcelllbl++;
221 } 193 }
222 194
223 fprintf(f, " = ");
224 if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) 195 if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
225 && (nnotstringlbl == 0)) { 196 && (nnotstringlbl == 0)) {
226 write_propval_string(f, prop->val); 197 return TYPE_STRING;
227 } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { 198 } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
228 write_propval_cells(f, prop->val); 199 return TYPE_UINT32;
229 } else {
230 write_propval_bytes(f, prop->val);
231 } 200 }
232 201
233 fprintf(f, ";\n"); 202 return TYPE_UINT8;
203}
204
205static void write_propval(FILE *f, struct property *prop)
206{
207 size_t len = prop->val.len;
208 struct marker *m = prop->val.markers;
209 struct marker dummy_marker;
210 enum markertype emit_type = TYPE_NONE;
211
212 if (len == 0) {
213 fprintf(f, ";\n");
214 return;
215 }
216
217 fprintf(f, " = ");
218
219 if (!next_type_marker(m)) {
220 /* data type information missing, need to guess */
221 dummy_marker.type = guess_value_type(prop);
222 dummy_marker.next = prop->val.markers;
223 dummy_marker.offset = 0;
224 dummy_marker.ref = NULL;
225 m = &dummy_marker;
226 }
227
228 struct marker *m_label = prop->val.markers;
229 for_each_marker(m) {
230 size_t chunk_len;
231 const char *p = &prop->val.val[m->offset];
232
233 if (!has_data_type_information(m))
234 continue;
235
236 chunk_len = type_marker_length(m);
237 if (!chunk_len)
238 chunk_len = len - m->offset;
239
240 if (emit_type != TYPE_NONE)
241 fprintf(f, "%s, ", delim_end[emit_type]);
242 emit_type = m->type;
243
244 for_each_marker_of_type(m_label, LABEL) {
245 if (m_label->offset > m->offset)
246 break;
247 fprintf(f, "%s: ", m_label->ref);
248 }
249
250 fprintf(f, "%s", delim_start[emit_type]);
251
252 if (chunk_len <= 0)
253 continue;
254
255 switch(emit_type) {
256 case TYPE_UINT16:
257 write_propval_int(f, p, chunk_len, 2);
258 break;
259 case TYPE_UINT32:
260 write_propval_int(f, p, chunk_len, 4);
261 break;
262 case TYPE_UINT64:
263 write_propval_int(f, p, chunk_len, 8);
264 break;
265 case TYPE_STRING:
266 write_propval_string(f, p, chunk_len);
267 break;
268 default:
269 write_propval_int(f, p, chunk_len, 1);
270 }
271 }
272
273 /* Wrap up any labels at the end of the value */
274 for_each_marker_of_type(m_label, LABEL) {
275 assert (m_label->offset == len);
276 fprintf(f, " %s:", m_label->ref);
277 }
278
279 fprintf(f, "%s;\n", delim_end[emit_type] ? : "");
234} 280}
235 281
236static void write_tree_source_node(FILE *f, struct node *tree, int level) 282static void write_tree_source_node(FILE *f, struct node *tree, int level)
@@ -281,4 +327,3 @@ void dt_to_source(FILE *f, struct dt_info *dti)
281 327
282 write_tree_source_node(f, dti->dt, 0); 328 write_tree_source_node(f, dti->dt, 0);
283} 329}
284
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
index 9953c32a0244..a69b7a13463d 100644
--- a/scripts/dtc/util.c
+++ b/scripts/dtc/util.c
@@ -227,11 +227,11 @@ char get_escape_char(const char *s, int *i)
227 return val; 227 return val;
228} 228}
229 229
230int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len) 230int utilfdt_read_err(const char *filename, char **buffp, size_t *len)
231{ 231{
232 int fd = 0; /* assume stdin */ 232 int fd = 0; /* assume stdin */
233 char *buf = NULL; 233 char *buf = NULL;
234 off_t bufsize = 1024, offset = 0; 234 size_t bufsize = 1024, offset = 0;
235 int ret = 0; 235 int ret = 0;
236 236
237 *buffp = NULL; 237 *buffp = NULL;
@@ -264,20 +264,15 @@ int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len)
264 free(buf); 264 free(buf);
265 else 265 else
266 *buffp = buf; 266 *buffp = buf;
267 *len = bufsize; 267 if (len)
268 *len = bufsize;
268 return ret; 269 return ret;
269} 270}
270 271
271int utilfdt_read_err(const char *filename, char **buffp) 272char *utilfdt_read(const char *filename, size_t *len)
272{
273 off_t len;
274 return utilfdt_read_err_len(filename, buffp, &len);
275}
276
277char *utilfdt_read_len(const char *filename, off_t *len)
278{ 273{
279 char *buff; 274 char *buff;
280 int ret = utilfdt_read_err_len(filename, &buff, len); 275 int ret = utilfdt_read_err(filename, &buff, len);
281 276
282 if (ret) { 277 if (ret) {
283 fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, 278 fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
@@ -288,12 +283,6 @@ char *utilfdt_read_len(const char *filename, off_t *len)
288 return buff; 283 return buff;
289} 284}
290 285
291char *utilfdt_read(const char *filename)
292{
293 off_t len;
294 return utilfdt_read_len(filename, &len);
295}
296
297int utilfdt_write_err(const char *filename, const void *blob) 286int utilfdt_write_err(const char *filename, const void *blob)
298{ 287{
299 int fd = 1; /* assume stdout */ 288 int fd = 1; /* assume stdout */
diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
index 66fba8ea709b..f6cea8274174 100644
--- a/scripts/dtc/util.h
+++ b/scripts/dtc/util.h
@@ -98,16 +98,10 @@ char get_escape_char(const char *s, int *i);
98 * stderr. 98 * stderr.
99 * 99 *
100 * @param filename The filename to read, or - for stdin 100 * @param filename The filename to read, or - for stdin
101 * @return Pointer to allocated buffer containing fdt, or NULL on error
102 */
103char *utilfdt_read(const char *filename);
104
105/**
106 * Like utilfdt_read(), but also passes back the size of the file read.
107 *
108 * @param len If non-NULL, the amount of data we managed to read 101 * @param len If non-NULL, the amount of data we managed to read
102 * @return Pointer to allocated buffer containing fdt, or NULL on error
109 */ 103 */
110char *utilfdt_read_len(const char *filename, off_t *len); 104char *utilfdt_read(const char *filename, size_t *len);
111 105
112/** 106/**
113 * Read a device tree file into a buffer. Does not report errors, but only 107 * Read a device tree file into a buffer. Does not report errors, but only
@@ -116,16 +110,10 @@ char *utilfdt_read_len(const char *filename, off_t *len);
116 * 110 *
117 * @param filename The filename to read, or - for stdin 111 * @param filename The filename to read, or - for stdin
118 * @param buffp Returns pointer to buffer containing fdt 112 * @param buffp Returns pointer to buffer containing fdt
119 * @return 0 if ok, else an errno value representing the error
120 */
121int utilfdt_read_err(const char *filename, char **buffp);
122
123/**
124 * Like utilfdt_read_err(), but also passes back the size of the file read.
125 *
126 * @param len If non-NULL, the amount of data we managed to read 113 * @param len If non-NULL, the amount of data we managed to read
114 * @return 0 if ok, else an errno value representing the error
127 */ 115 */
128int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len); 116int utilfdt_read_err(const char *filename, char **buffp, size_t *len);
129 117
130/** 118/**
131 * Write a device tree buffer to a file. This will report any errors on 119 * Write a device tree buffer to a file. This will report any errors on
diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h
index b00f14ff7a17..6d23fd095f16 100644
--- a/scripts/dtc/version_gen.h
+++ b/scripts/dtc/version_gen.h
@@ -1 +1 @@
#define DTC_VERSION "DTC 1.4.6-g84e414b0" #define DTC_VERSION "DTC 1.4.7-gc86da84d"
diff --git a/scripts/dtc/yamltree.c b/scripts/dtc/yamltree.c
new file mode 100644
index 000000000000..a00285a5a9ec
--- /dev/null
+++ b/scripts/dtc/yamltree.c
@@ -0,0 +1,247 @@
1/*
2 * (C) Copyright Linaro, Ltd. 2018
3 * (C) Copyright Arm Holdings. 2017
4 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
20 */
21
22#include <stdlib.h>
23#include <yaml.h>
24#include "dtc.h"
25#include "srcpos.h"
26
27char *yaml_error_name[] = {
28 [YAML_NO_ERROR] = "no error",
29 [YAML_MEMORY_ERROR] = "memory error",
30 [YAML_READER_ERROR] = "reader error",
31 [YAML_SCANNER_ERROR] = "scanner error",
32 [YAML_PARSER_ERROR] = "parser error",
33 [YAML_COMPOSER_ERROR] = "composer error",
34 [YAML_WRITER_ERROR] = "writer error",
35 [YAML_EMITTER_ERROR] = "emitter error",
36};
37
38#define yaml_emitter_emit_or_die(emitter, event) ( \
39{ \
40 if (!yaml_emitter_emit(emitter, event)) \
41 die("yaml '%s': %s in %s, line %i\n", \
42 yaml_error_name[(emitter)->error], \
43 (emitter)->problem, __func__, __LINE__); \
44})
45
46static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width)
47{
48 yaml_event_t event;
49 void *tag;
50 int off, start_offset = markers->offset;
51
52 switch(width) {
53 case 1: tag = "!u8"; break;
54 case 2: tag = "!u16"; break;
55 case 4: tag = "!u32"; break;
56 case 8: tag = "!u64"; break;
57 default:
58 die("Invalid width %i", width);
59 }
60 assert(len % width == 0);
61
62 yaml_sequence_start_event_initialize(&event, NULL,
63 (yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE);
64 yaml_emitter_emit_or_die(emitter, &event);
65
66 for (off = 0; off < len; off += width) {
67 char buf[32];
68 struct marker *m;
69 bool is_phandle = false;
70
71 switch(width) {
72 case 1:
73 sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off));
74 break;
75 case 2:
76 sprintf(buf, "0x%"PRIx16, fdt16_to_cpu(*(fdt16_t*)(data + off)));
77 break;
78 case 4:
79 sprintf(buf, "0x%"PRIx32, fdt32_to_cpu(*(fdt32_t*)(data + off)));
80 m = markers;
81 is_phandle = false;
82 for_each_marker_of_type(m, REF_PHANDLE) {
83 if (m->offset == (start_offset + off)) {
84 is_phandle = true;
85 break;
86 }
87 }
88 break;
89 case 8:
90 sprintf(buf, "0x%"PRIx64, fdt64_to_cpu(*(fdt64_t*)(data + off)));
91 break;
92 }
93
94 if (is_phandle)
95 yaml_scalar_event_initialize(&event, NULL,
96 (yaml_char_t*)"!phandle", (yaml_char_t *)buf,
97 strlen(buf), 0, 0, YAML_PLAIN_SCALAR_STYLE);
98 else
99 yaml_scalar_event_initialize(&event, NULL,
100 (yaml_char_t*)YAML_INT_TAG, (yaml_char_t *)buf,
101 strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE);
102 yaml_emitter_emit_or_die(emitter, &event);
103 }
104
105 yaml_sequence_end_event_initialize(&event);
106 yaml_emitter_emit_or_die(emitter, &event);
107}
108
109static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len)
110{
111 yaml_event_t event;
112 int i;
113
114 assert(str[len-1] == '\0');
115
116 /* Make sure the entire string is in the lower 7-bit ascii range */
117 for (i = 0; i < len; i++)
118 assert(isascii(str[i]));
119
120 yaml_scalar_event_initialize(&event, NULL,
121 (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str,
122 len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
123 yaml_emitter_emit_or_die(emitter, &event);
124}
125
126static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
127{
128 yaml_event_t event;
129 int len = prop->val.len;
130 struct marker *m = prop->val.markers;
131
132 /* Emit the property name */
133 yaml_scalar_event_initialize(&event, NULL,
134 (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)prop->name,
135 strlen(prop->name), 1, 1, YAML_PLAIN_SCALAR_STYLE);
136 yaml_emitter_emit_or_die(emitter, &event);
137
138 /* Boolean properties are easiest to deal with. Length is zero, so just emit 'true' */
139 if (len == 0) {
140 yaml_scalar_event_initialize(&event, NULL,
141 (yaml_char_t *)YAML_BOOL_TAG,
142 (yaml_char_t*)"true",
143 strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE);
144 yaml_emitter_emit_or_die(emitter, &event);
145 return;
146 }
147
148 if (!m)
149 die("No markers present in property '%s' value\n", prop->name);
150
151 yaml_sequence_start_event_initialize(&event, NULL,
152 (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE);
153 yaml_emitter_emit_or_die(emitter, &event);
154
155 for_each_marker(m) {
156 int chunk_len;
157 char *data = &prop->val.val[m->offset];
158
159 if (m->type < TYPE_UINT8)
160 continue;
161
162 chunk_len = type_marker_length(m) ? : len;
163 assert(chunk_len > 0);
164 len -= chunk_len;
165
166 switch(m->type) {
167 case TYPE_UINT16:
168 yaml_propval_int(emitter, m, data, chunk_len, 2);
169 break;
170 case TYPE_UINT32:
171 yaml_propval_int(emitter, m, data, chunk_len, 4);
172 break;
173 case TYPE_UINT64:
174 yaml_propval_int(emitter, m, data, chunk_len, 8);
175 break;
176 case TYPE_STRING:
177 yaml_propval_string(emitter, data, chunk_len);
178 break;
179 default:
180 yaml_propval_int(emitter, m, data, chunk_len, 1);
181 break;
182 }
183 }
184
185 yaml_sequence_end_event_initialize(&event);
186 yaml_emitter_emit_or_die(emitter, &event);
187}
188
189
190static void yaml_tree(struct node *tree, yaml_emitter_t *emitter)
191{
192 struct property *prop;
193 struct node *child;
194 yaml_event_t event;
195
196 if (tree->deleted)
197 return;
198
199 yaml_mapping_start_event_initialize(&event, NULL,
200 (yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE);
201 yaml_emitter_emit_or_die(emitter, &event);
202
203 for_each_property(tree, prop)
204 yaml_propval(emitter, prop);
205
206 /* Loop over all the children, emitting them into the map */
207 for_each_child(tree, child) {
208 yaml_scalar_event_initialize(&event, NULL,
209 (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)child->name,
210 strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE);
211 yaml_emitter_emit_or_die(emitter, &event);
212 yaml_tree(child, emitter);
213 }
214
215 yaml_mapping_end_event_initialize(&event);
216 yaml_emitter_emit_or_die(emitter, &event);
217}
218
219void dt_to_yaml(FILE *f, struct dt_info *dti)
220{
221 yaml_emitter_t emitter;
222 yaml_event_t event;
223
224 yaml_emitter_initialize(&emitter);
225 yaml_emitter_set_output_file(&emitter, f);
226 yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING);
227 yaml_emitter_emit_or_die(&emitter, &event);
228
229 yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
230 yaml_emitter_emit_or_die(&emitter, &event);
231
232 yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE);
233 yaml_emitter_emit_or_die(&emitter, &event);
234
235 yaml_tree(dti->dt, &emitter);
236
237 yaml_sequence_end_event_initialize(&event);
238 yaml_emitter_emit_or_die(&emitter, &event);
239
240 yaml_document_end_event_initialize(&event, 0);
241 yaml_emitter_emit_or_die(&emitter, &event);
242
243 yaml_stream_end_event_initialize(&event);
244 yaml_emitter_emit_or_die(&emitter, &event);
245
246 yaml_emitter_delete(&emitter);
247}