aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Herring <robh@kernel.org>2018-09-13 09:59:25 -0400
committerRob Herring <robh@kernel.org>2018-09-20 14:31:10 -0400
commitf858927fd6ce394a7f431153d44ad0a09e8f49a1 (patch)
tree6e6f1c2551a12796fedac46caa69a6dea69b25d1
parentc36d5a6c74e7f1529f1af0cf39d3ecaa46c52e83 (diff)
scripts/dtc: Update to upstream version v1.4.7-14-gc86da84d30e4
Major changes are I2C and SPI bus checks, YAML output format (for future validation), some new libfdt functions, and more libfdt validation of dtbs. The YAML addition adds an optional dependency on libyaml. pkg-config is used to test for it and pkg-config became a kconfig dependency in 4.18. This adds the following commits from upstream: c86da84d30e4 Add support for YAML encoded output 361b5e7d8067 Make type_marker_length helper public bfbfab047e45 pylibfdt: Add a means to add and delete notes 9005f4108e7c pylibfdt: Allow delprop() to return errors b94c056b137e Make valgrind optional fd06c54d4711 tests: Better testing of dtc -I fs mode c3f50c9a86d9 tests: Allow dtbs_equal_unordered to ignore mem reserves 0ac9fdee37c7 dtc: trivial '-I fs -O dts' test 0fd1c8c783f3 pylibfdt: fdt_get_mem_rsv returns 2 uint64_t values 04853cad18f4 pylibfdt: Don't incorrectly / unnecessarily override uint64_t typemap 9619c8619c37 Kill bogus TYPE_BLOB marker type ac68ff92ae20 parser: add TYPE_STRING marker to path references 90a190eb04d9 checks: add SPI bus checks 53a1bd546905 checks: add I2C bus checks 88f18909db73 dtc: Bump version to v1.4.7 85bce8b2f06d tests: Correction to vg_prepare_blob() 57f7f9e7bc7c tests: Don't call memcmp() with NULL arguments c12b2b0c20eb libfdt: fdt_address_cells() and fdt_size_cells() 3fe0eeda0b7f livetree: Set phandle properties type to uint32 853649acceba pylibfdt: Support the sequential-write interface 9b0e4fe26093 tests: Improve fdt_resize() tests 1087504bb3e8 libfdt: Add necessary header padding in fdt_create() c72fa777e613 libfdt: Copy the struct region in fdt_resize() 32b9c6130762 Preserve datatype markers when emitting dts format 6dcb8ba408ec libfdt: Add helpers for accessing unaligned words 42607f21d43e tests: Fix incorrect check name 'prop_name_chars' 9d78c33bf8a1 tests: fix grep for checks error messages b770f3d1c13f pylibfdt: Support setting the name of a node 2f0d07e678e0 pylibfdt: Add functions to set and get properties as strings 354d3dc55939 pylibfdt: Update the bytearray size with pack() 3c374d46acce pylibfdt: Allow reading integer values from properties 49d32ce40bb4 pylibfdt: Use an unsigned type for fdt32_t 481246a0c13a pylibfdt: Avoid accessing the internal _fdt member in tests 9aafa33d99ed pylibfdt: Add functions to update properties 5a598671fdbf pylibfdt: Support device-tree creation/expansion 483e170625e1 pylibfdt: Add support for reading the memory reserve map 29bb05aa4200 pylibfdt: Add support for the rest of the header functions 582a7159a5d0 pylibfdt: Add support for fdt_next_node() f0f8c9169819 pylibfdt: Reorder functions to match libfdt.h 64a69d123935 pylibfdt: Return string instead of bytearray from getprop() 4d09a83420df fdtput: Add documentation e617cbe1bd67 fdtget: Add documentation 180a93924014 Use <inttypes.h> format specifiers in a bunch of places we should b9af3b396576 scripts/dtc: Fixed format mismatch in fprintf 4b8fcc3d015c libfdt: Add fdt_check_full() function c14223fb2292 tests: Use valgrind client requests for better checking 5b67d2b955a3 tests: Better handling of valgrind errors saving blobs e2556aaeb506 tests: Remove unused #define fb9c6abddaa8 Use size_t for blob lengths in utilfdt_read* 0112fda03bf6 libfdt: Add fdt_header_size() 6473a21d8bfe Consolidate utilfdt_read_len() variants d5db5382c5e5 libfdt: Safer access to memory reservations 719d582e98ec libfdt: Propagate name errors in fdt_getprop_by_offset() 70166d62a27f libfdt: Safer access to strings section eb890c0f77dc libfdt: Make fdt_check_header() more thorough 899d6fad93f3 libfdt: Improve sequential write state checking 04b5b4062ccd libfdt: Clean up header checking functions 44d3efedc816 Preserve datatype information when parsing dts f0be81bd8de0 Make Property a subclass of bytearray 24b1f3f064d4 pylibfdt: Add a method to access the device tree directly Signed-off-by: Rob Herring <robh@kernel.org>
-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}