aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/dtc
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2009-04-30 01:25:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-05-02 19:52:26 -0400
commit9fffb55f66127b52c937ede5196ebfa0c0d50bce (patch)
tree11664fb82734ba8dcde9556b8d47e780451a740a /scripts/dtc
parentafc1e702e8e8355faa712d4e90d9afe26a4995a5 (diff)
Move dtc and libfdt sources from arch/powerpc/boot to scripts/dtc
The powerpc kernel always requires an Open Firmware like device tree to supply device information. On systems without OF, this comes from a flattened device tree blob. This blob is usually generated by dtc, a tool which compiles a text description of the device tree into the flattened format used by the kernel. Sometimes, the bootwrapper makes small changes to the pre-compiled device tree blob (e.g. filling in the size of RAM). To do this it uses the libfdt library. Because these are only used on powerpc, the code for both these tools is included under arch/powerpc/boot (these were imported and are periodically updated from the upstream dtc tree). However, the microblaze architecture, currently being prepared for merging to mainline also uses dtc to produce device tree blobs. A few other archs have also mentioned some interest in using dtc. Therefore, this patch moves dtc and libfdt from arch/powerpc into scripts, where it can be used by any architecture. The vast bulk of this patch is a literal move, the rest is adjusting the various Makefiles to use dtc and libfdt correctly from their new locations. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'scripts/dtc')
-rw-r--r--scripts/dtc/Makefile54
-rw-r--r--scripts/dtc/Makefile.dtc9
-rw-r--r--scripts/dtc/checks.c587
-rw-r--r--scripts/dtc/data.c321
-rw-r--r--scripts/dtc/dtc-lexer.l320
-rw-r--r--scripts/dtc/dtc-lexer.lex.c_shipped2187
-rw-r--r--scripts/dtc/dtc-parser.tab.c_shipped2040
-rw-r--r--scripts/dtc/dtc-parser.tab.h_shipped113
-rw-r--r--scripts/dtc/dtc-parser.y379
-rw-r--r--scripts/dtc/dtc.c226
-rw-r--r--scripts/dtc/dtc.h246
-rw-r--r--scripts/dtc/flattree.c906
-rw-r--r--scripts/dtc/fstree.c92
-rw-r--r--scripts/dtc/libfdt/Makefile.libfdt8
-rw-r--r--scripts/dtc/libfdt/fdt.c201
-rw-r--r--scripts/dtc/libfdt/fdt.h60
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c469
-rw-r--r--scripts/dtc/libfdt/fdt_rw.c463
-rw-r--r--scripts/dtc/libfdt/fdt_strerror.c96
-rw-r--r--scripts/dtc/libfdt/fdt_sw.c257
-rw-r--r--scripts/dtc/libfdt/fdt_wip.c145
-rw-r--r--scripts/dtc/libfdt/libfdt.h1076
-rw-r--r--scripts/dtc/libfdt/libfdt_env.h23
-rw-r--r--scripts/dtc/libfdt/libfdt_internal.h95
-rw-r--r--scripts/dtc/livetree.c308
-rw-r--r--scripts/dtc/srcpos.c116
-rw-r--r--scripts/dtc/srcpos.h85
-rw-r--r--scripts/dtc/treesource.c278
-rw-r--r--scripts/dtc/version_gen.h1
29 files changed, 11161 insertions, 0 deletions
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
new file mode 100644
index 000000000000..01cdb36fc583
--- /dev/null
+++ b/scripts/dtc/Makefile
@@ -0,0 +1,54 @@
1# scripts/dtc makefile
2
3hostprogs-y := dtc
4always := $(hostprogs-y)
5
6dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
7 srcpos.o checks.o
8dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
9
10# Source files need to get at the userspace version of libfdt_env.h to compile
11
12HOSTCFLAGS_DTC := -I$(src) -I$(src)/libfdt
13
14HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC)
15HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC)
16HOSTCFLAGS_dtc.o := $(HOSTCFLAGS_DTC)
17HOSTCFLAGS_flattree.o := $(HOSTCFLAGS_DTC)
18HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC)
19HOSTCFLAGS_livetree.o := $(HOSTCFLAGS_DTC)
20HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC)
21HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC)
22
23HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC)
24HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
25
26# dependencies on generated files need to be listed explicitly
27$(obj)/dtc-parser.tab.o: $(obj)/dtc-parser.tab.c $(obj)/dtc-parser.tab.h
28$(obj)/dtc-lexer.lex.o: $(obj)/dtc-lexer.lex.c $(obj)/dtc-parser.tab.h
29
30targets += dtc-parser.tab.c dtc-lexer.lex.c
31
32clean-files += dtc-parser.tab.h
33
34# GENERATE_PARSER := 1 # Uncomment to rebuild flex/bison output
35
36ifdef GENERATE_PARSER
37
38BISON = bison
39FLEX = flex
40
41quiet_cmd_bison = BISON $@
42 cmd_bison = $(BISON) -o$@ -d $<; cp $@ $@_shipped
43quiet_cmd_flex = FLEX $@
44 cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped
45
46$(obj)/dtc-parser.tab.c: $(src)/dtc-parser.y FORCE
47 $(call if_changed,bison)
48
49$(obj)/dtc-parser.tab.h: $(obj)/dtc-parser.tab.c
50
51$(obj)/dtc-lexer.lex.c: $(src)/dtc-lexer.l FORCE
52 $(call if_changed,flex)
53
54endif
diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc
new file mode 100644
index 000000000000..6ddf9ecac669
--- /dev/null
+++ b/scripts/dtc/Makefile.dtc
@@ -0,0 +1,9 @@
1# Makefile.dtc
2#
3# This is not a complete Makefile of itself. Instead, it is designed to
4# be easily embeddable into other systems of Makefiles.
5#
6DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
7 checks.c
8DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
9DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
new file mode 100644
index 000000000000..95485796f253
--- /dev/null
+++ b/scripts/dtc/checks.c
@@ -0,0 +1,587 @@
1/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2007.
3 *
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
21#include "dtc.h"
22
23#ifdef TRACE_CHECKS
24#define TRACE(c, ...) \
25 do { \
26 fprintf(stderr, "=== %s: ", (c)->name); \
27 fprintf(stderr, __VA_ARGS__); \
28 fprintf(stderr, "\n"); \
29 } while (0)
30#else
31#define TRACE(c, fmt, ...) do { } while (0)
32#endif
33
34enum checklevel {
35 IGNORE = 0,
36 WARN = 1,
37 ERROR = 2,
38};
39
40enum checkstatus {
41 UNCHECKED = 0,
42 PREREQ,
43 PASSED,
44 FAILED,
45};
46
47struct check;
48
49typedef void (*tree_check_fn)(struct check *c, struct node *dt);
50typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node);
51typedef void (*prop_check_fn)(struct check *c, struct node *dt,
52 struct node *node, struct property *prop);
53
54struct check {
55 const char *name;
56 tree_check_fn tree_fn;
57 node_check_fn node_fn;
58 prop_check_fn prop_fn;
59 void *data;
60 enum checklevel level;
61 enum checkstatus status;
62 int inprogress;
63 int num_prereqs;
64 struct check **prereq;
65};
66
67#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
68 static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
69 static struct check nm = { \
70 .name = #nm, \
71 .tree_fn = (tfn), \
72 .node_fn = (nfn), \
73 .prop_fn = (pfn), \
74 .data = (d), \
75 .level = (lvl), \
76 .status = UNCHECKED, \
77 .num_prereqs = ARRAY_SIZE(nm##_prereqs), \
78 .prereq = nm##_prereqs, \
79 };
80
81#define TREE_CHECK(nm, d, lvl, ...) \
82 CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
83#define NODE_CHECK(nm, d, lvl, ...) \
84 CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
85#define PROP_CHECK(nm, d, lvl, ...) \
86 CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
87#define BATCH_CHECK(nm, lvl, ...) \
88 CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__)
89
90#ifdef __GNUC__
91static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
92#endif
93static inline void check_msg(struct check *c, const char *fmt, ...)
94{
95 va_list ap;
96 va_start(ap, fmt);
97
98 if ((c->level < WARN) || (c->level <= quiet))
99 return; /* Suppress message */
100
101 fprintf(stderr, "%s (%s): ",
102 (c->level == ERROR) ? "ERROR" : "Warning", c->name);
103 vfprintf(stderr, fmt, ap);
104 fprintf(stderr, "\n");
105}
106
107#define FAIL(c, ...) \
108 do { \
109 TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
110 (c)->status = FAILED; \
111 check_msg((c), __VA_ARGS__); \
112 } while (0)
113
114static void check_nodes_props(struct check *c, struct node *dt, struct node *node)
115{
116 struct node *child;
117 struct property *prop;
118
119 TRACE(c, "%s", node->fullpath);
120 if (c->node_fn)
121 c->node_fn(c, dt, node);
122
123 if (c->prop_fn)
124 for_each_property(node, prop) {
125 TRACE(c, "%s\t'%s'", node->fullpath, prop->name);
126 c->prop_fn(c, dt, node, prop);
127 }
128
129 for_each_child(node, child)
130 check_nodes_props(c, dt, child);
131}
132
133static int run_check(struct check *c, struct node *dt)
134{
135 int error = 0;
136 int i;
137
138 assert(!c->inprogress);
139
140 if (c->status != UNCHECKED)
141 goto out;
142
143 c->inprogress = 1;
144
145 for (i = 0; i < c->num_prereqs; i++) {
146 struct check *prq = c->prereq[i];
147 error |= run_check(prq, dt);
148 if (prq->status != PASSED) {
149 c->status = PREREQ;
150 check_msg(c, "Failed prerequisite '%s'",
151 c->prereq[i]->name);
152 }
153 }
154
155 if (c->status != UNCHECKED)
156 goto out;
157
158 if (c->node_fn || c->prop_fn)
159 check_nodes_props(c, dt, dt);
160
161 if (c->tree_fn)
162 c->tree_fn(c, dt);
163 if (c->status == UNCHECKED)
164 c->status = PASSED;
165
166 TRACE(c, "\tCompleted, status %d", c->status);
167
168out:
169 c->inprogress = 0;
170 if ((c->status != PASSED) && (c->level == ERROR))
171 error = 1;
172 return error;
173}
174
175/*
176 * Utility check functions
177 */
178
179static void check_is_string(struct check *c, struct node *root,
180 struct node *node)
181{
182 struct property *prop;
183 char *propname = c->data;
184
185 prop = get_property(node, propname);
186 if (!prop)
187 return; /* Not present, assumed ok */
188
189 if (!data_is_one_string(prop->val))
190 FAIL(c, "\"%s\" property in %s is not a string",
191 propname, node->fullpath);
192}
193#define CHECK_IS_STRING(nm, propname, lvl) \
194 CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
195
196static void check_is_cell(struct check *c, struct node *root,
197 struct node *node)
198{
199 struct property *prop;
200 char *propname = c->data;
201
202 prop = get_property(node, propname);
203 if (!prop)
204 return; /* Not present, assumed ok */
205
206 if (prop->val.len != sizeof(cell_t))
207 FAIL(c, "\"%s\" property in %s is not a single cell",
208 propname, node->fullpath);
209}
210#define CHECK_IS_CELL(nm, propname, lvl) \
211 CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
212
213/*
214 * Structural check functions
215 */
216
217static void check_duplicate_node_names(struct check *c, struct node *dt,
218 struct node *node)
219{
220 struct node *child, *child2;
221
222 for_each_child(node, child)
223 for (child2 = child->next_sibling;
224 child2;
225 child2 = child2->next_sibling)
226 if (streq(child->name, child2->name))
227 FAIL(c, "Duplicate node name %s",
228 child->fullpath);
229}
230NODE_CHECK(duplicate_node_names, NULL, ERROR);
231
232static void check_duplicate_property_names(struct check *c, struct node *dt,
233 struct node *node)
234{
235 struct property *prop, *prop2;
236
237 for_each_property(node, prop)
238 for (prop2 = prop->next; prop2; prop2 = prop2->next)
239 if (streq(prop->name, prop2->name))
240 FAIL(c, "Duplicate property name %s in %s",
241 prop->name, node->fullpath);
242}
243NODE_CHECK(duplicate_property_names, NULL, ERROR);
244
245#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
246#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
247#define DIGITS "0123456789"
248#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
249
250static void check_node_name_chars(struct check *c, struct node *dt,
251 struct node *node)
252{
253 int n = strspn(node->name, c->data);
254
255 if (n < strlen(node->name))
256 FAIL(c, "Bad character '%c' in node %s",
257 node->name[n], node->fullpath);
258}
259NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
260
261static void check_node_name_format(struct check *c, struct node *dt,
262 struct node *node)
263{
264 if (strchr(get_unitname(node), '@'))
265 FAIL(c, "Node %s has multiple '@' characters in name",
266 node->fullpath);
267}
268NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
269
270static void check_property_name_chars(struct check *c, struct node *dt,
271 struct node *node, struct property *prop)
272{
273 int n = strspn(prop->name, c->data);
274
275 if (n < strlen(prop->name))
276 FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
277 prop->name[n], prop->name, node->fullpath);
278}
279PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
280
281static void check_explicit_phandles(struct check *c, struct node *root,
282 struct node *node)
283{
284 struct property *prop;
285 struct node *other;
286 cell_t phandle;
287
288 prop = get_property(node, "linux,phandle");
289 if (! prop)
290 return; /* No phandle, that's fine */
291
292 if (prop->val.len != sizeof(cell_t)) {
293 FAIL(c, "%s has bad length (%d) linux,phandle property",
294 node->fullpath, prop->val.len);
295 return;
296 }
297
298 phandle = propval_cell(prop);
299 if ((phandle == 0) || (phandle == -1)) {
300 FAIL(c, "%s has invalid linux,phandle value 0x%x",
301 node->fullpath, phandle);
302 return;
303 }
304
305 other = get_node_by_phandle(root, phandle);
306 if (other) {
307 FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
308 node->fullpath, phandle, other->fullpath);
309 return;
310 }
311
312 node->phandle = phandle;
313}
314NODE_CHECK(explicit_phandles, NULL, ERROR);
315
316static void check_name_properties(struct check *c, struct node *root,
317 struct node *node)
318{
319 struct property **pp, *prop = NULL;
320
321 for (pp = &node->proplist; *pp; pp = &((*pp)->next))
322 if (streq((*pp)->name, "name")) {
323 prop = *pp;
324 break;
325 }
326
327 if (!prop)
328 return; /* No name property, that's fine */
329
330 if ((prop->val.len != node->basenamelen+1)
331 || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
332 FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
333 " of base node name)", node->fullpath, prop->val.val);
334 } else {
335 /* The name property is correct, and therefore redundant.
336 * Delete it */
337 *pp = prop->next;
338 free(prop->name);
339 data_free(prop->val);
340 free(prop);
341 }
342}
343CHECK_IS_STRING(name_is_string, "name", ERROR);
344NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
345
346/*
347 * Reference fixup functions
348 */
349
350static void fixup_phandle_references(struct check *c, struct node *dt,
351 struct node *node, struct property *prop)
352{
353 struct marker *m = prop->val.markers;
354 struct node *refnode;
355 cell_t phandle;
356
357 for_each_marker_of_type(m, REF_PHANDLE) {
358 assert(m->offset + sizeof(cell_t) <= prop->val.len);
359
360 refnode = get_node_by_ref(dt, m->ref);
361 if (! refnode) {
362 FAIL(c, "Reference to non-existent node or label \"%s\"\n",
363 m->ref);
364 continue;
365 }
366
367 phandle = get_node_phandle(dt, refnode);
368 *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
369 }
370}
371CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
372 &duplicate_node_names, &explicit_phandles);
373
374static void fixup_path_references(struct check *c, struct node *dt,
375 struct node *node, struct property *prop)
376{
377 struct marker *m = prop->val.markers;
378 struct node *refnode;
379 char *path;
380
381 for_each_marker_of_type(m, REF_PATH) {
382 assert(m->offset <= prop->val.len);
383
384 refnode = get_node_by_ref(dt, m->ref);
385 if (!refnode) {
386 FAIL(c, "Reference to non-existent node or label \"%s\"\n",
387 m->ref);
388 continue;
389 }
390
391 path = refnode->fullpath;
392 prop->val = data_insert_at_marker(prop->val, m, path,
393 strlen(path) + 1);
394 }
395}
396CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
397 &duplicate_node_names);
398
399/*
400 * Semantic checks
401 */
402CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
403CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
404CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
405
406CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
407CHECK_IS_STRING(model_is_string, "model", WARN);
408CHECK_IS_STRING(status_is_string, "status", WARN);
409
410static void fixup_addr_size_cells(struct check *c, struct node *dt,
411 struct node *node)
412{
413 struct property *prop;
414
415 node->addr_cells = -1;
416 node->size_cells = -1;
417
418 prop = get_property(node, "#address-cells");
419 if (prop)
420 node->addr_cells = propval_cell(prop);
421
422 prop = get_property(node, "#size-cells");
423 if (prop)
424 node->size_cells = propval_cell(prop);
425}
426CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN,
427 &address_cells_is_cell, &size_cells_is_cell);
428
429#define node_addr_cells(n) \
430 (((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
431#define node_size_cells(n) \
432 (((n)->size_cells == -1) ? 1 : (n)->size_cells)
433
434static void check_reg_format(struct check *c, struct node *dt,
435 struct node *node)
436{
437 struct property *prop;
438 int addr_cells, size_cells, entrylen;
439
440 prop = get_property(node, "reg");
441 if (!prop)
442 return; /* No "reg", that's fine */
443
444 if (!node->parent) {
445 FAIL(c, "Root node has a \"reg\" property");
446 return;
447 }
448
449 if (prop->val.len == 0)
450 FAIL(c, "\"reg\" property in %s is empty", node->fullpath);
451
452 addr_cells = node_addr_cells(node->parent);
453 size_cells = node_size_cells(node->parent);
454 entrylen = (addr_cells + size_cells) * sizeof(cell_t);
455
456 if ((prop->val.len % entrylen) != 0)
457 FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
458 "(#address-cells == %d, #size-cells == %d)",
459 node->fullpath, prop->val.len, addr_cells, size_cells);
460}
461NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells);
462
463static void check_ranges_format(struct check *c, struct node *dt,
464 struct node *node)
465{
466 struct property *prop;
467 int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
468
469 prop = get_property(node, "ranges");
470 if (!prop)
471 return;
472
473 if (!node->parent) {
474 FAIL(c, "Root node has a \"ranges\" property");
475 return;
476 }
477
478 p_addr_cells = node_addr_cells(node->parent);
479 p_size_cells = node_size_cells(node->parent);
480 c_addr_cells = node_addr_cells(node);
481 c_size_cells = node_size_cells(node);
482 entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t);
483
484 if (prop->val.len == 0) {
485 if (p_addr_cells != c_addr_cells)
486 FAIL(c, "%s has empty \"ranges\" property but its "
487 "#address-cells (%d) differs from %s (%d)",
488 node->fullpath, c_addr_cells, node->parent->fullpath,
489 p_addr_cells);
490 if (p_size_cells != c_size_cells)
491 FAIL(c, "%s has empty \"ranges\" property but its "
492 "#size-cells (%d) differs from %s (%d)",
493 node->fullpath, c_size_cells, node->parent->fullpath,
494 p_size_cells);
495 } else if ((prop->val.len % entrylen) != 0) {
496 FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) "
497 "(parent #address-cells == %d, child #address-cells == %d, "
498 "#size-cells == %d)", node->fullpath, prop->val.len,
499 p_addr_cells, c_addr_cells, c_size_cells);
500 }
501}
502NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells);
503
504/*
505 * Style checks
506 */
507static void check_avoid_default_addr_size(struct check *c, struct node *dt,
508 struct node *node)
509{
510 struct property *reg, *ranges;
511
512 if (!node->parent)
513 return; /* Ignore root node */
514
515 reg = get_property(node, "reg");
516 ranges = get_property(node, "ranges");
517
518 if (!reg && !ranges)
519 return;
520
521 if ((node->parent->addr_cells == -1))
522 FAIL(c, "Relying on default #address-cells value for %s",
523 node->fullpath);
524
525 if ((node->parent->size_cells == -1))
526 FAIL(c, "Relying on default #size-cells value for %s",
527 node->fullpath);
528}
529NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells);
530
531static void check_obsolete_chosen_interrupt_controller(struct check *c,
532 struct node *dt)
533{
534 struct node *chosen;
535 struct property *prop;
536
537 chosen = get_node_by_path(dt, "/chosen");
538 if (!chosen)
539 return;
540
541 prop = get_property(chosen, "interrupt-controller");
542 if (prop)
543 FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
544 "property");
545}
546TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
547
548static struct check *check_table[] = {
549 &duplicate_node_names, &duplicate_property_names,
550 &node_name_chars, &node_name_format, &property_name_chars,
551 &name_is_string, &name_properties,
552 &explicit_phandles,
553 &phandle_references, &path_references,
554
555 &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
556 &device_type_is_string, &model_is_string, &status_is_string,
557
558 &addr_size_cells, &reg_format, &ranges_format,
559
560 &avoid_default_addr_size,
561 &obsolete_chosen_interrupt_controller,
562};
563
564void process_checks(int force, struct boot_info *bi)
565{
566 struct node *dt = bi->dt;
567 int i;
568 int error = 0;
569
570 for (i = 0; i < ARRAY_SIZE(check_table); i++) {
571 struct check *c = check_table[i];
572
573 if (c->level != IGNORE)
574 error = error || run_check(c, dt);
575 }
576
577 if (error) {
578 if (!force) {
579 fprintf(stderr, "ERROR: Input tree has errors, aborting "
580 "(use -f to force output)\n");
581 exit(2);
582 } else if (quiet < 3) {
583 fprintf(stderr, "Warning: Input tree has errors, "
584 "output forced\n");
585 }
586 }
587}
diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
new file mode 100644
index 000000000000..dd2e3d39d4c1
--- /dev/null
+++ b/scripts/dtc/data.c
@@ -0,0 +1,321 @@
1/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
3 *
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
21#include "dtc.h"
22
23void data_free(struct data d)
24{
25 struct marker *m, *nm;
26
27 m = d.markers;
28 while (m) {
29 nm = m->next;
30 free(m->ref);
31 free(m);
32 m = nm;
33 }
34
35 if (d.val)
36 free(d.val);
37}
38
39struct data data_grow_for(struct data d, int xlen)
40{
41 struct data nd;
42 int newsize;
43
44 if (xlen == 0)
45 return d;
46
47 nd = d;
48
49 newsize = xlen;
50
51 while ((d.len + xlen) > newsize)
52 newsize *= 2;
53
54 nd.val = xrealloc(d.val, newsize);
55
56 return nd;
57}
58
59struct data data_copy_mem(const char *mem, int len)
60{
61 struct data d;
62
63 d = data_grow_for(empty_data, len);
64
65 d.len = len;
66 memcpy(d.val, mem, len);
67
68 return d;
69}
70
71static char get_oct_char(const char *s, int *i)
72{
73 char x[4];
74 char *endx;
75 long val;
76
77 x[3] = '\0';
78 strncpy(x, s + *i, 3);
79
80 val = strtol(x, &endx, 8);
81
82 assert(endx > x);
83
84 (*i) += endx - x;
85 return val;
86}
87
88static char get_hex_char(const char *s, int *i)
89{
90 char x[3];
91 char *endx;
92 long val;
93
94 x[2] = '\0';
95 strncpy(x, s + *i, 2);
96
97 val = strtol(x, &endx, 16);
98 if (!(endx > x))
99 die("\\x used with no following hex digits\n");
100
101 (*i) += endx - x;
102 return val;
103}
104
105struct data data_copy_escape_string(const char *s, int len)
106{
107 int i = 0;
108 struct data d;
109 char *q;
110
111 d = data_grow_for(empty_data, strlen(s)+1);
112
113 q = d.val;
114 while (i < len) {
115 char c = s[i++];
116
117 if (c != '\\') {
118 q[d.len++] = c;
119 continue;
120 }
121
122 c = s[i++];
123 assert(c);
124 switch (c) {
125 case 'a':
126 q[d.len++] = '\a';
127 break;
128 case 'b':
129 q[d.len++] = '\b';
130 break;
131 case 't':
132 q[d.len++] = '\t';
133 break;
134 case 'n':
135 q[d.len++] = '\n';
136 break;
137 case 'v':
138 q[d.len++] = '\v';
139 break;
140 case 'f':
141 q[d.len++] = '\f';
142 break;
143 case 'r':
144 q[d.len++] = '\r';
145 break;
146 case '0':
147 case '1':
148 case '2':
149 case '3':
150 case '4':
151 case '5':
152 case '6':
153 case '7':
154 i--; /* need to re-read the first digit as
155 * part of the octal value */
156 q[d.len++] = get_oct_char(s, &i);
157 break;
158 case 'x':
159 q[d.len++] = get_hex_char(s, &i);
160 break;
161 default:
162 q[d.len++] = c;
163 }
164 }
165
166 q[d.len++] = '\0';
167 return d;
168}
169
170struct data data_copy_file(FILE *f, size_t maxlen)
171{
172 struct data d = empty_data;
173
174 while (!feof(f) && (d.len < maxlen)) {
175 size_t chunksize, ret;
176
177 if (maxlen == -1)
178 chunksize = 4096;
179 else
180 chunksize = maxlen - d.len;
181
182 d = data_grow_for(d, chunksize);
183 ret = fread(d.val + d.len, 1, chunksize, f);
184
185 if (ferror(f))
186 die("Error reading file into data: %s", strerror(errno));
187
188 if (d.len + ret < d.len)
189 die("Overflow reading file into data\n");
190
191 d.len += ret;
192 }
193
194 return d;
195}
196
197struct data data_append_data(struct data d, const void *p, int len)
198{
199 d = data_grow_for(d, len);
200 memcpy(d.val + d.len, p, len);
201 d.len += len;
202 return d;
203}
204
205struct data data_insert_at_marker(struct data d, struct marker *m,
206 const void *p, int len)
207{
208 d = data_grow_for(d, len);
209 memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset);
210 memcpy(d.val + m->offset, p, len);
211 d.len += len;
212
213 /* Adjust all markers after the one we're inserting at */
214 m = m->next;
215 for_each_marker(m)
216 m->offset += len;
217 return d;
218}
219
220struct data data_append_markers(struct data d, struct marker *m)
221{
222 struct marker **mp = &d.markers;
223
224 /* Find the end of the markerlist */
225 while (*mp)
226 mp = &((*mp)->next);
227 *mp = m;
228 return d;
229}
230
231struct data data_merge(struct data d1, struct data d2)
232{
233 struct data d;
234 struct marker *m2 = d2.markers;
235
236 d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2);
237
238 /* Adjust for the length of d1 */
239 for_each_marker(m2)
240 m2->offset += d1.len;
241
242 d2.markers = NULL; /* So data_free() doesn't clobber them */
243 data_free(d2);
244
245 return d;
246}
247
248struct data data_append_cell(struct data d, cell_t word)
249{
250 cell_t beword = cpu_to_fdt32(word);
251
252 return data_append_data(d, &beword, sizeof(beword));
253}
254
255struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
256{
257 struct fdt_reserve_entry bere;
258
259 bere.address = cpu_to_fdt64(re->address);
260 bere.size = cpu_to_fdt64(re->size);
261
262 return data_append_data(d, &bere, sizeof(bere));
263}
264
265struct data data_append_addr(struct data d, uint64_t addr)
266{
267 uint64_t beaddr = cpu_to_fdt64(addr);
268
269 return data_append_data(d, &beaddr, sizeof(beaddr));
270}
271
272struct data data_append_byte(struct data d, uint8_t byte)
273{
274 return data_append_data(d, &byte, 1);
275}
276
277struct data data_append_zeroes(struct data d, int len)
278{
279 d = data_grow_for(d, len);
280
281 memset(d.val + d.len, 0, len);
282 d.len += len;
283 return d;
284}
285
286struct data data_append_align(struct data d, int align)
287{
288 int newlen = ALIGN(d.len, align);
289 return data_append_zeroes(d, newlen - d.len);
290}
291
292struct data data_add_marker(struct data d, enum markertype type, char *ref)
293{
294 struct marker *m;
295
296 m = xmalloc(sizeof(*m));
297 m->offset = d.len;
298 m->type = type;
299 m->ref = ref;
300 m->next = NULL;
301
302 return data_append_markers(d, m);
303}
304
305int data_is_one_string(struct data d)
306{
307 int i;
308 int len = d.len;
309
310 if (len == 0)
311 return 0;
312
313 for (i = 0; i < len-1; i++)
314 if (d.val[i] == '\0')
315 return 0;
316
317 if (d.val[len-1] != '\0')
318 return 0;
319
320 return 1;
321}
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
new file mode 100644
index 000000000000..44dbfd3f0976
--- /dev/null
+++ b/scripts/dtc/dtc-lexer.l
@@ -0,0 +1,320 @@
1/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
3 *
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
21%option noyywrap nounput yylineno
22
23%x INCLUDE
24%x BYTESTRING
25%x PROPNODENAME
26%s V1
27
28PROPNODECHAR [a-zA-Z0-9,._+*#?@-]
29PATHCHAR ({PROPNODECHAR}|[/])
30LABEL [a-zA-Z_][a-zA-Z0-9_]*
31STRING \"([^\\"]|\\.)*\"
32WS [[:space:]]
33COMMENT "/*"([^*]|\*+[^*/])*\*+"/"
34LINECOMMENT "//".*\n
35
36%{
37#include "dtc.h"
38#include "srcpos.h"
39#include "dtc-parser.tab.h"
40
41
42/*#define LEXDEBUG 1*/
43
44#ifdef LEXDEBUG
45#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
46#else
47#define DPRINT(fmt, ...) do { } while (0)
48#endif
49
50static int dts_version; /* = 0 */
51
52#define BEGIN_DEFAULT() if (dts_version == 0) { \
53 DPRINT("<INITIAL>\n"); \
54 BEGIN(INITIAL); \
55 } else { \
56 DPRINT("<V1>\n"); \
57 BEGIN(V1); \
58 }
59
60static void push_input_file(const char *filename);
61static int pop_input_file(void);
62%}
63
64%%
65<*>"/include/"{WS}*{STRING} {
66 char *name = strchr(yytext, '\"') + 1;
67 yytext[yyleng-1] = '\0';
68 push_input_file(name);
69 }
70
71<*><<EOF>> {
72 if (!pop_input_file()) {
73 yyterminate();
74 }
75 }
76
77<*>{STRING} {
78 yylloc.file = srcpos_file;
79 yylloc.first_line = yylineno;
80 DPRINT("String: %s\n", yytext);
81 yylval.data = data_copy_escape_string(yytext+1,
82 yyleng-2);
83 yylloc.first_line = yylineno;
84 return DT_STRING;
85 }
86
87<*>"/dts-v1/" {
88 yylloc.file = srcpos_file;
89 yylloc.first_line = yylineno;
90 DPRINT("Keyword: /dts-v1/\n");
91 dts_version = 1;
92 BEGIN_DEFAULT();
93 return DT_V1;
94 }
95
96<*>"/memreserve/" {
97 yylloc.file = srcpos_file;
98 yylloc.first_line = yylineno;
99 DPRINT("Keyword: /memreserve/\n");
100 BEGIN_DEFAULT();
101 return DT_MEMRESERVE;
102 }
103
104<*>{LABEL}: {
105 yylloc.file = srcpos_file;
106 yylloc.first_line = yylineno;
107 DPRINT("Label: %s\n", yytext);
108 yylval.labelref = strdup(yytext);
109 yylval.labelref[yyleng-1] = '\0';
110 return DT_LABEL;
111 }
112
113<INITIAL>[bodh]# {
114 yylloc.file = srcpos_file;
115 yylloc.first_line = yylineno;
116 if (*yytext == 'b')
117 yylval.cbase = 2;
118 else if (*yytext == 'o')
119 yylval.cbase = 8;
120 else if (*yytext == 'd')
121 yylval.cbase = 10;
122 else
123 yylval.cbase = 16;
124 DPRINT("Base: %d\n", yylval.cbase);
125 return DT_BASE;
126 }
127
128<INITIAL>[0-9a-fA-F]+ {
129 yylloc.file = srcpos_file;
130 yylloc.first_line = yylineno;
131 yylval.literal = strdup(yytext);
132 DPRINT("Literal: '%s'\n", yylval.literal);
133 return DT_LEGACYLITERAL;
134 }
135
136<V1>[0-9]+|0[xX][0-9a-fA-F]+ {
137 yylloc.file = srcpos_file;
138 yylloc.first_line = yylineno;
139 yylval.literal = strdup(yytext);
140 DPRINT("Literal: '%s'\n", yylval.literal);
141 return DT_LITERAL;
142 }
143
144\&{LABEL} { /* label reference */
145 yylloc.file = srcpos_file;
146 yylloc.first_line = yylineno;
147 DPRINT("Ref: %s\n", yytext+1);
148 yylval.labelref = strdup(yytext+1);
149 return DT_REF;
150 }
151
152"&{/"{PATHCHAR}+\} { /* new-style path reference */
153 yylloc.file = srcpos_file;
154 yylloc.first_line = yylineno;
155 yytext[yyleng-1] = '\0';
156 DPRINT("Ref: %s\n", yytext+2);
157 yylval.labelref = strdup(yytext+2);
158 return DT_REF;
159 }
160
161<INITIAL>"&/"{PATHCHAR}+ { /* old-style path reference */
162 yylloc.file = srcpos_file;
163 yylloc.first_line = yylineno;
164 DPRINT("Ref: %s\n", yytext+1);
165 yylval.labelref = strdup(yytext+1);
166 return DT_REF;
167 }
168
169<BYTESTRING>[0-9a-fA-F]{2} {
170 yylloc.file = srcpos_file;
171 yylloc.first_line = yylineno;
172 yylval.byte = strtol(yytext, NULL, 16);
173 DPRINT("Byte: %02x\n", (int)yylval.byte);
174 return DT_BYTE;
175 }
176
177<BYTESTRING>"]" {
178 yylloc.file = srcpos_file;
179 yylloc.first_line = yylineno;
180 DPRINT("/BYTESTRING\n");
181 BEGIN_DEFAULT();
182 return ']';
183 }
184
185<PROPNODENAME>{PROPNODECHAR}+ {
186 yylloc.file = srcpos_file;
187 yylloc.first_line = yylineno;
188 DPRINT("PropNodeName: %s\n", yytext);
189 yylval.propnodename = strdup(yytext);
190 BEGIN_DEFAULT();
191 return DT_PROPNODENAME;
192 }
193
194"/incbin/" {
195 yylloc.file = srcpos_file;
196 yylloc.first_line = yylineno;
197 DPRINT("Binary Include\n");
198 return DT_INCBIN;
199 }
200
201<*>{WS}+ /* eat whitespace */
202<*>{COMMENT}+ /* eat C-style comments */
203<*>{LINECOMMENT}+ /* eat C++-style comments */
204
205<*>. {
206 yylloc.file = srcpos_file;
207 yylloc.first_line = yylineno;
208 DPRINT("Char: %c (\\x%02x)\n", yytext[0],
209 (unsigned)yytext[0]);
210 if (yytext[0] == '[') {
211 DPRINT("<BYTESTRING>\n");
212 BEGIN(BYTESTRING);
213 }
214 if ((yytext[0] == '{')
215 || (yytext[0] == ';')) {
216 DPRINT("<PROPNODENAME>\n");
217 BEGIN(PROPNODENAME);
218 }
219 return yytext[0];
220 }
221
222%%
223
224
225/*
226 * Stack of nested include file contexts.
227 */
228
229struct incl_file {
230 struct dtc_file *file;
231 YY_BUFFER_STATE yy_prev_buf;
232 int yy_prev_lineno;
233 struct incl_file *prev;
234};
235
236static struct incl_file *incl_file_stack;
237
238
239/*
240 * Detect infinite include recursion.
241 */
242#define MAX_INCLUDE_DEPTH (100)
243
244static int incl_depth = 0;
245
246
247static void push_input_file(const char *filename)
248{
249 struct incl_file *incl_file;
250 struct dtc_file *newfile;
251 struct search_path search, *searchptr = NULL;
252
253 assert(filename);
254
255 if (incl_depth++ >= MAX_INCLUDE_DEPTH)
256 die("Includes nested too deeply");
257
258 if (srcpos_file) {
259 search.dir = srcpos_file->dir;
260 search.next = NULL;
261 search.prev = NULL;
262 searchptr = &search;
263 }
264
265 newfile = dtc_open_file(filename, searchptr);
266
267 incl_file = xmalloc(sizeof(struct incl_file));
268
269 /*
270 * Save current context.
271 */
272 incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
273 incl_file->yy_prev_lineno = yylineno;
274 incl_file->file = srcpos_file;
275 incl_file->prev = incl_file_stack;
276
277 incl_file_stack = incl_file;
278
279 /*
280 * Establish new context.
281 */
282 srcpos_file = newfile;
283 yylineno = 1;
284 yyin = newfile->file;
285 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
286}
287
288
289static int pop_input_file(void)
290{
291 struct incl_file *incl_file;
292
293 if (incl_file_stack == 0)
294 return 0;
295
296 dtc_close_file(srcpos_file);
297
298 /*
299 * Pop.
300 */
301 --incl_depth;
302 incl_file = incl_file_stack;
303 incl_file_stack = incl_file->prev;
304
305 /*
306 * Recover old context.
307 */
308 yy_delete_buffer(YY_CURRENT_BUFFER);
309 yy_switch_to_buffer(incl_file->yy_prev_buf);
310 yylineno = incl_file->yy_prev_lineno;
311 srcpos_file = incl_file->file;
312 yyin = incl_file->file ? incl_file->file->file : NULL;
313
314 /*
315 * Free old state.
316 */
317 free(incl_file);
318
319 return 1;
320}
diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
new file mode 100644
index 000000000000..ac392cb040f6
--- /dev/null
+++ b/scripts/dtc/dtc-lexer.lex.c_shipped
@@ -0,0 +1,2187 @@
1#line 2 "dtc-lexer.lex.c"
2
3#line 4 "dtc-lexer.lex.c"
4
5#define YY_INT_ALIGNED short int
6
7/* A lexical scanner generated by flex */
8
9#define FLEX_SCANNER
10#define YY_FLEX_MAJOR_VERSION 2
11#define YY_FLEX_MINOR_VERSION 5
12#define YY_FLEX_SUBMINOR_VERSION 34
13#if YY_FLEX_SUBMINOR_VERSION > 0
14#define FLEX_BETA
15#endif
16
17/* First, we deal with platform-specific or compiler-specific issues. */
18
19/* begin standard C headers. */
20#include <stdio.h>
21#include <string.h>
22#include <errno.h>
23#include <stdlib.h>
24
25/* end standard C headers. */
26
27/* flex integer type definitions */
28
29#ifndef FLEXINT_H
30#define FLEXINT_H
31
32/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
33
34#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
35
36/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
37 * if you want the limit (max/min) macros for int types.
38 */
39#ifndef __STDC_LIMIT_MACROS
40#define __STDC_LIMIT_MACROS 1
41#endif
42
43#include <inttypes.h>
44typedef int8_t flex_int8_t;
45typedef uint8_t flex_uint8_t;
46typedef int16_t flex_int16_t;
47typedef uint16_t flex_uint16_t;
48typedef int32_t flex_int32_t;
49typedef uint32_t flex_uint32_t;
50#else
51typedef signed char flex_int8_t;
52typedef short int flex_int16_t;
53typedef int flex_int32_t;
54typedef unsigned char flex_uint8_t;
55typedef unsigned short int flex_uint16_t;
56typedef unsigned int flex_uint32_t;
57#endif /* ! C99 */
58
59/* Limits of integral types. */
60#ifndef INT8_MIN
61#define INT8_MIN (-128)
62#endif
63#ifndef INT16_MIN
64#define INT16_MIN (-32767-1)
65#endif
66#ifndef INT32_MIN
67#define INT32_MIN (-2147483647-1)
68#endif
69#ifndef INT8_MAX
70#define INT8_MAX (127)
71#endif
72#ifndef INT16_MAX
73#define INT16_MAX (32767)
74#endif
75#ifndef INT32_MAX
76#define INT32_MAX (2147483647)
77#endif
78#ifndef UINT8_MAX
79#define UINT8_MAX (255U)
80#endif
81#ifndef UINT16_MAX
82#define UINT16_MAX (65535U)
83#endif
84#ifndef UINT32_MAX
85#define UINT32_MAX (4294967295U)
86#endif
87
88#endif /* ! FLEXINT_H */
89
90#ifdef __cplusplus
91
92/* The "const" storage-class-modifier is valid. */
93#define YY_USE_CONST
94
95#else /* ! __cplusplus */
96
97/* C99 requires __STDC__ to be defined as 1. */
98#if defined (__STDC__)
99
100#define YY_USE_CONST
101
102#endif /* defined (__STDC__) */
103#endif /* ! __cplusplus */
104
105#ifdef YY_USE_CONST
106#define yyconst const
107#else
108#define yyconst
109#endif
110
111/* Returned upon end-of-file. */
112#define YY_NULL 0
113
114/* Promotes a possibly negative, possibly signed char to an unsigned
115 * integer for use as an array index. If the signed char is negative,
116 * we want to instead treat it as an 8-bit unsigned char, hence the
117 * double cast.
118 */
119#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
120
121/* Enter a start condition. This macro really ought to take a parameter,
122 * but we do it the disgusting crufty way forced on us by the ()-less
123 * definition of BEGIN.
124 */
125#define BEGIN (yy_start) = 1 + 2 *
126
127/* Translate the current start state into a value that can be later handed
128 * to BEGIN to return to the state. The YYSTATE alias is for lex
129 * compatibility.
130 */
131#define YY_START (((yy_start) - 1) / 2)
132#define YYSTATE YY_START
133
134/* Action number for EOF rule of a given start state. */
135#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
136
137/* Special action meaning "start processing a new file". */
138#define YY_NEW_FILE yyrestart(yyin )
139
140#define YY_END_OF_BUFFER_CHAR 0
141
142/* Size of default input buffer. */
143#ifndef YY_BUF_SIZE
144#define YY_BUF_SIZE 16384
145#endif
146
147/* The state buf must be large enough to hold one state per character in the main buffer.
148 */
149#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
150
151#ifndef YY_TYPEDEF_YY_BUFFER_STATE
152#define YY_TYPEDEF_YY_BUFFER_STATE
153typedef struct yy_buffer_state *YY_BUFFER_STATE;
154#endif
155
156extern int yyleng;
157
158extern FILE *yyin, *yyout;
159
160#define EOB_ACT_CONTINUE_SCAN 0
161#define EOB_ACT_END_OF_FILE 1
162#define EOB_ACT_LAST_MATCH 2
163
164 /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
165 * access to the local variable yy_act. Since yyless() is a macro, it would break
166 * existing scanners that call yyless() from OUTSIDE yylex.
167 * One obvious solution it to make yy_act a global. I tried that, and saw
168 * a 5% performance hit in a non-yylineno scanner, because yy_act is
169 * normally declared as a register variable-- so it is not worth it.
170 */
171 #define YY_LESS_LINENO(n) \
172 do { \
173 int yyl;\
174 for ( yyl = n; yyl < yyleng; ++yyl )\
175 if ( yytext[yyl] == '\n' )\
176 --yylineno;\
177 }while(0)
178
179/* Return all but the first "n" matched characters back to the input stream. */
180#define yyless(n) \
181 do \
182 { \
183 /* Undo effects of setting up yytext. */ \
184 int yyless_macro_arg = (n); \
185 YY_LESS_LINENO(yyless_macro_arg);\
186 *yy_cp = (yy_hold_char); \
187 YY_RESTORE_YY_MORE_OFFSET \
188 (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
189 YY_DO_BEFORE_ACTION; /* set up yytext again */ \
190 } \
191 while ( 0 )
192
193#define unput(c) yyunput( c, (yytext_ptr) )
194
195/* The following is because we cannot portably get our hands on size_t
196 * (without autoconf's help, which isn't available because we want
197 * flex-generated scanners to compile on their own).
198 * Given that the standard has decreed that size_t exists since 1989,
199 * I guess we can afford to depend on it. Manoj.
200 */
201
202#ifndef YY_TYPEDEF_YY_SIZE_T
203#define YY_TYPEDEF_YY_SIZE_T
204typedef size_t yy_size_t;
205#endif
206
207#ifndef YY_STRUCT_YY_BUFFER_STATE
208#define YY_STRUCT_YY_BUFFER_STATE
209struct yy_buffer_state
210 {
211 FILE *yy_input_file;
212
213 char *yy_ch_buf; /* input buffer */
214 char *yy_buf_pos; /* current position in input buffer */
215
216 /* Size of input buffer in bytes, not including room for EOB
217 * characters.
218 */
219 yy_size_t yy_buf_size;
220
221 /* Number of characters read into yy_ch_buf, not including EOB
222 * characters.
223 */
224 int yy_n_chars;
225
226 /* Whether we "own" the buffer - i.e., we know we created it,
227 * and can realloc() it to grow it, and should free() it to
228 * delete it.
229 */
230 int yy_is_our_buffer;
231
232 /* Whether this is an "interactive" input source; if so, and
233 * if we're using stdio for input, then we want to use getc()
234 * instead of fread(), to make sure we stop fetching input after
235 * each newline.
236 */
237 int yy_is_interactive;
238
239 /* Whether we're considered to be at the beginning of a line.
240 * If so, '^' rules will be active on the next match, otherwise
241 * not.
242 */
243 int yy_at_bol;
244
245 int yy_bs_lineno; /**< The line count. */
246 int yy_bs_column; /**< The column count. */
247
248 /* Whether to try to fill the input buffer when we reach the
249 * end of it.
250 */
251 int yy_fill_buffer;
252
253 int yy_buffer_status;
254
255#define YY_BUFFER_NEW 0
256#define YY_BUFFER_NORMAL 1
257 /* When an EOF's been seen but there's still some text to process
258 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
259 * shouldn't try reading from the input source any more. We might
260 * still have a bunch of tokens to match, though, because of
261 * possible backing-up.
262 *
263 * When we actually see the EOF, we change the status to "new"
264 * (via yyrestart()), so that the user can continue scanning by
265 * just pointing yyin at a new input file.
266 */
267#define YY_BUFFER_EOF_PENDING 2
268
269 };
270#endif /* !YY_STRUCT_YY_BUFFER_STATE */
271
272/* Stack of input buffers. */
273static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
274static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
275static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
276
277/* We provide macros for accessing buffer states in case in the
278 * future we want to put the buffer states in a more general
279 * "scanner state".
280 *
281 * Returns the top of the stack, or NULL.
282 */
283#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
284 ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
285 : NULL)
286
287/* Same as previous macro, but useful when we know that the buffer stack is not
288 * NULL or when we need an lvalue. For internal use only.
289 */
290#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
291
292/* yy_hold_char holds the character lost when yytext is formed. */
293static char yy_hold_char;
294static int yy_n_chars; /* number of characters read into yy_ch_buf */
295int yyleng;
296
297/* Points to current character in buffer. */
298static char *yy_c_buf_p = (char *) 0;
299static int yy_init = 0; /* whether we need to initialize */
300static int yy_start = 0; /* start state number */
301
302/* Flag which is used to allow yywrap()'s to do buffer switches
303 * instead of setting up a fresh yyin. A bit of a hack ...
304 */
305static int yy_did_buffer_switch_on_eof;
306
307void yyrestart (FILE *input_file );
308void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
309YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
310void yy_delete_buffer (YY_BUFFER_STATE b );
311void yy_flush_buffer (YY_BUFFER_STATE b );
312void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
313void yypop_buffer_state (void );
314
315static void yyensure_buffer_stack (void );
316static void yy_load_buffer_state (void );
317static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
318
319#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
320
321YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
322YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
323YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len );
324
325void *yyalloc (yy_size_t );
326void *yyrealloc (void *,yy_size_t );
327void yyfree (void * );
328
329#define yy_new_buffer yy_create_buffer
330
331#define yy_set_interactive(is_interactive) \
332 { \
333 if ( ! YY_CURRENT_BUFFER ){ \
334 yyensure_buffer_stack (); \
335 YY_CURRENT_BUFFER_LVALUE = \
336 yy_create_buffer(yyin,YY_BUF_SIZE ); \
337 } \
338 YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
339 }
340
341#define yy_set_bol(at_bol) \
342 { \
343 if ( ! YY_CURRENT_BUFFER ){\
344 yyensure_buffer_stack (); \
345 YY_CURRENT_BUFFER_LVALUE = \
346 yy_create_buffer(yyin,YY_BUF_SIZE ); \
347 } \
348 YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
349 }
350
351#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
352
353/* Begin user sect3 */
354
355#define yywrap(n) 1
356#define YY_SKIP_YYWRAP
357
358typedef unsigned char YY_CHAR;
359
360FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
361
362typedef int yy_state_type;
363
364extern int yylineno;
365
366int yylineno = 1;
367
368extern char *yytext;
369#define yytext_ptr yytext
370
371static yy_state_type yy_get_previous_state (void );
372static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
373static int yy_get_next_buffer (void );
374static void yy_fatal_error (yyconst char msg[] );
375
376/* Done after the current pattern has been matched and before the
377 * corresponding action - sets up yytext.
378 */
379#define YY_DO_BEFORE_ACTION \
380 (yytext_ptr) = yy_bp; \
381 yyleng = (size_t) (yy_cp - yy_bp); \
382 (yy_hold_char) = *yy_cp; \
383 *yy_cp = '\0'; \
384 (yy_c_buf_p) = yy_cp;
385
386#define YY_NUM_RULES 20
387#define YY_END_OF_BUFFER 21
388/* This struct is not used in this scanner,
389 but its presence is necessary. */
390struct yy_trans_info
391 {
392 flex_int32_t yy_verify;
393 flex_int32_t yy_nxt;
394 };
395static yyconst flex_int16_t yy_accept[104] =
396 { 0,
397 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
398 21, 19, 16, 16, 19, 19, 19, 7, 7, 19,
399 7, 19, 19, 19, 19, 13, 14, 14, 19, 8,
400 8, 16, 0, 2, 0, 0, 9, 0, 0, 0,
401 0, 0, 0, 7, 7, 5, 0, 6, 0, 12,
402 12, 14, 14, 8, 0, 11, 9, 0, 0, 0,
403 0, 18, 0, 0, 0, 0, 8, 0, 17, 0,
404 0, 0, 0, 0, 10, 0, 0, 0, 0, 0,
405 0, 0, 0, 0, 0, 0, 0, 0, 3, 15,
406 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
407
408 0, 4, 0
409 } ;
410
411static yyconst flex_int32_t yy_ec[256] =
412 { 0,
413 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
414 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
415 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
416 1, 2, 1, 4, 5, 1, 1, 6, 1, 1,
417 1, 7, 8, 8, 9, 8, 10, 11, 12, 13,
418 13, 13, 13, 13, 13, 13, 13, 14, 1, 1,
419 1, 1, 8, 8, 15, 15, 15, 15, 15, 15,
420 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
421 16, 16, 16, 16, 16, 16, 16, 17, 16, 16,
422 1, 18, 19, 1, 16, 1, 15, 20, 21, 22,
423
424 23, 15, 16, 24, 25, 16, 16, 26, 27, 28,
425 24, 16, 16, 29, 30, 31, 32, 33, 16, 17,
426 16, 16, 34, 1, 35, 1, 1, 1, 1, 1,
427 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
428 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
429 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
430 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
431 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
432 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
433 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
434
435 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
436 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
437 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
438 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
439 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
440 1, 1, 1, 1, 1
441 } ;
442
443static yyconst flex_int32_t yy_meta[36] =
444 { 0,
445 1, 1, 1, 1, 2, 1, 2, 2, 2, 3,
446 4, 4, 4, 5, 6, 7, 7, 1, 1, 6,
447 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
448 7, 7, 7, 8, 1
449 } ;
450
451static yyconst flex_int16_t yy_base[117] =
452 { 0,
453 0, 0, 30, 0, 44, 0, 67, 0, 97, 105,
454 302, 303, 35, 44, 40, 94, 112, 0, 129, 152,
455 296, 295, 159, 0, 176, 303, 0, 116, 95, 165,
456 49, 46, 102, 303, 296, 0, 0, 288, 290, 293,
457 264, 266, 270, 0, 0, 303, 0, 303, 264, 303,
458 0, 0, 195, 101, 0, 0, 0, 0, 284, 125,
459 277, 265, 225, 230, 216, 218, 0, 202, 224, 221,
460 217, 107, 196, 188, 303, 206, 179, 186, 178, 185,
461 183, 162, 161, 150, 169, 160, 145, 125, 303, 303,
462 137, 109, 190, 103, 203, 167, 108, 197, 303, 123,
463
464 29, 303, 303, 215, 221, 226, 229, 234, 240, 246,
465 250, 257, 265, 270, 275, 282
466 } ;
467
468static yyconst flex_int16_t yy_def[117] =
469 { 0,
470 103, 1, 1, 3, 3, 5, 103, 7, 3, 3,
471 103, 103, 103, 103, 104, 105, 103, 106, 103, 19,
472 19, 20, 103, 107, 20, 103, 108, 109, 105, 103,
473 103, 103, 104, 103, 104, 110, 111, 103, 112, 113,
474 103, 103, 103, 106, 19, 103, 20, 103, 103, 103,
475 20, 108, 109, 103, 114, 110, 111, 115, 112, 112,
476 113, 103, 103, 103, 103, 103, 114, 115, 103, 103,
477 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
478 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
479 103, 103, 103, 103, 103, 116, 103, 116, 103, 116,
480
481 103, 103, 0, 103, 103, 103, 103, 103, 103, 103,
482 103, 103, 103, 103, 103, 103
483 } ;
484
485static yyconst flex_int16_t yy_nxt[339] =
486 { 0,
487 12, 13, 14, 15, 12, 16, 12, 12, 12, 17,
488 18, 18, 18, 12, 19, 20, 20, 12, 12, 21,
489 19, 21, 19, 22, 20, 20, 20, 20, 20, 20,
490 20, 20, 20, 12, 12, 12, 32, 32, 102, 23,
491 12, 12, 12, 34, 20, 32, 32, 32, 32, 20,
492 20, 20, 20, 20, 24, 24, 24, 35, 25, 54,
493 54, 54, 26, 25, 25, 25, 25, 12, 13, 14,
494 15, 27, 12, 27, 27, 27, 23, 27, 27, 27,
495 12, 28, 28, 28, 12, 12, 28, 28, 28, 28,
496 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
497
498 12, 12, 29, 36, 103, 34, 17, 30, 31, 31,
499 29, 54, 54, 54, 17, 30, 31, 31, 39, 35,
500 52, 40, 52, 52, 52, 103, 78, 38, 38, 46,
501 101, 60, 79, 41, 69, 97, 42, 94, 43, 45,
502 45, 45, 46, 45, 47, 47, 93, 92, 45, 45,
503 45, 45, 47, 47, 47, 47, 47, 47, 47, 47,
504 47, 47, 47, 47, 47, 39, 47, 91, 40, 90,
505 99, 47, 47, 47, 47, 54, 54, 54, 89, 88,
506 41, 55, 87, 49, 100, 43, 51, 51, 51, 86,
507 51, 95, 95, 96, 85, 51, 51, 51, 51, 52,
508
509 99, 52, 52, 52, 95, 95, 96, 84, 46, 83,
510 82, 81, 39, 79, 100, 33, 33, 33, 33, 33,
511 33, 33, 33, 37, 80, 77, 37, 37, 37, 44,
512 40, 44, 50, 76, 50, 52, 75, 52, 74, 52,
513 52, 53, 73, 53, 53, 53, 53, 56, 56, 56,
514 72, 56, 56, 57, 71, 57, 57, 59, 59, 59,
515 59, 59, 59, 59, 59, 61, 61, 61, 61, 61,
516 61, 61, 61, 67, 70, 67, 68, 68, 68, 62,
517 68, 68, 98, 98, 98, 98, 98, 98, 98, 98,
518 60, 66, 65, 64, 63, 62, 60, 58, 103, 48,
519
520 48, 103, 11, 103, 103, 103, 103, 103, 103, 103,
521 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
522 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
523 103, 103, 103, 103, 103, 103, 103, 103
524 } ;
525
526static yyconst flex_int16_t yy_chk[339] =
527 { 0,
528 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
529 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
530 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
531 1, 1, 1, 1, 1, 3, 13, 13, 101, 3,
532 3, 3, 3, 15, 3, 14, 14, 32, 32, 3,
533 3, 3, 3, 3, 5, 5, 5, 15, 5, 31,
534 31, 31, 5, 5, 5, 5, 5, 7, 7, 7,
535 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
536 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
537 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
538
539 7, 7, 9, 16, 29, 33, 9, 9, 9, 9,
540 10, 54, 54, 54, 10, 10, 10, 10, 17, 33,
541 28, 17, 28, 28, 28, 100, 72, 16, 29, 28,
542 97, 60, 72, 17, 60, 94, 17, 92, 17, 19,
543 19, 19, 19, 19, 19, 19, 91, 88, 19, 19,
544 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
545 19, 19, 20, 20, 20, 23, 20, 87, 23, 86,
546 96, 20, 20, 20, 20, 30, 30, 30, 85, 84,
547 23, 30, 83, 23, 96, 23, 25, 25, 25, 82,
548 25, 93, 93, 93, 81, 25, 25, 25, 25, 53,
549
550 98, 53, 53, 53, 95, 95, 95, 80, 53, 79,
551 78, 77, 76, 74, 98, 104, 104, 104, 104, 104,
552 104, 104, 104, 105, 73, 71, 105, 105, 105, 106,
553 70, 106, 107, 69, 107, 108, 68, 108, 66, 108,
554 108, 109, 65, 109, 109, 109, 109, 110, 110, 110,
555 64, 110, 110, 111, 63, 111, 111, 112, 112, 112,
556 112, 112, 112, 112, 112, 113, 113, 113, 113, 113,
557 113, 113, 113, 114, 62, 114, 115, 115, 115, 61,
558 115, 115, 116, 116, 116, 116, 116, 116, 116, 116,
559 59, 49, 43, 42, 41, 40, 39, 38, 35, 22,
560
561 21, 11, 103, 103, 103, 103, 103, 103, 103, 103,
562 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
563 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
564 103, 103, 103, 103, 103, 103, 103, 103
565 } ;
566
567/* Table of booleans, true if rule could match eol. */
568static yyconst flex_int32_t yy_rule_can_match_eol[21] =
569 { 0,
5701, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
571 0, };
572
573static yy_state_type yy_last_accepting_state;
574static char *yy_last_accepting_cpos;
575
576extern int yy_flex_debug;
577int yy_flex_debug = 0;
578
579/* The intent behind this definition is that it'll catch
580 * any uses of REJECT which flex missed.
581 */
582#define REJECT reject_used_but_not_detected
583#define yymore() yymore_used_but_not_detected
584#define YY_MORE_ADJ 0
585#define YY_RESTORE_YY_MORE_OFFSET
586char *yytext;
587#line 1 "dtc-lexer.l"
588/*
589 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
590 *
591 *
592 * This program is free software; you can redistribute it and/or
593 * modify it under the terms of the GNU General Public License as
594 * published by the Free Software Foundation; either version 2 of the
595 * License, or (at your option) any later version.
596 *
597 * This program is distributed in the hope that it will be useful,
598 * but WITHOUT ANY WARRANTY; without even the implied warranty of
599 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
600 * General Public License for more details.
601 *
602 * You should have received a copy of the GNU General Public License
603 * along with this program; if not, write to the Free Software
604 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
605 * USA
606 */
607
608
609
610
611#line 37 "dtc-lexer.l"
612#include "dtc.h"
613#include "srcpos.h"
614#include "dtc-parser.tab.h"
615
616
617/*#define LEXDEBUG 1*/
618
619#ifdef LEXDEBUG
620#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
621#else
622#define DPRINT(fmt, ...) do { } while (0)
623#endif
624
625static int dts_version; /* = 0 */
626
627#define BEGIN_DEFAULT() if (dts_version == 0) { \
628 DPRINT("<INITIAL>\n"); \
629 BEGIN(INITIAL); \
630 } else { \
631 DPRINT("<V1>\n"); \
632 BEGIN(V1); \
633 }
634
635static void push_input_file(const char *filename);
636static int pop_input_file(void);
637#line 638 "dtc-lexer.lex.c"
638
639#define INITIAL 0
640#define INCLUDE 1
641#define BYTESTRING 2
642#define PROPNODENAME 3
643#define V1 4
644
645#ifndef YY_NO_UNISTD_H
646/* Special case for "unistd.h", since it is non-ANSI. We include it way
647 * down here because we want the user's section 1 to have been scanned first.
648 * The user has a chance to override it with an option.
649 */
650#include <unistd.h>
651#endif
652
653#ifndef YY_EXTRA_TYPE
654#define YY_EXTRA_TYPE void *
655#endif
656
657static int yy_init_globals (void );
658
659/* Macros after this point can all be overridden by user definitions in
660 * section 1.
661 */
662
663#ifndef YY_SKIP_YYWRAP
664#ifdef __cplusplus
665extern "C" int yywrap (void );
666#else
667extern int yywrap (void );
668#endif
669#endif
670
671#ifndef yytext_ptr
672static void yy_flex_strncpy (char *,yyconst char *,int );
673#endif
674
675#ifdef YY_NEED_STRLEN
676static int yy_flex_strlen (yyconst char * );
677#endif
678
679#ifndef YY_NO_INPUT
680
681#ifdef __cplusplus
682static int yyinput (void );
683#else
684static int input (void );
685#endif
686
687#endif
688
689/* Amount of stuff to slurp up with each read. */
690#ifndef YY_READ_BUF_SIZE
691#define YY_READ_BUF_SIZE 8192
692#endif
693
694/* Copy whatever the last rule matched to the standard output. */
695#ifndef ECHO
696/* This used to be an fputs(), but since the string might contain NUL's,
697 * we now use fwrite().
698 */
699#define ECHO fwrite( yytext, yyleng, 1, yyout )
700#endif
701
702/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
703 * is returned in "result".
704 */
705#ifndef YY_INPUT
706#define YY_INPUT(buf,result,max_size) \
707 if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
708 { \
709 int c = '*'; \
710 int n; \
711 for ( n = 0; n < max_size && \
712 (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
713 buf[n] = (char) c; \
714 if ( c == '\n' ) \
715 buf[n++] = (char) c; \
716 if ( c == EOF && ferror( yyin ) ) \
717 YY_FATAL_ERROR( "input in flex scanner failed" ); \
718 result = n; \
719 } \
720 else \
721 { \
722 errno=0; \
723 while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
724 { \
725 if( errno != EINTR) \
726 { \
727 YY_FATAL_ERROR( "input in flex scanner failed" ); \
728 break; \
729 } \
730 errno=0; \
731 clearerr(yyin); \
732 } \
733 }\
734\
735
736#endif
737
738/* No semi-colon after return; correct usage is to write "yyterminate();" -
739 * we don't want an extra ';' after the "return" because that will cause
740 * some compilers to complain about unreachable statements.
741 */
742#ifndef yyterminate
743#define yyterminate() return YY_NULL
744#endif
745
746/* Number of entries by which start-condition stack grows. */
747#ifndef YY_START_STACK_INCR
748#define YY_START_STACK_INCR 25
749#endif
750
751/* Report a fatal error. */
752#ifndef YY_FATAL_ERROR
753#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
754#endif
755
756/* end tables serialization structures and prototypes */
757
758/* Default declaration of generated scanner - a define so the user can
759 * easily add parameters.
760 */
761#ifndef YY_DECL
762#define YY_DECL_IS_OURS 1
763
764extern int yylex (void);
765
766#define YY_DECL int yylex (void)
767#endif /* !YY_DECL */
768
769/* Code executed at the beginning of each rule, after yytext and yyleng
770 * have been set up.
771 */
772#ifndef YY_USER_ACTION
773#define YY_USER_ACTION
774#endif
775
776/* Code executed at the end of each rule. */
777#ifndef YY_BREAK
778#define YY_BREAK break;
779#endif
780
781#define YY_RULE_SETUP \
782 YY_USER_ACTION
783
784/** The main scanner function which does all the work.
785 */
786YY_DECL
787{
788 register yy_state_type yy_current_state;
789 register char *yy_cp, *yy_bp;
790 register int yy_act;
791
792#line 64 "dtc-lexer.l"
793
794#line 795 "dtc-lexer.lex.c"
795
796 if ( !(yy_init) )
797 {
798 (yy_init) = 1;
799
800#ifdef YY_USER_INIT
801 YY_USER_INIT;
802#endif
803
804 if ( ! (yy_start) )
805 (yy_start) = 1; /* first start state */
806
807 if ( ! yyin )
808 yyin = stdin;
809
810 if ( ! yyout )
811 yyout = stdout;
812
813 if ( ! YY_CURRENT_BUFFER ) {
814 yyensure_buffer_stack ();
815 YY_CURRENT_BUFFER_LVALUE =
816 yy_create_buffer(yyin,YY_BUF_SIZE );
817 }
818
819 yy_load_buffer_state( );
820 }
821
822 while ( 1 ) /* loops until end-of-file is reached */
823 {
824 yy_cp = (yy_c_buf_p);
825
826 /* Support of yytext. */
827 *yy_cp = (yy_hold_char);
828
829 /* yy_bp points to the position in yy_ch_buf of the start of
830 * the current run.
831 */
832 yy_bp = yy_cp;
833
834 yy_current_state = (yy_start);
835yy_match:
836 do
837 {
838 register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
839 if ( yy_accept[yy_current_state] )
840 {
841 (yy_last_accepting_state) = yy_current_state;
842 (yy_last_accepting_cpos) = yy_cp;
843 }
844 while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
845 {
846 yy_current_state = (int) yy_def[yy_current_state];
847 if ( yy_current_state >= 104 )
848 yy_c = yy_meta[(unsigned int) yy_c];
849 }
850 yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
851 ++yy_cp;
852 }
853 while ( yy_base[yy_current_state] != 303 );
854
855yy_find_action:
856 yy_act = yy_accept[yy_current_state];
857 if ( yy_act == 0 )
858 { /* have to back up */
859 yy_cp = (yy_last_accepting_cpos);
860 yy_current_state = (yy_last_accepting_state);
861 yy_act = yy_accept[yy_current_state];
862 }
863
864 YY_DO_BEFORE_ACTION;
865
866 if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
867 {
868 int yyl;
869 for ( yyl = 0; yyl < yyleng; ++yyl )
870 if ( yytext[yyl] == '\n' )
871
872 yylineno++;
873;
874 }
875
876do_action: /* This label is used only to access EOF actions. */
877
878 switch ( yy_act )
879 { /* beginning of action switch */
880 case 0: /* must back up */
881 /* undo the effects of YY_DO_BEFORE_ACTION */
882 *yy_cp = (yy_hold_char);
883 yy_cp = (yy_last_accepting_cpos);
884 yy_current_state = (yy_last_accepting_state);
885 goto yy_find_action;
886
887case 1:
888/* rule 1 can match eol */
889YY_RULE_SETUP
890#line 65 "dtc-lexer.l"
891{
892 char *name = strchr(yytext, '\"') + 1;
893 yytext[yyleng-1] = '\0';
894 push_input_file(name);
895 }
896 YY_BREAK
897case YY_STATE_EOF(INITIAL):
898case YY_STATE_EOF(INCLUDE):
899case YY_STATE_EOF(BYTESTRING):
900case YY_STATE_EOF(PROPNODENAME):
901case YY_STATE_EOF(V1):
902#line 71 "dtc-lexer.l"
903{
904 if (!pop_input_file()) {
905 yyterminate();
906 }
907 }
908 YY_BREAK
909case 2:
910/* rule 2 can match eol */
911YY_RULE_SETUP
912#line 77 "dtc-lexer.l"
913{
914 yylloc.file = srcpos_file;
915 yylloc.first_line = yylineno;
916 DPRINT("String: %s\n", yytext);
917 yylval.data = data_copy_escape_string(yytext+1,
918 yyleng-2);
919 yylloc.first_line = yylineno;
920 return DT_STRING;
921 }
922 YY_BREAK
923case 3:
924YY_RULE_SETUP
925#line 87 "dtc-lexer.l"
926{
927 yylloc.file = srcpos_file;
928 yylloc.first_line = yylineno;
929 DPRINT("Keyword: /dts-v1/\n");
930 dts_version = 1;
931 BEGIN_DEFAULT();
932 return DT_V1;
933 }
934 YY_BREAK
935case 4:
936YY_RULE_SETUP
937#line 96 "dtc-lexer.l"
938{
939 yylloc.file = srcpos_file;
940 yylloc.first_line = yylineno;
941 DPRINT("Keyword: /memreserve/\n");
942 BEGIN_DEFAULT();
943 return DT_MEMRESERVE;
944 }
945 YY_BREAK
946case 5:
947YY_RULE_SETUP
948#line 104 "dtc-lexer.l"
949{
950 yylloc.file = srcpos_file;
951 yylloc.first_line = yylineno;
952 DPRINT("Label: %s\n", yytext);
953 yylval.labelref = strdup(yytext);
954 yylval.labelref[yyleng-1] = '\0';
955 return DT_LABEL;
956 }
957 YY_BREAK
958case 6:
959YY_RULE_SETUP
960#line 113 "dtc-lexer.l"
961{
962 yylloc.file = srcpos_file;
963 yylloc.first_line = yylineno;
964 if (*yytext == 'b')
965 yylval.cbase = 2;
966 else if (*yytext == 'o')
967 yylval.cbase = 8;
968 else if (*yytext == 'd')
969 yylval.cbase = 10;
970 else
971 yylval.cbase = 16;
972 DPRINT("Base: %d\n", yylval.cbase);
973 return DT_BASE;
974 }
975 YY_BREAK
976case 7:
977YY_RULE_SETUP
978#line 128 "dtc-lexer.l"
979{
980 yylloc.file = srcpos_file;
981 yylloc.first_line = yylineno;
982 yylval.literal = strdup(yytext);
983 DPRINT("Literal: '%s'\n", yylval.literal);
984 return DT_LEGACYLITERAL;
985 }
986 YY_BREAK
987case 8:
988YY_RULE_SETUP
989#line 136 "dtc-lexer.l"
990{
991 yylloc.file = srcpos_file;
992 yylloc.first_line = yylineno;
993 yylval.literal = strdup(yytext);
994 DPRINT("Literal: '%s'\n", yylval.literal);
995 return DT_LITERAL;
996 }
997 YY_BREAK
998case 9:
999YY_RULE_SETUP
1000#line 144 "dtc-lexer.l"
1001{ /* label reference */
1002 yylloc.file = srcpos_file;
1003 yylloc.first_line = yylineno;
1004 DPRINT("Ref: %s\n", yytext+1);
1005 yylval.labelref = strdup(yytext+1);
1006 return DT_REF;
1007 }
1008 YY_BREAK
1009case 10:
1010YY_RULE_SETUP
1011#line 152 "dtc-lexer.l"
1012{ /* new-style path reference */
1013 yylloc.file = srcpos_file;
1014 yylloc.first_line = yylineno;
1015 yytext[yyleng-1] = '\0';
1016 DPRINT("Ref: %s\n", yytext+2);
1017 yylval.labelref = strdup(yytext+2);
1018 return DT_REF;
1019 }
1020 YY_BREAK
1021case 11:
1022YY_RULE_SETUP
1023#line 161 "dtc-lexer.l"
1024{ /* old-style path reference */
1025 yylloc.file = srcpos_file;
1026 yylloc.first_line = yylineno;
1027 DPRINT("Ref: %s\n", yytext+1);
1028 yylval.labelref = strdup(yytext+1);
1029 return DT_REF;
1030 }
1031 YY_BREAK
1032case 12:
1033YY_RULE_SETUP
1034#line 169 "dtc-lexer.l"
1035{
1036 yylloc.file = srcpos_file;
1037 yylloc.first_line = yylineno;
1038 yylval.byte = strtol(yytext, NULL, 16);
1039 DPRINT("Byte: %02x\n", (int)yylval.byte);
1040 return DT_BYTE;
1041 }
1042 YY_BREAK
1043case 13:
1044YY_RULE_SETUP
1045#line 177 "dtc-lexer.l"
1046{
1047 yylloc.file = srcpos_file;
1048 yylloc.first_line = yylineno;
1049 DPRINT("/BYTESTRING\n");
1050 BEGIN_DEFAULT();
1051 return ']';
1052 }
1053 YY_BREAK
1054case 14:
1055YY_RULE_SETUP
1056#line 185 "dtc-lexer.l"
1057{
1058 yylloc.file = srcpos_file;
1059 yylloc.first_line = yylineno;
1060 DPRINT("PropNodeName: %s\n", yytext);
1061 yylval.propnodename = strdup(yytext);
1062 BEGIN_DEFAULT();
1063 return DT_PROPNODENAME;
1064 }
1065 YY_BREAK
1066case 15:
1067YY_RULE_SETUP
1068#line 194 "dtc-lexer.l"
1069{
1070 yylloc.file = srcpos_file;
1071 yylloc.first_line = yylineno;
1072 DPRINT("Binary Include\n");
1073 return DT_INCBIN;
1074 }
1075 YY_BREAK
1076case 16:
1077/* rule 16 can match eol */
1078YY_RULE_SETUP
1079#line 201 "dtc-lexer.l"
1080/* eat whitespace */
1081 YY_BREAK
1082case 17:
1083/* rule 17 can match eol */
1084YY_RULE_SETUP
1085#line 202 "dtc-lexer.l"
1086/* eat C-style comments */
1087 YY_BREAK
1088case 18:
1089/* rule 18 can match eol */
1090YY_RULE_SETUP
1091#line 203 "dtc-lexer.l"
1092/* eat C++-style comments */
1093 YY_BREAK
1094case 19:
1095YY_RULE_SETUP
1096#line 205 "dtc-lexer.l"
1097{
1098 yylloc.file = srcpos_file;
1099 yylloc.first_line = yylineno;
1100 DPRINT("Char: %c (\\x%02x)\n", yytext[0],
1101 (unsigned)yytext[0]);
1102 if (yytext[0] == '[') {
1103 DPRINT("<BYTESTRING>\n");
1104 BEGIN(BYTESTRING);
1105 }
1106 if ((yytext[0] == '{')
1107 || (yytext[0] == ';')) {
1108 DPRINT("<PROPNODENAME>\n");
1109 BEGIN(PROPNODENAME);
1110 }
1111 return yytext[0];
1112 }
1113 YY_BREAK
1114case 20:
1115YY_RULE_SETUP
1116#line 222 "dtc-lexer.l"
1117ECHO;
1118 YY_BREAK
1119#line 1120 "dtc-lexer.lex.c"
1120
1121 case YY_END_OF_BUFFER:
1122 {
1123 /* Amount of text matched not including the EOB char. */
1124 int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
1125
1126 /* Undo the effects of YY_DO_BEFORE_ACTION. */
1127 *yy_cp = (yy_hold_char);
1128 YY_RESTORE_YY_MORE_OFFSET
1129
1130 if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
1131 {
1132 /* We're scanning a new file or input source. It's
1133 * possible that this happened because the user
1134 * just pointed yyin at a new source and called
1135 * yylex(). If so, then we have to assure
1136 * consistency between YY_CURRENT_BUFFER and our
1137 * globals. Here is the right place to do so, because
1138 * this is the first action (other than possibly a
1139 * back-up) that will match for the new input source.
1140 */
1141 (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
1142 YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
1143 YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
1144 }
1145
1146 /* Note that here we test for yy_c_buf_p "<=" to the position
1147 * of the first EOB in the buffer, since yy_c_buf_p will
1148 * already have been incremented past the NUL character
1149 * (since all states make transitions on EOB to the
1150 * end-of-buffer state). Contrast this with the test
1151 * in input().
1152 */
1153 if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
1154 { /* This was really a NUL. */
1155 yy_state_type yy_next_state;
1156
1157 (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
1158
1159 yy_current_state = yy_get_previous_state( );
1160
1161 /* Okay, we're now positioned to make the NUL
1162 * transition. We couldn't have
1163 * yy_get_previous_state() go ahead and do it
1164 * for us because it doesn't know how to deal
1165 * with the possibility of jamming (and we don't
1166 * want to build jamming into it because then it
1167 * will run more slowly).
1168 */
1169
1170 yy_next_state = yy_try_NUL_trans( yy_current_state );
1171
1172 yy_bp = (yytext_ptr) + YY_MORE_ADJ;
1173
1174 if ( yy_next_state )
1175 {
1176 /* Consume the NUL. */
1177 yy_cp = ++(yy_c_buf_p);
1178 yy_current_state = yy_next_state;
1179 goto yy_match;
1180 }
1181
1182 else
1183 {
1184 yy_cp = (yy_c_buf_p);
1185 goto yy_find_action;
1186 }
1187 }
1188
1189 else switch ( yy_get_next_buffer( ) )
1190 {
1191 case EOB_ACT_END_OF_FILE:
1192 {
1193 (yy_did_buffer_switch_on_eof) = 0;
1194
1195 if ( yywrap( ) )
1196 {
1197 /* Note: because we've taken care in
1198 * yy_get_next_buffer() to have set up
1199 * yytext, we can now set up
1200 * yy_c_buf_p so that if some total
1201 * hoser (like flex itself) wants to
1202 * call the scanner after we return the
1203 * YY_NULL, it'll still work - another
1204 * YY_NULL will get returned.
1205 */
1206 (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
1207
1208 yy_act = YY_STATE_EOF(YY_START);
1209 goto do_action;
1210 }
1211
1212 else
1213 {
1214 if ( ! (yy_did_buffer_switch_on_eof) )
1215 YY_NEW_FILE;
1216 }
1217 break;
1218 }
1219
1220 case EOB_ACT_CONTINUE_SCAN:
1221 (yy_c_buf_p) =
1222 (yytext_ptr) + yy_amount_of_matched_text;
1223
1224 yy_current_state = yy_get_previous_state( );
1225
1226 yy_cp = (yy_c_buf_p);
1227 yy_bp = (yytext_ptr) + YY_MORE_ADJ;
1228 goto yy_match;
1229
1230 case EOB_ACT_LAST_MATCH:
1231 (yy_c_buf_p) =
1232 &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
1233
1234 yy_current_state = yy_get_previous_state( );
1235
1236 yy_cp = (yy_c_buf_p);
1237 yy_bp = (yytext_ptr) + YY_MORE_ADJ;
1238 goto yy_find_action;
1239 }
1240 break;
1241 }
1242
1243 default:
1244 YY_FATAL_ERROR(
1245 "fatal flex scanner internal error--no action found" );
1246 } /* end of action switch */
1247 } /* end of scanning one token */
1248} /* end of yylex */
1249
1250/* yy_get_next_buffer - try to read in a new buffer
1251 *
1252 * Returns a code representing an action:
1253 * EOB_ACT_LAST_MATCH -
1254 * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
1255 * EOB_ACT_END_OF_FILE - end of file
1256 */
1257static int yy_get_next_buffer (void)
1258{
1259 register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
1260 register char *source = (yytext_ptr);
1261 register int number_to_move, i;
1262 int ret_val;
1263
1264 if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
1265 YY_FATAL_ERROR(
1266 "fatal flex scanner internal error--end of buffer missed" );
1267
1268 if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
1269 { /* Don't try to fill the buffer, so this is an EOF. */
1270 if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
1271 {
1272 /* We matched a single character, the EOB, so
1273 * treat this as a final EOF.
1274 */
1275 return EOB_ACT_END_OF_FILE;
1276 }
1277
1278 else
1279 {
1280 /* We matched some text prior to the EOB, first
1281 * process it.
1282 */
1283 return EOB_ACT_LAST_MATCH;
1284 }
1285 }
1286
1287 /* Try to read more data. */
1288
1289 /* First move last chars to start of buffer. */
1290 number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
1291
1292 for ( i = 0; i < number_to_move; ++i )
1293 *(dest++) = *(source++);
1294
1295 if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
1296 /* don't do the read, it's not guaranteed to return an EOF,
1297 * just force an EOF
1298 */
1299 YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
1300
1301 else
1302 {
1303 int num_to_read =
1304 YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
1305
1306 while ( num_to_read <= 0 )
1307 { /* Not enough room in the buffer - grow it. */
1308
1309 /* just a shorter name for the current buffer */
1310 YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
1311
1312 int yy_c_buf_p_offset =
1313 (int) ((yy_c_buf_p) - b->yy_ch_buf);
1314
1315 if ( b->yy_is_our_buffer )
1316 {
1317 int new_size = b->yy_buf_size * 2;
1318
1319 if ( new_size <= 0 )
1320 b->yy_buf_size += b->yy_buf_size / 8;
1321 else
1322 b->yy_buf_size *= 2;
1323
1324 b->yy_ch_buf = (char *)
1325 /* Include room in for 2 EOB chars. */
1326 yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
1327 }
1328 else
1329 /* Can't grow it, we don't own it. */
1330 b->yy_ch_buf = 0;
1331
1332 if ( ! b->yy_ch_buf )
1333 YY_FATAL_ERROR(
1334 "fatal error - scanner input buffer overflow" );
1335
1336 (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
1337
1338 num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
1339 number_to_move - 1;
1340
1341 }
1342
1343 if ( num_to_read > YY_READ_BUF_SIZE )
1344 num_to_read = YY_READ_BUF_SIZE;
1345
1346 /* Read in more data. */
1347 YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
1348 (yy_n_chars), (size_t) num_to_read );
1349
1350 YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
1351 }
1352
1353 if ( (yy_n_chars) == 0 )
1354 {
1355 if ( number_to_move == YY_MORE_ADJ )
1356 {
1357 ret_val = EOB_ACT_END_OF_FILE;
1358 yyrestart(yyin );
1359 }
1360
1361 else
1362 {
1363 ret_val = EOB_ACT_LAST_MATCH;
1364 YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
1365 YY_BUFFER_EOF_PENDING;
1366 }
1367 }
1368
1369 else
1370 ret_val = EOB_ACT_CONTINUE_SCAN;
1371
1372 if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
1373 /* Extend the array by 50%, plus the number we really need. */
1374 yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
1375 YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
1376 if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
1377 YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
1378 }
1379
1380 (yy_n_chars) += number_to_move;
1381 YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
1382 YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
1383
1384 (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
1385
1386 return ret_val;
1387}
1388
1389/* yy_get_previous_state - get the state just before the EOB char was reached */
1390
1391 static yy_state_type yy_get_previous_state (void)
1392{
1393 register yy_state_type yy_current_state;
1394 register char *yy_cp;
1395
1396 yy_current_state = (yy_start);
1397
1398 for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
1399 {
1400 register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
1401 if ( yy_accept[yy_current_state] )
1402 {
1403 (yy_last_accepting_state) = yy_current_state;
1404 (yy_last_accepting_cpos) = yy_cp;
1405 }
1406 while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
1407 {
1408 yy_current_state = (int) yy_def[yy_current_state];
1409 if ( yy_current_state >= 104 )
1410 yy_c = yy_meta[(unsigned int) yy_c];
1411 }
1412 yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
1413 }
1414
1415 return yy_current_state;
1416}
1417
1418/* yy_try_NUL_trans - try to make a transition on the NUL character
1419 *
1420 * synopsis
1421 * next_state = yy_try_NUL_trans( current_state );
1422 */
1423 static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
1424{
1425 register int yy_is_jam;
1426 register char *yy_cp = (yy_c_buf_p);
1427
1428 register YY_CHAR yy_c = 1;
1429 if ( yy_accept[yy_current_state] )
1430 {
1431 (yy_last_accepting_state) = yy_current_state;
1432 (yy_last_accepting_cpos) = yy_cp;
1433 }
1434 while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
1435 {
1436 yy_current_state = (int) yy_def[yy_current_state];
1437 if ( yy_current_state >= 104 )
1438 yy_c = yy_meta[(unsigned int) yy_c];
1439 }
1440 yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
1441 yy_is_jam = (yy_current_state == 103);
1442
1443 return yy_is_jam ? 0 : yy_current_state;
1444}
1445
1446#ifndef YY_NO_INPUT
1447#ifdef __cplusplus
1448 static int yyinput (void)
1449#else
1450 static int input (void)
1451#endif
1452
1453{
1454 int c;
1455
1456 *(yy_c_buf_p) = (yy_hold_char);
1457
1458 if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
1459 {
1460 /* yy_c_buf_p now points to the character we want to return.
1461 * If this occurs *before* the EOB characters, then it's a
1462 * valid NUL; if not, then we've hit the end of the buffer.
1463 */
1464 if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
1465 /* This was really a NUL. */
1466 *(yy_c_buf_p) = '\0';
1467
1468 else
1469 { /* need more input */
1470 int offset = (yy_c_buf_p) - (yytext_ptr);
1471 ++(yy_c_buf_p);
1472
1473 switch ( yy_get_next_buffer( ) )
1474 {
1475 case EOB_ACT_LAST_MATCH:
1476 /* This happens because yy_g_n_b()
1477 * sees that we've accumulated a
1478 * token and flags that we need to
1479 * try matching the token before
1480 * proceeding. But for input(),
1481 * there's no matching to consider.
1482 * So convert the EOB_ACT_LAST_MATCH
1483 * to EOB_ACT_END_OF_FILE.
1484 */
1485
1486 /* Reset buffer status. */
1487 yyrestart(yyin );
1488
1489 /*FALLTHROUGH*/
1490
1491 case EOB_ACT_END_OF_FILE:
1492 {
1493 if ( yywrap( ) )
1494 return EOF;
1495
1496 if ( ! (yy_did_buffer_switch_on_eof) )
1497 YY_NEW_FILE;
1498#ifdef __cplusplus
1499 return yyinput();
1500#else
1501 return input();
1502#endif
1503 }
1504
1505 case EOB_ACT_CONTINUE_SCAN:
1506 (yy_c_buf_p) = (yytext_ptr) + offset;
1507 break;
1508 }
1509 }
1510 }
1511
1512 c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
1513 *(yy_c_buf_p) = '\0'; /* preserve yytext */
1514 (yy_hold_char) = *++(yy_c_buf_p);
1515
1516 if ( c == '\n' )
1517
1518 yylineno++;
1519;
1520
1521 return c;
1522}
1523#endif /* ifndef YY_NO_INPUT */
1524
1525/** Immediately switch to a different input stream.
1526 * @param input_file A readable stream.
1527 *
1528 * @note This function does not reset the start condition to @c INITIAL .
1529 */
1530 void yyrestart (FILE * input_file )
1531{
1532
1533 if ( ! YY_CURRENT_BUFFER ){
1534 yyensure_buffer_stack ();
1535 YY_CURRENT_BUFFER_LVALUE =
1536 yy_create_buffer(yyin,YY_BUF_SIZE );
1537 }
1538
1539 yy_init_buffer(YY_CURRENT_BUFFER,input_file );
1540 yy_load_buffer_state( );
1541}
1542
1543/** Switch to a different input buffer.
1544 * @param new_buffer The new input buffer.
1545 *
1546 */
1547 void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
1548{
1549
1550 /* TODO. We should be able to replace this entire function body
1551 * with
1552 * yypop_buffer_state();
1553 * yypush_buffer_state(new_buffer);
1554 */
1555 yyensure_buffer_stack ();
1556 if ( YY_CURRENT_BUFFER == new_buffer )
1557 return;
1558
1559 if ( YY_CURRENT_BUFFER )
1560 {
1561 /* Flush out information for old buffer. */
1562 *(yy_c_buf_p) = (yy_hold_char);
1563 YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
1564 YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
1565 }
1566
1567 YY_CURRENT_BUFFER_LVALUE = new_buffer;
1568 yy_load_buffer_state( );
1569
1570 /* We don't actually know whether we did this switch during
1571 * EOF (yywrap()) processing, but the only time this flag
1572 * is looked at is after yywrap() is called, so it's safe
1573 * to go ahead and always set it.
1574 */
1575 (yy_did_buffer_switch_on_eof) = 1;
1576}
1577
1578static void yy_load_buffer_state (void)
1579{
1580 (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
1581 (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
1582 yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
1583 (yy_hold_char) = *(yy_c_buf_p);
1584}
1585
1586/** Allocate and initialize an input buffer state.
1587 * @param file A readable stream.
1588 * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
1589 *
1590 * @return the allocated buffer state.
1591 */
1592 YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
1593{
1594 YY_BUFFER_STATE b;
1595
1596 b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
1597 if ( ! b )
1598 YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
1599
1600 b->yy_buf_size = size;
1601
1602 /* yy_ch_buf has to be 2 characters longer than the size given because
1603 * we need to put in 2 end-of-buffer characters.
1604 */
1605 b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
1606 if ( ! b->yy_ch_buf )
1607 YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
1608
1609 b->yy_is_our_buffer = 1;
1610
1611 yy_init_buffer(b,file );
1612
1613 return b;
1614}
1615
1616/** Destroy the buffer.
1617 * @param b a buffer created with yy_create_buffer()
1618 *
1619 */
1620 void yy_delete_buffer (YY_BUFFER_STATE b )
1621{
1622
1623 if ( ! b )
1624 return;
1625
1626 if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
1627 YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
1628
1629 if ( b->yy_is_our_buffer )
1630 yyfree((void *) b->yy_ch_buf );
1631
1632 yyfree((void *) b );
1633}
1634
1635#ifndef __cplusplus
1636extern int isatty (int );
1637#endif /* __cplusplus */
1638
1639/* Initializes or reinitializes a buffer.
1640 * This function is sometimes called more than once on the same buffer,
1641 * such as during a yyrestart() or at EOF.
1642 */
1643 static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
1644
1645{
1646 int oerrno = errno;
1647
1648 yy_flush_buffer(b );
1649
1650 b->yy_input_file = file;
1651 b->yy_fill_buffer = 1;
1652
1653 /* If b is the current buffer, then yy_init_buffer was _probably_
1654 * called from yyrestart() or through yy_get_next_buffer.
1655 * In that case, we don't want to reset the lineno or column.
1656 */
1657 if (b != YY_CURRENT_BUFFER){
1658 b->yy_bs_lineno = 1;
1659 b->yy_bs_column = 0;
1660 }
1661
1662 b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
1663
1664 errno = oerrno;
1665}
1666
1667/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
1668 * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
1669 *
1670 */
1671 void yy_flush_buffer (YY_BUFFER_STATE b )
1672{
1673 if ( ! b )
1674 return;
1675
1676 b->yy_n_chars = 0;
1677
1678 /* We always need two end-of-buffer characters. The first causes
1679 * a transition to the end-of-buffer state. The second causes
1680 * a jam in that state.
1681 */
1682 b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
1683 b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
1684
1685 b->yy_buf_pos = &b->yy_ch_buf[0];
1686
1687 b->yy_at_bol = 1;
1688 b->yy_buffer_status = YY_BUFFER_NEW;
1689
1690 if ( b == YY_CURRENT_BUFFER )
1691 yy_load_buffer_state( );
1692}
1693
1694/** Pushes the new state onto the stack. The new state becomes
1695 * the current state. This function will allocate the stack
1696 * if necessary.
1697 * @param new_buffer The new state.
1698 *
1699 */
1700void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
1701{
1702 if (new_buffer == NULL)
1703 return;
1704
1705 yyensure_buffer_stack();
1706
1707 /* This block is copied from yy_switch_to_buffer. */
1708 if ( YY_CURRENT_BUFFER )
1709 {
1710 /* Flush out information for old buffer. */
1711 *(yy_c_buf_p) = (yy_hold_char);
1712 YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
1713 YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
1714 }
1715
1716 /* Only push if top exists. Otherwise, replace top. */
1717 if (YY_CURRENT_BUFFER)
1718 (yy_buffer_stack_top)++;
1719 YY_CURRENT_BUFFER_LVALUE = new_buffer;
1720
1721 /* copied from yy_switch_to_buffer. */
1722 yy_load_buffer_state( );
1723 (yy_did_buffer_switch_on_eof) = 1;
1724}
1725
1726/** Removes and deletes the top of the stack, if present.
1727 * The next element becomes the new top.
1728 *
1729 */
1730void yypop_buffer_state (void)
1731{
1732 if (!YY_CURRENT_BUFFER)
1733 return;
1734
1735 yy_delete_buffer(YY_CURRENT_BUFFER );
1736 YY_CURRENT_BUFFER_LVALUE = NULL;
1737 if ((yy_buffer_stack_top) > 0)
1738 --(yy_buffer_stack_top);
1739
1740 if (YY_CURRENT_BUFFER) {
1741 yy_load_buffer_state( );
1742 (yy_did_buffer_switch_on_eof) = 1;
1743 }
1744}
1745
1746/* Allocates the stack if it does not exist.
1747 * Guarantees space for at least one push.
1748 */
1749static void yyensure_buffer_stack (void)
1750{
1751 int num_to_alloc;
1752
1753 if (!(yy_buffer_stack)) {
1754
1755 /* First allocation is just for 2 elements, since we don't know if this
1756 * scanner will even need a stack. We use 2 instead of 1 to avoid an
1757 * immediate realloc on the next call.
1758 */
1759 num_to_alloc = 1;
1760 (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
1761 (num_to_alloc * sizeof(struct yy_buffer_state*)
1762 );
1763 if ( ! (yy_buffer_stack) )
1764 YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
1765
1766 memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
1767
1768 (yy_buffer_stack_max) = num_to_alloc;
1769 (yy_buffer_stack_top) = 0;
1770 return;
1771 }
1772
1773 if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
1774
1775 /* Increase the buffer to prepare for a possible push. */
1776 int grow_size = 8 /* arbitrary grow size */;
1777
1778 num_to_alloc = (yy_buffer_stack_max) + grow_size;
1779 (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
1780 ((yy_buffer_stack),
1781 num_to_alloc * sizeof(struct yy_buffer_state*)
1782 );
1783 if ( ! (yy_buffer_stack) )
1784 YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
1785
1786 /* zero only the new slots.*/
1787 memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
1788 (yy_buffer_stack_max) = num_to_alloc;
1789 }
1790}
1791
1792/** Setup the input buffer state to scan directly from a user-specified character buffer.
1793 * @param base the character buffer
1794 * @param size the size in bytes of the character buffer
1795 *
1796 * @return the newly allocated buffer state object.
1797 */
1798YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
1799{
1800 YY_BUFFER_STATE b;
1801
1802 if ( size < 2 ||
1803 base[size-2] != YY_END_OF_BUFFER_CHAR ||
1804 base[size-1] != YY_END_OF_BUFFER_CHAR )
1805 /* They forgot to leave room for the EOB's. */
1806 return 0;
1807
1808 b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
1809 if ( ! b )
1810 YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
1811
1812 b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
1813 b->yy_buf_pos = b->yy_ch_buf = base;
1814 b->yy_is_our_buffer = 0;
1815 b->yy_input_file = 0;
1816 b->yy_n_chars = b->yy_buf_size;
1817 b->yy_is_interactive = 0;
1818 b->yy_at_bol = 1;
1819 b->yy_fill_buffer = 0;
1820 b->yy_buffer_status = YY_BUFFER_NEW;
1821
1822 yy_switch_to_buffer(b );
1823
1824 return b;
1825}
1826
1827/** Setup the input buffer state to scan a string. The next call to yylex() will
1828 * scan from a @e copy of @a str.
1829 * @param yystr a NUL-terminated string to scan
1830 *
1831 * @return the newly allocated buffer state object.
1832 * @note If you want to scan bytes that may contain NUL values, then use
1833 * yy_scan_bytes() instead.
1834 */
1835YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
1836{
1837
1838 return yy_scan_bytes(yystr,strlen(yystr) );
1839}
1840
1841/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
1842 * scan from a @e copy of @a bytes.
1843 * @param bytes the byte buffer to scan
1844 * @param len the number of bytes in the buffer pointed to by @a bytes.
1845 *
1846 * @return the newly allocated buffer state object.
1847 */
1848YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
1849{
1850 YY_BUFFER_STATE b;
1851 char *buf;
1852 yy_size_t n;
1853 int i;
1854
1855 /* Get memory for full buffer, including space for trailing EOB's. */
1856 n = _yybytes_len + 2;
1857 buf = (char *) yyalloc(n );
1858 if ( ! buf )
1859 YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
1860
1861 for ( i = 0; i < _yybytes_len; ++i )
1862 buf[i] = yybytes[i];
1863
1864 buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
1865
1866 b = yy_scan_buffer(buf,n );
1867 if ( ! b )
1868 YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
1869
1870 /* It's okay to grow etc. this buffer, and we should throw it
1871 * away when we're done.
1872 */
1873 b->yy_is_our_buffer = 1;
1874
1875 return b;
1876}
1877
1878#ifndef YY_EXIT_FAILURE
1879#define YY_EXIT_FAILURE 2
1880#endif
1881
1882static void yy_fatal_error (yyconst char* msg )
1883{
1884 (void) fprintf( stderr, "%s\n", msg );
1885 exit( YY_EXIT_FAILURE );
1886}
1887
1888/* Redefine yyless() so it works in section 3 code. */
1889
1890#undef yyless
1891#define yyless(n) \
1892 do \
1893 { \
1894 /* Undo effects of setting up yytext. */ \
1895 int yyless_macro_arg = (n); \
1896 YY_LESS_LINENO(yyless_macro_arg);\
1897 yytext[yyleng] = (yy_hold_char); \
1898 (yy_c_buf_p) = yytext + yyless_macro_arg; \
1899 (yy_hold_char) = *(yy_c_buf_p); \
1900 *(yy_c_buf_p) = '\0'; \
1901 yyleng = yyless_macro_arg; \
1902 } \
1903 while ( 0 )
1904
1905/* Accessor methods (get/set functions) to struct members. */
1906
1907/** Get the current line number.
1908 *
1909 */
1910int yyget_lineno (void)
1911{
1912
1913 return yylineno;
1914}
1915
1916/** Get the input stream.
1917 *
1918 */
1919FILE *yyget_in (void)
1920{
1921 return yyin;
1922}
1923
1924/** Get the output stream.
1925 *
1926 */
1927FILE *yyget_out (void)
1928{
1929 return yyout;
1930}
1931
1932/** Get the length of the current token.
1933 *
1934 */
1935int yyget_leng (void)
1936{
1937 return yyleng;
1938}
1939
1940/** Get the current token.
1941 *
1942 */
1943
1944char *yyget_text (void)
1945{
1946 return yytext;
1947}
1948
1949/** Set the current line number.
1950 * @param line_number
1951 *
1952 */
1953void yyset_lineno (int line_number )
1954{
1955
1956 yylineno = line_number;
1957}
1958
1959/** Set the input stream. This does not discard the current
1960 * input buffer.
1961 * @param in_str A readable stream.
1962 *
1963 * @see yy_switch_to_buffer
1964 */
1965void yyset_in (FILE * in_str )
1966{
1967 yyin = in_str ;
1968}
1969
1970void yyset_out (FILE * out_str )
1971{
1972 yyout = out_str ;
1973}
1974
1975int yyget_debug (void)
1976{
1977 return yy_flex_debug;
1978}
1979
1980void yyset_debug (int bdebug )
1981{
1982 yy_flex_debug = bdebug ;
1983}
1984
1985static int yy_init_globals (void)
1986{
1987 /* Initialization is the same as for the non-reentrant scanner.
1988 * This function is called from yylex_destroy(), so don't allocate here.
1989 */
1990
1991 /* We do not touch yylineno unless the option is enabled. */
1992 yylineno = 1;
1993
1994 (yy_buffer_stack) = 0;
1995 (yy_buffer_stack_top) = 0;
1996 (yy_buffer_stack_max) = 0;
1997 (yy_c_buf_p) = (char *) 0;
1998 (yy_init) = 0;
1999 (yy_start) = 0;
2000
2001/* Defined in main.c */
2002#ifdef YY_STDINIT
2003 yyin = stdin;
2004 yyout = stdout;
2005#else
2006 yyin = (FILE *) 0;
2007 yyout = (FILE *) 0;
2008#endif
2009
2010 /* For future reference: Set errno on error, since we are called by
2011 * yylex_init()
2012 */
2013 return 0;
2014}
2015
2016/* yylex_destroy is for both reentrant and non-reentrant scanners. */
2017int yylex_destroy (void)
2018{
2019
2020 /* Pop the buffer stack, destroying each element. */
2021 while(YY_CURRENT_BUFFER){
2022 yy_delete_buffer(YY_CURRENT_BUFFER );
2023 YY_CURRENT_BUFFER_LVALUE = NULL;
2024 yypop_buffer_state();
2025 }
2026
2027 /* Destroy the stack itself. */
2028 yyfree((yy_buffer_stack) );
2029 (yy_buffer_stack) = NULL;
2030
2031 /* Reset the globals. This is important in a non-reentrant scanner so the next time
2032 * yylex() is called, initialization will occur. */
2033 yy_init_globals( );
2034
2035 return 0;
2036}
2037
2038/*
2039 * Internal utility routines.
2040 */
2041
2042#ifndef yytext_ptr
2043static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
2044{
2045 register int i;
2046 for ( i = 0; i < n; ++i )
2047 s1[i] = s2[i];
2048}
2049#endif
2050
2051#ifdef YY_NEED_STRLEN
2052static int yy_flex_strlen (yyconst char * s )
2053{
2054 register int n;
2055 for ( n = 0; s[n]; ++n )
2056 ;
2057
2058 return n;
2059}
2060#endif
2061
2062void *yyalloc (yy_size_t size )
2063{
2064 return (void *) malloc( size );
2065}
2066
2067void *yyrealloc (void * ptr, yy_size_t size )
2068{
2069 /* The cast to (char *) in the following accommodates both
2070 * implementations that use char* generic pointers, and those
2071 * that use void* generic pointers. It works with the latter
2072 * because both ANSI C and C++ allow castless assignment from
2073 * any pointer type to void*, and deal with argument conversions
2074 * as though doing an assignment.
2075 */
2076 return (void *) realloc( (char *) ptr, size );
2077}
2078
2079void yyfree (void * ptr )
2080{
2081 free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
2082}
2083
2084#define YYTABLES_NAME "yytables"
2085
2086#line 222 "dtc-lexer.l"
2087
2088
2089
2090
2091/*
2092 * Stack of nested include file contexts.
2093 */
2094
2095struct incl_file {
2096 struct dtc_file *file;
2097 YY_BUFFER_STATE yy_prev_buf;
2098 int yy_prev_lineno;
2099 struct incl_file *prev;
2100};
2101
2102static struct incl_file *incl_file_stack;
2103
2104
2105/*
2106 * Detect infinite include recursion.
2107 */
2108#define MAX_INCLUDE_DEPTH (100)
2109
2110static int incl_depth = 0;
2111
2112
2113static void push_input_file(const char *filename)
2114{
2115 struct incl_file *incl_file;
2116 struct dtc_file *newfile;
2117 struct search_path search, *searchptr = NULL;
2118
2119 assert(filename);
2120
2121 if (incl_depth++ >= MAX_INCLUDE_DEPTH)
2122 die("Includes nested too deeply");
2123
2124 if (srcpos_file) {
2125 search.dir = srcpos_file->dir;
2126 search.next = NULL;
2127 search.prev = NULL;
2128 searchptr = &search;
2129 }
2130
2131 newfile = dtc_open_file(filename, searchptr);
2132
2133 incl_file = xmalloc(sizeof(struct incl_file));
2134
2135 /*
2136 * Save current context.
2137 */
2138 incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
2139 incl_file->yy_prev_lineno = yylineno;
2140 incl_file->file = srcpos_file;
2141 incl_file->prev = incl_file_stack;
2142
2143 incl_file_stack = incl_file;
2144
2145 /*
2146 * Establish new context.
2147 */
2148 srcpos_file = newfile;
2149 yylineno = 1;
2150 yyin = newfile->file;
2151 yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE));
2152}
2153
2154
2155static int pop_input_file(void)
2156{
2157 struct incl_file *incl_file;
2158
2159 if (incl_file_stack == 0)
2160 return 0;
2161
2162 dtc_close_file(srcpos_file);
2163
2164 /*
2165 * Pop.
2166 */
2167 --incl_depth;
2168 incl_file = incl_file_stack;
2169 incl_file_stack = incl_file->prev;
2170
2171 /*
2172 * Recover old context.
2173 */
2174 yy_delete_buffer(YY_CURRENT_BUFFER);
2175 yy_switch_to_buffer(incl_file->yy_prev_buf);
2176 yylineno = incl_file->yy_prev_lineno;
2177 srcpos_file = incl_file->file;
2178 yyin = incl_file->file ? incl_file->file->file : NULL;
2179
2180 /*
2181 * Free old state.
2182 */
2183 free(incl_file);
2184
2185 return 1;
2186}
2187
diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
new file mode 100644
index 000000000000..27129377e5d2
--- /dev/null
+++ b/scripts/dtc/dtc-parser.tab.c_shipped
@@ -0,0 +1,2040 @@
1/* A Bison parser, made by GNU Bison 2.3. */
2
3/* Skeleton implementation for Bison's Yacc-like parsers in C
4
5 Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
6 Free Software Foundation, Inc.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
22
23/* As a special exception, you may create a larger work that contains
24 part or all of the Bison parser skeleton and distribute that work
25 under terms of your choice, so long as that work isn't itself a
26 parser generator using the skeleton or a modified version thereof
27 as a parser skeleton. Alternatively, if you modify or redistribute
28 the parser skeleton itself, you may (at your option) remove this
29 special exception, which will cause the skeleton and the resulting
30 Bison output files to be licensed under the GNU General Public
31 License without this special exception.
32
33 This special exception was added by the Free Software Foundation in
34 version 2.2 of Bison. */
35
36/* C LALR(1) parser skeleton written by Richard Stallman, by
37 simplifying the original so-called "semantic" parser. */
38
39/* All symbols defined below should begin with yy or YY, to avoid
40 infringing on user name space. This should be done even for local
41 variables, as they might otherwise be expanded by user macros.
42 There are some unavoidable exceptions within include files to
43 define necessary library symbols; they are noted "INFRINGES ON
44 USER NAME SPACE" below. */
45
46/* Identify Bison output. */
47#define YYBISON 1
48
49/* Bison version. */
50#define YYBISON_VERSION "2.3"
51
52/* Skeleton name. */
53#define YYSKELETON_NAME "yacc.c"
54
55/* Pure parsers. */
56#define YYPURE 0
57
58/* Using locations. */
59#define YYLSP_NEEDED 1
60
61
62
63/* Tokens. */
64#ifndef YYTOKENTYPE
65# define YYTOKENTYPE
66 /* Put the tokens into the symbol table, so that GDB and other debuggers
67 know about them. */
68 enum yytokentype {
69 DT_V1 = 258,
70 DT_MEMRESERVE = 259,
71 DT_PROPNODENAME = 260,
72 DT_LITERAL = 261,
73 DT_LEGACYLITERAL = 262,
74 DT_BASE = 263,
75 DT_BYTE = 264,
76 DT_STRING = 265,
77 DT_LABEL = 266,
78 DT_REF = 267,
79 DT_INCBIN = 268
80 };
81#endif
82/* Tokens. */
83#define DT_V1 258
84#define DT_MEMRESERVE 259
85#define DT_PROPNODENAME 260
86#define DT_LITERAL 261
87#define DT_LEGACYLITERAL 262
88#define DT_BASE 263
89#define DT_BYTE 264
90#define DT_STRING 265
91#define DT_LABEL 266
92#define DT_REF 267
93#define DT_INCBIN 268
94
95
96
97
98/* Copy the first part of user declarations. */
99#line 23 "dtc-parser.y"
100
101#include <stdio.h>
102
103#include "dtc.h"
104#include "srcpos.h"
105
106extern int yylex(void);
107
108extern struct boot_info *the_boot_info;
109extern int treesource_error;
110
111static unsigned long long eval_literal(const char *s, int base, int bits);
112
113
114/* Enabling traces. */
115#ifndef YYDEBUG
116# define YYDEBUG 0
117#endif
118
119/* Enabling verbose error messages. */
120#ifdef YYERROR_VERBOSE
121# undef YYERROR_VERBOSE
122# define YYERROR_VERBOSE 1
123#else
124# define YYERROR_VERBOSE 0
125#endif
126
127/* Enabling the token table. */
128#ifndef YYTOKEN_TABLE
129# define YYTOKEN_TABLE 0
130#endif
131
132#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
133typedef union YYSTYPE
134#line 37 "dtc-parser.y"
135{
136 char *propnodename;
137 char *literal;
138 char *labelref;
139 unsigned int cbase;
140 uint8_t byte;
141 struct data data;
142
143 uint64_t addr;
144 cell_t cell;
145 struct property *prop;
146 struct property *proplist;
147 struct node *node;
148 struct node *nodelist;
149 struct reserve_info *re;
150}
151/* Line 187 of yacc.c. */
152#line 153 "dtc-parser.tab.c"
153 YYSTYPE;
154# define yystype YYSTYPE /* obsolescent; will be withdrawn */
155# define YYSTYPE_IS_DECLARED 1
156# define YYSTYPE_IS_TRIVIAL 1
157#endif
158
159#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
160typedef struct YYLTYPE
161{
162 int first_line;
163 int first_column;
164 int last_line;
165 int last_column;
166} YYLTYPE;
167# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
168# define YYLTYPE_IS_DECLARED 1
169# define YYLTYPE_IS_TRIVIAL 1
170#endif
171
172
173/* Copy the second part of user declarations. */
174
175
176/* Line 216 of yacc.c. */
177#line 178 "dtc-parser.tab.c"
178
179#ifdef short
180# undef short
181#endif
182
183#ifdef YYTYPE_UINT8
184typedef YYTYPE_UINT8 yytype_uint8;
185#else
186typedef unsigned char yytype_uint8;
187#endif
188
189#ifdef YYTYPE_INT8
190typedef YYTYPE_INT8 yytype_int8;
191#elif (defined __STDC__ || defined __C99__FUNC__ \
192 || defined __cplusplus || defined _MSC_VER)
193typedef signed char yytype_int8;
194#else
195typedef short int yytype_int8;
196#endif
197
198#ifdef YYTYPE_UINT16
199typedef YYTYPE_UINT16 yytype_uint16;
200#else
201typedef unsigned short int yytype_uint16;
202#endif
203
204#ifdef YYTYPE_INT16
205typedef YYTYPE_INT16 yytype_int16;
206#else
207typedef short int yytype_int16;
208#endif
209
210#ifndef YYSIZE_T
211# ifdef __SIZE_TYPE__
212# define YYSIZE_T __SIZE_TYPE__
213# elif defined size_t
214# define YYSIZE_T size_t
215# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
216 || defined __cplusplus || defined _MSC_VER)
217# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
218# define YYSIZE_T size_t
219# else
220# define YYSIZE_T unsigned int
221# endif
222#endif
223
224#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
225
226#ifndef YY_
227# if YYENABLE_NLS
228# if ENABLE_NLS
229# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
230# define YY_(msgid) dgettext ("bison-runtime", msgid)
231# endif
232# endif
233# ifndef YY_
234# define YY_(msgid) msgid
235# endif
236#endif
237
238/* Suppress unused-variable warnings by "using" E. */
239#if ! defined lint || defined __GNUC__
240# define YYUSE(e) ((void) (e))
241#else
242# define YYUSE(e) /* empty */
243#endif
244
245/* Identity function, used to suppress warnings about constant conditions. */
246#ifndef lint
247# define YYID(n) (n)
248#else
249#if (defined __STDC__ || defined __C99__FUNC__ \
250 || defined __cplusplus || defined _MSC_VER)
251static int
252YYID (int i)
253#else
254static int
255YYID (i)
256 int i;
257#endif
258{
259 return i;
260}
261#endif
262
263#if ! defined yyoverflow || YYERROR_VERBOSE
264
265/* The parser invokes alloca or malloc; define the necessary symbols. */
266
267# ifdef YYSTACK_USE_ALLOCA
268# if YYSTACK_USE_ALLOCA
269# ifdef __GNUC__
270# define YYSTACK_ALLOC __builtin_alloca
271# elif defined __BUILTIN_VA_ARG_INCR
272# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
273# elif defined _AIX
274# define YYSTACK_ALLOC __alloca
275# elif defined _MSC_VER
276# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
277# define alloca _alloca
278# else
279# define YYSTACK_ALLOC alloca
280# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
281 || defined __cplusplus || defined _MSC_VER)
282# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
283# ifndef _STDLIB_H
284# define _STDLIB_H 1
285# endif
286# endif
287# endif
288# endif
289# endif
290
291# ifdef YYSTACK_ALLOC
292 /* Pacify GCC's `empty if-body' warning. */
293# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
294# ifndef YYSTACK_ALLOC_MAXIMUM
295 /* The OS might guarantee only one guard page at the bottom of the stack,
296 and a page size can be as small as 4096 bytes. So we cannot safely
297 invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
298 to allow for a few compiler-allocated temporary stack slots. */
299# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
300# endif
301# else
302# define YYSTACK_ALLOC YYMALLOC
303# define YYSTACK_FREE YYFREE
304# ifndef YYSTACK_ALLOC_MAXIMUM
305# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
306# endif
307# if (defined __cplusplus && ! defined _STDLIB_H \
308 && ! ((defined YYMALLOC || defined malloc) \
309 && (defined YYFREE || defined free)))
310# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
311# ifndef _STDLIB_H
312# define _STDLIB_H 1
313# endif
314# endif
315# ifndef YYMALLOC
316# define YYMALLOC malloc
317# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
318 || defined __cplusplus || defined _MSC_VER)
319void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
320# endif
321# endif
322# ifndef YYFREE
323# define YYFREE free
324# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
325 || defined __cplusplus || defined _MSC_VER)
326void free (void *); /* INFRINGES ON USER NAME SPACE */
327# endif
328# endif
329# endif
330#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
331
332
333#if (! defined yyoverflow \
334 && (! defined __cplusplus \
335 || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
336 && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
337
338/* A type that is properly aligned for any stack member. */
339union yyalloc
340{
341 yytype_int16 yyss;
342 YYSTYPE yyvs;
343 YYLTYPE yyls;
344};
345
346/* The size of the maximum gap between one aligned stack and the next. */
347# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
348
349/* The size of an array large to enough to hold all stacks, each with
350 N elements. */
351# define YYSTACK_BYTES(N) \
352 ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
353 + 2 * YYSTACK_GAP_MAXIMUM)
354
355/* Copy COUNT objects from FROM to TO. The source and destination do
356 not overlap. */
357# ifndef YYCOPY
358# if defined __GNUC__ && 1 < __GNUC__
359# define YYCOPY(To, From, Count) \
360 __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
361# else
362# define YYCOPY(To, From, Count) \
363 do \
364 { \
365 YYSIZE_T yyi; \
366 for (yyi = 0; yyi < (Count); yyi++) \
367 (To)[yyi] = (From)[yyi]; \
368 } \
369 while (YYID (0))
370# endif
371# endif
372
373/* Relocate STACK from its old location to the new one. The
374 local variables YYSIZE and YYSTACKSIZE give the old and new number of
375 elements in the stack, and YYPTR gives the new location of the
376 stack. Advance YYPTR to a properly aligned location for the next
377 stack. */
378# define YYSTACK_RELOCATE(Stack) \
379 do \
380 { \
381 YYSIZE_T yynewbytes; \
382 YYCOPY (&yyptr->Stack, Stack, yysize); \
383 Stack = &yyptr->Stack; \
384 yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
385 yyptr += yynewbytes / sizeof (*yyptr); \
386 } \
387 while (YYID (0))
388
389#endif
390
391/* YYFINAL -- State number of the termination state. */
392#define YYFINAL 9
393/* YYLAST -- Last index in YYTABLE. */
394#define YYLAST 73
395
396/* YYNTOKENS -- Number of terminals. */
397#define YYNTOKENS 27
398/* YYNNTS -- Number of nonterminals. */
399#define YYNNTS 20
400/* YYNRULES -- Number of rules. */
401#define YYNRULES 45
402/* YYNRULES -- Number of states. */
403#define YYNSTATES 76
404
405/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
406#define YYUNDEFTOK 2
407#define YYMAXUTOK 268
408
409#define YYTRANSLATE(YYX) \
410 ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
411
412/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
413static const yytype_uint8 yytranslate[] =
414{
415 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
416 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
417 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
418 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
419 24, 26, 2, 2, 25, 15, 2, 16, 2, 2,
420 2, 2, 2, 2, 2, 2, 2, 2, 2, 14,
421 20, 19, 21, 2, 2, 2, 2, 2, 2, 2,
422 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
423 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
424 2, 22, 2, 23, 2, 2, 2, 2, 2, 2,
425 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
426 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
427 2, 2, 2, 17, 2, 18, 2, 2, 2, 2,
428 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
429 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
430 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
431 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
432 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
433 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
434 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
435 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
436 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
437 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
438 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
439 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
440 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
441 5, 6, 7, 8, 9, 10, 11, 12, 13
442};
443
444#if YYDEBUG
445/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
446 YYRHS. */
447static const yytype_uint8 yyprhs[] =
448{
449 0, 0, 3, 8, 11, 12, 15, 21, 22, 25,
450 27, 34, 36, 38, 41, 47, 48, 51, 57, 61,
451 64, 69, 74, 77, 87, 93, 96, 97, 100, 103,
452 104, 107, 110, 113, 114, 116, 118, 121, 122, 125,
453 128, 129, 132, 135, 139, 140
454};
455
456/* YYRHS -- A `-1'-separated list of the rules' RHS. */
457static const yytype_int8 yyrhs[] =
458{
459 28, 0, -1, 3, 14, 29, 34, -1, 31, 34,
460 -1, -1, 30, 29, -1, 46, 4, 33, 33, 14,
461 -1, -1, 32, 31, -1, 30, -1, 46, 4, 33,
462 15, 33, 14, -1, 6, -1, 7, -1, 16, 35,
463 -1, 17, 36, 44, 18, 14, -1, -1, 36, 37,
464 -1, 46, 5, 19, 38, 14, -1, 46, 5, 14,
465 -1, 39, 10, -1, 39, 20, 40, 21, -1, 39,
466 22, 43, 23, -1, 39, 12, -1, 39, 13, 24,
467 10, 25, 33, 25, 33, 26, -1, 39, 13, 24,
468 10, 26, -1, 38, 11, -1, -1, 38, 25, -1,
469 39, 11, -1, -1, 40, 42, -1, 40, 12, -1,
470 40, 11, -1, -1, 8, -1, 6, -1, 41, 7,
471 -1, -1, 43, 9, -1, 43, 11, -1, -1, 45,
472 44, -1, 45, 37, -1, 46, 5, 35, -1, -1,
473 11, -1
474};
475
476/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
477static const yytype_uint16 yyrline[] =
478{
479 0, 89, 89, 93, 101, 104, 111, 119, 122, 129,
480 133, 140, 144, 151, 158, 166, 169, 176, 180, 187,
481 191, 195, 199, 203, 220, 231, 239, 242, 246, 254,
482 257, 261, 266, 274, 277, 281, 285, 293, 296, 300,
483 308, 311, 315, 323, 331, 334
484};
485#endif
486
487#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
488/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
489 First, the terminals, then, starting at YYNTOKENS, nonterminals. */
490static const char *const yytname[] =
491{
492 "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE",
493 "DT_PROPNODENAME", "DT_LITERAL", "DT_LEGACYLITERAL", "DT_BASE",
494 "DT_BYTE", "DT_STRING", "DT_LABEL", "DT_REF", "DT_INCBIN", "';'", "'-'",
495 "'/'", "'{'", "'}'", "'='", "'<'", "'>'", "'['", "']'", "'('", "','",
496 "')'", "$accept", "sourcefile", "memreserves", "memreserve",
497 "v0_memreserves", "v0_memreserve", "addr", "devicetree", "nodedef",
498 "proplist", "propdef", "propdata", "propdataprefix", "celllist",
499 "cellbase", "cellval", "bytestring", "subnodes", "subnode", "label", 0
500};
501#endif
502
503# ifdef YYPRINT
504/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
505 token YYLEX-NUM. */
506static const yytype_uint16 yytoknum[] =
507{
508 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
509 265, 266, 267, 268, 59, 45, 47, 123, 125, 61,
510 60, 62, 91, 93, 40, 44, 41
511};
512# endif
513
514/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
515static const yytype_uint8 yyr1[] =
516{
517 0, 27, 28, 28, 29, 29, 30, 31, 31, 32,
518 32, 33, 33, 34, 35, 36, 36, 37, 37, 38,
519 38, 38, 38, 38, 38, 38, 39, 39, 39, 40,
520 40, 40, 40, 41, 41, 42, 42, 43, 43, 43,
521 44, 44, 44, 45, 46, 46
522};
523
524/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
525static const yytype_uint8 yyr2[] =
526{
527 0, 2, 4, 2, 0, 2, 5, 0, 2, 1,
528 6, 1, 1, 2, 5, 0, 2, 5, 3, 2,
529 4, 4, 2, 9, 5, 2, 0, 2, 2, 0,
530 2, 2, 2, 0, 1, 1, 2, 0, 2, 2,
531 0, 2, 2, 3, 0, 1
532};
533
534/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
535 STATE-NUM when YYTABLE doesn't specify something else to do. Zero
536 means the default is an error. */
537static const yytype_uint8 yydefact[] =
538{
539 7, 0, 45, 0, 9, 0, 7, 0, 4, 1,
540 0, 3, 8, 0, 0, 4, 0, 15, 13, 11,
541 12, 0, 2, 5, 0, 40, 0, 0, 0, 16,
542 0, 40, 0, 0, 6, 0, 42, 41, 0, 10,
543 14, 18, 26, 43, 0, 0, 25, 17, 27, 19,
544 28, 22, 0, 29, 37, 0, 33, 0, 0, 35,
545 34, 32, 31, 20, 0, 30, 38, 39, 21, 0,
546 24, 36, 0, 0, 0, 23
547};
548
549/* YYDEFGOTO[NTERM-NUM]. */
550static const yytype_int8 yydefgoto[] =
551{
552 -1, 3, 14, 4, 5, 6, 27, 11, 18, 25,
553 29, 44, 45, 56, 64, 65, 57, 30, 31, 7
554};
555
556/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
557 STATE-NUM. */
558#define YYPACT_NINF -14
559static const yytype_int8 yypact[] =
560{
561 30, -11, -14, 7, -14, -1, 27, 13, 27, -14,
562 8, -14, -14, 40, -1, 27, 35, -14, -14, -14,
563 -14, 21, -14, -14, 40, 24, 40, 28, 40, -14,
564 32, 24, 46, 38, -14, 39, -14, -14, 26, -14,
565 -14, -14, -14, -14, -9, 10, -14, -14, -14, -14,
566 -14, -14, 31, -14, -14, 44, -2, 3, 23, -14,
567 -14, -14, -14, -14, 50, -14, -14, -14, -14, 40,
568 -14, -14, 33, 40, 36, -14
569};
570
571/* YYPGOTO[NTERM-NUM]. */
572static const yytype_int8 yypgoto[] =
573{
574 -14, -14, 48, 29, 53, -14, -13, 47, 34, -14,
575 37, -14, -14, -14, -14, -14, -14, 42, -14, -7
576};
577
578/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
579 positive, shift that token. If negative, reduce the rule which
580 number is the opposite. If zero, do what YYDEFACT says.
581 If YYTABLE_NINF, syntax error. */
582#define YYTABLE_NINF -45
583static const yytype_int8 yytable[] =
584{
585 21, 16, 46, 8, 59, 47, 60, 9, 16, 61,
586 62, 28, 66, 33, 67, 10, 48, 13, 32, 63,
587 49, 50, 51, 52, 32, 17, 68, 19, 20, -44,
588 53, -44, 54, 1, -44, 2, 26, 15, 2, 24,
589 41, 2, 34, 17, 15, 42, 19, 20, 69, 70,
590 35, 38, 39, 40, 58, 55, 72, 71, 73, 12,
591 74, 22, 75, 23, 0, 0, 0, 0, 36, 0,
592 0, 0, 43, 37
593};
594
595static const yytype_int8 yycheck[] =
596{
597 13, 8, 11, 14, 6, 14, 8, 0, 15, 11,
598 12, 24, 9, 26, 11, 16, 25, 4, 25, 21,
599 10, 11, 12, 13, 31, 17, 23, 6, 7, 5,
600 20, 4, 22, 3, 4, 11, 15, 8, 11, 4,
601 14, 11, 14, 17, 15, 19, 6, 7, 25, 26,
602 18, 5, 14, 14, 10, 24, 69, 7, 25, 6,
603 73, 14, 26, 15, -1, -1, -1, -1, 31, -1,
604 -1, -1, 38, 31
605};
606
607/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
608 symbol of state STATE-NUM. */
609static const yytype_uint8 yystos[] =
610{
611 0, 3, 11, 28, 30, 31, 32, 46, 14, 0,
612 16, 34, 31, 4, 29, 30, 46, 17, 35, 6,
613 7, 33, 34, 29, 4, 36, 15, 33, 33, 37,
614 44, 45, 46, 33, 14, 18, 37, 44, 5, 14,
615 14, 14, 19, 35, 38, 39, 11, 14, 25, 10,
616 11, 12, 13, 20, 22, 24, 40, 43, 10, 6,
617 8, 11, 12, 21, 41, 42, 9, 11, 23, 25,
618 26, 7, 33, 25, 33, 26
619};
620
621#define yyerrok (yyerrstatus = 0)
622#define yyclearin (yychar = YYEMPTY)
623#define YYEMPTY (-2)
624#define YYEOF 0
625
626#define YYACCEPT goto yyacceptlab
627#define YYABORT goto yyabortlab
628#define YYERROR goto yyerrorlab
629
630
631/* Like YYERROR except do call yyerror. This remains here temporarily
632 to ease the transition to the new meaning of YYERROR, for GCC.
633 Once GCC version 2 has supplanted version 1, this can go. */
634
635#define YYFAIL goto yyerrlab
636
637#define YYRECOVERING() (!!yyerrstatus)
638
639#define YYBACKUP(Token, Value) \
640do \
641 if (yychar == YYEMPTY && yylen == 1) \
642 { \
643 yychar = (Token); \
644 yylval = (Value); \
645 yytoken = YYTRANSLATE (yychar); \
646 YYPOPSTACK (1); \
647 goto yybackup; \
648 } \
649 else \
650 { \
651 yyerror (YY_("syntax error: cannot back up")); \
652 YYERROR; \
653 } \
654while (YYID (0))
655
656
657#define YYTERROR 1
658#define YYERRCODE 256
659
660
661/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
662 If N is 0, then set CURRENT to the empty location which ends
663 the previous symbol: RHS[0] (always defined). */
664
665#define YYRHSLOC(Rhs, K) ((Rhs)[K])
666#ifndef YYLLOC_DEFAULT
667# define YYLLOC_DEFAULT(Current, Rhs, N) \
668 do \
669 if (YYID (N)) \
670 { \
671 (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
672 (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
673 (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
674 (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
675 } \
676 else \
677 { \
678 (Current).first_line = (Current).last_line = \
679 YYRHSLOC (Rhs, 0).last_line; \
680 (Current).first_column = (Current).last_column = \
681 YYRHSLOC (Rhs, 0).last_column; \
682 } \
683 while (YYID (0))
684#endif
685
686
687/* YY_LOCATION_PRINT -- Print the location on the stream.
688 This macro was not mandated originally: define only if we know
689 we won't break user code: when these are the locations we know. */
690
691#ifndef YY_LOCATION_PRINT
692# if YYLTYPE_IS_TRIVIAL
693# define YY_LOCATION_PRINT(File, Loc) \
694 fprintf (File, "%d.%d-%d.%d", \
695 (Loc).first_line, (Loc).first_column, \
696 (Loc).last_line, (Loc).last_column)
697# else
698# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
699# endif
700#endif
701
702
703/* YYLEX -- calling `yylex' with the right arguments. */
704
705#ifdef YYLEX_PARAM
706# define YYLEX yylex (YYLEX_PARAM)
707#else
708# define YYLEX yylex ()
709#endif
710
711/* Enable debugging if requested. */
712#if YYDEBUG
713
714# ifndef YYFPRINTF
715# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
716# define YYFPRINTF fprintf
717# endif
718
719# define YYDPRINTF(Args) \
720do { \
721 if (yydebug) \
722 YYFPRINTF Args; \
723} while (YYID (0))
724
725# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
726do { \
727 if (yydebug) \
728 { \
729 YYFPRINTF (stderr, "%s ", Title); \
730 yy_symbol_print (stderr, \
731 Type, Value, Location); \
732 YYFPRINTF (stderr, "\n"); \
733 } \
734} while (YYID (0))
735
736
737/*--------------------------------.
738| Print this symbol on YYOUTPUT. |
739`--------------------------------*/
740
741/*ARGSUSED*/
742#if (defined __STDC__ || defined __C99__FUNC__ \
743 || defined __cplusplus || defined _MSC_VER)
744static void
745yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
746#else
747static void
748yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
749 FILE *yyoutput;
750 int yytype;
751 YYSTYPE const * const yyvaluep;
752 YYLTYPE const * const yylocationp;
753#endif
754{
755 if (!yyvaluep)
756 return;
757 YYUSE (yylocationp);
758# ifdef YYPRINT
759 if (yytype < YYNTOKENS)
760 YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
761# else
762 YYUSE (yyoutput);
763# endif
764 switch (yytype)
765 {
766 default:
767 break;
768 }
769}
770
771
772/*--------------------------------.
773| Print this symbol on YYOUTPUT. |
774`--------------------------------*/
775
776#if (defined __STDC__ || defined __C99__FUNC__ \
777 || defined __cplusplus || defined _MSC_VER)
778static void
779yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
780#else
781static void
782yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp)
783 FILE *yyoutput;
784 int yytype;
785 YYSTYPE const * const yyvaluep;
786 YYLTYPE const * const yylocationp;
787#endif
788{
789 if (yytype < YYNTOKENS)
790 YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
791 else
792 YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
793
794 YY_LOCATION_PRINT (yyoutput, *yylocationp);
795 YYFPRINTF (yyoutput, ": ");
796 yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp);
797 YYFPRINTF (yyoutput, ")");
798}
799
800/*------------------------------------------------------------------.
801| yy_stack_print -- Print the state stack from its BOTTOM up to its |
802| TOP (included). |
803`------------------------------------------------------------------*/
804
805#if (defined __STDC__ || defined __C99__FUNC__ \
806 || defined __cplusplus || defined _MSC_VER)
807static void
808yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
809#else
810static void
811yy_stack_print (bottom, top)
812 yytype_int16 *bottom;
813 yytype_int16 *top;
814#endif
815{
816 YYFPRINTF (stderr, "Stack now");
817 for (; bottom <= top; ++bottom)
818 YYFPRINTF (stderr, " %d", *bottom);
819 YYFPRINTF (stderr, "\n");
820}
821
822# define YY_STACK_PRINT(Bottom, Top) \
823do { \
824 if (yydebug) \
825 yy_stack_print ((Bottom), (Top)); \
826} while (YYID (0))
827
828
829/*------------------------------------------------.
830| Report that the YYRULE is going to be reduced. |
831`------------------------------------------------*/
832
833#if (defined __STDC__ || defined __C99__FUNC__ \
834 || defined __cplusplus || defined _MSC_VER)
835static void
836yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule)
837#else
838static void
839yy_reduce_print (yyvsp, yylsp, yyrule)
840 YYSTYPE *yyvsp;
841 YYLTYPE *yylsp;
842 int yyrule;
843#endif
844{
845 int yynrhs = yyr2[yyrule];
846 int yyi;
847 unsigned long int yylno = yyrline[yyrule];
848 YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
849 yyrule - 1, yylno);
850 /* The symbols being reduced. */
851 for (yyi = 0; yyi < yynrhs; yyi++)
852 {
853 fprintf (stderr, " $%d = ", yyi + 1);
854 yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
855 &(yyvsp[(yyi + 1) - (yynrhs)])
856 , &(yylsp[(yyi + 1) - (yynrhs)]) );
857 fprintf (stderr, "\n");
858 }
859}
860
861# define YY_REDUCE_PRINT(Rule) \
862do { \
863 if (yydebug) \
864 yy_reduce_print (yyvsp, yylsp, Rule); \
865} while (YYID (0))
866
867/* Nonzero means print parse trace. It is left uninitialized so that
868 multiple parsers can coexist. */
869int yydebug;
870#else /* !YYDEBUG */
871# define YYDPRINTF(Args)
872# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
873# define YY_STACK_PRINT(Bottom, Top)
874# define YY_REDUCE_PRINT(Rule)
875#endif /* !YYDEBUG */
876
877
878/* YYINITDEPTH -- initial size of the parser's stacks. */
879#ifndef YYINITDEPTH
880# define YYINITDEPTH 200
881#endif
882
883/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
884 if the built-in stack extension method is used).
885
886 Do not make this value too large; the results are undefined if
887 YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
888 evaluated with infinite-precision integer arithmetic. */
889
890#ifndef YYMAXDEPTH
891# define YYMAXDEPTH 10000
892#endif
893
894
895
896#if YYERROR_VERBOSE
897
898# ifndef yystrlen
899# if defined __GLIBC__ && defined _STRING_H
900# define yystrlen strlen
901# else
902/* Return the length of YYSTR. */
903#if (defined __STDC__ || defined __C99__FUNC__ \
904 || defined __cplusplus || defined _MSC_VER)
905static YYSIZE_T
906yystrlen (const char *yystr)
907#else
908static YYSIZE_T
909yystrlen (yystr)
910 const char *yystr;
911#endif
912{
913 YYSIZE_T yylen;
914 for (yylen = 0; yystr[yylen]; yylen++)
915 continue;
916 return yylen;
917}
918# endif
919# endif
920
921# ifndef yystpcpy
922# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
923# define yystpcpy stpcpy
924# else
925/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
926 YYDEST. */
927#if (defined __STDC__ || defined __C99__FUNC__ \
928 || defined __cplusplus || defined _MSC_VER)
929static char *
930yystpcpy (char *yydest, const char *yysrc)
931#else
932static char *
933yystpcpy (yydest, yysrc)
934 char *yydest;
935 const char *yysrc;
936#endif
937{
938 char *yyd = yydest;
939 const char *yys = yysrc;
940
941 while ((*yyd++ = *yys++) != '\0')
942 continue;
943
944 return yyd - 1;
945}
946# endif
947# endif
948
949# ifndef yytnamerr
950/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
951 quotes and backslashes, so that it's suitable for yyerror. The
952 heuristic is that double-quoting is unnecessary unless the string
953 contains an apostrophe, a comma, or backslash (other than
954 backslash-backslash). YYSTR is taken from yytname. If YYRES is
955 null, do not copy; instead, return the length of what the result
956 would have been. */
957static YYSIZE_T
958yytnamerr (char *yyres, const char *yystr)
959{
960 if (*yystr == '"')
961 {
962 YYSIZE_T yyn = 0;
963 char const *yyp = yystr;
964
965 for (;;)
966 switch (*++yyp)
967 {
968 case '\'':
969 case ',':
970 goto do_not_strip_quotes;
971
972 case '\\':
973 if (*++yyp != '\\')
974 goto do_not_strip_quotes;
975 /* Fall through. */
976 default:
977 if (yyres)
978 yyres[yyn] = *yyp;
979 yyn++;
980 break;
981
982 case '"':
983 if (yyres)
984 yyres[yyn] = '\0';
985 return yyn;
986 }
987 do_not_strip_quotes: ;
988 }
989
990 if (! yyres)
991 return yystrlen (yystr);
992
993 return yystpcpy (yyres, yystr) - yyres;
994}
995# endif
996
997/* Copy into YYRESULT an error message about the unexpected token
998 YYCHAR while in state YYSTATE. Return the number of bytes copied,
999 including the terminating null byte. If YYRESULT is null, do not
1000 copy anything; just return the number of bytes that would be
1001 copied. As a special case, return 0 if an ordinary "syntax error"
1002 message will do. Return YYSIZE_MAXIMUM if overflow occurs during
1003 size calculation. */
1004static YYSIZE_T
1005yysyntax_error (char *yyresult, int yystate, int yychar)
1006{
1007 int yyn = yypact[yystate];
1008
1009 if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
1010 return 0;
1011 else
1012 {
1013 int yytype = YYTRANSLATE (yychar);
1014 YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
1015 YYSIZE_T yysize = yysize0;
1016 YYSIZE_T yysize1;
1017 int yysize_overflow = 0;
1018 enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
1019 char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
1020 int yyx;
1021
1022# if 0
1023 /* This is so xgettext sees the translatable formats that are
1024 constructed on the fly. */
1025 YY_("syntax error, unexpected %s");
1026 YY_("syntax error, unexpected %s, expecting %s");
1027 YY_("syntax error, unexpected %s, expecting %s or %s");
1028 YY_("syntax error, unexpected %s, expecting %s or %s or %s");
1029 YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
1030# endif
1031 char *yyfmt;
1032 char const *yyf;
1033 static char const yyunexpected[] = "syntax error, unexpected %s";
1034 static char const yyexpecting[] = ", expecting %s";
1035 static char const yyor[] = " or %s";
1036 char yyformat[sizeof yyunexpected
1037 + sizeof yyexpecting - 1
1038 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
1039 * (sizeof yyor - 1))];
1040 char const *yyprefix = yyexpecting;
1041
1042 /* Start YYX at -YYN if negative to avoid negative indexes in
1043 YYCHECK. */
1044 int yyxbegin = yyn < 0 ? -yyn : 0;
1045
1046 /* Stay within bounds of both yycheck and yytname. */
1047 int yychecklim = YYLAST - yyn + 1;
1048 int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
1049 int yycount = 1;
1050
1051 yyarg[0] = yytname[yytype];
1052 yyfmt = yystpcpy (yyformat, yyunexpected);
1053
1054 for (yyx = yyxbegin; yyx < yyxend; ++yyx)
1055 if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
1056 {
1057 if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
1058 {
1059 yycount = 1;
1060 yysize = yysize0;
1061 yyformat[sizeof yyunexpected - 1] = '\0';
1062 break;
1063 }
1064 yyarg[yycount++] = yytname[yyx];
1065 yysize1 = yysize + yytnamerr (0, yytname[yyx]);
1066 yysize_overflow |= (yysize1 < yysize);
1067 yysize = yysize1;
1068 yyfmt = yystpcpy (yyfmt, yyprefix);
1069 yyprefix = yyor;
1070 }
1071
1072 yyf = YY_(yyformat);
1073 yysize1 = yysize + yystrlen (yyf);
1074 yysize_overflow |= (yysize1 < yysize);
1075 yysize = yysize1;
1076
1077 if (yysize_overflow)
1078 return YYSIZE_MAXIMUM;
1079
1080 if (yyresult)
1081 {
1082 /* Avoid sprintf, as that infringes on the user's name space.
1083 Don't have undefined behavior even if the translation
1084 produced a string with the wrong number of "%s"s. */
1085 char *yyp = yyresult;
1086 int yyi = 0;
1087 while ((*yyp = *yyf) != '\0')
1088 {
1089 if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
1090 {
1091 yyp += yytnamerr (yyp, yyarg[yyi++]);
1092 yyf += 2;
1093 }
1094 else
1095 {
1096 yyp++;
1097 yyf++;
1098 }
1099 }
1100 }
1101 return yysize;
1102 }
1103}
1104#endif /* YYERROR_VERBOSE */
1105
1106
1107/*-----------------------------------------------.
1108| Release the memory associated to this symbol. |
1109`-----------------------------------------------*/
1110
1111/*ARGSUSED*/
1112#if (defined __STDC__ || defined __C99__FUNC__ \
1113 || defined __cplusplus || defined _MSC_VER)
1114static void
1115yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp)
1116#else
1117static void
1118yydestruct (yymsg, yytype, yyvaluep, yylocationp)
1119 const char *yymsg;
1120 int yytype;
1121 YYSTYPE *yyvaluep;
1122 YYLTYPE *yylocationp;
1123#endif
1124{
1125 YYUSE (yyvaluep);
1126 YYUSE (yylocationp);
1127
1128 if (!yymsg)
1129 yymsg = "Deleting";
1130 YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
1131
1132 switch (yytype)
1133 {
1134
1135 default:
1136 break;
1137 }
1138}
1139
1140
1141/* Prevent warnings from -Wmissing-prototypes. */
1142
1143#ifdef YYPARSE_PARAM
1144#if defined __STDC__ || defined __cplusplus
1145int yyparse (void *YYPARSE_PARAM);
1146#else
1147int yyparse ();
1148#endif
1149#else /* ! YYPARSE_PARAM */
1150#if defined __STDC__ || defined __cplusplus
1151int yyparse (void);
1152#else
1153int yyparse ();
1154#endif
1155#endif /* ! YYPARSE_PARAM */
1156
1157
1158
1159/* The look-ahead symbol. */
1160int yychar;
1161
1162/* The semantic value of the look-ahead symbol. */
1163YYSTYPE yylval;
1164
1165/* Number of syntax errors so far. */
1166int yynerrs;
1167/* Location data for the look-ahead symbol. */
1168YYLTYPE yylloc;
1169
1170
1171
1172/*----------.
1173| yyparse. |
1174`----------*/
1175
1176#ifdef YYPARSE_PARAM
1177#if (defined __STDC__ || defined __C99__FUNC__ \
1178 || defined __cplusplus || defined _MSC_VER)
1179int
1180yyparse (void *YYPARSE_PARAM)
1181#else
1182int
1183yyparse (YYPARSE_PARAM)
1184 void *YYPARSE_PARAM;
1185#endif
1186#else /* ! YYPARSE_PARAM */
1187#if (defined __STDC__ || defined __C99__FUNC__ \
1188 || defined __cplusplus || defined _MSC_VER)
1189int
1190yyparse (void)
1191#else
1192int
1193yyparse ()
1194
1195#endif
1196#endif
1197{
1198
1199 int yystate;
1200 int yyn;
1201 int yyresult;
1202 /* Number of tokens to shift before error messages enabled. */
1203 int yyerrstatus;
1204 /* Look-ahead token as an internal (translated) token number. */
1205 int yytoken = 0;
1206#if YYERROR_VERBOSE
1207 /* Buffer for error messages, and its allocated size. */
1208 char yymsgbuf[128];
1209 char *yymsg = yymsgbuf;
1210 YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
1211#endif
1212
1213 /* Three stacks and their tools:
1214 `yyss': related to states,
1215 `yyvs': related to semantic values,
1216 `yyls': related to locations.
1217
1218 Refer to the stacks thru separate pointers, to allow yyoverflow
1219 to reallocate them elsewhere. */
1220
1221 /* The state stack. */
1222 yytype_int16 yyssa[YYINITDEPTH];
1223 yytype_int16 *yyss = yyssa;
1224 yytype_int16 *yyssp;
1225
1226 /* The semantic value stack. */
1227 YYSTYPE yyvsa[YYINITDEPTH];
1228 YYSTYPE *yyvs = yyvsa;
1229 YYSTYPE *yyvsp;
1230
1231 /* The location stack. */
1232 YYLTYPE yylsa[YYINITDEPTH];
1233 YYLTYPE *yyls = yylsa;
1234 YYLTYPE *yylsp;
1235 /* The locations where the error started and ended. */
1236 YYLTYPE yyerror_range[2];
1237
1238#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
1239
1240 YYSIZE_T yystacksize = YYINITDEPTH;
1241
1242 /* The variables used to return semantic value and location from the
1243 action routines. */
1244 YYSTYPE yyval;
1245 YYLTYPE yyloc;
1246
1247 /* The number of symbols on the RHS of the reduced rule.
1248 Keep to zero when no symbol should be popped. */
1249 int yylen = 0;
1250
1251 YYDPRINTF ((stderr, "Starting parse\n"));
1252
1253 yystate = 0;
1254 yyerrstatus = 0;
1255 yynerrs = 0;
1256 yychar = YYEMPTY; /* Cause a token to be read. */
1257
1258 /* Initialize stack pointers.
1259 Waste one element of value and location stack
1260 so that they stay on the same level as the state stack.
1261 The wasted elements are never initialized. */
1262
1263 yyssp = yyss;
1264 yyvsp = yyvs;
1265 yylsp = yyls;
1266#if YYLTYPE_IS_TRIVIAL
1267 /* Initialize the default location before parsing starts. */
1268 yylloc.first_line = yylloc.last_line = 1;
1269 yylloc.first_column = yylloc.last_column = 0;
1270#endif
1271
1272 goto yysetstate;
1273
1274/*------------------------------------------------------------.
1275| yynewstate -- Push a new state, which is found in yystate. |
1276`------------------------------------------------------------*/
1277 yynewstate:
1278 /* In all cases, when you get here, the value and location stacks
1279 have just been pushed. So pushing a state here evens the stacks. */
1280 yyssp++;
1281
1282 yysetstate:
1283 *yyssp = yystate;
1284
1285 if (yyss + yystacksize - 1 <= yyssp)
1286 {
1287 /* Get the current used size of the three stacks, in elements. */
1288 YYSIZE_T yysize = yyssp - yyss + 1;
1289
1290#ifdef yyoverflow
1291 {
1292 /* Give user a chance to reallocate the stack. Use copies of
1293 these so that the &'s don't force the real ones into
1294 memory. */
1295 YYSTYPE *yyvs1 = yyvs;
1296 yytype_int16 *yyss1 = yyss;
1297 YYLTYPE *yyls1 = yyls;
1298
1299 /* Each stack pointer address is followed by the size of the
1300 data in use in that stack, in bytes. This used to be a
1301 conditional around just the two extra args, but that might
1302 be undefined if yyoverflow is a macro. */
1303 yyoverflow (YY_("memory exhausted"),
1304 &yyss1, yysize * sizeof (*yyssp),
1305 &yyvs1, yysize * sizeof (*yyvsp),
1306 &yyls1, yysize * sizeof (*yylsp),
1307 &yystacksize);
1308 yyls = yyls1;
1309 yyss = yyss1;
1310 yyvs = yyvs1;
1311 }
1312#else /* no yyoverflow */
1313# ifndef YYSTACK_RELOCATE
1314 goto yyexhaustedlab;
1315# else
1316 /* Extend the stack our own way. */
1317 if (YYMAXDEPTH <= yystacksize)
1318 goto yyexhaustedlab;
1319 yystacksize *= 2;
1320 if (YYMAXDEPTH < yystacksize)
1321 yystacksize = YYMAXDEPTH;
1322
1323 {
1324 yytype_int16 *yyss1 = yyss;
1325 union yyalloc *yyptr =
1326 (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
1327 if (! yyptr)
1328 goto yyexhaustedlab;
1329 YYSTACK_RELOCATE (yyss);
1330 YYSTACK_RELOCATE (yyvs);
1331 YYSTACK_RELOCATE (yyls);
1332# undef YYSTACK_RELOCATE
1333 if (yyss1 != yyssa)
1334 YYSTACK_FREE (yyss1);
1335 }
1336# endif
1337#endif /* no yyoverflow */
1338
1339 yyssp = yyss + yysize - 1;
1340 yyvsp = yyvs + yysize - 1;
1341 yylsp = yyls + yysize - 1;
1342
1343 YYDPRINTF ((stderr, "Stack size increased to %lu\n",
1344 (unsigned long int) yystacksize));
1345
1346 if (yyss + yystacksize - 1 <= yyssp)
1347 YYABORT;
1348 }
1349
1350 YYDPRINTF ((stderr, "Entering state %d\n", yystate));
1351
1352 goto yybackup;
1353
1354/*-----------.
1355| yybackup. |
1356`-----------*/
1357yybackup:
1358
1359 /* Do appropriate processing given the current state. Read a
1360 look-ahead token if we need one and don't already have one. */
1361
1362 /* First try to decide what to do without reference to look-ahead token. */
1363 yyn = yypact[yystate];
1364 if (yyn == YYPACT_NINF)
1365 goto yydefault;
1366
1367 /* Not known => get a look-ahead token if don't already have one. */
1368
1369 /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
1370 if (yychar == YYEMPTY)
1371 {
1372 YYDPRINTF ((stderr, "Reading a token: "));
1373 yychar = YYLEX;
1374 }
1375
1376 if (yychar <= YYEOF)
1377 {
1378 yychar = yytoken = YYEOF;
1379 YYDPRINTF ((stderr, "Now at end of input.\n"));
1380 }
1381 else
1382 {
1383 yytoken = YYTRANSLATE (yychar);
1384 YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
1385 }
1386
1387 /* If the proper action on seeing token YYTOKEN is to reduce or to
1388 detect an error, take that action. */
1389 yyn += yytoken;
1390 if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
1391 goto yydefault;
1392 yyn = yytable[yyn];
1393 if (yyn <= 0)
1394 {
1395 if (yyn == 0 || yyn == YYTABLE_NINF)
1396 goto yyerrlab;
1397 yyn = -yyn;
1398 goto yyreduce;
1399 }
1400
1401 if (yyn == YYFINAL)
1402 YYACCEPT;
1403
1404 /* Count tokens shifted since error; after three, turn off error
1405 status. */
1406 if (yyerrstatus)
1407 yyerrstatus--;
1408
1409 /* Shift the look-ahead token. */
1410 YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
1411
1412 /* Discard the shifted token unless it is eof. */
1413 if (yychar != YYEOF)
1414 yychar = YYEMPTY;
1415
1416 yystate = yyn;
1417 *++yyvsp = yylval;
1418 *++yylsp = yylloc;
1419 goto yynewstate;
1420
1421
1422/*-----------------------------------------------------------.
1423| yydefault -- do the default action for the current state. |
1424`-----------------------------------------------------------*/
1425yydefault:
1426 yyn = yydefact[yystate];
1427 if (yyn == 0)
1428 goto yyerrlab;
1429 goto yyreduce;
1430
1431
1432/*-----------------------------.
1433| yyreduce -- Do a reduction. |
1434`-----------------------------*/
1435yyreduce:
1436 /* yyn is the number of a rule to reduce with. */
1437 yylen = yyr2[yyn];
1438
1439 /* If YYLEN is nonzero, implement the default value of the action:
1440 `$$ = $1'.
1441
1442 Otherwise, the following line sets YYVAL to garbage.
1443 This behavior is undocumented and Bison
1444 users should not rely upon it. Assigning to YYVAL
1445 unconditionally makes the parser a bit smaller, and it avoids a
1446 GCC warning that YYVAL may be used uninitialized. */
1447 yyval = yyvsp[1-yylen];
1448
1449 /* Default location. */
1450 YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
1451 YY_REDUCE_PRINT (yyn);
1452 switch (yyn)
1453 {
1454 case 2:
1455#line 90 "dtc-parser.y"
1456 {
1457 the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node), 0);
1458 ;}
1459 break;
1460
1461 case 3:
1462#line 94 "dtc-parser.y"
1463 {
1464 the_boot_info = build_boot_info((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].node), 0);
1465 ;}
1466 break;
1467
1468 case 4:
1469#line 101 "dtc-parser.y"
1470 {
1471 (yyval.re) = NULL;
1472 ;}
1473 break;
1474
1475 case 5:
1476#line 105 "dtc-parser.y"
1477 {
1478 (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
1479 ;}
1480 break;
1481
1482 case 6:
1483#line 112 "dtc-parser.y"
1484 {
1485 (yyval.re) = build_reserve_entry((yyvsp[(3) - (5)].addr), (yyvsp[(4) - (5)].addr), (yyvsp[(1) - (5)].labelref));
1486 ;}
1487 break;
1488
1489 case 7:
1490#line 119 "dtc-parser.y"
1491 {
1492 (yyval.re) = NULL;
1493 ;}
1494 break;
1495
1496 case 8:
1497#line 123 "dtc-parser.y"
1498 {
1499 (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
1500 ;}
1501 break;
1502
1503 case 9:
1504#line 130 "dtc-parser.y"
1505 {
1506 (yyval.re) = (yyvsp[(1) - (1)].re);
1507 ;}
1508 break;
1509
1510 case 10:
1511#line 134 "dtc-parser.y"
1512 {
1513 (yyval.re) = build_reserve_entry((yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].addr) - (yyvsp[(3) - (6)].addr) + 1, (yyvsp[(1) - (6)].labelref));
1514 ;}
1515 break;
1516
1517 case 11:
1518#line 141 "dtc-parser.y"
1519 {
1520 (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
1521 ;}
1522 break;
1523
1524 case 12:
1525#line 145 "dtc-parser.y"
1526 {
1527 (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 16, 64);
1528 ;}
1529 break;
1530
1531 case 13:
1532#line 152 "dtc-parser.y"
1533 {
1534 (yyval.node) = name_node((yyvsp[(2) - (2)].node), "", NULL);
1535 ;}
1536 break;
1537
1538 case 14:
1539#line 159 "dtc-parser.y"
1540 {
1541 (yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
1542 ;}
1543 break;
1544
1545 case 15:
1546#line 166 "dtc-parser.y"
1547 {
1548 (yyval.proplist) = NULL;
1549 ;}
1550 break;
1551
1552 case 16:
1553#line 170 "dtc-parser.y"
1554 {
1555 (yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
1556 ;}
1557 break;
1558
1559 case 17:
1560#line 177 "dtc-parser.y"
1561 {
1562 (yyval.prop) = build_property((yyvsp[(2) - (5)].propnodename), (yyvsp[(4) - (5)].data), (yyvsp[(1) - (5)].labelref));
1563 ;}
1564 break;
1565
1566 case 18:
1567#line 181 "dtc-parser.y"
1568 {
1569 (yyval.prop) = build_property((yyvsp[(2) - (3)].propnodename), empty_data, (yyvsp[(1) - (3)].labelref));
1570 ;}
1571 break;
1572
1573 case 19:
1574#line 188 "dtc-parser.y"
1575 {
1576 (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
1577 ;}
1578 break;
1579
1580 case 20:
1581#line 192 "dtc-parser.y"
1582 {
1583 (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
1584 ;}
1585 break;
1586
1587 case 21:
1588#line 196 "dtc-parser.y"
1589 {
1590 (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
1591 ;}
1592 break;
1593
1594 case 22:
1595#line 200 "dtc-parser.y"
1596 {
1597 (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
1598 ;}
1599 break;
1600
1601 case 23:
1602#line 204 "dtc-parser.y"
1603 {
1604 struct search_path path = { srcpos_file->dir, NULL, NULL };
1605 struct dtc_file *file = dtc_open_file((yyvsp[(4) - (9)].data).val, &path);
1606 struct data d = empty_data;
1607
1608 if ((yyvsp[(6) - (9)].addr) != 0)
1609 if (fseek(file->file, (yyvsp[(6) - (9)].addr), SEEK_SET) != 0)
1610 yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
1611 (unsigned long long)(yyvsp[(6) - (9)].addr),
1612 (yyvsp[(4) - (9)].data).val, strerror(errno));
1613
1614 d = data_copy_file(file->file, (yyvsp[(8) - (9)].addr));
1615
1616 (yyval.data) = data_merge((yyvsp[(1) - (9)].data), d);
1617 dtc_close_file(file);
1618 ;}
1619 break;
1620
1621 case 24:
1622#line 221 "dtc-parser.y"
1623 {
1624 struct search_path path = { srcpos_file->dir, NULL, NULL };
1625 struct dtc_file *file = dtc_open_file((yyvsp[(4) - (5)].data).val, &path);
1626 struct data d = empty_data;
1627
1628 d = data_copy_file(file->file, -1);
1629
1630 (yyval.data) = data_merge((yyvsp[(1) - (5)].data), d);
1631 dtc_close_file(file);
1632 ;}
1633 break;
1634
1635 case 25:
1636#line 232 "dtc-parser.y"
1637 {
1638 (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
1639 ;}
1640 break;
1641
1642 case 26:
1643#line 239 "dtc-parser.y"
1644 {
1645 (yyval.data) = empty_data;
1646 ;}
1647 break;
1648
1649 case 27:
1650#line 243 "dtc-parser.y"
1651 {
1652 (yyval.data) = (yyvsp[(1) - (2)].data);
1653 ;}
1654 break;
1655
1656 case 28:
1657#line 247 "dtc-parser.y"
1658 {
1659 (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
1660 ;}
1661 break;
1662
1663 case 29:
1664#line 254 "dtc-parser.y"
1665 {
1666 (yyval.data) = empty_data;
1667 ;}
1668 break;
1669
1670 case 30:
1671#line 258 "dtc-parser.y"
1672 {
1673 (yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell));
1674 ;}
1675 break;
1676
1677 case 31:
1678#line 262 "dtc-parser.y"
1679 {
1680 (yyval.data) = data_append_cell(data_add_marker((yyvsp[(1) - (2)].data), REF_PHANDLE,
1681 (yyvsp[(2) - (2)].labelref)), -1);
1682 ;}
1683 break;
1684
1685 case 32:
1686#line 267 "dtc-parser.y"
1687 {
1688 (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
1689 ;}
1690 break;
1691
1692 case 33:
1693#line 274 "dtc-parser.y"
1694 {
1695 (yyval.cbase) = 16;
1696 ;}
1697 break;
1698
1699 case 35:
1700#line 282 "dtc-parser.y"
1701 {
1702 (yyval.cell) = eval_literal((yyvsp[(1) - (1)].literal), 0, 32);
1703 ;}
1704 break;
1705
1706 case 36:
1707#line 286 "dtc-parser.y"
1708 {
1709 (yyval.cell) = eval_literal((yyvsp[(2) - (2)].literal), (yyvsp[(1) - (2)].cbase), 32);
1710 ;}
1711 break;
1712
1713 case 37:
1714#line 293 "dtc-parser.y"
1715 {
1716 (yyval.data) = empty_data;
1717 ;}
1718 break;
1719
1720 case 38:
1721#line 297 "dtc-parser.y"
1722 {
1723 (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
1724 ;}
1725 break;
1726
1727 case 39:
1728#line 301 "dtc-parser.y"
1729 {
1730 (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
1731 ;}
1732 break;
1733
1734 case 40:
1735#line 308 "dtc-parser.y"
1736 {
1737 (yyval.nodelist) = NULL;
1738 ;}
1739 break;
1740
1741 case 41:
1742#line 312 "dtc-parser.y"
1743 {
1744 (yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
1745 ;}
1746 break;
1747
1748 case 42:
1749#line 316 "dtc-parser.y"
1750 {
1751 yyerror("syntax error: properties must precede subnodes");
1752 YYERROR;
1753 ;}
1754 break;
1755
1756 case 43:
1757#line 324 "dtc-parser.y"
1758 {
1759 (yyval.node) = name_node((yyvsp[(3) - (3)].node), (yyvsp[(2) - (3)].propnodename), (yyvsp[(1) - (3)].labelref));
1760 ;}
1761 break;
1762
1763 case 44:
1764#line 331 "dtc-parser.y"
1765 {
1766 (yyval.labelref) = NULL;
1767 ;}
1768 break;
1769
1770 case 45:
1771#line 335 "dtc-parser.y"
1772 {
1773 (yyval.labelref) = (yyvsp[(1) - (1)].labelref);
1774 ;}
1775 break;
1776
1777
1778/* Line 1267 of yacc.c. */
1779#line 1780 "dtc-parser.tab.c"
1780 default: break;
1781 }
1782 YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
1783
1784 YYPOPSTACK (yylen);
1785 yylen = 0;
1786 YY_STACK_PRINT (yyss, yyssp);
1787
1788 *++yyvsp = yyval;
1789 *++yylsp = yyloc;
1790
1791 /* Now `shift' the result of the reduction. Determine what state
1792 that goes to, based on the state we popped back to and the rule
1793 number reduced by. */
1794
1795 yyn = yyr1[yyn];
1796
1797 yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
1798 if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1799 yystate = yytable[yystate];
1800 else
1801 yystate = yydefgoto[yyn - YYNTOKENS];
1802
1803 goto yynewstate;
1804
1805
1806/*------------------------------------.
1807| yyerrlab -- here on detecting error |
1808`------------------------------------*/
1809yyerrlab:
1810 /* If not already recovering from an error, report this error. */
1811 if (!yyerrstatus)
1812 {
1813 ++yynerrs;
1814#if ! YYERROR_VERBOSE
1815 yyerror (YY_("syntax error"));
1816#else
1817 {
1818 YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
1819 if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
1820 {
1821 YYSIZE_T yyalloc = 2 * yysize;
1822 if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
1823 yyalloc = YYSTACK_ALLOC_MAXIMUM;
1824 if (yymsg != yymsgbuf)
1825 YYSTACK_FREE (yymsg);
1826 yymsg = (char *) YYSTACK_ALLOC (yyalloc);
1827 if (yymsg)
1828 yymsg_alloc = yyalloc;
1829 else
1830 {
1831 yymsg = yymsgbuf;
1832 yymsg_alloc = sizeof yymsgbuf;
1833 }
1834 }
1835
1836 if (0 < yysize && yysize <= yymsg_alloc)
1837 {
1838 (void) yysyntax_error (yymsg, yystate, yychar);
1839 yyerror (yymsg);
1840 }
1841 else
1842 {
1843 yyerror (YY_("syntax error"));
1844 if (yysize != 0)
1845 goto yyexhaustedlab;
1846 }
1847 }
1848#endif
1849 }
1850
1851 yyerror_range[0] = yylloc;
1852
1853 if (yyerrstatus == 3)
1854 {
1855 /* If just tried and failed to reuse look-ahead token after an
1856 error, discard it. */
1857
1858 if (yychar <= YYEOF)
1859 {
1860 /* Return failure if at end of input. */
1861 if (yychar == YYEOF)
1862 YYABORT;
1863 }
1864 else
1865 {
1866 yydestruct ("Error: discarding",
1867 yytoken, &yylval, &yylloc);
1868 yychar = YYEMPTY;
1869 }
1870 }
1871
1872 /* Else will try to reuse look-ahead token after shifting the error
1873 token. */
1874 goto yyerrlab1;
1875
1876
1877/*---------------------------------------------------.
1878| yyerrorlab -- error raised explicitly by YYERROR. |
1879`---------------------------------------------------*/
1880yyerrorlab:
1881
1882 /* Pacify compilers like GCC when the user code never invokes
1883 YYERROR and the label yyerrorlab therefore never appears in user
1884 code. */
1885 if (/*CONSTCOND*/ 0)
1886 goto yyerrorlab;
1887
1888 yyerror_range[0] = yylsp[1-yylen];
1889 /* Do not reclaim the symbols of the rule which action triggered
1890 this YYERROR. */
1891 YYPOPSTACK (yylen);
1892 yylen = 0;
1893 YY_STACK_PRINT (yyss, yyssp);
1894 yystate = *yyssp;
1895 goto yyerrlab1;
1896
1897
1898/*-------------------------------------------------------------.
1899| yyerrlab1 -- common code for both syntax error and YYERROR. |
1900`-------------------------------------------------------------*/
1901yyerrlab1:
1902 yyerrstatus = 3; /* Each real token shifted decrements this. */
1903
1904 for (;;)
1905 {
1906 yyn = yypact[yystate];
1907 if (yyn != YYPACT_NINF)
1908 {
1909 yyn += YYTERROR;
1910 if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
1911 {
1912 yyn = yytable[yyn];
1913 if (0 < yyn)
1914 break;
1915 }
1916 }
1917
1918 /* Pop the current state because it cannot handle the error token. */
1919 if (yyssp == yyss)
1920 YYABORT;
1921
1922 yyerror_range[0] = *yylsp;
1923 yydestruct ("Error: popping",
1924 yystos[yystate], yyvsp, yylsp);
1925 YYPOPSTACK (1);
1926 yystate = *yyssp;
1927 YY_STACK_PRINT (yyss, yyssp);
1928 }
1929
1930 if (yyn == YYFINAL)
1931 YYACCEPT;
1932
1933 *++yyvsp = yylval;
1934
1935 yyerror_range[1] = yylloc;
1936 /* Using YYLLOC is tempting, but would change the location of
1937 the look-ahead. YYLOC is available though. */
1938 YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
1939 *++yylsp = yyloc;
1940
1941 /* Shift the error token. */
1942 YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
1943
1944 yystate = yyn;
1945 goto yynewstate;
1946
1947
1948/*-------------------------------------.
1949| yyacceptlab -- YYACCEPT comes here. |
1950`-------------------------------------*/
1951yyacceptlab:
1952 yyresult = 0;
1953 goto yyreturn;
1954
1955/*-----------------------------------.
1956| yyabortlab -- YYABORT comes here. |
1957`-----------------------------------*/
1958yyabortlab:
1959 yyresult = 1;
1960 goto yyreturn;
1961
1962#ifndef yyoverflow
1963/*-------------------------------------------------.
1964| yyexhaustedlab -- memory exhaustion comes here. |
1965`-------------------------------------------------*/
1966yyexhaustedlab:
1967 yyerror (YY_("memory exhausted"));
1968 yyresult = 2;
1969 /* Fall through. */
1970#endif
1971
1972yyreturn:
1973 if (yychar != YYEOF && yychar != YYEMPTY)
1974 yydestruct ("Cleanup: discarding lookahead",
1975 yytoken, &yylval, &yylloc);
1976 /* Do not reclaim the symbols of the rule which action triggered
1977 this YYABORT or YYACCEPT. */
1978 YYPOPSTACK (yylen);
1979 YY_STACK_PRINT (yyss, yyssp);
1980 while (yyssp != yyss)
1981 {
1982 yydestruct ("Cleanup: popping",
1983 yystos[*yyssp], yyvsp, yylsp);
1984 YYPOPSTACK (1);
1985 }
1986#ifndef yyoverflow
1987 if (yyss != yyssa)
1988 YYSTACK_FREE (yyss);
1989#endif
1990#if YYERROR_VERBOSE
1991 if (yymsg != yymsgbuf)
1992 YYSTACK_FREE (yymsg);
1993#endif
1994 /* Make sure YYID is used. */
1995 return YYID (yyresult);
1996}
1997
1998
1999#line 340 "dtc-parser.y"
2000
2001
2002void yyerrorf(char const *s, ...)
2003{
2004 const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
2005 va_list va;
2006 va_start(va, s);
2007
2008 if (strcmp(fname, "-") == 0)
2009 fname = "stdin";
2010
2011 fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
2012 vfprintf(stderr, s, va);
2013 fprintf(stderr, "\n");
2014
2015 treesource_error = 1;
2016 va_end(va);
2017}
2018
2019void yyerror (char const *s)
2020{
2021 yyerrorf("%s", s);
2022}
2023
2024static unsigned long long eval_literal(const char *s, int base, int bits)
2025{
2026 unsigned long long val;
2027 char *e;
2028
2029 errno = 0;
2030 val = strtoull(s, &e, base);
2031 if (*e)
2032 yyerror("bad characters in literal");
2033 else if ((errno == ERANGE)
2034 || ((bits < 64) && (val >= (1ULL << bits))))
2035 yyerror("literal out of range");
2036 else if (errno != 0)
2037 yyerror("bad literal");
2038 return val;
2039}
2040
diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped
new file mode 100644
index 000000000000..ba99100d55c9
--- /dev/null
+++ b/scripts/dtc/dtc-parser.tab.h_shipped
@@ -0,0 +1,113 @@
1/* A Bison parser, made by GNU Bison 2.3. */
2
3/* Skeleton interface for Bison's Yacc-like parsers in C
4
5 Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
6 Free Software Foundation, Inc.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
22
23/* As a special exception, you may create a larger work that contains
24 part or all of the Bison parser skeleton and distribute that work
25 under terms of your choice, so long as that work isn't itself a
26 parser generator using the skeleton or a modified version thereof
27 as a parser skeleton. Alternatively, if you modify or redistribute
28 the parser skeleton itself, you may (at your option) remove this
29 special exception, which will cause the skeleton and the resulting
30 Bison output files to be licensed under the GNU General Public
31 License without this special exception.
32
33 This special exception was added by the Free Software Foundation in
34 version 2.2 of Bison. */
35
36/* Tokens. */
37#ifndef YYTOKENTYPE
38# define YYTOKENTYPE
39 /* Put the tokens into the symbol table, so that GDB and other debuggers
40 know about them. */
41 enum yytokentype {
42 DT_V1 = 258,
43 DT_MEMRESERVE = 259,
44 DT_PROPNODENAME = 260,
45 DT_LITERAL = 261,
46 DT_LEGACYLITERAL = 262,
47 DT_BASE = 263,
48 DT_BYTE = 264,
49 DT_STRING = 265,
50 DT_LABEL = 266,
51 DT_REF = 267,
52 DT_INCBIN = 268
53 };
54#endif
55/* Tokens. */
56#define DT_V1 258
57#define DT_MEMRESERVE 259
58#define DT_PROPNODENAME 260
59#define DT_LITERAL 261
60#define DT_LEGACYLITERAL 262
61#define DT_BASE 263
62#define DT_BYTE 264
63#define DT_STRING 265
64#define DT_LABEL 266
65#define DT_REF 267
66#define DT_INCBIN 268
67
68
69
70
71#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
72typedef union YYSTYPE
73#line 37 "dtc-parser.y"
74{
75 char *propnodename;
76 char *literal;
77 char *labelref;
78 unsigned int cbase;
79 uint8_t byte;
80 struct data data;
81
82 uint64_t addr;
83 cell_t cell;
84 struct property *prop;
85 struct property *proplist;
86 struct node *node;
87 struct node *nodelist;
88 struct reserve_info *re;
89}
90/* Line 1489 of yacc.c. */
91#line 92 "dtc-parser.tab.h"
92 YYSTYPE;
93# define yystype YYSTYPE /* obsolescent; will be withdrawn */
94# define YYSTYPE_IS_DECLARED 1
95# define YYSTYPE_IS_TRIVIAL 1
96#endif
97
98extern YYSTYPE yylval;
99
100#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
101typedef struct YYLTYPE
102{
103 int first_line;
104 int first_column;
105 int last_line;
106 int last_column;
107} YYLTYPE;
108# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
109# define YYLTYPE_IS_DECLARED 1
110# define YYLTYPE_IS_TRIVIAL 1
111#endif
112
113extern YYLTYPE yylloc;
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
new file mode 100644
index 000000000000..b2ab562420ea
--- /dev/null
+++ b/scripts/dtc/dtc-parser.y
@@ -0,0 +1,379 @@
1/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
3 *
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
21%locations
22
23%{
24#include <stdio.h>
25
26#include "dtc.h"
27#include "srcpos.h"
28
29extern int yylex(void);
30
31extern struct boot_info *the_boot_info;
32extern int treesource_error;
33
34static unsigned long long eval_literal(const char *s, int base, int bits);
35%}
36
37%union {
38 char *propnodename;
39 char *literal;
40 char *labelref;
41 unsigned int cbase;
42 uint8_t byte;
43 struct data data;
44
45 uint64_t addr;
46 cell_t cell;
47 struct property *prop;
48 struct property *proplist;
49 struct node *node;
50 struct node *nodelist;
51 struct reserve_info *re;
52}
53
54%token DT_V1
55%token DT_MEMRESERVE
56%token <propnodename> DT_PROPNODENAME
57%token <literal> DT_LITERAL
58%token <literal> DT_LEGACYLITERAL
59%token <cbase> DT_BASE
60%token <byte> DT_BYTE
61%token <data> DT_STRING
62%token <labelref> DT_LABEL
63%token <labelref> DT_REF
64%token DT_INCBIN
65
66%type <data> propdata
67%type <data> propdataprefix
68%type <re> memreserve
69%type <re> memreserves
70%type <re> v0_memreserve
71%type <re> v0_memreserves
72%type <addr> addr
73%type <data> celllist
74%type <cbase> cellbase
75%type <cell> cellval
76%type <data> bytestring
77%type <prop> propdef
78%type <proplist> proplist
79
80%type <node> devicetree
81%type <node> nodedef
82%type <node> subnode
83%type <nodelist> subnodes
84%type <labelref> label
85
86%%
87
88sourcefile:
89 DT_V1 ';' memreserves devicetree
90 {
91 the_boot_info = build_boot_info($3, $4, 0);
92 }
93 | v0_memreserves devicetree
94 {
95 the_boot_info = build_boot_info($1, $2, 0);
96 }
97 ;
98
99memreserves:
100 /* empty */
101 {
102 $$ = NULL;
103 }
104 | memreserve memreserves
105 {
106 $$ = chain_reserve_entry($1, $2);
107 }
108 ;
109
110memreserve:
111 label DT_MEMRESERVE addr addr ';'
112 {
113 $$ = build_reserve_entry($3, $4, $1);
114 }
115 ;
116
117v0_memreserves:
118 /* empty */
119 {
120 $$ = NULL;
121 }
122 | v0_memreserve v0_memreserves
123 {
124 $$ = chain_reserve_entry($1, $2);
125 };
126 ;
127
128v0_memreserve:
129 memreserve
130 {
131 $$ = $1;
132 }
133 | label DT_MEMRESERVE addr '-' addr ';'
134 {
135 $$ = build_reserve_entry($3, $5 - $3 + 1, $1);
136 }
137 ;
138
139addr:
140 DT_LITERAL
141 {
142 $$ = eval_literal($1, 0, 64);
143 }
144 | DT_LEGACYLITERAL
145 {
146 $$ = eval_literal($1, 16, 64);
147 }
148 ;
149
150devicetree:
151 '/' nodedef
152 {
153 $$ = name_node($2, "", NULL);
154 }
155 ;
156
157nodedef:
158 '{' proplist subnodes '}' ';'
159 {
160 $$ = build_node($2, $3);
161 }
162 ;
163
164proplist:
165 /* empty */
166 {
167 $$ = NULL;
168 }
169 | proplist propdef
170 {
171 $$ = chain_property($2, $1);
172 }
173 ;
174
175propdef:
176 label DT_PROPNODENAME '=' propdata ';'
177 {
178 $$ = build_property($2, $4, $1);
179 }
180 | label DT_PROPNODENAME ';'
181 {
182 $$ = build_property($2, empty_data, $1);
183 }
184 ;
185
186propdata:
187 propdataprefix DT_STRING
188 {
189 $$ = data_merge($1, $2);
190 }
191 | propdataprefix '<' celllist '>'
192 {
193 $$ = data_merge($1, $3);
194 }
195 | propdataprefix '[' bytestring ']'
196 {
197 $$ = data_merge($1, $3);
198 }
199 | propdataprefix DT_REF
200 {
201 $$ = data_add_marker($1, REF_PATH, $2);
202 }
203 | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
204 {
205 struct search_path path = { srcpos_file->dir, NULL, NULL };
206 struct dtc_file *file = dtc_open_file($4.val, &path);
207 struct data d = empty_data;
208
209 if ($6 != 0)
210 if (fseek(file->file, $6, SEEK_SET) != 0)
211 yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
212 (unsigned long long)$6,
213 $4.val, strerror(errno));
214
215 d = data_copy_file(file->file, $8);
216
217 $$ = data_merge($1, d);
218 dtc_close_file(file);
219 }
220 | propdataprefix DT_INCBIN '(' DT_STRING ')'
221 {
222 struct search_path path = { srcpos_file->dir, NULL, NULL };
223 struct dtc_file *file = dtc_open_file($4.val, &path);
224 struct data d = empty_data;
225
226 d = data_copy_file(file->file, -1);
227
228 $$ = data_merge($1, d);
229 dtc_close_file(file);
230 }
231 | propdata DT_LABEL
232 {
233 $$ = data_add_marker($1, LABEL, $2);
234 }
235 ;
236
237propdataprefix:
238 /* empty */
239 {
240 $$ = empty_data;
241 }
242 | propdata ','
243 {
244 $$ = $1;
245 }
246 | propdataprefix DT_LABEL
247 {
248 $$ = data_add_marker($1, LABEL, $2);
249 }
250 ;
251
252celllist:
253 /* empty */
254 {
255 $$ = empty_data;
256 }
257 | celllist cellval
258 {
259 $$ = data_append_cell($1, $2);
260 }
261 | celllist DT_REF
262 {
263 $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
264 $2), -1);
265 }
266 | celllist DT_LABEL
267 {
268 $$ = data_add_marker($1, LABEL, $2);
269 }
270 ;
271
272cellbase:
273 /* empty */
274 {
275 $$ = 16;
276 }
277 | DT_BASE
278 ;
279
280cellval:
281 DT_LITERAL
282 {
283 $$ = eval_literal($1, 0, 32);
284 }
285 | cellbase DT_LEGACYLITERAL
286 {
287 $$ = eval_literal($2, $1, 32);
288 }
289 ;
290
291bytestring:
292 /* empty */
293 {
294 $$ = empty_data;
295 }
296 | bytestring DT_BYTE
297 {
298 $$ = data_append_byte($1, $2);
299 }
300 | bytestring DT_LABEL
301 {
302 $$ = data_add_marker($1, LABEL, $2);
303 }
304 ;
305
306subnodes:
307 /* empty */
308 {
309 $$ = NULL;
310 }
311 | subnode subnodes
312 {
313 $$ = chain_node($1, $2);
314 }
315 | subnode propdef
316 {
317 yyerror("syntax error: properties must precede subnodes");
318 YYERROR;
319 }
320 ;
321
322subnode:
323 label DT_PROPNODENAME nodedef
324 {
325 $$ = name_node($3, $2, $1);
326 }
327 ;
328
329label:
330 /* empty */
331 {
332 $$ = NULL;
333 }
334 | DT_LABEL
335 {
336 $$ = $1;
337 }
338 ;
339
340%%
341
342void yyerrorf(char const *s, ...)
343{
344 const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
345 va_list va;
346 va_start(va, s);
347
348 if (strcmp(fname, "-") == 0)
349 fname = "stdin";
350
351 fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
352 vfprintf(stderr, s, va);
353 fprintf(stderr, "\n");
354
355 treesource_error = 1;
356 va_end(va);
357}
358
359void yyerror (char const *s)
360{
361 yyerrorf("%s", s);
362}
363
364static unsigned long long eval_literal(const char *s, int base, int bits)
365{
366 unsigned long long val;
367 char *e;
368
369 errno = 0;
370 val = strtoull(s, &e, base);
371 if (*e)
372 yyerror("bad characters in literal");
373 else if ((errno == ERANGE)
374 || ((bits < 64) && (val >= (1ULL << bits))))
375 yyerror("literal out of range");
376 else if (errno != 0)
377 yyerror("bad literal");
378 return val;
379}
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
new file mode 100644
index 000000000000..d8fd43b4ac1a
--- /dev/null
+++ b/scripts/dtc/dtc.c
@@ -0,0 +1,226 @@
1/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
3 *
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
21#include "dtc.h"
22#include "srcpos.h"
23
24#include "version_gen.h"
25
26/*
27 * Command line options
28 */
29int quiet; /* Level of quietness */
30int reservenum; /* Number of memory reservation slots */
31int minsize; /* Minimum blob size */
32int padsize; /* Additional padding to blob */
33
34char *join_path(const char *path, const char *name)
35{
36 int lenp = strlen(path);
37 int lenn = strlen(name);
38 int len;
39 int needslash = 1;
40 char *str;
41
42 len = lenp + lenn + 2;
43 if ((lenp > 0) && (path[lenp-1] == '/')) {
44 needslash = 0;
45 len--;
46 }
47
48 str = xmalloc(len);
49 memcpy(str, path, lenp);
50 if (needslash) {
51 str[lenp] = '/';
52 lenp++;
53 }
54 memcpy(str+lenp, name, lenn+1);
55 return str;
56}
57
58static void fill_fullpaths(struct node *tree, const char *prefix)
59{
60 struct node *child;
61 const char *unit;
62
63 tree->fullpath = join_path(prefix, tree->name);
64
65 unit = strchr(tree->name, '@');
66 if (unit)
67 tree->basenamelen = unit - tree->name;
68 else
69 tree->basenamelen = strlen(tree->name);
70
71 for_each_child(tree, child)
72 fill_fullpaths(child, tree->fullpath);
73}
74
75static void __attribute__ ((noreturn)) usage(void)
76{
77 fprintf(stderr, "Usage:\n");
78 fprintf(stderr, "\tdtc [options] <input file>\n");
79 fprintf(stderr, "\nOptions:\n");
80 fprintf(stderr, "\t-h\n");
81 fprintf(stderr, "\t\tThis help text\n");
82 fprintf(stderr, "\t-q\n");
83 fprintf(stderr, "\t\tQuiet: -q suppress warnings, -qq errors, -qqq all\n");
84 fprintf(stderr, "\t-I <input format>\n");
85 fprintf(stderr, "\t\tInput formats are:\n");
86 fprintf(stderr, "\t\t\tdts - device tree source text\n");
87 fprintf(stderr, "\t\t\tdtb - device tree blob\n");
88 fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n");
89 fprintf(stderr, "\t-o <output file>\n");
90 fprintf(stderr, "\t-O <output format>\n");
91 fprintf(stderr, "\t\tOutput formats are:\n");
92 fprintf(stderr, "\t\t\tdts - device tree source text\n");
93 fprintf(stderr, "\t\t\tdtb - device tree blob\n");
94 fprintf(stderr, "\t\t\tasm - assembler source\n");
95 fprintf(stderr, "\t-V <output version>\n");
96 fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION);
97 fprintf(stderr, "\t-R <number>\n");
98 fprintf(stderr, "\t\tMake space for <number> reserve map entries (relevant for \n\t\tdtb and asm output only)\n");
99 fprintf(stderr, "\t-S <bytes>\n");
100 fprintf(stderr, "\t\tMake the blob at least <bytes> long (extra space)\n");
101 fprintf(stderr, "\t-p <bytes>\n");
102 fprintf(stderr, "\t\tAdd padding to the blob of <bytes> long (extra space)\n");
103 fprintf(stderr, "\t-b <number>\n");
104 fprintf(stderr, "\t\tSet the physical boot cpu\n");
105 fprintf(stderr, "\t-f\n");
106 fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
107 fprintf(stderr, "\t-v\n");
108 fprintf(stderr, "\t\tPrint DTC version and exit\n");
109 exit(3);
110}
111
112int main(int argc, char *argv[])
113{
114 struct boot_info *bi;
115 const char *inform = "dts";
116 const char *outform = "dts";
117 const char *outname = "-";
118 int force = 0, check = 0;
119 const char *arg;
120 int opt;
121 FILE *outf = NULL;
122 int outversion = DEFAULT_FDT_VERSION;
123 long long cmdline_boot_cpuid = -1;
124
125 quiet = 0;
126 reservenum = 0;
127 minsize = 0;
128 padsize = 0;
129
130 while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:v")) != EOF) {
131 switch (opt) {
132 case 'I':
133 inform = optarg;
134 break;
135 case 'O':
136 outform = optarg;
137 break;
138 case 'o':
139 outname = optarg;
140 break;
141 case 'V':
142 outversion = strtol(optarg, NULL, 0);
143 break;
144 case 'R':
145 reservenum = strtol(optarg, NULL, 0);
146 break;
147 case 'S':
148 minsize = strtol(optarg, NULL, 0);
149 break;
150 case 'p':
151 padsize = strtol(optarg, NULL, 0);
152 break;
153 case 'f':
154 force = 1;
155 break;
156 case 'c':
157 check = 1;
158 break;
159 case 'q':
160 quiet++;
161 break;
162 case 'b':
163 cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
164 break;
165 case 'v':
166 printf("Version: %s\n", DTC_VERSION);
167 exit(0);
168 case 'h':
169 default:
170 usage();
171 }
172 }
173
174 if (argc > (optind+1))
175 usage();
176 else if (argc < (optind+1))
177 arg = "-";
178 else
179 arg = argv[optind];
180
181 /* minsize and padsize are mutually exclusive */
182 if (minsize && padsize)
183 die("Can't set both -p and -S\n");
184
185 fprintf(stderr, "DTC: %s->%s on file \"%s\"\n",
186 inform, outform, arg);
187
188 if (streq(inform, "dts"))
189 bi = dt_from_source(arg);
190 else if (streq(inform, "fs"))
191 bi = dt_from_fs(arg);
192 else if(streq(inform, "dtb"))
193 bi = dt_from_blob(arg);
194 else
195 die("Unknown input format \"%s\"\n", inform);
196
197 if (cmdline_boot_cpuid != -1)
198 bi->boot_cpuid_phys = cmdline_boot_cpuid;
199
200 fill_fullpaths(bi->dt, "");
201 process_checks(force, bi);
202
203
204 if (streq(outname, "-")) {
205 outf = stdout;
206 } else {
207 outf = fopen(outname, "w");
208 if (! outf)
209 die("Couldn't open output file %s: %s\n",
210 outname, strerror(errno));
211 }
212
213 if (streq(outform, "dts")) {
214 dt_to_source(outf, bi);
215 } else if (streq(outform, "dtb")) {
216 dt_to_blob(outf, bi, outversion);
217 } else if (streq(outform, "asm")) {
218 dt_to_asm(outf, bi, outversion);
219 } else if (streq(outform, "null")) {
220 /* do nothing */
221 } else {
222 die("Unknown output format \"%s\"\n", outform);
223 }
224
225 exit(0);
226}
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
new file mode 100644
index 000000000000..08d54c870086
--- /dev/null
+++ b/scripts/dtc/dtc.h
@@ -0,0 +1,246 @@
1#ifndef _DTC_H
2#define _DTC_H
3
4/*
5 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
6 *
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 */
23
24#include <stdio.h>
25#include <string.h>
26#include <stdlib.h>
27#include <stdint.h>
28#include <stdarg.h>
29#include <assert.h>
30#include <ctype.h>
31#include <errno.h>
32#include <unistd.h>
33
34#include <libfdt_env.h>
35#include <fdt.h>
36
37#define DEFAULT_FDT_VERSION 17
38/*
39 * Command line options
40 */
41extern int quiet; /* Level of quietness */
42extern int reservenum; /* Number of memory reservation slots */
43extern int minsize; /* Minimum blob size */
44extern int padsize; /* Additional padding to blob */
45
46static inline void __attribute__((noreturn)) die(char * str, ...)
47{
48 va_list ap;
49
50 va_start(ap, str);
51 fprintf(stderr, "FATAL ERROR: ");
52 vfprintf(stderr, str, ap);
53 exit(1);
54}
55
56static inline void *xmalloc(size_t len)
57{
58 void *new = malloc(len);
59
60 if (! new)
61 die("malloc() failed\n");
62
63 return new;
64}
65
66static inline void *xrealloc(void *p, size_t len)
67{
68 void *new = realloc(p, len);
69
70 if (! new)
71 die("realloc() failed (len=%d)\n", len);
72
73 return new;
74}
75
76typedef uint32_t cell_t;
77
78
79#define streq(a, b) (strcmp((a), (b)) == 0)
80#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
81
82#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
83#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
84
85/* Data blobs */
86enum markertype {
87 REF_PHANDLE,
88 REF_PATH,
89 LABEL,
90};
91
92struct marker {
93 enum markertype type;
94 int offset;
95 char *ref;
96 struct marker *next;
97};
98
99struct data {
100 int len;
101 char *val;
102 struct marker *markers;
103};
104
105
106#define empty_data ((struct data){ /* all .members = 0 or NULL */ })
107
108#define for_each_marker(m) \
109 for (; (m); (m) = (m)->next)
110#define for_each_marker_of_type(m, t) \
111 for_each_marker(m) \
112 if ((m)->type == (t))
113
114void data_free(struct data d);
115
116struct data data_grow_for(struct data d, int xlen);
117
118struct data data_copy_mem(const char *mem, int len);
119struct data data_copy_escape_string(const char *s, int len);
120struct data data_copy_file(FILE *f, size_t len);
121
122struct data data_append_data(struct data d, const void *p, int len);
123struct data data_insert_at_marker(struct data d, struct marker *m,
124 const void *p, int len);
125struct data data_merge(struct data d1, struct data d2);
126struct data data_append_cell(struct data d, cell_t word);
127struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
128struct data data_append_addr(struct data d, uint64_t addr);
129struct data data_append_byte(struct data d, uint8_t byte);
130struct data data_append_zeroes(struct data d, int len);
131struct data data_append_align(struct data d, int align);
132
133struct data data_add_marker(struct data d, enum markertype type, char *ref);
134
135int data_is_one_string(struct data d);
136
137/* DT constraints */
138
139#define MAX_PROPNAME_LEN 31
140#define MAX_NODENAME_LEN 31
141
142/* Live trees */
143struct property {
144 char *name;
145 struct data val;
146
147 struct property *next;
148
149 char *label;
150};
151
152struct node {
153 char *name;
154 struct property *proplist;
155 struct node *children;
156
157 struct node *parent;
158 struct node *next_sibling;
159
160 char *fullpath;
161 int basenamelen;
162
163 cell_t phandle;
164 int addr_cells, size_cells;
165
166 char *label;
167};
168
169#define for_each_property(n, p) \
170 for ((p) = (n)->proplist; (p); (p) = (p)->next)
171
172#define for_each_child(n, c) \
173 for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
174
175struct property *build_property(char *name, struct data val, char *label);
176struct property *chain_property(struct property *first, struct property *list);
177struct property *reverse_properties(struct property *first);
178
179struct node *build_node(struct property *proplist, struct node *children);
180struct node *name_node(struct node *node, char *name, char *label);
181struct node *chain_node(struct node *first, struct node *list);
182
183void add_property(struct node *node, struct property *prop);
184void add_child(struct node *parent, struct node *child);
185
186const char *get_unitname(struct node *node);
187struct property *get_property(struct node *node, const char *propname);
188cell_t propval_cell(struct property *prop);
189struct node *get_subnode(struct node *node, const char *nodename);
190struct node *get_node_by_path(struct node *tree, const char *path);
191struct node *get_node_by_label(struct node *tree, const char *label);
192struct node *get_node_by_phandle(struct node *tree, cell_t phandle);
193struct node *get_node_by_ref(struct node *tree, const char *ref);
194cell_t get_node_phandle(struct node *root, struct node *node);
195
196/* Boot info (tree plus memreserve information */
197
198struct reserve_info {
199 struct fdt_reserve_entry re;
200
201 struct reserve_info *next;
202
203 char *label;
204};
205
206struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len, char *label);
207struct reserve_info *chain_reserve_entry(struct reserve_info *first,
208 struct reserve_info *list);
209struct reserve_info *add_reserve_entry(struct reserve_info *list,
210 struct reserve_info *new);
211
212
213struct boot_info {
214 struct reserve_info *reservelist;
215 struct node *dt; /* the device tree */
216 uint32_t boot_cpuid_phys;
217};
218
219struct boot_info *build_boot_info(struct reserve_info *reservelist,
220 struct node *tree, uint32_t boot_cpuid_phys);
221
222/* Checks */
223
224void process_checks(int force, struct boot_info *bi);
225
226/* Flattened trees */
227
228void dt_to_blob(FILE *f, struct boot_info *bi, int version);
229void dt_to_asm(FILE *f, struct boot_info *bi, int version);
230
231struct boot_info *dt_from_blob(const char *fname);
232
233/* Tree source */
234
235void dt_to_source(FILE *f, struct boot_info *bi);
236struct boot_info *dt_from_source(const char *f);
237
238/* FS trees */
239
240struct boot_info *dt_from_fs(const char *dirname);
241
242/* misc */
243
244char *join_path(const char *path, const char *name);
245
246#endif /* _DTC_H */
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
new file mode 100644
index 000000000000..76acd28c068d
--- /dev/null
+++ b/scripts/dtc/flattree.c
@@ -0,0 +1,906 @@
1/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
3 *
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
21#include "dtc.h"
22#include "srcpos.h"
23
24#define FTF_FULLPATH 0x1
25#define FTF_VARALIGN 0x2
26#define FTF_NAMEPROPS 0x4
27#define FTF_BOOTCPUID 0x8
28#define FTF_STRTABSIZE 0x10
29#define FTF_STRUCTSIZE 0x20
30#define FTF_NOPS 0x40
31
32static struct version_info {
33 int version;
34 int last_comp_version;
35 int hdr_size;
36 int flags;
37} version_table[] = {
38 {1, 1, FDT_V1_SIZE,
39 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS},
40 {2, 1, FDT_V2_SIZE,
41 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID},
42 {3, 1, FDT_V3_SIZE,
43 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE},
44 {16, 16, FDT_V3_SIZE,
45 FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_NOPS},
46 {17, 16, FDT_V17_SIZE,
47 FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS},
48};
49
50struct emitter {
51 void (*cell)(void *, cell_t);
52 void (*string)(void *, char *, int);
53 void (*align)(void *, int);
54 void (*data)(void *, struct data);
55 void (*beginnode)(void *, const char *);
56 void (*endnode)(void *, const char *);
57 void (*property)(void *, const char *);
58};
59
60static void bin_emit_cell(void *e, cell_t val)
61{
62 struct data *dtbuf = e;
63
64 *dtbuf = data_append_cell(*dtbuf, val);
65}
66
67static void bin_emit_string(void *e, char *str, int len)
68{
69 struct data *dtbuf = e;
70
71 if (len == 0)
72 len = strlen(str);
73
74 *dtbuf = data_append_data(*dtbuf, str, len);
75 *dtbuf = data_append_byte(*dtbuf, '\0');
76}
77
78static void bin_emit_align(void *e, int a)
79{
80 struct data *dtbuf = e;
81
82 *dtbuf = data_append_align(*dtbuf, a);
83}
84
85static void bin_emit_data(void *e, struct data d)
86{
87 struct data *dtbuf = e;
88
89 *dtbuf = data_append_data(*dtbuf, d.val, d.len);
90}
91
92static void bin_emit_beginnode(void *e, const char *label)
93{
94 bin_emit_cell(e, FDT_BEGIN_NODE);
95}
96
97static void bin_emit_endnode(void *e, const char *label)
98{
99 bin_emit_cell(e, FDT_END_NODE);
100}
101
102static void bin_emit_property(void *e, const char *label)
103{
104 bin_emit_cell(e, FDT_PROP);
105}
106
107static struct emitter bin_emitter = {
108 .cell = bin_emit_cell,
109 .string = bin_emit_string,
110 .align = bin_emit_align,
111 .data = bin_emit_data,
112 .beginnode = bin_emit_beginnode,
113 .endnode = bin_emit_endnode,
114 .property = bin_emit_property,
115};
116
117static void emit_label(FILE *f, const char *prefix, const char *label)
118{
119 fprintf(f, "\t.globl\t%s_%s\n", prefix, label);
120 fprintf(f, "%s_%s:\n", prefix, label);
121 fprintf(f, "_%s_%s:\n", prefix, label);
122}
123
124static void emit_offset_label(FILE *f, const char *label, int offset)
125{
126 fprintf(f, "\t.globl\t%s\n", label);
127 fprintf(f, "%s\t= . + %d\n", label, offset);
128}
129
130static void asm_emit_cell(void *e, cell_t val)
131{
132 FILE *f = e;
133
134 fprintf(f, "\t.long\t0x%x\n", val);
135}
136
137static void asm_emit_string(void *e, char *str, int len)
138{
139 FILE *f = e;
140 char c = 0;
141
142 if (len != 0) {
143 /* XXX: ewww */
144 c = str[len];
145 str[len] = '\0';
146 }
147
148 fprintf(f, "\t.string\t\"%s\"\n", str);
149
150 if (len != 0) {
151 str[len] = c;
152 }
153}
154
155static void asm_emit_align(void *e, int a)
156{
157 FILE *f = e;
158
159 fprintf(f, "\t.balign\t%d\n", a);
160}
161
162static void asm_emit_data(void *e, struct data d)
163{
164 FILE *f = e;
165 int off = 0;
166 struct marker *m = d.markers;
167
168 for_each_marker_of_type(m, LABEL)
169 emit_offset_label(f, m->ref, m->offset);
170
171 while ((d.len - off) >= sizeof(uint32_t)) {
172 fprintf(f, "\t.long\t0x%x\n",
173 fdt32_to_cpu(*((uint32_t *)(d.val+off))));
174 off += sizeof(uint32_t);
175 }
176
177 while ((d.len - off) >= 1) {
178 fprintf(f, "\t.byte\t0x%hhx\n", d.val[off]);
179 off += 1;
180 }
181
182 assert(off == d.len);
183}
184
185static void asm_emit_beginnode(void *e, const char *label)
186{
187 FILE *f = e;
188
189 if (label) {
190 fprintf(f, "\t.globl\t%s\n", label);
191 fprintf(f, "%s:\n", label);
192 }
193 fprintf(f, "\t.long\tFDT_BEGIN_NODE\n");
194}
195
196static void asm_emit_endnode(void *e, const char *label)
197{
198 FILE *f = e;
199
200 fprintf(f, "\t.long\tFDT_END_NODE\n");
201 if (label) {
202 fprintf(f, "\t.globl\t%s_end\n", label);
203 fprintf(f, "%s_end:\n", label);
204 }
205}
206
207static void asm_emit_property(void *e, const char *label)
208{
209 FILE *f = e;
210
211 if (label) {
212 fprintf(f, "\t.globl\t%s\n", label);
213 fprintf(f, "%s:\n", label);
214 }
215 fprintf(f, "\t.long\tFDT_PROP\n");
216}
217
218static struct emitter asm_emitter = {
219 .cell = asm_emit_cell,
220 .string = asm_emit_string,
221 .align = asm_emit_align,
222 .data = asm_emit_data,
223 .beginnode = asm_emit_beginnode,
224 .endnode = asm_emit_endnode,
225 .property = asm_emit_property,
226};
227
228static int stringtable_insert(struct data *d, const char *str)
229{
230 int i;
231
232 /* FIXME: do this more efficiently? */
233
234 for (i = 0; i < d->len; i++) {
235 if (streq(str, d->val + i))
236 return i;
237 }
238
239 *d = data_append_data(*d, str, strlen(str)+1);
240 return i;
241}
242
243static void flatten_tree(struct node *tree, struct emitter *emit,
244 void *etarget, struct data *strbuf,
245 struct version_info *vi)
246{
247 struct property *prop;
248 struct node *child;
249 int seen_name_prop = 0;
250
251 emit->beginnode(etarget, tree->label);
252
253 if (vi->flags & FTF_FULLPATH)
254 emit->string(etarget, tree->fullpath, 0);
255 else
256 emit->string(etarget, tree->name, 0);
257
258 emit->align(etarget, sizeof(cell_t));
259
260 for_each_property(tree, prop) {
261 int nameoff;
262
263 if (streq(prop->name, "name"))
264 seen_name_prop = 1;
265
266 nameoff = stringtable_insert(strbuf, prop->name);
267
268 emit->property(etarget, prop->label);
269 emit->cell(etarget, prop->val.len);
270 emit->cell(etarget, nameoff);
271
272 if ((vi->flags & FTF_VARALIGN) && (prop->val.len >= 8))
273 emit->align(etarget, 8);
274
275 emit->data(etarget, prop->val);
276 emit->align(etarget, sizeof(cell_t));
277 }
278
279 if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) {
280 emit->property(etarget, NULL);
281 emit->cell(etarget, tree->basenamelen+1);
282 emit->cell(etarget, stringtable_insert(strbuf, "name"));
283
284 if ((vi->flags & FTF_VARALIGN) && ((tree->basenamelen+1) >= 8))
285 emit->align(etarget, 8);
286
287 emit->string(etarget, tree->name, tree->basenamelen);
288 emit->align(etarget, sizeof(cell_t));
289 }
290
291 for_each_child(tree, child) {
292 flatten_tree(child, emit, etarget, strbuf, vi);
293 }
294
295 emit->endnode(etarget, tree->label);
296}
297
298static struct data flatten_reserve_list(struct reserve_info *reservelist,
299 struct version_info *vi)
300{
301 struct reserve_info *re;
302 struct data d = empty_data;
303 static struct fdt_reserve_entry null_re = {0,0};
304 int j;
305
306 for (re = reservelist; re; re = re->next) {
307 d = data_append_re(d, &re->re);
308 }
309 /*
310 * Add additional reserved slots if the user asked for them.
311 */
312 for (j = 0; j < reservenum; j++) {
313 d = data_append_re(d, &null_re);
314 }
315
316 return d;
317}
318
319static void make_fdt_header(struct fdt_header *fdt,
320 struct version_info *vi,
321 int reservesize, int dtsize, int strsize,
322 int boot_cpuid_phys)
323{
324 int reserve_off;
325
326 reservesize += sizeof(struct fdt_reserve_entry);
327
328 memset(fdt, 0xff, sizeof(*fdt));
329
330 fdt->magic = cpu_to_fdt32(FDT_MAGIC);
331 fdt->version = cpu_to_fdt32(vi->version);
332 fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version);
333
334 /* Reserve map should be doubleword aligned */
335 reserve_off = ALIGN(vi->hdr_size, 8);
336
337 fdt->off_mem_rsvmap = cpu_to_fdt32(reserve_off);
338 fdt->off_dt_struct = cpu_to_fdt32(reserve_off + reservesize);
339 fdt->off_dt_strings = cpu_to_fdt32(reserve_off + reservesize
340 + dtsize);
341 fdt->totalsize = cpu_to_fdt32(reserve_off + reservesize + dtsize + strsize);
342
343 if (vi->flags & FTF_BOOTCPUID)
344 fdt->boot_cpuid_phys = cpu_to_fdt32(boot_cpuid_phys);
345 if (vi->flags & FTF_STRTABSIZE)
346 fdt->size_dt_strings = cpu_to_fdt32(strsize);
347 if (vi->flags & FTF_STRUCTSIZE)
348 fdt->size_dt_struct = cpu_to_fdt32(dtsize);
349}
350
351void dt_to_blob(FILE *f, struct boot_info *bi, int version)
352{
353 struct version_info *vi = NULL;
354 int i;
355 struct data blob = empty_data;
356 struct data reservebuf = empty_data;
357 struct data dtbuf = empty_data;
358 struct data strbuf = empty_data;
359 struct fdt_header fdt;
360 int padlen = 0;
361
362 for (i = 0; i < ARRAY_SIZE(version_table); i++) {
363 if (version_table[i].version == version)
364 vi = &version_table[i];
365 }
366 if (!vi)
367 die("Unknown device tree blob version %d\n", version);
368
369 flatten_tree(bi->dt, &bin_emitter, &dtbuf, &strbuf, vi);
370 bin_emit_cell(&dtbuf, FDT_END);
371
372 reservebuf = flatten_reserve_list(bi->reservelist, vi);
373
374 /* Make header */
375 make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
376 bi->boot_cpuid_phys);
377
378 /*
379 * If the user asked for more space than is used, adjust the totalsize.
380 */
381 if (minsize > 0) {
382 padlen = minsize - fdt32_to_cpu(fdt.totalsize);
383 if ((padlen < 0) && (quiet < 1))
384 fprintf(stderr,
385 "Warning: blob size %d >= minimum size %d\n",
386 fdt32_to_cpu(fdt.totalsize), minsize);
387 }
388
389 if (padsize > 0)
390 padlen = padsize;
391
392 if (padlen > 0) {
393 int tsize = fdt32_to_cpu(fdt.totalsize);
394 tsize += padlen;
395 fdt.totalsize = cpu_to_fdt32(tsize);
396 }
397
398 /*
399 * Assemble the blob: start with the header, add with alignment
400 * the reserve buffer, add the reserve map terminating zeroes,
401 * the device tree itself, and finally the strings.
402 */
403 blob = data_append_data(blob, &fdt, vi->hdr_size);
404 blob = data_append_align(blob, 8);
405 blob = data_merge(blob, reservebuf);
406 blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry));
407 blob = data_merge(blob, dtbuf);
408 blob = data_merge(blob, strbuf);
409
410 /*
411 * If the user asked for more space than is used, pad out the blob.
412 */
413 if (padlen > 0)
414 blob = data_append_zeroes(blob, padlen);
415
416 fwrite(blob.val, blob.len, 1, f);
417
418 if (ferror(f))
419 die("Error writing device tree blob: %s\n", strerror(errno));
420
421 /*
422 * data_merge() frees the right-hand element so only the blob
423 * remains to be freed.
424 */
425 data_free(blob);
426}
427
428static void dump_stringtable_asm(FILE *f, struct data strbuf)
429{
430 const char *p;
431 int len;
432
433 p = strbuf.val;
434
435 while (p < (strbuf.val + strbuf.len)) {
436 len = strlen(p);
437 fprintf(f, "\t.string \"%s\"\n", p);
438 p += len+1;
439 }
440}
441
442void dt_to_asm(FILE *f, struct boot_info *bi, int version)
443{
444 struct version_info *vi = NULL;
445 int i;
446 struct data strbuf = empty_data;
447 struct reserve_info *re;
448 const char *symprefix = "dt";
449
450 for (i = 0; i < ARRAY_SIZE(version_table); i++) {
451 if (version_table[i].version == version)
452 vi = &version_table[i];
453 }
454 if (!vi)
455 die("Unknown device tree blob version %d\n", version);
456
457 fprintf(f, "/* autogenerated by dtc, do not edit */\n\n");
458 fprintf(f, "#define FDT_MAGIC 0x%x\n", FDT_MAGIC);
459 fprintf(f, "#define FDT_BEGIN_NODE 0x%x\n", FDT_BEGIN_NODE);
460 fprintf(f, "#define FDT_END_NODE 0x%x\n", FDT_END_NODE);
461 fprintf(f, "#define FDT_PROP 0x%x\n", FDT_PROP);
462 fprintf(f, "#define FDT_END 0x%x\n", FDT_END);
463 fprintf(f, "\n");
464
465 emit_label(f, symprefix, "blob_start");
466 emit_label(f, symprefix, "header");
467 fprintf(f, "\t.long\tFDT_MAGIC\t\t\t\t/* magic */\n");
468 fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start\t/* totalsize */\n",
469 symprefix, symprefix);
470 fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start\t/* off_dt_struct */\n",
471 symprefix, symprefix);
472 fprintf(f, "\t.long\t_%s_strings_start - _%s_blob_start\t/* off_dt_strings */\n",
473 symprefix, symprefix);
474 fprintf(f, "\t.long\t_%s_reserve_map - _%s_blob_start\t/* off_dt_strings */\n",
475 symprefix, symprefix);
476 fprintf(f, "\t.long\t%d\t\t\t\t\t/* version */\n", vi->version);
477 fprintf(f, "\t.long\t%d\t\t\t\t\t/* last_comp_version */\n",
478 vi->last_comp_version);
479
480 if (vi->flags & FTF_BOOTCPUID)
481 fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n",
482 bi->boot_cpuid_phys);
483
484 if (vi->flags & FTF_STRTABSIZE)
485 fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n",
486 symprefix, symprefix);
487
488 if (vi->flags & FTF_STRUCTSIZE)
489 fprintf(f, "\t.long\t_%s_struct_end - _%s_struct_start\t/* size_dt_struct */\n",
490 symprefix, symprefix);
491
492 /*
493 * Reserve map entries.
494 * Align the reserve map to a doubleword boundary.
495 * Each entry is an (address, size) pair of u64 values.
496 * Always supply a zero-sized temination entry.
497 */
498 asm_emit_align(f, 8);
499 emit_label(f, symprefix, "reserve_map");
500
501 fprintf(f, "/* Memory reserve map from source file */\n");
502
503 /*
504 * Use .long on high and low halfs of u64s to avoid .quad
505 * as it appears .quad isn't available in some assemblers.
506 */
507 for (re = bi->reservelist; re; re = re->next) {
508 if (re->label) {
509 fprintf(f, "\t.globl\t%s\n", re->label);
510 fprintf(f, "%s:\n", re->label);
511 }
512 fprintf(f, "\t.long\t0x%08x, 0x%08x\n",
513 (unsigned int)(re->re.address >> 32),
514 (unsigned int)(re->re.address & 0xffffffff));
515 fprintf(f, "\t.long\t0x%08x, 0x%08x\n",
516 (unsigned int)(re->re.size >> 32),
517 (unsigned int)(re->re.size & 0xffffffff));
518 }
519 for (i = 0; i < reservenum; i++) {
520 fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
521 }
522
523 fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
524
525 emit_label(f, symprefix, "struct_start");
526 flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi);
527 fprintf(f, "\t.long\tFDT_END\n");
528 emit_label(f, symprefix, "struct_end");
529
530 emit_label(f, symprefix, "strings_start");
531 dump_stringtable_asm(f, strbuf);
532 emit_label(f, symprefix, "strings_end");
533
534 emit_label(f, symprefix, "blob_end");
535
536 /*
537 * If the user asked for more space than is used, pad it out.
538 */
539 if (minsize > 0) {
540 fprintf(f, "\t.space\t%d - (_%s_blob_end - _%s_blob_start), 0\n",
541 minsize, symprefix, symprefix);
542 }
543 if (padsize > 0) {
544 fprintf(f, "\t.space\t%d, 0\n", padsize);
545 }
546 emit_label(f, symprefix, "blob_abs_end");
547
548 data_free(strbuf);
549}
550
551struct inbuf {
552 char *base, *limit, *ptr;
553};
554
555static void inbuf_init(struct inbuf *inb, void *base, void *limit)
556{
557 inb->base = base;
558 inb->limit = limit;
559 inb->ptr = inb->base;
560}
561
562static void flat_read_chunk(struct inbuf *inb, void *p, int len)
563{
564 if ((inb->ptr + len) > inb->limit)
565 die("Premature end of data parsing flat device tree\n");
566
567 memcpy(p, inb->ptr, len);
568
569 inb->ptr += len;
570}
571
572static uint32_t flat_read_word(struct inbuf *inb)
573{
574 uint32_t val;
575
576 assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
577
578 flat_read_chunk(inb, &val, sizeof(val));
579
580 return fdt32_to_cpu(val);
581}
582
583static void flat_realign(struct inbuf *inb, int align)
584{
585 int off = inb->ptr - inb->base;
586
587 inb->ptr = inb->base + ALIGN(off, align);
588 if (inb->ptr > inb->limit)
589 die("Premature end of data parsing flat device tree\n");
590}
591
592static char *flat_read_string(struct inbuf *inb)
593{
594 int len = 0;
595 const char *p = inb->ptr;
596 char *str;
597
598 do {
599 if (p >= inb->limit)
600 die("Premature end of data parsing flat device tree\n");
601 len++;
602 } while ((*p++) != '\0');
603
604 str = strdup(inb->ptr);
605
606 inb->ptr += len;
607
608 flat_realign(inb, sizeof(uint32_t));
609
610 return str;
611}
612
613static struct data flat_read_data(struct inbuf *inb, int len)
614{
615 struct data d = empty_data;
616
617 if (len == 0)
618 return empty_data;
619
620 d = data_grow_for(d, len);
621 d.len = len;
622
623 flat_read_chunk(inb, d.val, len);
624
625 flat_realign(inb, sizeof(uint32_t));
626
627 return d;
628}
629
630static char *flat_read_stringtable(struct inbuf *inb, int offset)
631{
632 const char *p;
633
634 p = inb->base + offset;
635 while (1) {
636 if (p >= inb->limit || p < inb->base)
637 die("String offset %d overruns string table\n",
638 offset);
639
640 if (*p == '\0')
641 break;
642
643 p++;
644 }
645
646 return strdup(inb->base + offset);
647}
648
649static struct property *flat_read_property(struct inbuf *dtbuf,
650 struct inbuf *strbuf, int flags)
651{
652 uint32_t proplen, stroff;
653 char *name;
654 struct data val;
655
656 proplen = flat_read_word(dtbuf);
657 stroff = flat_read_word(dtbuf);
658
659 name = flat_read_stringtable(strbuf, stroff);
660
661 if ((flags & FTF_VARALIGN) && (proplen >= 8))
662 flat_realign(dtbuf, 8);
663
664 val = flat_read_data(dtbuf, proplen);
665
666 return build_property(name, val, NULL);
667}
668
669
670static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
671{
672 struct reserve_info *reservelist = NULL;
673 struct reserve_info *new;
674 const char *p;
675 struct fdt_reserve_entry re;
676
677 /*
678 * Each entry is a pair of u64 (addr, size) values for 4 cell_t's.
679 * List terminates at an entry with size equal to zero.
680 *
681 * First pass, count entries.
682 */
683 p = inb->ptr;
684 while (1) {
685 flat_read_chunk(inb, &re, sizeof(re));
686 re.address = fdt64_to_cpu(re.address);
687 re.size = fdt64_to_cpu(re.size);
688 if (re.size == 0)
689 break;
690
691 new = build_reserve_entry(re.address, re.size, NULL);
692 reservelist = add_reserve_entry(reservelist, new);
693 }
694
695 return reservelist;
696}
697
698
699static char *nodename_from_path(const char *ppath, const char *cpath)
700{
701 int plen;
702
703 plen = strlen(ppath);
704
705 if (!strneq(ppath, cpath, plen))
706 die("Path \"%s\" is not valid as a child of \"%s\"\n",
707 cpath, ppath);
708
709 /* root node is a special case */
710 if (!streq(ppath, "/"))
711 plen++;
712
713 return strdup(cpath + plen);
714}
715
716static struct node *unflatten_tree(struct inbuf *dtbuf,
717 struct inbuf *strbuf,
718 const char *parent_flatname, int flags)
719{
720 struct node *node;
721 char *flatname;
722 uint32_t val;
723
724 node = build_node(NULL, NULL);
725
726 flatname = flat_read_string(dtbuf);
727
728 if (flags & FTF_FULLPATH)
729 node->name = nodename_from_path(parent_flatname, flatname);
730 else
731 node->name = flatname;
732
733 do {
734 struct property *prop;
735 struct node *child;
736
737 val = flat_read_word(dtbuf);
738 switch (val) {
739 case FDT_PROP:
740 if (node->children)
741 fprintf(stderr, "Warning: Flat tree input has "
742 "subnodes preceding a property.\n");
743 prop = flat_read_property(dtbuf, strbuf, flags);
744 add_property(node, prop);
745 break;
746
747 case FDT_BEGIN_NODE:
748 child = unflatten_tree(dtbuf,strbuf, flatname, flags);
749 add_child(node, child);
750 break;
751
752 case FDT_END_NODE:
753 break;
754
755 case FDT_END:
756 die("Premature FDT_END in device tree blob\n");
757 break;
758
759 case FDT_NOP:
760 if (!(flags & FTF_NOPS))
761 fprintf(stderr, "Warning: NOP tag found in flat tree"
762 " version <16\n");
763
764 /* Ignore */
765 break;
766
767 default:
768 die("Invalid opcode word %08x in device tree blob\n",
769 val);
770 }
771 } while (val != FDT_END_NODE);
772
773 return node;
774}
775
776
777struct boot_info *dt_from_blob(const char *fname)
778{
779 struct dtc_file *dtcf;
780 uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
781 uint32_t off_dt, off_str, off_mem_rsvmap;
782 int rc;
783 char *blob;
784 struct fdt_header *fdt;
785 char *p;
786 struct inbuf dtbuf, strbuf;
787 struct inbuf memresvbuf;
788 int sizeleft;
789 struct reserve_info *reservelist;
790 struct node *tree;
791 uint32_t val;
792 int flags = 0;
793
794 dtcf = dtc_open_file(fname, NULL);
795
796 rc = fread(&magic, sizeof(magic), 1, dtcf->file);
797 if (ferror(dtcf->file))
798 die("Error reading DT blob magic number: %s\n",
799 strerror(errno));
800 if (rc < 1) {
801 if (feof(dtcf->file))
802 die("EOF reading DT blob magic number\n");
803 else
804 die("Mysterious short read reading magic number\n");
805 }
806
807 magic = fdt32_to_cpu(magic);
808 if (magic != FDT_MAGIC)
809 die("Blob has incorrect magic number\n");
810
811 rc = fread(&totalsize, sizeof(totalsize), 1, dtcf->file);
812 if (ferror(dtcf->file))
813 die("Error reading DT blob size: %s\n", strerror(errno));
814 if (rc < 1) {
815 if (feof(dtcf->file))
816 die("EOF reading DT blob size\n");
817 else
818 die("Mysterious short read reading blob size\n");
819 }
820
821 totalsize = fdt32_to_cpu(totalsize);
822 if (totalsize < FDT_V1_SIZE)
823 die("DT blob size (%d) is too small\n", totalsize);
824
825 blob = xmalloc(totalsize);
826
827 fdt = (struct fdt_header *)blob;
828 fdt->magic = cpu_to_fdt32(magic);
829 fdt->totalsize = cpu_to_fdt32(totalsize);
830
831 sizeleft = totalsize - sizeof(magic) - sizeof(totalsize);
832 p = blob + sizeof(magic) + sizeof(totalsize);
833
834 while (sizeleft) {
835 if (feof(dtcf->file))
836 die("EOF before reading %d bytes of DT blob\n",
837 totalsize);
838
839 rc = fread(p, 1, sizeleft, dtcf->file);
840 if (ferror(dtcf->file))
841 die("Error reading DT blob: %s\n",
842 strerror(errno));
843
844 sizeleft -= rc;
845 p += rc;
846 }
847
848 off_dt = fdt32_to_cpu(fdt->off_dt_struct);
849 off_str = fdt32_to_cpu(fdt->off_dt_strings);
850 off_mem_rsvmap = fdt32_to_cpu(fdt->off_mem_rsvmap);
851 version = fdt32_to_cpu(fdt->version);
852 boot_cpuid_phys = fdt32_to_cpu(fdt->boot_cpuid_phys);
853
854 if (off_mem_rsvmap >= totalsize)
855 die("Mem Reserve structure offset exceeds total size\n");
856
857 if (off_dt >= totalsize)
858 die("DT structure offset exceeds total size\n");
859
860 if (off_str > totalsize)
861 die("String table offset exceeds total size\n");
862
863 if (version >= 3) {
864 uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings);
865 if (off_str+size_str > totalsize)
866 die("String table extends past total size\n");
867 inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
868 } else {
869 inbuf_init(&strbuf, blob + off_str, blob + totalsize);
870 }
871
872 if (version >= 17) {
873 size_dt = fdt32_to_cpu(fdt->size_dt_struct);
874 if (off_dt+size_dt > totalsize)
875 die("Structure block extends past total size\n");
876 }
877
878 if (version < 16) {
879 flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN;
880 } else {
881 flags |= FTF_NOPS;
882 }
883
884 inbuf_init(&memresvbuf,
885 blob + off_mem_rsvmap, blob + totalsize);
886 inbuf_init(&dtbuf, blob + off_dt, blob + totalsize);
887
888 reservelist = flat_read_mem_reserve(&memresvbuf);
889
890 val = flat_read_word(&dtbuf);
891
892 if (val != FDT_BEGIN_NODE)
893 die("Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%08x)\n", val);
894
895 tree = unflatten_tree(&dtbuf, &strbuf, "", flags);
896
897 val = flat_read_word(&dtbuf);
898 if (val != FDT_END)
899 die("Device tree blob doesn't end with FDT_END\n");
900
901 free(blob);
902
903 dtc_close_file(dtcf);
904
905 return build_boot_info(reservelist, tree, boot_cpuid_phys);
906}
diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c
new file mode 100644
index 000000000000..766b2694d935
--- /dev/null
+++ b/scripts/dtc/fstree.c
@@ -0,0 +1,92 @@
1/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
3 *
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
21#include "dtc.h"
22
23#include <dirent.h>
24#include <sys/stat.h>
25
26static struct node *read_fstree(const char *dirname)
27{
28 DIR *d;
29 struct dirent *de;
30 struct stat st;
31 struct node *tree;
32
33 d = opendir(dirname);
34 if (!d)
35 die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));
36
37 tree = build_node(NULL, NULL);
38
39 while ((de = readdir(d)) != NULL) {
40 char *tmpnam;
41
42 if (streq(de->d_name, ".")
43 || streq(de->d_name, ".."))
44 continue;
45
46 tmpnam = join_path(dirname, de->d_name);
47
48 if (lstat(tmpnam, &st) < 0)
49 die("stat(%s): %s\n", tmpnam, strerror(errno));
50
51 if (S_ISREG(st.st_mode)) {
52 struct property *prop;
53 FILE *pfile;
54
55 pfile = fopen(tmpnam, "r");
56 if (! pfile) {
57 fprintf(stderr,
58 "WARNING: Cannot open %s: %s\n",
59 tmpnam, strerror(errno));
60 } else {
61 prop = build_property(strdup(de->d_name),
62 data_copy_file(pfile,
63 st.st_size),
64 NULL);
65 add_property(tree, prop);
66 fclose(pfile);
67 }
68 } else if (S_ISDIR(st.st_mode)) {
69 struct node *newchild;
70
71 newchild = read_fstree(tmpnam);
72 newchild = name_node(newchild, strdup(de->d_name),
73 NULL);
74 add_child(tree, newchild);
75 }
76
77 free(tmpnam);
78 }
79
80 return tree;
81}
82
83struct boot_info *dt_from_fs(const char *dirname)
84{
85 struct node *tree;
86
87 tree = read_fstree(dirname);
88 tree = name_node(tree, "", NULL);
89
90 return build_boot_info(NULL, tree, 0);
91}
92
diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt
new file mode 100644
index 000000000000..6c42acfa21ec
--- /dev/null
+++ b/scripts/dtc/libfdt/Makefile.libfdt
@@ -0,0 +1,8 @@
1# Makefile.libfdt
2#
3# This is not a complete Makefile of itself. Instead, it is designed to
4# be easily embeddable into other systems of Makefiles.
5#
6LIBFDT_INCLUDES = fdt.h libfdt.h
7LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
8LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
new file mode 100644
index 000000000000..2acaec5923ae
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt.c
@@ -0,0 +1,201 @@
1/*
2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2006 David Gibson, IBM Corporation.
4 *
5 * libfdt is dual licensed: you can use it either under the terms of
6 * the GPL, or the BSD license, at your option.
7 *
8 * a) This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 * MA 02110-1301 USA
22 *
23 * Alternatively,
24 *
25 * b) Redistribution and use in source and binary forms, with or
26 * without modification, are permitted provided that the following
27 * conditions are met:
28 *
29 * 1. Redistributions of source code must retain the above
30 * copyright notice, this list of conditions and the following
31 * disclaimer.
32 * 2. Redistributions in binary form must reproduce the above
33 * copyright notice, this list of conditions and the following
34 * disclaimer in the documentation and/or other materials
35 * provided with the distribution.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
38 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
39 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
42 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
48 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
49 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 */
51#include "libfdt_env.h"
52
53#include <fdt.h>
54#include <libfdt.h>
55
56#include "libfdt_internal.h"
57
58int fdt_check_header(const void *fdt)
59{
60 if (fdt_magic(fdt) == FDT_MAGIC) {
61 /* Complete tree */
62 if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
63 return -FDT_ERR_BADVERSION;
64 if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
65 return -FDT_ERR_BADVERSION;
66 } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
67 /* Unfinished sequential-write blob */
68 if (fdt_size_dt_struct(fdt) == 0)
69 return -FDT_ERR_BADSTATE;
70 } else {
71 return -FDT_ERR_BADMAGIC;
72 }
73
74 return 0;
75}
76
77const void *fdt_offset_ptr(const void *fdt, int offset, int len)
78{
79 const char *p;
80
81 if (fdt_version(fdt) >= 0x11)
82 if (((offset + len) < offset)
83 || ((offset + len) > fdt_size_dt_struct(fdt)))
84 return NULL;
85
86 p = _fdt_offset_ptr(fdt, offset);
87
88 if (p + len < p)
89 return NULL;
90 return p;
91}
92
93uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
94{
95 const uint32_t *tagp, *lenp;
96 uint32_t tag;
97 const char *p;
98
99 if (offset % FDT_TAGSIZE)
100 return -1;
101
102 tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
103 if (! tagp)
104 return FDT_END; /* premature end */
105 tag = fdt32_to_cpu(*tagp);
106 offset += FDT_TAGSIZE;
107
108 switch (tag) {
109 case FDT_BEGIN_NODE:
110 /* skip name */
111 do {
112 p = fdt_offset_ptr(fdt, offset++, 1);
113 } while (p && (*p != '\0'));
114 if (! p)
115 return FDT_END;
116 break;
117 case FDT_PROP:
118 lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
119 if (! lenp)
120 return FDT_END;
121 /* skip name offset, length and value */
122 offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
123 break;
124 }
125
126 if (nextoffset)
127 *nextoffset = FDT_TAGALIGN(offset);
128
129 return tag;
130}
131
132int _fdt_check_node_offset(const void *fdt, int offset)
133{
134 if ((offset < 0) || (offset % FDT_TAGSIZE)
135 || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
136 return -FDT_ERR_BADOFFSET;
137
138 return offset;
139}
140
141int fdt_next_node(const void *fdt, int offset, int *depth)
142{
143 int nextoffset = 0;
144 uint32_t tag;
145
146 if (offset >= 0)
147 if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
148 return nextoffset;
149
150 do {
151 offset = nextoffset;
152 tag = fdt_next_tag(fdt, offset, &nextoffset);
153
154 switch (tag) {
155 case FDT_PROP:
156 case FDT_NOP:
157 break;
158
159 case FDT_BEGIN_NODE:
160 if (depth)
161 (*depth)++;
162 break;
163
164 case FDT_END_NODE:
165 if (depth)
166 (*depth)--;
167 break;
168
169 case FDT_END:
170 return -FDT_ERR_NOTFOUND;
171
172 default:
173 return -FDT_ERR_BADSTRUCTURE;
174 }
175 } while (tag != FDT_BEGIN_NODE);
176
177 return offset;
178}
179
180const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
181{
182 int len = strlen(s) + 1;
183 const char *last = strtab + tabsize - len;
184 const char *p;
185
186 for (p = strtab; p <= last; p++)
187 if (memcmp(p, s, len) == 0)
188 return p;
189 return NULL;
190}
191
192int fdt_move(const void *fdt, void *buf, int bufsize)
193{
194 FDT_CHECK_HEADER(fdt);
195
196 if (fdt_totalsize(fdt) > bufsize)
197 return -FDT_ERR_NOSPACE;
198
199 memmove(buf, fdt, fdt_totalsize(fdt));
200 return 0;
201}
diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/libfdt/fdt.h
new file mode 100644
index 000000000000..48ccfd910000
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt.h
@@ -0,0 +1,60 @@
1#ifndef _FDT_H
2#define _FDT_H
3
4#ifndef __ASSEMBLY__
5
6struct fdt_header {
7 uint32_t magic; /* magic word FDT_MAGIC */
8 uint32_t totalsize; /* total size of DT block */
9 uint32_t off_dt_struct; /* offset to structure */
10 uint32_t off_dt_strings; /* offset to strings */
11 uint32_t off_mem_rsvmap; /* offset to memory reserve map */
12 uint32_t version; /* format version */
13 uint32_t last_comp_version; /* last compatible version */
14
15 /* version 2 fields below */
16 uint32_t boot_cpuid_phys; /* Which physical CPU id we're
17 booting on */
18 /* version 3 fields below */
19 uint32_t size_dt_strings; /* size of the strings block */
20
21 /* version 17 fields below */
22 uint32_t size_dt_struct; /* size of the structure block */
23};
24
25struct fdt_reserve_entry {
26 uint64_t address;
27 uint64_t size;
28};
29
30struct fdt_node_header {
31 uint32_t tag;
32 char name[0];
33};
34
35struct fdt_property {
36 uint32_t tag;
37 uint32_t len;
38 uint32_t nameoff;
39 char data[0];
40};
41
42#endif /* !__ASSEMBLY */
43
44#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
45#define FDT_TAGSIZE sizeof(uint32_t)
46
47#define FDT_BEGIN_NODE 0x1 /* Start node: full name */
48#define FDT_END_NODE 0x2 /* End node */
49#define FDT_PROP 0x3 /* Property: name off,
50 size, content */
51#define FDT_NOP 0x4 /* nop */
52#define FDT_END 0x9
53
54#define FDT_V1_SIZE (7*sizeof(uint32_t))
55#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(uint32_t))
56#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(uint32_t))
57#define FDT_V16_SIZE FDT_V3_SIZE
58#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(uint32_t))
59
60#endif /* _FDT_H */
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
new file mode 100644
index 000000000000..fbbba44fcd0d
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -0,0 +1,469 @@
1/*
2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2006 David Gibson, IBM Corporation.
4 *
5 * libfdt is dual licensed: you can use it either under the terms of
6 * the GPL, or the BSD license, at your option.
7 *
8 * a) This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 * MA 02110-1301 USA
22 *
23 * Alternatively,
24 *
25 * b) Redistribution and use in source and binary forms, with or
26 * without modification, are permitted provided that the following
27 * conditions are met:
28 *
29 * 1. Redistributions of source code must retain the above
30 * copyright notice, this list of conditions and the following
31 * disclaimer.
32 * 2. Redistributions in binary form must reproduce the above
33 * copyright notice, this list of conditions and the following
34 * disclaimer in the documentation and/or other materials
35 * provided with the distribution.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
38 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
39 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
42 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
48 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
49 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 */
51#include "libfdt_env.h"
52
53#include <fdt.h>
54#include <libfdt.h>
55
56#include "libfdt_internal.h"
57
58static int _fdt_nodename_eq(const void *fdt, int offset,
59 const char *s, int len)
60{
61 const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
62
63 if (! p)
64 /* short match */
65 return 0;
66
67 if (memcmp(p, s, len) != 0)
68 return 0;
69
70 if (p[len] == '\0')
71 return 1;
72 else if (!memchr(s, '@', len) && (p[len] == '@'))
73 return 1;
74 else
75 return 0;
76}
77
78const char *fdt_string(const void *fdt, int stroffset)
79{
80 return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
81}
82
83int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
84{
85 FDT_CHECK_HEADER(fdt);
86 *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
87 *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
88 return 0;
89}
90
91int fdt_num_mem_rsv(const void *fdt)
92{
93 int i = 0;
94
95 while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
96 i++;
97 return i;
98}
99
100int fdt_subnode_offset_namelen(const void *fdt, int offset,
101 const char *name, int namelen)
102{
103 int depth;
104
105 FDT_CHECK_HEADER(fdt);
106
107 for (depth = 0, offset = fdt_next_node(fdt, offset, &depth);
108 (offset >= 0) && (depth > 0);
109 offset = fdt_next_node(fdt, offset, &depth)) {
110 if (depth < 0)
111 return -FDT_ERR_NOTFOUND;
112 else if ((depth == 1)
113 && _fdt_nodename_eq(fdt, offset, name, namelen))
114 return offset;
115 }
116
117 if (offset < 0)
118 return offset; /* error */
119 else
120 return -FDT_ERR_NOTFOUND;
121}
122
123int fdt_subnode_offset(const void *fdt, int parentoffset,
124 const char *name)
125{
126 return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
127}
128
129int fdt_path_offset(const void *fdt, const char *path)
130{
131 const char *end = path + strlen(path);
132 const char *p = path;
133 int offset = 0;
134
135 FDT_CHECK_HEADER(fdt);
136
137 if (*path != '/')
138 return -FDT_ERR_BADPATH;
139
140 while (*p) {
141 const char *q;
142
143 while (*p == '/')
144 p++;
145 if (! *p)
146 return offset;
147 q = strchr(p, '/');
148 if (! q)
149 q = end;
150
151 offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
152 if (offset < 0)
153 return offset;
154
155 p = q;
156 }
157
158 return offset;
159}
160
161const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
162{
163 const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
164 int err;
165
166 if (((err = fdt_check_header(fdt)) != 0)
167 || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
168 goto fail;
169
170 if (len)
171 *len = strlen(nh->name);
172
173 return nh->name;
174
175 fail:
176 if (len)
177 *len = err;
178 return NULL;
179}
180
181const struct fdt_property *fdt_get_property(const void *fdt,
182 int nodeoffset,
183 const char *name, int *lenp)
184{
185 uint32_t tag;
186 const struct fdt_property *prop;
187 int namestroff;
188 int offset, nextoffset;
189 int err;
190
191 if (((err = fdt_check_header(fdt)) != 0)
192 || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
193 goto fail;
194
195 nextoffset = err;
196 do {
197 offset = nextoffset;
198
199 tag = fdt_next_tag(fdt, offset, &nextoffset);
200 switch (tag) {
201 case FDT_END:
202 err = -FDT_ERR_TRUNCATED;
203 goto fail;
204
205 case FDT_BEGIN_NODE:
206 case FDT_END_NODE:
207 case FDT_NOP:
208 break;
209
210 case FDT_PROP:
211 err = -FDT_ERR_BADSTRUCTURE;
212 prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
213 if (! prop)
214 goto fail;
215 namestroff = fdt32_to_cpu(prop->nameoff);
216 if (strcmp(fdt_string(fdt, namestroff), name) == 0) {
217 /* Found it! */
218 int len = fdt32_to_cpu(prop->len);
219 prop = fdt_offset_ptr(fdt, offset,
220 sizeof(*prop)+len);
221 if (! prop)
222 goto fail;
223
224 if (lenp)
225 *lenp = len;
226
227 return prop;
228 }
229 break;
230
231 default:
232 err = -FDT_ERR_BADSTRUCTURE;
233 goto fail;
234 }
235 } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
236
237 err = -FDT_ERR_NOTFOUND;
238 fail:
239 if (lenp)
240 *lenp = err;
241 return NULL;
242}
243
244const void *fdt_getprop(const void *fdt, int nodeoffset,
245 const char *name, int *lenp)
246{
247 const struct fdt_property *prop;
248
249 prop = fdt_get_property(fdt, nodeoffset, name, lenp);
250 if (! prop)
251 return NULL;
252
253 return prop->data;
254}
255
256uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
257{
258 const uint32_t *php;
259 int len;
260
261 php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
262 if (!php || (len != sizeof(*php)))
263 return 0;
264
265 return fdt32_to_cpu(*php);
266}
267
268int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
269{
270 int pdepth = 0, p = 0;
271 int offset, depth, namelen;
272 const char *name;
273
274 FDT_CHECK_HEADER(fdt);
275
276 if (buflen < 2)
277 return -FDT_ERR_NOSPACE;
278
279 for (offset = 0, depth = 0;
280 (offset >= 0) && (offset <= nodeoffset);
281 offset = fdt_next_node(fdt, offset, &depth)) {
282 if (pdepth < depth)
283 continue; /* overflowed buffer */
284
285 while (pdepth > depth) {
286 do {
287 p--;
288 } while (buf[p-1] != '/');
289 pdepth--;
290 }
291
292 name = fdt_get_name(fdt, offset, &namelen);
293 if (!name)
294 return namelen;
295 if ((p + namelen + 1) <= buflen) {
296 memcpy(buf + p, name, namelen);
297 p += namelen;
298 buf[p++] = '/';
299 pdepth++;
300 }
301
302 if (offset == nodeoffset) {
303 if (pdepth < (depth + 1))
304 return -FDT_ERR_NOSPACE;
305
306 if (p > 1) /* special case so that root path is "/", not "" */
307 p--;
308 buf[p] = '\0';
309 return p;
310 }
311 }
312
313 if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
314 return -FDT_ERR_BADOFFSET;
315 else if (offset == -FDT_ERR_BADOFFSET)
316 return -FDT_ERR_BADSTRUCTURE;
317
318 return offset; /* error from fdt_next_node() */
319}
320
321int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
322 int supernodedepth, int *nodedepth)
323{
324 int offset, depth;
325 int supernodeoffset = -FDT_ERR_INTERNAL;
326
327 FDT_CHECK_HEADER(fdt);
328
329 if (supernodedepth < 0)
330 return -FDT_ERR_NOTFOUND;
331
332 for (offset = 0, depth = 0;
333 (offset >= 0) && (offset <= nodeoffset);
334 offset = fdt_next_node(fdt, offset, &depth)) {
335 if (depth == supernodedepth)
336 supernodeoffset = offset;
337
338 if (offset == nodeoffset) {
339 if (nodedepth)
340 *nodedepth = depth;
341
342 if (supernodedepth > depth)
343 return -FDT_ERR_NOTFOUND;
344 else
345 return supernodeoffset;
346 }
347 }
348
349 if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
350 return -FDT_ERR_BADOFFSET;
351 else if (offset == -FDT_ERR_BADOFFSET)
352 return -FDT_ERR_BADSTRUCTURE;
353
354 return offset; /* error from fdt_next_node() */
355}
356
357int fdt_node_depth(const void *fdt, int nodeoffset)
358{
359 int nodedepth;
360 int err;
361
362 err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
363 if (err)
364 return (err < 0) ? err : -FDT_ERR_INTERNAL;
365 return nodedepth;
366}
367
368int fdt_parent_offset(const void *fdt, int nodeoffset)
369{
370 int nodedepth = fdt_node_depth(fdt, nodeoffset);
371
372 if (nodedepth < 0)
373 return nodedepth;
374 return fdt_supernode_atdepth_offset(fdt, nodeoffset,
375 nodedepth - 1, NULL);
376}
377
378int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
379 const char *propname,
380 const void *propval, int proplen)
381{
382 int offset;
383 const void *val;
384 int len;
385
386 FDT_CHECK_HEADER(fdt);
387
388 /* FIXME: The algorithm here is pretty horrible: we scan each
389 * property of a node in fdt_getprop(), then if that didn't
390 * find what we want, we scan over them again making our way
391 * to the next node. Still it's the easiest to implement
392 * approach; performance can come later. */
393 for (offset = fdt_next_node(fdt, startoffset, NULL);
394 offset >= 0;
395 offset = fdt_next_node(fdt, offset, NULL)) {
396 val = fdt_getprop(fdt, offset, propname, &len);
397 if (val && (len == proplen)
398 && (memcmp(val, propval, len) == 0))
399 return offset;
400 }
401
402 return offset; /* error from fdt_next_node() */
403}
404
405int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
406{
407 if ((phandle == 0) || (phandle == -1))
408 return -FDT_ERR_BADPHANDLE;
409 phandle = cpu_to_fdt32(phandle);
410 return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
411 &phandle, sizeof(phandle));
412}
413
414int _stringlist_contains(const char *strlist, int listlen, const char *str)
415{
416 int len = strlen(str);
417 const char *p;
418
419 while (listlen >= len) {
420 if (memcmp(str, strlist, len+1) == 0)
421 return 1;
422 p = memchr(strlist, '\0', listlen);
423 if (!p)
424 return 0; /* malformed strlist.. */
425 listlen -= (p-strlist) + 1;
426 strlist = p + 1;
427 }
428 return 0;
429}
430
431int fdt_node_check_compatible(const void *fdt, int nodeoffset,
432 const char *compatible)
433{
434 const void *prop;
435 int len;
436
437 prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
438 if (!prop)
439 return len;
440 if (_stringlist_contains(prop, len, compatible))
441 return 0;
442 else
443 return 1;
444}
445
446int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
447 const char *compatible)
448{
449 int offset, err;
450
451 FDT_CHECK_HEADER(fdt);
452
453 /* FIXME: The algorithm here is pretty horrible: we scan each
454 * property of a node in fdt_node_check_compatible(), then if
455 * that didn't find what we want, we scan over them again
456 * making our way to the next node. Still it's the easiest to
457 * implement approach; performance can come later. */
458 for (offset = fdt_next_node(fdt, startoffset, NULL);
459 offset >= 0;
460 offset = fdt_next_node(fdt, offset, NULL)) {
461 err = fdt_node_check_compatible(fdt, offset, compatible);
462 if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
463 return err;
464 else if (err == 0)
465 return offset;
466 }
467
468 return offset; /* error from fdt_next_node() */
469}
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
new file mode 100644
index 000000000000..8e7ec4cb7bcd
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -0,0 +1,463 @@
1/*
2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2006 David Gibson, IBM Corporation.
4 *
5 * libfdt is dual licensed: you can use it either under the terms of
6 * the GPL, or the BSD license, at your option.
7 *
8 * a) This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 * MA 02110-1301 USA
22 *
23 * Alternatively,
24 *
25 * b) Redistribution and use in source and binary forms, with or
26 * without modification, are permitted provided that the following
27 * conditions are met:
28 *
29 * 1. Redistributions of source code must retain the above
30 * copyright notice, this list of conditions and the following
31 * disclaimer.
32 * 2. Redistributions in binary form must reproduce the above
33 * copyright notice, this list of conditions and the following
34 * disclaimer in the documentation and/or other materials
35 * provided with the distribution.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
38 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
39 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
42 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
48 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
49 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 */
51#include "libfdt_env.h"
52
53#include <fdt.h>
54#include <libfdt.h>
55
56#include "libfdt_internal.h"
57
58static int _fdt_blocks_misordered(const void *fdt,
59 int mem_rsv_size, int struct_size)
60{
61 return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
62 || (fdt_off_dt_struct(fdt) <
63 (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
64 || (fdt_off_dt_strings(fdt) <
65 (fdt_off_dt_struct(fdt) + struct_size))
66 || (fdt_totalsize(fdt) <
67 (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
68}
69
70static int _fdt_rw_check_header(void *fdt)
71{
72 FDT_CHECK_HEADER(fdt);
73
74 if (fdt_version(fdt) < 17)
75 return -FDT_ERR_BADVERSION;
76 if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
77 fdt_size_dt_struct(fdt)))
78 return -FDT_ERR_BADLAYOUT;
79 if (fdt_version(fdt) > 17)
80 fdt_set_version(fdt, 17);
81
82 return 0;
83}
84
85#define FDT_RW_CHECK_HEADER(fdt) \
86 { \
87 int err; \
88 if ((err = _fdt_rw_check_header(fdt)) != 0) \
89 return err; \
90 }
91
92static inline int _fdt_data_size(void *fdt)
93{
94 return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
95}
96
97static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
98{
99 char *p = splicepoint;
100 char *end = (char *)fdt + _fdt_data_size(fdt);
101
102 if (((p + oldlen) < p) || ((p + oldlen) > end))
103 return -FDT_ERR_BADOFFSET;
104 if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
105 return -FDT_ERR_NOSPACE;
106 memmove(p + newlen, p + oldlen, end - p - oldlen);
107 return 0;
108}
109
110static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
111 int oldn, int newn)
112{
113 int delta = (newn - oldn) * sizeof(*p);
114 int err;
115 err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
116 if (err)
117 return err;
118 fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
119 fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
120 return 0;
121}
122
123static int _fdt_splice_struct(void *fdt, void *p,
124 int oldlen, int newlen)
125{
126 int delta = newlen - oldlen;
127 int err;
128
129 if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
130 return err;
131
132 fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
133 fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
134 return 0;
135}
136
137static int _fdt_splice_string(void *fdt, int newlen)
138{
139 void *p = (char *)fdt
140 + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
141 int err;
142
143 if ((err = _fdt_splice(fdt, p, 0, newlen)))
144 return err;
145
146 fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
147 return 0;
148}
149
150static int _fdt_find_add_string(void *fdt, const char *s)
151{
152 char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
153 const char *p;
154 char *new;
155 int len = strlen(s) + 1;
156 int err;
157
158 p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
159 if (p)
160 /* found it */
161 return (p - strtab);
162
163 new = strtab + fdt_size_dt_strings(fdt);
164 err = _fdt_splice_string(fdt, len);
165 if (err)
166 return err;
167
168 memcpy(new, s, len);
169 return (new - strtab);
170}
171
172int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
173{
174 struct fdt_reserve_entry *re;
175 int err;
176
177 FDT_RW_CHECK_HEADER(fdt);
178
179 re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
180 err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
181 if (err)
182 return err;
183
184 re->address = cpu_to_fdt64(address);
185 re->size = cpu_to_fdt64(size);
186 return 0;
187}
188
189int fdt_del_mem_rsv(void *fdt, int n)
190{
191 struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
192 int err;
193
194 FDT_RW_CHECK_HEADER(fdt);
195
196 if (n >= fdt_num_mem_rsv(fdt))
197 return -FDT_ERR_NOTFOUND;
198
199 err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
200 if (err)
201 return err;
202 return 0;
203}
204
205static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
206 int len, struct fdt_property **prop)
207{
208 int oldlen;
209 int err;
210
211 *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
212 if (! (*prop))
213 return oldlen;
214
215 if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
216 FDT_TAGALIGN(len))))
217 return err;
218
219 (*prop)->len = cpu_to_fdt32(len);
220 return 0;
221}
222
223static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
224 int len, struct fdt_property **prop)
225{
226 int proplen;
227 int nextoffset;
228 int namestroff;
229 int err;
230
231 if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
232 return nextoffset;
233
234 namestroff = _fdt_find_add_string(fdt, name);
235 if (namestroff < 0)
236 return namestroff;
237
238 *prop = _fdt_offset_ptr_w(fdt, nextoffset);
239 proplen = sizeof(**prop) + FDT_TAGALIGN(len);
240
241 err = _fdt_splice_struct(fdt, *prop, 0, proplen);
242 if (err)
243 return err;
244
245 (*prop)->tag = cpu_to_fdt32(FDT_PROP);
246 (*prop)->nameoff = cpu_to_fdt32(namestroff);
247 (*prop)->len = cpu_to_fdt32(len);
248 return 0;
249}
250
251int fdt_set_name(void *fdt, int nodeoffset, const char *name)
252{
253 char *namep;
254 int oldlen, newlen;
255 int err;
256
257 FDT_RW_CHECK_HEADER(fdt);
258
259 namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
260 if (!namep)
261 return oldlen;
262
263 newlen = strlen(name);
264
265 err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
266 FDT_TAGALIGN(newlen+1));
267 if (err)
268 return err;
269
270 memcpy(namep, name, newlen+1);
271 return 0;
272}
273
274int fdt_setprop(void *fdt, int nodeoffset, const char *name,
275 const void *val, int len)
276{
277 struct fdt_property *prop;
278 int err;
279
280 FDT_RW_CHECK_HEADER(fdt);
281
282 err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
283 if (err == -FDT_ERR_NOTFOUND)
284 err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
285 if (err)
286 return err;
287
288 memcpy(prop->data, val, len);
289 return 0;
290}
291
292int fdt_delprop(void *fdt, int nodeoffset, const char *name)
293{
294 struct fdt_property *prop;
295 int len, proplen;
296
297 FDT_RW_CHECK_HEADER(fdt);
298
299 prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
300 if (! prop)
301 return len;
302
303 proplen = sizeof(*prop) + FDT_TAGALIGN(len);
304 return _fdt_splice_struct(fdt, prop, proplen, 0);
305}
306
307int fdt_add_subnode_namelen(void *fdt, int parentoffset,
308 const char *name, int namelen)
309{
310 struct fdt_node_header *nh;
311 int offset, nextoffset;
312 int nodelen;
313 int err;
314 uint32_t tag;
315 uint32_t *endtag;
316
317 FDT_RW_CHECK_HEADER(fdt);
318
319 offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
320 if (offset >= 0)
321 return -FDT_ERR_EXISTS;
322 else if (offset != -FDT_ERR_NOTFOUND)
323 return offset;
324
325 /* Try to place the new node after the parent's properties */
326 fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
327 do {
328 offset = nextoffset;
329 tag = fdt_next_tag(fdt, offset, &nextoffset);
330 } while ((tag == FDT_PROP) || (tag == FDT_NOP));
331
332 nh = _fdt_offset_ptr_w(fdt, offset);
333 nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
334
335 err = _fdt_splice_struct(fdt, nh, 0, nodelen);
336 if (err)
337 return err;
338
339 nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
340 memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
341 memcpy(nh->name, name, namelen);
342 endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
343 *endtag = cpu_to_fdt32(FDT_END_NODE);
344
345 return offset;
346}
347
348int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
349{
350 return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
351}
352
353int fdt_del_node(void *fdt, int nodeoffset)
354{
355 int endoffset;
356
357 FDT_RW_CHECK_HEADER(fdt);
358
359 endoffset = _fdt_node_end_offset(fdt, nodeoffset);
360 if (endoffset < 0)
361 return endoffset;
362
363 return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
364 endoffset - nodeoffset, 0);
365}
366
367static void _fdt_packblocks(const char *old, char *new,
368 int mem_rsv_size, int struct_size)
369{
370 int mem_rsv_off, struct_off, strings_off;
371
372 mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
373 struct_off = mem_rsv_off + mem_rsv_size;
374 strings_off = struct_off + struct_size;
375
376 memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size);
377 fdt_set_off_mem_rsvmap(new, mem_rsv_off);
378
379 memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size);
380 fdt_set_off_dt_struct(new, struct_off);
381 fdt_set_size_dt_struct(new, struct_size);
382
383 memmove(new + strings_off, old + fdt_off_dt_strings(old),
384 fdt_size_dt_strings(old));
385 fdt_set_off_dt_strings(new, strings_off);
386 fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
387}
388
389int fdt_open_into(const void *fdt, void *buf, int bufsize)
390{
391 int err;
392 int mem_rsv_size, struct_size;
393 int newsize;
394 const char *fdtstart = fdt;
395 const char *fdtend = fdtstart + fdt_totalsize(fdt);
396 char *tmp;
397
398 FDT_CHECK_HEADER(fdt);
399
400 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
401 * sizeof(struct fdt_reserve_entry);
402
403 if (fdt_version(fdt) >= 17) {
404 struct_size = fdt_size_dt_struct(fdt);
405 } else {
406 struct_size = 0;
407 while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
408 ;
409 }
410
411 if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
412 /* no further work necessary */
413 err = fdt_move(fdt, buf, bufsize);
414 if (err)
415 return err;
416 fdt_set_version(buf, 17);
417 fdt_set_size_dt_struct(buf, struct_size);
418 fdt_set_totalsize(buf, bufsize);
419 return 0;
420 }
421
422 /* Need to reorder */
423 newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
424 + struct_size + fdt_size_dt_strings(fdt);
425
426 if (bufsize < newsize)
427 return -FDT_ERR_NOSPACE;
428
429 /* First attempt to build converted tree at beginning of buffer */
430 tmp = buf;
431 /* But if that overlaps with the old tree... */
432 if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {
433 /* Try right after the old tree instead */
434 tmp = (char *)(uintptr_t)fdtend;
435 if ((tmp + newsize) > ((char *)buf + bufsize))
436 return -FDT_ERR_NOSPACE;
437 }
438
439 _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
440 memmove(buf, tmp, newsize);
441
442 fdt_set_magic(buf, FDT_MAGIC);
443 fdt_set_totalsize(buf, bufsize);
444 fdt_set_version(buf, 17);
445 fdt_set_last_comp_version(buf, 16);
446 fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
447
448 return 0;
449}
450
451int fdt_pack(void *fdt)
452{
453 int mem_rsv_size;
454
455 FDT_RW_CHECK_HEADER(fdt);
456
457 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
458 * sizeof(struct fdt_reserve_entry);
459 _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
460 fdt_set_totalsize(fdt, _fdt_data_size(fdt));
461
462 return 0;
463}
diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c
new file mode 100644
index 000000000000..e6c3ceee8c58
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt_strerror.c
@@ -0,0 +1,96 @@
1/*
2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2006 David Gibson, IBM Corporation.
4 *
5 * libfdt is dual licensed: you can use it either under the terms of
6 * the GPL, or the BSD license, at your option.
7 *
8 * a) This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 * MA 02110-1301 USA
22 *
23 * Alternatively,
24 *
25 * b) Redistribution and use in source and binary forms, with or
26 * without modification, are permitted provided that the following
27 * conditions are met:
28 *
29 * 1. Redistributions of source code must retain the above
30 * copyright notice, this list of conditions and the following
31 * disclaimer.
32 * 2. Redistributions in binary form must reproduce the above
33 * copyright notice, this list of conditions and the following
34 * disclaimer in the documentation and/or other materials
35 * provided with the distribution.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
38 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
39 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
42 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
48 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
49 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 */
51#include "libfdt_env.h"
52
53#include <fdt.h>
54#include <libfdt.h>
55
56#include "libfdt_internal.h"
57
58struct fdt_errtabent {
59 const char *str;
60};
61
62#define FDT_ERRTABENT(val) \
63 [(val)] = { .str = #val, }
64
65static struct fdt_errtabent fdt_errtable[] = {
66 FDT_ERRTABENT(FDT_ERR_NOTFOUND),
67 FDT_ERRTABENT(FDT_ERR_EXISTS),
68 FDT_ERRTABENT(FDT_ERR_NOSPACE),
69
70 FDT_ERRTABENT(FDT_ERR_BADOFFSET),
71 FDT_ERRTABENT(FDT_ERR_BADPATH),
72 FDT_ERRTABENT(FDT_ERR_BADSTATE),
73
74 FDT_ERRTABENT(FDT_ERR_TRUNCATED),
75 FDT_ERRTABENT(FDT_ERR_BADMAGIC),
76 FDT_ERRTABENT(FDT_ERR_BADVERSION),
77 FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
78 FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
79};
80#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
81
82const char *fdt_strerror(int errval)
83{
84 if (errval > 0)
85 return "<valid offset/length>";
86 else if (errval == 0)
87 return "<no error>";
88 else if (errval > -FDT_ERRTABSIZE) {
89 const char *s = fdt_errtable[-errval].str;
90
91 if (s)
92 return s;
93 }
94
95 return "<unknown error>";
96}
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
new file mode 100644
index 000000000000..698329e0ccaf
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt_sw.c
@@ -0,0 +1,257 @@
1/*
2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2006 David Gibson, IBM Corporation.
4 *
5 * libfdt is dual licensed: you can use it either under the terms of
6 * the GPL, or the BSD license, at your option.
7 *
8 * a) This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 * MA 02110-1301 USA
22 *
23 * Alternatively,
24 *
25 * b) Redistribution and use in source and binary forms, with or
26 * without modification, are permitted provided that the following
27 * conditions are met:
28 *
29 * 1. Redistributions of source code must retain the above
30 * copyright notice, this list of conditions and the following
31 * disclaimer.
32 * 2. Redistributions in binary form must reproduce the above
33 * copyright notice, this list of conditions and the following
34 * disclaimer in the documentation and/or other materials
35 * provided with the distribution.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
38 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
39 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
42 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
48 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
49 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 */
51#include "libfdt_env.h"
52
53#include <fdt.h>
54#include <libfdt.h>
55
56#include "libfdt_internal.h"
57
58static int _fdt_sw_check_header(void *fdt)
59{
60 if (fdt_magic(fdt) != FDT_SW_MAGIC)
61 return -FDT_ERR_BADMAGIC;
62 /* FIXME: should check more details about the header state */
63 return 0;
64}
65
66#define FDT_SW_CHECK_HEADER(fdt) \
67 { \
68 int err; \
69 if ((err = _fdt_sw_check_header(fdt)) != 0) \
70 return err; \
71 }
72
73static void *_fdt_grab_space(void *fdt, int len)
74{
75 int offset = fdt_size_dt_struct(fdt);
76 int spaceleft;
77
78 spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
79 - fdt_size_dt_strings(fdt);
80
81 if ((offset + len < offset) || (offset + len > spaceleft))
82 return NULL;
83
84 fdt_set_size_dt_struct(fdt, offset + len);
85 return fdt_offset_ptr_w(fdt, offset, len);
86}
87
88int fdt_create(void *buf, int bufsize)
89{
90 void *fdt = buf;
91
92 if (bufsize < sizeof(struct fdt_header))
93 return -FDT_ERR_NOSPACE;
94
95 memset(buf, 0, bufsize);
96
97 fdt_set_magic(fdt, FDT_SW_MAGIC);
98 fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
99 fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
100 fdt_set_totalsize(fdt, bufsize);
101
102 fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
103 sizeof(struct fdt_reserve_entry)));
104 fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
105 fdt_set_off_dt_strings(fdt, bufsize);
106
107 return 0;
108}
109
110int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
111{
112 struct fdt_reserve_entry *re;
113 int offset;
114
115 FDT_SW_CHECK_HEADER(fdt);
116
117 if (fdt_size_dt_struct(fdt))
118 return -FDT_ERR_BADSTATE;
119
120 offset = fdt_off_dt_struct(fdt);
121 if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
122 return -FDT_ERR_NOSPACE;
123
124 re = (struct fdt_reserve_entry *)((char *)fdt + offset);
125 re->address = cpu_to_fdt64(addr);
126 re->size = cpu_to_fdt64(size);
127
128 fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
129
130 return 0;
131}
132
133int fdt_finish_reservemap(void *fdt)
134{
135 return fdt_add_reservemap_entry(fdt, 0, 0);
136}
137
138int fdt_begin_node(void *fdt, const char *name)
139{
140 struct fdt_node_header *nh;
141 int namelen = strlen(name) + 1;
142
143 FDT_SW_CHECK_HEADER(fdt);
144
145 nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
146 if (! nh)
147 return -FDT_ERR_NOSPACE;
148
149 nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
150 memcpy(nh->name, name, namelen);
151 return 0;
152}
153
154int fdt_end_node(void *fdt)
155{
156 uint32_t *en;
157
158 FDT_SW_CHECK_HEADER(fdt);
159
160 en = _fdt_grab_space(fdt, FDT_TAGSIZE);
161 if (! en)
162 return -FDT_ERR_NOSPACE;
163
164 *en = cpu_to_fdt32(FDT_END_NODE);
165 return 0;
166}
167
168static int _fdt_find_add_string(void *fdt, const char *s)
169{
170 char *strtab = (char *)fdt + fdt_totalsize(fdt);
171 const char *p;
172 int strtabsize = fdt_size_dt_strings(fdt);
173 int len = strlen(s) + 1;
174 int struct_top, offset;
175
176 p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
177 if (p)
178 return p - strtab;
179
180 /* Add it */
181 offset = -strtabsize - len;
182 struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
183 if (fdt_totalsize(fdt) + offset < struct_top)
184 return 0; /* no more room :( */
185
186 memcpy(strtab + offset, s, len);
187 fdt_set_size_dt_strings(fdt, strtabsize + len);
188 return offset;
189}
190
191int fdt_property(void *fdt, const char *name, const void *val, int len)
192{
193 struct fdt_property *prop;
194 int nameoff;
195
196 FDT_SW_CHECK_HEADER(fdt);
197
198 nameoff = _fdt_find_add_string(fdt, name);
199 if (nameoff == 0)
200 return -FDT_ERR_NOSPACE;
201
202 prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
203 if (! prop)
204 return -FDT_ERR_NOSPACE;
205
206 prop->tag = cpu_to_fdt32(FDT_PROP);
207 prop->nameoff = cpu_to_fdt32(nameoff);
208 prop->len = cpu_to_fdt32(len);
209 memcpy(prop->data, val, len);
210 return 0;
211}
212
213int fdt_finish(void *fdt)
214{
215 char *p = (char *)fdt;
216 uint32_t *end;
217 int oldstroffset, newstroffset;
218 uint32_t tag;
219 int offset, nextoffset;
220
221 FDT_SW_CHECK_HEADER(fdt);
222
223 /* Add terminator */
224 end = _fdt_grab_space(fdt, sizeof(*end));
225 if (! end)
226 return -FDT_ERR_NOSPACE;
227 *end = cpu_to_fdt32(FDT_END);
228
229 /* Relocate the string table */
230 oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
231 newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
232 memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
233 fdt_set_off_dt_strings(fdt, newstroffset);
234
235 /* Walk the structure, correcting string offsets */
236 offset = 0;
237 while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
238 if (tag == FDT_PROP) {
239 struct fdt_property *prop =
240 fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
241 int nameoff;
242
243 if (! prop)
244 return -FDT_ERR_BADSTRUCTURE;
245
246 nameoff = fdt32_to_cpu(prop->nameoff);
247 nameoff += fdt_size_dt_strings(fdt);
248 prop->nameoff = cpu_to_fdt32(nameoff);
249 }
250 offset = nextoffset;
251 }
252
253 /* Finally, adjust the header */
254 fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
255 fdt_set_magic(fdt, FDT_MAGIC);
256 return 0;
257}
diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
new file mode 100644
index 000000000000..a4652c6e787e
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt_wip.c
@@ -0,0 +1,145 @@
1/*
2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2006 David Gibson, IBM Corporation.
4 *
5 * libfdt is dual licensed: you can use it either under the terms of
6 * the GPL, or the BSD license, at your option.
7 *
8 * a) This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 * MA 02110-1301 USA
22 *
23 * Alternatively,
24 *
25 * b) Redistribution and use in source and binary forms, with or
26 * without modification, are permitted provided that the following
27 * conditions are met:
28 *
29 * 1. Redistributions of source code must retain the above
30 * copyright notice, this list of conditions and the following
31 * disclaimer.
32 * 2. Redistributions in binary form must reproduce the above
33 * copyright notice, this list of conditions and the following
34 * disclaimer in the documentation and/or other materials
35 * provided with the distribution.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
38 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
39 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
42 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
48 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
49 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 */
51#include "libfdt_env.h"
52
53#include <fdt.h>
54#include <libfdt.h>
55
56#include "libfdt_internal.h"
57
58int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
59 const void *val, int len)
60{
61 void *propval;
62 int proplen;
63
64 propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
65 if (! propval)
66 return proplen;
67
68 if (proplen != len)
69 return -FDT_ERR_NOSPACE;
70
71 memcpy(propval, val, len);
72 return 0;
73}
74
75static void _fdt_nop_region(void *start, int len)
76{
77 uint32_t *p;
78
79 for (p = start; (char *)p < ((char *)start + len); p++)
80 *p = cpu_to_fdt32(FDT_NOP);
81}
82
83int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
84{
85 struct fdt_property *prop;
86 int len;
87
88 prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
89 if (! prop)
90 return len;
91
92 _fdt_nop_region(prop, len + sizeof(*prop));
93
94 return 0;
95}
96
97int _fdt_node_end_offset(void *fdt, int nodeoffset)
98{
99 int level = 0;
100 uint32_t tag;
101 int offset, nextoffset;
102
103 tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
104 if (tag != FDT_BEGIN_NODE)
105 return -FDT_ERR_BADOFFSET;
106 do {
107 offset = nextoffset;
108 tag = fdt_next_tag(fdt, offset, &nextoffset);
109
110 switch (tag) {
111 case FDT_END:
112 return offset;
113
114 case FDT_BEGIN_NODE:
115 level++;
116 break;
117
118 case FDT_END_NODE:
119 level--;
120 break;
121
122 case FDT_PROP:
123 case FDT_NOP:
124 break;
125
126 default:
127 return -FDT_ERR_BADSTRUCTURE;
128 }
129 } while (level >= 0);
130
131 return nextoffset;
132}
133
134int fdt_nop_node(void *fdt, int nodeoffset)
135{
136 int endoffset;
137
138 endoffset = _fdt_node_end_offset(fdt, nodeoffset);
139 if (endoffset < 0)
140 return endoffset;
141
142 _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
143 endoffset - nodeoffset);
144 return 0;
145}
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
new file mode 100644
index 000000000000..ce80e4fb41b2
--- /dev/null
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -0,0 +1,1076 @@
1#ifndef _LIBFDT_H
2#define _LIBFDT_H
3/*
4 * libfdt - Flat Device Tree manipulation
5 * Copyright (C) 2006 David Gibson, IBM Corporation.
6 *
7 * libfdt is dual licensed: you can use it either under the terms of
8 * the GPL, or the BSD license, at your option.
9 *
10 * a) This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
23 * MA 02110-1301 USA
24 *
25 * Alternatively,
26 *
27 * b) Redistribution and use in source and binary forms, with or
28 * without modification, are permitted provided that the following
29 * conditions are met:
30 *
31 * 1. Redistributions of source code must retain the above
32 * copyright notice, this list of conditions and the following
33 * disclaimer.
34 * 2. Redistributions in binary form must reproduce the above
35 * copyright notice, this list of conditions and the following
36 * disclaimer in the documentation and/or other materials
37 * provided with the distribution.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
40 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
41 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
42 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
44 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
49 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
50 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
51 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 */
53
54#include <libfdt_env.h>
55#include <fdt.h>
56
57#define FDT_FIRST_SUPPORTED_VERSION 0x10
58#define FDT_LAST_SUPPORTED_VERSION 0x11
59
60/* Error codes: informative error codes */
61#define FDT_ERR_NOTFOUND 1
62 /* FDT_ERR_NOTFOUND: The requested node or property does not exist */
63#define FDT_ERR_EXISTS 2
64 /* FDT_ERR_EXISTS: Attemped to create a node or property which
65 * already exists */
66#define FDT_ERR_NOSPACE 3
67 /* FDT_ERR_NOSPACE: Operation needed to expand the device
68 * tree, but its buffer did not have sufficient space to
69 * contain the expanded tree. Use fdt_open_into() to move the
70 * device tree to a buffer with more space. */
71
72/* Error codes: codes for bad parameters */
73#define FDT_ERR_BADOFFSET 4
74 /* FDT_ERR_BADOFFSET: Function was passed a structure block
75 * offset which is out-of-bounds, or which points to an
76 * unsuitable part of the structure for the operation. */
77#define FDT_ERR_BADPATH 5
78 /* FDT_ERR_BADPATH: Function was passed a badly formatted path
79 * (e.g. missing a leading / for a function which requires an
80 * absolute path) */
81#define FDT_ERR_BADPHANDLE 6
82 /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
83 * value. phandle values of 0 and -1 are not permitted. */
84#define FDT_ERR_BADSTATE 7
85 /* FDT_ERR_BADSTATE: Function was passed an incomplete device
86 * tree created by the sequential-write functions, which is
87 * not sufficiently complete for the requested operation. */
88
89/* Error codes: codes for bad device tree blobs */
90#define FDT_ERR_TRUNCATED 8
91 /* FDT_ERR_TRUNCATED: Structure block of the given device tree
92 * ends without an FDT_END tag. */
93#define FDT_ERR_BADMAGIC 9
94 /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
95 * device tree at all - it is missing the flattened device
96 * tree magic number. */
97#define FDT_ERR_BADVERSION 10
98 /* FDT_ERR_BADVERSION: Given device tree has a version which
99 * can't be handled by the requested operation. For
100 * read-write functions, this may mean that fdt_open_into() is
101 * required to convert the tree to the expected version. */
102#define FDT_ERR_BADSTRUCTURE 11
103 /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt
104 * structure block or other serious error (e.g. misnested
105 * nodes, or subnodes preceding properties). */
106#define FDT_ERR_BADLAYOUT 12
107 /* FDT_ERR_BADLAYOUT: For read-write functions, the given
108 * device tree has it's sub-blocks in an order that the
109 * function can't handle (memory reserve map, then structure,
110 * then strings). Use fdt_open_into() to reorganize the tree
111 * into a form suitable for the read-write operations. */
112
113/* "Can't happen" error indicating a bug in libfdt */
114#define FDT_ERR_INTERNAL 13
115 /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.
116 * Should never be returned, if it is, it indicates a bug in
117 * libfdt itself. */
118
119#define FDT_ERR_MAX 13
120
121/**********************************************************************/
122/* Low-level functions (you probably don't need these) */
123/**********************************************************************/
124
125const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
126static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
127{
128 return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
129}
130
131uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
132
133/**********************************************************************/
134/* Traversal functions */
135/**********************************************************************/
136
137int fdt_next_node(const void *fdt, int offset, int *depth);
138
139/**********************************************************************/
140/* General functions */
141/**********************************************************************/
142
143#define fdt_get_header(fdt, field) \
144 (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
145#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
146#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
147#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
148#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))
149#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
150#define fdt_version(fdt) (fdt_get_header(fdt, version))
151#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
152#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
153#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
154#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
155
156#define __fdt_set_hdr(name) \
157 static inline void fdt_set_##name(void *fdt, uint32_t val) \
158 { \
159 struct fdt_header *fdth = fdt; \
160 fdth->name = cpu_to_fdt32(val); \
161 }
162__fdt_set_hdr(magic);
163__fdt_set_hdr(totalsize);
164__fdt_set_hdr(off_dt_struct);
165__fdt_set_hdr(off_dt_strings);
166__fdt_set_hdr(off_mem_rsvmap);
167__fdt_set_hdr(version);
168__fdt_set_hdr(last_comp_version);
169__fdt_set_hdr(boot_cpuid_phys);
170__fdt_set_hdr(size_dt_strings);
171__fdt_set_hdr(size_dt_struct);
172#undef __fdt_set_hdr
173
174/**
175 * fdt_check_header - sanity check a device tree or possible device tree
176 * @fdt: pointer to data which might be a flattened device tree
177 *
178 * fdt_check_header() checks that the given buffer contains what
179 * appears to be a flattened device tree with sane information in its
180 * header.
181 *
182 * returns:
183 * 0, if the buffer appears to contain a valid device tree
184 * -FDT_ERR_BADMAGIC,
185 * -FDT_ERR_BADVERSION,
186 * -FDT_ERR_BADSTATE, standard meanings, as above
187 */
188int fdt_check_header(const void *fdt);
189
190/**
191 * fdt_move - move a device tree around in memory
192 * @fdt: pointer to the device tree to move
193 * @buf: pointer to memory where the device is to be moved
194 * @bufsize: size of the memory space at buf
195 *
196 * fdt_move() relocates, if possible, the device tree blob located at
197 * fdt to the buffer at buf of size bufsize. The buffer may overlap
198 * with the existing device tree blob at fdt. Therefore,
199 * fdt_move(fdt, fdt, fdt_totalsize(fdt))
200 * should always succeed.
201 *
202 * returns:
203 * 0, on success
204 * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree
205 * -FDT_ERR_BADMAGIC,
206 * -FDT_ERR_BADVERSION,
207 * -FDT_ERR_BADSTATE, standard meanings
208 */
209int fdt_move(const void *fdt, void *buf, int bufsize);
210
211/**********************************************************************/
212/* Read-only functions */
213/**********************************************************************/
214
215/**
216 * fdt_string - retrieve a string from the strings block of a device tree
217 * @fdt: pointer to the device tree blob
218 * @stroffset: offset of the string within the strings block (native endian)
219 *
220 * fdt_string() retrieves a pointer to a single string from the
221 * strings block of the device tree blob at fdt.
222 *
223 * returns:
224 * a pointer to the string, on success
225 * NULL, if stroffset is out of bounds
226 */
227const char *fdt_string(const void *fdt, int stroffset);
228
229/**
230 * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
231 * @fdt: pointer to the device tree blob
232 *
233 * Returns the number of entries in the device tree blob's memory
234 * reservation map. This does not include the terminating 0,0 entry
235 * or any other (0,0) entries reserved for expansion.
236 *
237 * returns:
238 * the number of entries
239 */
240int fdt_num_mem_rsv(const void *fdt);
241
242/**
243 * fdt_get_mem_rsv - retrieve one memory reserve map entry
244 * @fdt: pointer to the device tree blob
245 * @address, @size: pointers to 64-bit variables
246 *
247 * On success, *address and *size will contain the address and size of
248 * the n-th reserve map entry from the device tree blob, in
249 * native-endian format.
250 *
251 * returns:
252 * 0, on success
253 * -FDT_ERR_BADMAGIC,
254 * -FDT_ERR_BADVERSION,
255 * -FDT_ERR_BADSTATE, standard meanings
256 */
257int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
258
259/**
260 * fdt_subnode_offset_namelen - find a subnode based on substring
261 * @fdt: pointer to the device tree blob
262 * @parentoffset: structure block offset of a node
263 * @name: name of the subnode to locate
264 * @namelen: number of characters of name to consider
265 *
266 * Identical to fdt_subnode_offset(), but only examine the first
267 * namelen characters of name for matching the subnode name. This is
268 * useful for finding subnodes based on a portion of a larger string,
269 * such as a full path.
270 */
271int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
272 const char *name, int namelen);
273/**
274 * fdt_subnode_offset - find a subnode of a given node
275 * @fdt: pointer to the device tree blob
276 * @parentoffset: structure block offset of a node
277 * @name: name of the subnode to locate
278 *
279 * fdt_subnode_offset() finds a subnode of the node at structure block
280 * offset parentoffset with the given name. name may include a unit
281 * address, in which case fdt_subnode_offset() will find the subnode
282 * with that unit address, or the unit address may be omitted, in
283 * which case fdt_subnode_offset() will find an arbitrary subnode
284 * whose name excluding unit address matches the given name.
285 *
286 * returns:
287 * structure block offset of the requested subnode (>=0), on success
288 * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
289 * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
290 * -FDT_ERR_BADMAGIC,
291 * -FDT_ERR_BADVERSION,
292 * -FDT_ERR_BADSTATE,
293 * -FDT_ERR_BADSTRUCTURE,
294 * -FDT_ERR_TRUNCATED, standard meanings.
295 */
296int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
297
298/**
299 * fdt_path_offset - find a tree node by its full path
300 * @fdt: pointer to the device tree blob
301 * @path: full path of the node to locate
302 *
303 * fdt_path_offset() finds a node of a given path in the device tree.
304 * Each path component may omit the unit address portion, but the
305 * results of this are undefined if any such path component is
306 * ambiguous (that is if there are multiple nodes at the relevant
307 * level matching the given component, differentiated only by unit
308 * address).
309 *
310 * returns:
311 * structure block offset of the node with the requested path (>=0), on success
312 * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
313 * -FDT_ERR_NOTFOUND, if the requested node does not exist
314 * -FDT_ERR_BADMAGIC,
315 * -FDT_ERR_BADVERSION,
316 * -FDT_ERR_BADSTATE,
317 * -FDT_ERR_BADSTRUCTURE,
318 * -FDT_ERR_TRUNCATED, standard meanings.
319 */
320int fdt_path_offset(const void *fdt, const char *path);
321
322/**
323 * fdt_get_name - retrieve the name of a given node
324 * @fdt: pointer to the device tree blob
325 * @nodeoffset: structure block offset of the starting node
326 * @lenp: pointer to an integer variable (will be overwritten) or NULL
327 *
328 * fdt_get_name() retrieves the name (including unit address) of the
329 * device tree node at structure block offset nodeoffset. If lenp is
330 * non-NULL, the length of this name is also returned, in the integer
331 * pointed to by lenp.
332 *
333 * returns:
334 * pointer to the node's name, on success
335 * If lenp is non-NULL, *lenp contains the length of that name (>=0)
336 * NULL, on error
337 * if lenp is non-NULL *lenp contains an error code (<0):
338 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
339 * -FDT_ERR_BADMAGIC,
340 * -FDT_ERR_BADVERSION,
341 * -FDT_ERR_BADSTATE, standard meanings
342 */
343const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
344
345/**
346 * fdt_get_property - find a given property in a given node
347 * @fdt: pointer to the device tree blob
348 * @nodeoffset: offset of the node whose property to find
349 * @name: name of the property to find
350 * @lenp: pointer to an integer variable (will be overwritten) or NULL
351 *
352 * fdt_get_property() retrieves a pointer to the fdt_property
353 * structure within the device tree blob corresponding to the property
354 * named 'name' of the node at offset nodeoffset. If lenp is
355 * non-NULL, the length of the property value is also returned, in the
356 * integer pointed to by lenp.
357 *
358 * returns:
359 * pointer to the structure representing the property
360 * if lenp is non-NULL, *lenp contains the length of the property
361 * value (>=0)
362 * NULL, on error
363 * if lenp is non-NULL, *lenp contains an error code (<0):
364 * -FDT_ERR_NOTFOUND, node does not have named property
365 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
366 * -FDT_ERR_BADMAGIC,
367 * -FDT_ERR_BADVERSION,
368 * -FDT_ERR_BADSTATE,
369 * -FDT_ERR_BADSTRUCTURE,
370 * -FDT_ERR_TRUNCATED, standard meanings
371 */
372const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
373 const char *name, int *lenp);
374static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
375 const char *name,
376 int *lenp)
377{
378 return (struct fdt_property *)(uintptr_t)
379 fdt_get_property(fdt, nodeoffset, name, lenp);
380}
381
382/**
383 * fdt_getprop - retrieve the value of a given property
384 * @fdt: pointer to the device tree blob
385 * @nodeoffset: offset of the node whose property to find
386 * @name: name of the property to find
387 * @lenp: pointer to an integer variable (will be overwritten) or NULL
388 *
389 * fdt_getprop() retrieves a pointer to the value of the property
390 * named 'name' of the node at offset nodeoffset (this will be a
391 * pointer to within the device blob itself, not a copy of the value).
392 * If lenp is non-NULL, the length of the property value is also
393 * returned, in the integer pointed to by lenp.
394 *
395 * returns:
396 * pointer to the property's value
397 * if lenp is non-NULL, *lenp contains the length of the property
398 * value (>=0)
399 * NULL, on error
400 * if lenp is non-NULL, *lenp contains an error code (<0):
401 * -FDT_ERR_NOTFOUND, node does not have named property
402 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
403 * -FDT_ERR_BADMAGIC,
404 * -FDT_ERR_BADVERSION,
405 * -FDT_ERR_BADSTATE,
406 * -FDT_ERR_BADSTRUCTURE,
407 * -FDT_ERR_TRUNCATED, standard meanings
408 */
409const void *fdt_getprop(const void *fdt, int nodeoffset,
410 const char *name, int *lenp);
411static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
412 const char *name, int *lenp)
413{
414 return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp);
415}
416
417/**
418 * fdt_get_phandle - retrieve the phandle of a given node
419 * @fdt: pointer to the device tree blob
420 * @nodeoffset: structure block offset of the node
421 *
422 * fdt_get_phandle() retrieves the phandle of the device tree node at
423 * structure block offset nodeoffset.
424 *
425 * returns:
426 * the phandle of the node at nodeoffset, on success (!= 0, != -1)
427 * 0, if the node has no phandle, or another error occurs
428 */
429uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
430
431/**
432 * fdt_get_path - determine the full path of a node
433 * @fdt: pointer to the device tree blob
434 * @nodeoffset: offset of the node whose path to find
435 * @buf: character buffer to contain the returned path (will be overwritten)
436 * @buflen: size of the character buffer at buf
437 *
438 * fdt_get_path() computes the full path of the node at offset
439 * nodeoffset, and records that path in the buffer at buf.
440 *
441 * NOTE: This function is expensive, as it must scan the device tree
442 * structure from the start to nodeoffset.
443 *
444 * returns:
445 * 0, on success
446 * buf contains the absolute path of the node at
447 * nodeoffset, as a NUL-terminated string.
448 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
449 * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
450 * characters and will not fit in the given buffer.
451 * -FDT_ERR_BADMAGIC,
452 * -FDT_ERR_BADVERSION,
453 * -FDT_ERR_BADSTATE,
454 * -FDT_ERR_BADSTRUCTURE, standard meanings
455 */
456int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
457
458/**
459 * fdt_supernode_atdepth_offset - find a specific ancestor of a node
460 * @fdt: pointer to the device tree blob
461 * @nodeoffset: offset of the node whose parent to find
462 * @supernodedepth: depth of the ancestor to find
463 * @nodedepth: pointer to an integer variable (will be overwritten) or NULL
464 *
465 * fdt_supernode_atdepth_offset() finds an ancestor of the given node
466 * at a specific depth from the root (where the root itself has depth
467 * 0, its immediate subnodes depth 1 and so forth). So
468 * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);
469 * will always return 0, the offset of the root node. If the node at
470 * nodeoffset has depth D, then:
471 * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);
472 * will return nodeoffset itself.
473 *
474 * NOTE: This function is expensive, as it must scan the device tree
475 * structure from the start to nodeoffset.
476 *
477 * returns:
478
479 * structure block offset of the node at node offset's ancestor
480 * of depth supernodedepth (>=0), on success
481 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
482* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
483 * -FDT_ERR_BADMAGIC,
484 * -FDT_ERR_BADVERSION,
485 * -FDT_ERR_BADSTATE,
486 * -FDT_ERR_BADSTRUCTURE, standard meanings
487 */
488int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
489 int supernodedepth, int *nodedepth);
490
491/**
492 * fdt_node_depth - find the depth of a given node
493 * @fdt: pointer to the device tree blob
494 * @nodeoffset: offset of the node whose parent to find
495 *
496 * fdt_node_depth() finds the depth of a given node. The root node
497 * has depth 0, its immediate subnodes depth 1 and so forth.
498 *
499 * NOTE: This function is expensive, as it must scan the device tree
500 * structure from the start to nodeoffset.
501 *
502 * returns:
503 * depth of the node at nodeoffset (>=0), on success
504 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
505 * -FDT_ERR_BADMAGIC,
506 * -FDT_ERR_BADVERSION,
507 * -FDT_ERR_BADSTATE,
508 * -FDT_ERR_BADSTRUCTURE, standard meanings
509 */
510int fdt_node_depth(const void *fdt, int nodeoffset);
511
512/**
513 * fdt_parent_offset - find the parent of a given node
514 * @fdt: pointer to the device tree blob
515 * @nodeoffset: offset of the node whose parent to find
516 *
517 * fdt_parent_offset() locates the parent node of a given node (that
518 * is, it finds the offset of the node which contains the node at
519 * nodeoffset as a subnode).
520 *
521 * NOTE: This function is expensive, as it must scan the device tree
522 * structure from the start to nodeoffset, *twice*.
523 *
524 * returns:
525 * structure block offset of the parent of the node at nodeoffset
526 * (>=0), on success
527 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
528 * -FDT_ERR_BADMAGIC,
529 * -FDT_ERR_BADVERSION,
530 * -FDT_ERR_BADSTATE,
531 * -FDT_ERR_BADSTRUCTURE, standard meanings
532 */
533int fdt_parent_offset(const void *fdt, int nodeoffset);
534
535/**
536 * fdt_node_offset_by_prop_value - find nodes with a given property value
537 * @fdt: pointer to the device tree blob
538 * @startoffset: only find nodes after this offset
539 * @propname: property name to check
540 * @propval: property value to search for
541 * @proplen: length of the value in propval
542 *
543 * fdt_node_offset_by_prop_value() returns the offset of the first
544 * node after startoffset, which has a property named propname whose
545 * value is of length proplen and has value equal to propval; or if
546 * startoffset is -1, the very first such node in the tree.
547 *
548 * To iterate through all nodes matching the criterion, the following
549 * idiom can be used:
550 * offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
551 * propval, proplen);
552 * while (offset != -FDT_ERR_NOTFOUND) {
553 * // other code here
554 * offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
555 * propval, proplen);
556 * }
557 *
558 * Note the -1 in the first call to the function, if 0 is used here
559 * instead, the function will never locate the root node, even if it
560 * matches the criterion.
561 *
562 * returns:
563 * structure block offset of the located node (>= 0, >startoffset),
564 * on success
565 * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
566 * tree after startoffset
567 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
568 * -FDT_ERR_BADMAGIC,
569 * -FDT_ERR_BADVERSION,
570 * -FDT_ERR_BADSTATE,
571 * -FDT_ERR_BADSTRUCTURE, standard meanings
572 */
573int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
574 const char *propname,
575 const void *propval, int proplen);
576
577/**
578 * fdt_node_offset_by_phandle - find the node with a given phandle
579 * @fdt: pointer to the device tree blob
580 * @phandle: phandle value
581 *
582 * fdt_node_offset_by_phandle() returns the offset of the node
583 * which has the given phandle value. If there is more than one node
584 * in the tree with the given phandle (an invalid tree), results are
585 * undefined.
586 *
587 * returns:
588 * structure block offset of the located node (>= 0), on success
589 * -FDT_ERR_NOTFOUND, no node with that phandle exists
590 * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)
591 * -FDT_ERR_BADMAGIC,
592 * -FDT_ERR_BADVERSION,
593 * -FDT_ERR_BADSTATE,
594 * -FDT_ERR_BADSTRUCTURE, standard meanings
595 */
596int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
597
598/**
599 * fdt_node_check_compatible: check a node's compatible property
600 * @fdt: pointer to the device tree blob
601 * @nodeoffset: offset of a tree node
602 * @compatible: string to match against
603 *
604 *
605 * fdt_node_check_compatible() returns 0 if the given node contains a
606 * 'compatible' property with the given string as one of its elements,
607 * it returns non-zero otherwise, or on error.
608 *
609 * returns:
610 * 0, if the node has a 'compatible' property listing the given string
611 * 1, if the node has a 'compatible' property, but it does not list
612 * the given string
613 * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
614 * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
615 * -FDT_ERR_BADMAGIC,
616 * -FDT_ERR_BADVERSION,
617 * -FDT_ERR_BADSTATE,
618 * -FDT_ERR_BADSTRUCTURE, standard meanings
619 */
620int fdt_node_check_compatible(const void *fdt, int nodeoffset,
621 const char *compatible);
622
623/**
624 * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
625 * @fdt: pointer to the device tree blob
626 * @startoffset: only find nodes after this offset
627 * @compatible: 'compatible' string to match against
628 *
629 * fdt_node_offset_by_compatible() returns the offset of the first
630 * node after startoffset, which has a 'compatible' property which
631 * lists the given compatible string; or if startoffset is -1, the
632 * very first such node in the tree.
633 *
634 * To iterate through all nodes matching the criterion, the following
635 * idiom can be used:
636 * offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
637 * while (offset != -FDT_ERR_NOTFOUND) {
638 * // other code here
639 * offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
640 * }
641 *
642 * Note the -1 in the first call to the function, if 0 is used here
643 * instead, the function will never locate the root node, even if it
644 * matches the criterion.
645 *
646 * returns:
647 * structure block offset of the located node (>= 0, >startoffset),
648 * on success
649 * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
650 * tree after startoffset
651 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
652 * -FDT_ERR_BADMAGIC,
653 * -FDT_ERR_BADVERSION,
654 * -FDT_ERR_BADSTATE,
655 * -FDT_ERR_BADSTRUCTURE, standard meanings
656 */
657int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
658 const char *compatible);
659
660/**********************************************************************/
661/* Write-in-place functions */
662/**********************************************************************/
663
664/**
665 * fdt_setprop_inplace - change a property's value, but not its size
666 * @fdt: pointer to the device tree blob
667 * @nodeoffset: offset of the node whose property to change
668 * @name: name of the property to change
669 * @val: pointer to data to replace the property value with
670 * @len: length of the property value
671 *
672 * fdt_setprop_inplace() replaces the value of a given property with
673 * the data in val, of length len. This function cannot change the
674 * size of a property, and so will only work if len is equal to the
675 * current length of the property.
676 *
677 * This function will alter only the bytes in the blob which contain
678 * the given property value, and will not alter or move any other part
679 * of the tree.
680 *
681 * returns:
682 * 0, on success
683 * -FDT_ERR_NOSPACE, if len is not equal to the property's current length
684 * -FDT_ERR_NOTFOUND, node does not have the named property
685 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
686 * -FDT_ERR_BADMAGIC,
687 * -FDT_ERR_BADVERSION,
688 * -FDT_ERR_BADSTATE,
689 * -FDT_ERR_BADSTRUCTURE,
690 * -FDT_ERR_TRUNCATED, standard meanings
691 */
692int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
693 const void *val, int len);
694
695/**
696 * fdt_setprop_inplace_cell - change the value of a single-cell property
697 * @fdt: pointer to the device tree blob
698 * @nodeoffset: offset of the node whose property to change
699 * @name: name of the property to change
700 * @val: cell (32-bit integer) value to replace the property with
701 *
702 * fdt_setprop_inplace_cell() replaces the value of a given property
703 * with the 32-bit integer cell value in val, converting val to
704 * big-endian if necessary. This function cannot change the size of a
705 * property, and so will only work if the property already exists and
706 * has length 4.
707 *
708 * This function will alter only the bytes in the blob which contain
709 * the given property value, and will not alter or move any other part
710 * of the tree.
711 *
712 * returns:
713 * 0, on success
714 * -FDT_ERR_NOSPACE, if the property's length is not equal to 4
715 * -FDT_ERR_NOTFOUND, node does not have the named property
716 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
717 * -FDT_ERR_BADMAGIC,
718 * -FDT_ERR_BADVERSION,
719 * -FDT_ERR_BADSTATE,
720 * -FDT_ERR_BADSTRUCTURE,
721 * -FDT_ERR_TRUNCATED, standard meanings
722 */
723static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
724 const char *name, uint32_t val)
725{
726 val = cpu_to_fdt32(val);
727 return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
728}
729
730/**
731 * fdt_nop_property - replace a property with nop tags
732 * @fdt: pointer to the device tree blob
733 * @nodeoffset: offset of the node whose property to nop
734 * @name: name of the property to nop
735 *
736 * fdt_nop_property() will replace a given property's representation
737 * in the blob with FDT_NOP tags, effectively removing it from the
738 * tree.
739 *
740 * This function will alter only the bytes in the blob which contain
741 * the property, and will not alter or move any other part of the
742 * tree.
743 *
744 * returns:
745 * 0, on success
746 * -FDT_ERR_NOTFOUND, node does not have the named property
747 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
748 * -FDT_ERR_BADMAGIC,
749 * -FDT_ERR_BADVERSION,
750 * -FDT_ERR_BADSTATE,
751 * -FDT_ERR_BADSTRUCTURE,
752 * -FDT_ERR_TRUNCATED, standard meanings
753 */
754int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
755
756/**
757 * fdt_nop_node - replace a node (subtree) with nop tags
758 * @fdt: pointer to the device tree blob
759 * @nodeoffset: offset of the node to nop
760 *
761 * fdt_nop_node() will replace a given node's representation in the
762 * blob, including all its subnodes, if any, with FDT_NOP tags,
763 * effectively removing it from the tree.
764 *
765 * This function will alter only the bytes in the blob which contain
766 * the node and its properties and subnodes, and will not alter or
767 * move any other part of the tree.
768 *
769 * returns:
770 * 0, on success
771 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
772 * -FDT_ERR_BADMAGIC,
773 * -FDT_ERR_BADVERSION,
774 * -FDT_ERR_BADSTATE,
775 * -FDT_ERR_BADSTRUCTURE,
776 * -FDT_ERR_TRUNCATED, standard meanings
777 */
778int fdt_nop_node(void *fdt, int nodeoffset);
779
780/**********************************************************************/
781/* Sequential write functions */
782/**********************************************************************/
783
784int fdt_create(void *buf, int bufsize);
785int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
786int fdt_finish_reservemap(void *fdt);
787int fdt_begin_node(void *fdt, const char *name);
788int fdt_property(void *fdt, const char *name, const void *val, int len);
789static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
790{
791 val = cpu_to_fdt32(val);
792 return fdt_property(fdt, name, &val, sizeof(val));
793}
794#define fdt_property_string(fdt, name, str) \
795 fdt_property(fdt, name, str, strlen(str)+1)
796int fdt_end_node(void *fdt);
797int fdt_finish(void *fdt);
798
799/**********************************************************************/
800/* Read-write functions */
801/**********************************************************************/
802
803int fdt_open_into(const void *fdt, void *buf, int bufsize);
804int fdt_pack(void *fdt);
805
806/**
807 * fdt_add_mem_rsv - add one memory reserve map entry
808 * @fdt: pointer to the device tree blob
809 * @address, @size: 64-bit values (native endian)
810 *
811 * Adds a reserve map entry to the given blob reserving a region at
812 * address address of length size.
813 *
814 * This function will insert data into the reserve map and will
815 * therefore change the indexes of some entries in the table.
816 *
817 * returns:
818 * 0, on success
819 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
820 * contain the new reservation entry
821 * -FDT_ERR_BADMAGIC,
822 * -FDT_ERR_BADVERSION,
823 * -FDT_ERR_BADSTATE,
824 * -FDT_ERR_BADSTRUCTURE,
825 * -FDT_ERR_BADLAYOUT,
826 * -FDT_ERR_TRUNCATED, standard meanings
827 */
828int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);
829
830/**
831 * fdt_del_mem_rsv - remove a memory reserve map entry
832 * @fdt: pointer to the device tree blob
833 * @n: entry to remove
834 *
835 * fdt_del_mem_rsv() removes the n-th memory reserve map entry from
836 * the blob.
837 *
838 * This function will delete data from the reservation table and will
839 * therefore change the indexes of some entries in the table.
840 *
841 * returns:
842 * 0, on success
843 * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there
844 * are less than n+1 reserve map entries)
845 * -FDT_ERR_BADMAGIC,
846 * -FDT_ERR_BADVERSION,
847 * -FDT_ERR_BADSTATE,
848 * -FDT_ERR_BADSTRUCTURE,
849 * -FDT_ERR_BADLAYOUT,
850 * -FDT_ERR_TRUNCATED, standard meanings
851 */
852int fdt_del_mem_rsv(void *fdt, int n);
853
854/**
855 * fdt_set_name - change the name of a given node
856 * @fdt: pointer to the device tree blob
857 * @nodeoffset: structure block offset of a node
858 * @name: name to give the node
859 *
860 * fdt_set_name() replaces the name (including unit address, if any)
861 * of the given node with the given string. NOTE: this function can't
862 * efficiently check if the new name is unique amongst the given
863 * node's siblings; results are undefined if this function is invoked
864 * with a name equal to one of the given node's siblings.
865 *
866 * This function may insert or delete data from the blob, and will
867 * therefore change the offsets of some existing nodes.
868 *
869 * returns:
870 * 0, on success
871 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob
872 * to contain the new name
873 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
874 * -FDT_ERR_BADMAGIC,
875 * -FDT_ERR_BADVERSION,
876 * -FDT_ERR_BADSTATE, standard meanings
877 */
878int fdt_set_name(void *fdt, int nodeoffset, const char *name);
879
880/**
881 * fdt_setprop - create or change a property
882 * @fdt: pointer to the device tree blob
883 * @nodeoffset: offset of the node whose property to change
884 * @name: name of the property to change
885 * @val: pointer to data to set the property value to
886 * @len: length of the property value
887 *
888 * fdt_setprop() sets the value of the named property in the given
889 * node to the given value and length, creating the property if it
890 * does not already exist.
891 *
892 * This function may insert or delete data from the blob, and will
893 * therefore change the offsets of some existing nodes.
894 *
895 * returns:
896 * 0, on success
897 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
898 * contain the new property value
899 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
900 * -FDT_ERR_BADLAYOUT,
901 * -FDT_ERR_BADMAGIC,
902 * -FDT_ERR_BADVERSION,
903 * -FDT_ERR_BADSTATE,
904 * -FDT_ERR_BADSTRUCTURE,
905 * -FDT_ERR_BADLAYOUT,
906 * -FDT_ERR_TRUNCATED, standard meanings
907 */
908int fdt_setprop(void *fdt, int nodeoffset, const char *name,
909 const void *val, int len);
910
911/**
912 * fdt_setprop_cell - set a property to a single cell value
913 * @fdt: pointer to the device tree blob
914 * @nodeoffset: offset of the node whose property to change
915 * @name: name of the property to change
916 * @val: 32-bit integer value for the property (native endian)
917 *
918 * fdt_setprop_cell() sets the value of the named property in the
919 * given node to the given cell value (converting to big-endian if
920 * necessary), or creates a new property with that value if it does
921 * not already exist.
922 *
923 * This function may insert or delete data from the blob, and will
924 * therefore change the offsets of some existing nodes.
925 *
926 * returns:
927 * 0, on success
928 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
929 * contain the new property value
930 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
931 * -FDT_ERR_BADLAYOUT,
932 * -FDT_ERR_BADMAGIC,
933 * -FDT_ERR_BADVERSION,
934 * -FDT_ERR_BADSTATE,
935 * -FDT_ERR_BADSTRUCTURE,
936 * -FDT_ERR_BADLAYOUT,
937 * -FDT_ERR_TRUNCATED, standard meanings
938 */
939static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
940 uint32_t val)
941{
942 val = cpu_to_fdt32(val);
943 return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
944}
945
946/**
947 * fdt_setprop_string - set a property to a string value
948 * @fdt: pointer to the device tree blob
949 * @nodeoffset: offset of the node whose property to change
950 * @name: name of the property to change
951 * @str: string value for the property
952 *
953 * fdt_setprop_string() sets the value of the named property in the
954 * given node to the given string value (using the length of the
955 * string to determine the new length of the property), or creates a
956 * new property with that value if it does not already exist.
957 *
958 * This function may insert or delete data from the blob, and will
959 * therefore change the offsets of some existing nodes.
960 *
961 * returns:
962 * 0, on success
963 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
964 * contain the new property value
965 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
966 * -FDT_ERR_BADLAYOUT,
967 * -FDT_ERR_BADMAGIC,
968 * -FDT_ERR_BADVERSION,
969 * -FDT_ERR_BADSTATE,
970 * -FDT_ERR_BADSTRUCTURE,
971 * -FDT_ERR_BADLAYOUT,
972 * -FDT_ERR_TRUNCATED, standard meanings
973 */
974#define fdt_setprop_string(fdt, nodeoffset, name, str) \
975 fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
976
977/**
978 * fdt_delprop - delete a property
979 * @fdt: pointer to the device tree blob
980 * @nodeoffset: offset of the node whose property to nop
981 * @name: name of the property to nop
982 *
983 * fdt_del_property() will delete the given property.
984 *
985 * This function will delete data from the blob, and will therefore
986 * change the offsets of some existing nodes.
987 *
988 * returns:
989 * 0, on success
990 * -FDT_ERR_NOTFOUND, node does not have the named property
991 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
992 * -FDT_ERR_BADLAYOUT,
993 * -FDT_ERR_BADMAGIC,
994 * -FDT_ERR_BADVERSION,
995 * -FDT_ERR_BADSTATE,
996 * -FDT_ERR_BADSTRUCTURE,
997 * -FDT_ERR_TRUNCATED, standard meanings
998 */
999int fdt_delprop(void *fdt, int nodeoffset, const char *name);
1000
1001/**
1002 * fdt_add_subnode_namelen - creates a new node based on substring
1003 * @fdt: pointer to the device tree blob
1004 * @parentoffset: structure block offset of a node
1005 * @name: name of the subnode to locate
1006 * @namelen: number of characters of name to consider
1007 *
1008 * Identical to fdt_add_subnode(), but use only the first namelen
1009 * characters of name as the name of the new node. This is useful for
1010 * creating subnodes based on a portion of a larger string, such as a
1011 * full path.
1012 */
1013int fdt_add_subnode_namelen(void *fdt, int parentoffset,
1014 const char *name, int namelen);
1015
1016/**
1017 * fdt_add_subnode - creates a new node
1018 * @fdt: pointer to the device tree blob
1019 * @parentoffset: structure block offset of a node
1020 * @name: name of the subnode to locate
1021 *
1022 * fdt_add_subnode() creates a new node as a subnode of the node at
1023 * structure block offset parentoffset, with the given name (which
1024 * should include the unit address, if any).
1025 *
1026 * This function will insert data into the blob, and will therefore
1027 * change the offsets of some existing nodes.
1028
1029 * returns:
1030 * structure block offset of the created nodeequested subnode (>=0), on success
1031 * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
1032 * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
1033 * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
1034 * the given name
1035 * -FDT_ERR_NOSPACE, if there is insufficient free space in the
1036 * blob to contain the new node
1037 * -FDT_ERR_NOSPACE
1038 * -FDT_ERR_BADLAYOUT
1039 * -FDT_ERR_BADMAGIC,
1040 * -FDT_ERR_BADVERSION,
1041 * -FDT_ERR_BADSTATE,
1042 * -FDT_ERR_BADSTRUCTURE,
1043 * -FDT_ERR_TRUNCATED, standard meanings.
1044 */
1045int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
1046
1047/**
1048 * fdt_del_node - delete a node (subtree)
1049 * @fdt: pointer to the device tree blob
1050 * @nodeoffset: offset of the node to nop
1051 *
1052 * fdt_del_node() will remove the given node, including all its
1053 * subnodes if any, from the blob.
1054 *
1055 * This function will delete data from the blob, and will therefore
1056 * change the offsets of some existing nodes.
1057 *
1058 * returns:
1059 * 0, on success
1060 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
1061 * -FDT_ERR_BADLAYOUT,
1062 * -FDT_ERR_BADMAGIC,
1063 * -FDT_ERR_BADVERSION,
1064 * -FDT_ERR_BADSTATE,
1065 * -FDT_ERR_BADSTRUCTURE,
1066 * -FDT_ERR_TRUNCATED, standard meanings
1067 */
1068int fdt_del_node(void *fdt, int nodeoffset);
1069
1070/**********************************************************************/
1071/* Debugging / informational functions */
1072/**********************************************************************/
1073
1074const char *fdt_strerror(int errval);
1075
1076#endif /* _LIBFDT_H */
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
new file mode 100644
index 000000000000..449bf602daf1
--- /dev/null
+++ b/scripts/dtc/libfdt/libfdt_env.h
@@ -0,0 +1,23 @@
1#ifndef _LIBFDT_ENV_H
2#define _LIBFDT_ENV_H
3
4#include <stddef.h>
5#include <stdint.h>
6#include <string.h>
7
8#define _B(n) ((unsigned long long)((uint8_t *)&x)[n])
9static inline uint32_t fdt32_to_cpu(uint32_t x)
10{
11 return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3);
12}
13#define cpu_to_fdt32(x) fdt32_to_cpu(x)
14
15static inline uint64_t fdt64_to_cpu(uint64_t x)
16{
17 return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32)
18 | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7);
19}
20#define cpu_to_fdt64(x) fdt64_to_cpu(x)
21#undef _B
22
23#endif /* _LIBFDT_ENV_H */
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
new file mode 100644
index 000000000000..46eb93e4af5c
--- /dev/null
+++ b/scripts/dtc/libfdt/libfdt_internal.h
@@ -0,0 +1,95 @@
1#ifndef _LIBFDT_INTERNAL_H
2#define _LIBFDT_INTERNAL_H
3/*
4 * libfdt - Flat Device Tree manipulation
5 * Copyright (C) 2006 David Gibson, IBM Corporation.
6 *
7 * libfdt is dual licensed: you can use it either under the terms of
8 * the GPL, or the BSD license, at your option.
9 *
10 * a) This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
23 * MA 02110-1301 USA
24 *
25 * Alternatively,
26 *
27 * b) Redistribution and use in source and binary forms, with or
28 * without modification, are permitted provided that the following
29 * conditions are met:
30 *
31 * 1. Redistributions of source code must retain the above
32 * copyright notice, this list of conditions and the following
33 * disclaimer.
34 * 2. Redistributions in binary form must reproduce the above
35 * copyright notice, this list of conditions and the following
36 * disclaimer in the documentation and/or other materials
37 * provided with the distribution.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
40 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
41 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
42 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
44 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
49 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
50 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
51 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 */
53#include <fdt.h>
54
55#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
56#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
57
58#define FDT_CHECK_HEADER(fdt) \
59 { \
60 int err; \
61 if ((err = fdt_check_header(fdt)) != 0) \
62 return err; \
63 }
64
65uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
66int _fdt_check_node_offset(const void *fdt, int offset);
67const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
68int _fdt_node_end_offset(void *fdt, int nodeoffset);
69
70static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
71{
72 return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
73}
74
75static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
76{
77 return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
78}
79
80static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
81{
82 const struct fdt_reserve_entry *rsv_table =
83 (const struct fdt_reserve_entry *)
84 ((const char *)fdt + fdt_off_mem_rsvmap(fdt));
85
86 return rsv_table + n;
87}
88static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
89{
90 return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
91}
92
93#define FDT_SW_MAGIC (~FDT_MAGIC)
94
95#endif /* _LIBFDT_INTERNAL_H */
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
new file mode 100644
index 000000000000..0ca3de550b3f
--- /dev/null
+++ b/scripts/dtc/livetree.c
@@ -0,0 +1,308 @@
1/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
3 *
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
21#include "dtc.h"
22
23/*
24 * Tree building functions
25 */
26
27struct property *build_property(char *name, struct data val, char *label)
28{
29 struct property *new = xmalloc(sizeof(*new));
30
31 new->name = name;
32 new->val = val;
33
34 new->next = NULL;
35
36 new->label = label;
37
38 return new;
39}
40
41struct property *chain_property(struct property *first, struct property *list)
42{
43 assert(first->next == NULL);
44
45 first->next = list;
46 return first;
47}
48
49struct property *reverse_properties(struct property *first)
50{
51 struct property *p = first;
52 struct property *head = NULL;
53 struct property *next;
54
55 while (p) {
56 next = p->next;
57 p->next = head;
58 head = p;
59 p = next;
60 }
61 return head;
62}
63
64struct node *build_node(struct property *proplist, struct node *children)
65{
66 struct node *new = xmalloc(sizeof(*new));
67 struct node *child;
68
69 memset(new, 0, sizeof(*new));
70
71 new->proplist = reverse_properties(proplist);
72 new->children = children;
73
74 for_each_child(new, child) {
75 child->parent = new;
76 }
77
78 return new;
79}
80
81struct node *name_node(struct node *node, char *name, char * label)
82{
83 assert(node->name == NULL);
84
85 node->name = name;
86
87 node->label = label;
88
89 return node;
90}
91
92struct node *chain_node(struct node *first, struct node *list)
93{
94 assert(first->next_sibling == NULL);
95
96 first->next_sibling = list;
97 return first;
98}
99
100void add_property(struct node *node, struct property *prop)
101{
102 struct property **p;
103
104 prop->next = NULL;
105
106 p = &node->proplist;
107 while (*p)
108 p = &((*p)->next);
109
110 *p = prop;
111}
112
113void add_child(struct node *parent, struct node *child)
114{
115 struct node **p;
116
117 child->next_sibling = NULL;
118 child->parent = parent;
119
120 p = &parent->children;
121 while (*p)
122 p = &((*p)->next_sibling);
123
124 *p = child;
125}
126
127struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size,
128 char *label)
129{
130 struct reserve_info *new = xmalloc(sizeof(*new));
131
132 new->re.address = address;
133 new->re.size = size;
134
135 new->next = NULL;
136
137 new->label = label;
138
139 return new;
140}
141
142struct reserve_info *chain_reserve_entry(struct reserve_info *first,
143 struct reserve_info *list)
144{
145 assert(first->next == NULL);
146
147 first->next = list;
148 return first;
149}
150
151struct reserve_info *add_reserve_entry(struct reserve_info *list,
152 struct reserve_info *new)
153{
154 struct reserve_info *last;
155
156 new->next = NULL;
157
158 if (! list)
159 return new;
160
161 for (last = list; last->next; last = last->next)
162 ;
163
164 last->next = new;
165
166 return list;
167}
168
169struct boot_info *build_boot_info(struct reserve_info *reservelist,
170 struct node *tree, uint32_t boot_cpuid_phys)
171{
172 struct boot_info *bi;
173
174 bi = xmalloc(sizeof(*bi));
175 bi->reservelist = reservelist;
176 bi->dt = tree;
177 bi->boot_cpuid_phys = boot_cpuid_phys;
178
179 return bi;
180}
181
182/*
183 * Tree accessor functions
184 */
185
186const char *get_unitname(struct node *node)
187{
188 if (node->name[node->basenamelen] == '\0')
189 return "";
190 else
191 return node->name + node->basenamelen + 1;
192}
193
194struct property *get_property(struct node *node, const char *propname)
195{
196 struct property *prop;
197
198 for_each_property(node, prop)
199 if (streq(prop->name, propname))
200 return prop;
201
202 return NULL;
203}
204
205cell_t propval_cell(struct property *prop)
206{
207 assert(prop->val.len == sizeof(cell_t));
208 return fdt32_to_cpu(*((cell_t *)prop->val.val));
209}
210
211struct node *get_subnode(struct node *node, const char *nodename)
212{
213 struct node *child;
214
215 for_each_child(node, child)
216 if (streq(child->name, nodename))
217 return child;
218
219 return NULL;
220}
221
222struct node *get_node_by_path(struct node *tree, const char *path)
223{
224 const char *p;
225 struct node *child;
226
227 if (!path || ! (*path))
228 return tree;
229
230 while (path[0] == '/')
231 path++;
232
233 p = strchr(path, '/');
234
235 for_each_child(tree, child) {
236 if (p && strneq(path, child->name, p-path))
237 return get_node_by_path(child, p+1);
238 else if (!p && streq(path, child->name))
239 return child;
240 }
241
242 return NULL;
243}
244
245struct node *get_node_by_label(struct node *tree, const char *label)
246{
247 struct node *child, *node;
248
249 assert(label && (strlen(label) > 0));
250
251 if (tree->label && streq(tree->label, label))
252 return tree;
253
254 for_each_child(tree, child) {
255 node = get_node_by_label(child, label);
256 if (node)
257 return node;
258 }
259
260 return NULL;
261}
262
263struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
264{
265 struct node *child, *node;
266
267 assert((phandle != 0) && (phandle != -1));
268
269 if (tree->phandle == phandle)
270 return tree;
271
272 for_each_child(tree, child) {
273 node = get_node_by_phandle(child, phandle);
274 if (node)
275 return node;
276 }
277
278 return NULL;
279}
280
281struct node *get_node_by_ref(struct node *tree, const char *ref)
282{
283 if (ref[0] == '/')
284 return get_node_by_path(tree, ref);
285 else
286 return get_node_by_label(tree, ref);
287}
288
289cell_t get_node_phandle(struct node *root, struct node *node)
290{
291 static cell_t phandle = 1; /* FIXME: ick, static local */
292
293 if ((node->phandle != 0) && (node->phandle != -1))
294 return node->phandle;
295
296 assert(! get_property(node, "linux,phandle"));
297
298 while (get_node_by_phandle(root, phandle))
299 phandle++;
300
301 node->phandle = phandle;
302 add_property(node,
303 build_property("linux,phandle",
304 data_append_cell(empty_data, phandle),
305 NULL));
306
307 return node->phandle;
308}
diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
new file mode 100644
index 000000000000..9641b7628b4d
--- /dev/null
+++ b/scripts/dtc/srcpos.c
@@ -0,0 +1,116 @@
1/*
2 * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17 * USA
18 */
19
20#include "dtc.h"
21#include "srcpos.h"
22
23/*
24 * Like yylineno, this is the current open file pos.
25 */
26
27struct dtc_file *srcpos_file;
28
29static int dtc_open_one(struct dtc_file *file,
30 const char *search,
31 const char *fname)
32{
33 char *fullname;
34
35 if (search) {
36 fullname = xmalloc(strlen(search) + strlen(fname) + 2);
37
38 strcpy(fullname, search);
39 strcat(fullname, "/");
40 strcat(fullname, fname);
41 } else {
42 fullname = strdup(fname);
43 }
44
45 file->file = fopen(fullname, "r");
46 if (!file->file) {
47 free(fullname);
48 return 0;
49 }
50
51 file->name = fullname;
52 return 1;
53}
54
55
56struct dtc_file *dtc_open_file(const char *fname,
57 const struct search_path *search)
58{
59 static const struct search_path default_search = { NULL, NULL, NULL };
60
61 struct dtc_file *file;
62 const char *slash;
63
64 file = xmalloc(sizeof(struct dtc_file));
65
66 slash = strrchr(fname, '/');
67 if (slash) {
68 char *dir = xmalloc(slash - fname + 1);
69
70 memcpy(dir, fname, slash - fname);
71 dir[slash - fname] = 0;
72 file->dir = dir;
73 } else {
74 file->dir = NULL;
75 }
76
77 if (streq(fname, "-")) {
78 file->name = "stdin";
79 file->file = stdin;
80 return file;
81 }
82
83 if (fname[0] == '/') {
84 file->file = fopen(fname, "r");
85 if (!file->file)
86 goto fail;
87
88 file->name = strdup(fname);
89 return file;
90 }
91
92 if (!search)
93 search = &default_search;
94
95 while (search) {
96 if (dtc_open_one(file, search->dir, fname))
97 return file;
98
99 if (errno != ENOENT)
100 goto fail;
101
102 search = search->next;
103 }
104
105fail:
106 die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
107}
108
109void dtc_close_file(struct dtc_file *file)
110{
111 if (fclose(file->file))
112 die("Error closing \"%s\": %s\n", file->name, strerror(errno));
113
114 free(file->dir);
115 free(file);
116}
diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h
new file mode 100644
index 000000000000..e17c7c04db8e
--- /dev/null
+++ b/scripts/dtc/srcpos.h
@@ -0,0 +1,85 @@
1/*
2 * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17 * USA
18 */
19
20/*
21 * Augment the standard YYLTYPE with a filenum index into an
22 * array of all opened filenames.
23 */
24
25#include <stdio.h>
26
27struct dtc_file {
28 char *dir;
29 const char *name;
30 FILE *file;
31};
32
33#if ! defined(YYLTYPE) && ! defined(YYLTYPE_IS_DECLARED)
34typedef struct YYLTYPE {
35 int first_line;
36 int first_column;
37 int last_line;
38 int last_column;
39 struct dtc_file *file;
40} YYLTYPE;
41
42#define YYLTYPE_IS_DECLARED 1
43#define YYLTYPE_IS_TRIVIAL 1
44#endif
45
46/* Cater to old parser templates. */
47#ifndef YYID
48#define YYID(n) (n)
49#endif
50
51#define YYLLOC_DEFAULT(Current, Rhs, N) \
52 do \
53 if (YYID (N)) \
54 { \
55 (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
56 (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
57 (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
58 (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
59 (Current).file = YYRHSLOC (Rhs, N).file; \
60 } \
61 else \
62 { \
63 (Current).first_line = (Current).last_line = \
64 YYRHSLOC (Rhs, 0).last_line; \
65 (Current).first_column = (Current).last_column = \
66 YYRHSLOC (Rhs, 0).last_column; \
67 (Current).file = YYRHSLOC (Rhs, 0).file; \
68 } \
69 while (YYID (0))
70
71
72
73extern void yyerror(char const *);
74extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2)));
75
76extern struct dtc_file *srcpos_file;
77
78struct search_path {
79 const char *dir; /* NULL for current directory */
80 struct search_path *prev, *next;
81};
82
83extern struct dtc_file *dtc_open_file(const char *fname,
84 const struct search_path *search);
85extern void dtc_close_file(struct dtc_file *file);
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
new file mode 100644
index 000000000000..ebeb6eb27907
--- /dev/null
+++ b/scripts/dtc/treesource.c
@@ -0,0 +1,278 @@
1/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
3 *
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
21#include "dtc.h"
22#include "srcpos.h"
23
24extern FILE *yyin;
25extern int yyparse(void);
26
27struct boot_info *the_boot_info;
28int treesource_error;
29
30struct boot_info *dt_from_source(const char *fname)
31{
32 the_boot_info = NULL;
33 treesource_error = 0;
34
35 srcpos_file = dtc_open_file(fname, NULL);
36 yyin = srcpos_file->file;
37
38 if (yyparse() != 0)
39 die("Unable to parse input tree\n");
40
41 if (treesource_error)
42 die("Syntax error parsing input tree\n");
43
44 return the_boot_info;
45}
46
47static void write_prefix(FILE *f, int level)
48{
49 int i;
50
51 for (i = 0; i < level; i++)
52 fputc('\t', f);
53}
54
55int isstring(char c)
56{
57 return (isprint(c)
58 || (c == '\0')
59 || strchr("\a\b\t\n\v\f\r", c));
60}
61
62static void write_propval_string(FILE *f, struct data val)
63{
64 const char *str = val.val;
65 int i;
66 int newchunk = 1;
67 struct marker *m = val.markers;
68
69 assert(str[val.len-1] == '\0');
70
71 for (i = 0; i < (val.len-1); i++) {
72 char c = str[i];
73
74 if (newchunk) {
75 while (m && (m->offset <= i)) {
76 if (m->type == LABEL) {
77 assert(m->offset == i);
78 fprintf(f, "%s: ", m->ref);
79 }
80 m = m->next;
81 }
82 fprintf(f, "\"");
83 newchunk = 0;
84 }
85
86 switch (c) {
87 case '\a':
88 fprintf(f, "\\a");
89 break;
90 case '\b':
91 fprintf(f, "\\b");
92 break;
93 case '\t':
94 fprintf(f, "\\t");
95 break;
96 case '\n':
97 fprintf(f, "\\n");
98 break;
99 case '\v':
100 fprintf(f, "\\v");
101 break;
102 case '\f':
103 fprintf(f, "\\f");
104 break;
105 case '\r':
106 fprintf(f, "\\r");
107 break;
108 case '\\':
109 fprintf(f, "\\\\");
110 break;
111 case '\"':
112 fprintf(f, "\\\"");
113 break;
114 case '\0':
115 fprintf(f, "\", ");
116 newchunk = 1;
117 break;
118 default:
119 if (isprint(c))
120 fprintf(f, "%c", c);
121 else
122 fprintf(f, "\\x%02hhx", c);
123 }
124 }
125 fprintf(f, "\"");
126
127 /* Wrap up any labels at the end of the value */
128 for_each_marker_of_type(m, LABEL) {
129 assert (m->offset == val.len);
130 fprintf(f, " %s:", m->ref);
131 }
132}
133
134static void write_propval_cells(FILE *f, struct data val)
135{
136 void *propend = val.val + val.len;
137 cell_t *cp = (cell_t *)val.val;
138 struct marker *m = val.markers;
139
140 fprintf(f, "<");
141 for (;;) {
142 while (m && (m->offset <= ((char *)cp - val.val))) {
143 if (m->type == LABEL) {
144 assert(m->offset == ((char *)cp - val.val));
145 fprintf(f, "%s: ", m->ref);
146 }
147 m = m->next;
148 }
149
150 fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
151 if ((void *)cp >= propend)
152 break;
153 fprintf(f, " ");
154 }
155
156 /* Wrap up any labels at the end of the value */
157 for_each_marker_of_type(m, LABEL) {
158 assert (m->offset == val.len);
159 fprintf(f, " %s:", m->ref);
160 }
161 fprintf(f, ">");
162}
163
164static void write_propval_bytes(FILE *f, struct data val)
165{
166 void *propend = val.val + val.len;
167 const char *bp = val.val;
168 struct marker *m = val.markers;
169
170 fprintf(f, "[");
171 for (;;) {
172 while (m && (m->offset == (bp-val.val))) {
173 if (m->type == LABEL)
174 fprintf(f, "%s: ", m->ref);
175 m = m->next;
176 }
177
178 fprintf(f, "%02hhx", *bp++);
179 if ((const void *)bp >= propend)
180 break;
181 fprintf(f, " ");
182 }
183
184 /* Wrap up any labels at the end of the value */
185 for_each_marker_of_type(m, LABEL) {
186 assert (m->offset == val.len);
187 fprintf(f, " %s:", m->ref);
188 }
189 fprintf(f, "]");
190}
191
192static void write_propval(FILE *f, struct property *prop)
193{
194 int len = prop->val.len;
195 const char *p = prop->val.val;
196 struct marker *m = prop->val.markers;
197 int nnotstring = 0, nnul = 0;
198 int nnotstringlbl = 0, nnotcelllbl = 0;
199 int i;
200
201 if (len == 0) {
202 fprintf(f, ";\n");
203 return;
204 }
205
206 for (i = 0; i < len; i++) {
207 if (! isstring(p[i]))
208 nnotstring++;
209 if (p[i] == '\0')
210 nnul++;
211 }
212
213 for_each_marker_of_type(m, LABEL) {
214 if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
215 nnotstringlbl++;
216 if ((m->offset % sizeof(cell_t)) != 0)
217 nnotcelllbl++;
218 }
219
220 fprintf(f, " = ");
221 if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
222 && (nnotstringlbl == 0)) {
223 write_propval_string(f, prop->val);
224 } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
225 write_propval_cells(f, prop->val);
226 } else {
227 write_propval_bytes(f, prop->val);
228 }
229
230 fprintf(f, ";\n");
231}
232
233static void write_tree_source_node(FILE *f, struct node *tree, int level)
234{
235 struct property *prop;
236 struct node *child;
237
238 write_prefix(f, level);
239 if (tree->label)
240 fprintf(f, "%s: ", tree->label);
241 if (tree->name && (*tree->name))
242 fprintf(f, "%s {\n", tree->name);
243 else
244 fprintf(f, "/ {\n");
245
246 for_each_property(tree, prop) {
247 write_prefix(f, level+1);
248 if (prop->label)
249 fprintf(f, "%s: ", prop->label);
250 fprintf(f, "%s", prop->name);
251 write_propval(f, prop);
252 }
253 for_each_child(tree, child) {
254 fprintf(f, "\n");
255 write_tree_source_node(f, child, level+1);
256 }
257 write_prefix(f, level);
258 fprintf(f, "};\n");
259}
260
261
262void dt_to_source(FILE *f, struct boot_info *bi)
263{
264 struct reserve_info *re;
265
266 fprintf(f, "/dts-v1/;\n\n");
267
268 for (re = bi->reservelist; re; re = re->next) {
269 if (re->label)
270 fprintf(f, "%s: ", re->label);
271 fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
272 (unsigned long long)re->re.address,
273 (unsigned long long)re->re.size);
274 }
275
276 write_tree_source_node(f, bi->dt, 0);
277}
278
diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h
new file mode 100644
index 000000000000..658ff42429d6
--- /dev/null
+++ b/scripts/dtc/version_gen.h
@@ -0,0 +1 @@
#define DTC_VERSION "DTC 1.2.0"