xref: /freebsd/usr.bin/dtc/fdt.cc (revision 6e660824a82f590542932de52f128db584029893)
1 /*-
2  * Copyright (c) 2013 David Chisnall
3  * All rights reserved.
4  *
5  * This software was developed by SRI International and the University of
6  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7  * ("CTSRD"), as part of the DARPA CRASH research programme.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32 
33 #define __STDC_LIMIT_MACROS 1
34 
35 #include "fdt.hh"
36 
37 #include <algorithm>
38 #include <ctype.h>
39 #include <fcntl.h>
40 #include <inttypes.h>
41 #include <libgen.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include "dtb.hh"
46 
47 namespace dtc
48 {
49 
50 namespace fdt
51 {
52 
53 uint32_t
54 property_value::get_as_uint32()
55 {
56 	if (byte_data.size() != 4)
57 	{
58 		return 0;
59 	}
60 	uint32_t v = 0;
61 	v &= byte_data[0] << 24;
62 	v &= byte_data[1] << 16;
63 	v &= byte_data[2] << 8;
64 	v &= byte_data[3] << 0;
65 	return v;
66 }
67 
68 void
69 property_value::push_to_buffer(byte_buffer &buffer)
70 {
71 	if (!byte_data.empty())
72 	{
73 		buffer.insert(buffer.end(), byte_data.begin(), byte_data.end());
74 	}
75 	else
76 	{
77 		string_data.push_to_buffer(buffer, true);
78 		// Trailing nul
79 		buffer.push_back(0);
80 	}
81 }
82 
83 void
84 property_value::write_dts(FILE *file)
85 {
86 	resolve_type();
87 	switch (type)
88 	{
89 		default:
90 			assert(0 && "Invalid type");
91 		case STRING:
92 		case STRING_LIST:
93 		case CROSS_REFERENCE:
94 			write_as_string(file);
95 			break;
96 		case PHANDLE:
97 			write_as_cells(file);
98 			break;
99 		case BINARY:
100 			if (byte_data.size() % 4 == 0)
101 			{
102 				write_as_cells(file);
103 				break;
104 			}
105 			write_as_bytes(file);
106 			break;
107 	}
108 }
109 
110 void
111 property_value::resolve_type()
112 {
113 	if (type != UNKNOWN)
114 	{
115 		return;
116 	}
117 	if (byte_data.empty())
118 	{
119 		type = STRING;
120 		return;
121 	}
122 	if (byte_data.back() == 0)
123 	{
124 		bool is_all_printable = true;
125 		int nuls = 0;
126 		int bytes = 0;
127 		for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i<e ; i++)
128 		{
129 			bytes++;
130 			is_all_printable &= (*i == '\0') || isprint(*i);
131 			if (*i == '\0')
132 			{
133 				nuls++;
134 			}
135 			if (!is_all_printable)
136 			{
137 				break;
138 			}
139 		}
140 		if (is_all_printable && (bytes > nuls))
141 		{
142 			type = STRING;
143 			if (nuls > 0)
144 			{
145 				type = STRING_LIST;
146 			}
147 			return;
148 		}
149 	}
150 	type = BINARY;
151 }
152 
153 void
154 property_value::write_as_string(FILE *file)
155 {
156 	putc('"', file);
157 	if (byte_data.empty())
158 	{
159 		string_data.print(file);
160 	}
161 	else
162 	{
163 		for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i!=e ; ++i)
164 		{
165 			// FIXME Escape tabs, newlines, and so on.
166 			if (*i == '\0')
167 			{
168 				fputs("\", \"", file);
169 				continue;
170 			}
171 			putc(*i, file);
172 		}
173 	}
174 	putc('"', file);
175 }
176 
177 void
178 property_value::write_as_cells(FILE *file)
179 {
180 	putc('<', file);
181 	assert((byte_data.size() % 4) == 0);
182 	for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; ++i)
183 	{
184 		uint32_t v = 0;
185 		v = (v << 8) | *i;
186 		++i;
187 		v = (v << 8) | *i;
188 		++i;
189 		v = (v << 8) | *i;
190 		++i;
191 		v = (v << 8) | *i;
192 		fprintf(file, "0x%" PRIx32, v);
193 		if (i+1 != e)
194 		{
195 			putc(' ', file);
196 		}
197 	}
198 	putc('>', file);
199 }
200 
201 void
202 property_value::write_as_bytes(FILE *file)
203 {
204 	putc('[', file);
205 	for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; i++)
206 	{
207 		fprintf(file, "%hhx", *i);
208 		if (i+1 != e)
209 		{
210 			putc(' ', file);
211 		}
212 	}
213 	putc(']', file);
214 }
215 
216 void
217 property::parse_string(input_buffer &input)
218 {
219 	property_value v;
220 	assert(input[0] == '"');
221 	++input;
222 	const char *start = (const char*)input;
223 	int length = 0;
224 	while (char c = input[0])
225 	{
226 		if (c == '"' && input[-1] != '\\')
227 		{
228 			input.consume('"');
229 			break;
230 		}
231 		++input;
232 		++length;
233 	}
234 	v.string_data = string(start, length);
235 	values.push_back(v);
236 }
237 
238 void
239 property::parse_cells(input_buffer &input)
240 {
241 	assert(input[0] == '<');
242 	++input;
243 	property_value v;
244 	input.next_token();
245 	while (!input.consume('>'))
246 	{
247 		input.next_token();
248 		// If this is a phandle then we need to get the name of the
249 		// referenced node
250 		if (input.consume('&'))
251 		{
252 			input.next_token();
253 			// FIXME: We should support full paths here, but we
254 			// don't.
255 			string referenced = string::parse_node_name(input);
256 			if (referenced.empty())
257 			{
258 				input.parse_error("Expected node name");
259 				valid = false;
260 				return;
261 			}
262 			input.next_token();
263 			// If we already have some bytes, make the phandle a
264 			// separate component.
265 			if (!v.byte_data.empty())
266 			{
267 				values.push_back(v);
268 				v = property_value();
269 			}
270 			v.string_data = referenced;
271 			v.type = property_value::PHANDLE;
272 			values.push_back(v);
273 			v = property_value();
274 		}
275 		else
276 		{
277 			//FIXME: We should support labels in the middle
278 			//of these, but we don't.
279 			long long val;
280 			if (!input.consume_integer(val))
281 			{
282 				input.parse_error("Expected numbers in array of cells");
283 				valid = false;
284 				return;
285 			}
286 			if ((val < 0) || (val > UINT32_MAX))
287 			{
288 				input.parse_error("Value out of range");
289 				valid = false;
290 				return;
291 			}
292 			push_big_endian(v.byte_data, (uint32_t)val);
293 			input.next_token();
294 		}
295 	}
296 	// Don't store an empty string value here.
297 	if (v.byte_data.size() > 0)
298 	{
299 		values.push_back(v);
300 	}
301 }
302 
303 void
304 property::parse_bytes(input_buffer &input)
305 {
306 	assert(input[0] == '[');
307 	++input;
308 	property_value v;
309 	input.next_token();
310 	while (!input.consume(']'))
311 	{
312 		{
313 			//FIXME: We should support
314 			//labels in the middle of
315 			//these, but we don't.
316 			uint8_t val;
317 			if (!input.consume_hex_byte(val))
318 			{
319 				input.parse_error("Expected hex bytes in array of bytes");
320 				valid = false;
321 				return;
322 			}
323 			v.byte_data.push_back(val);
324 			input.next_token();
325 		}
326 	}
327 	values.push_back(v);
328 }
329 
330 void
331 property::parse_reference(input_buffer &input)
332 {
333 	assert(input[0] == '&');
334 	++input;
335 	input.next_token();
336 	property_value v;
337 	v.string_data = string::parse_node_name(input);
338 	if (v.string_data.empty())
339 	{
340 		input.parse_error("Expected node name");
341 		valid = false;
342 		return;
343 	}
344 	v.type = property_value::CROSS_REFERENCE;
345 	values.push_back(v);
346 }
347 
348 property::property(input_buffer &structs, input_buffer &strings)
349 {
350 	uint32_t name_offset;
351 	uint32_t length;
352 	valid = structs.consume_binary(length) &&
353 		structs.consume_binary(name_offset);
354 	if (!valid)
355 	{
356 		fprintf(stderr, "Failed to read property\n");
357 		return;
358 	}
359 	// Find the name
360 	input_buffer name_buffer = strings.buffer_from_offset(name_offset);
361 	if (name_buffer.empty())
362 	{
363 		fprintf(stderr, "Property name offset %" PRIu32
364 			" is past the end of the strings table\n",
365 			name_offset);
366 		valid = false;
367 		return;
368 	}
369 	key = string(name_buffer);
370 	// Read the value
371 	uint8_t byte;
372 	property_value v;
373 	for (uint32_t i=0 ; i<length ; i++)
374 	{
375 		if (!(valid = structs.consume_binary(byte)))
376 		{
377 			fprintf(stderr, "Failed to read property value\n");
378 			return;
379 		}
380 		v.byte_data.push_back(byte);
381 	}
382 	values.push_back(v);
383 }
384 
385 property::property(input_buffer &input, string k, string l) : key(k), label(l),
386 	valid(true)
387 {
388 	do {
389 		input.next_token();
390 		switch (input[0])
391 		{
392 			default:
393 				input.parse_error("Invalid property value.");
394 				valid = false;
395 				return;
396 			case '"':
397 				parse_string(input);
398 				break;
399 			case '<':
400 				parse_cells(input);
401 				break;
402 			case '[':
403 				parse_bytes(input);
404 				break;
405 			case '&':
406 				parse_reference(input);
407 				break;
408 			case ';':
409 			{
410 				break;
411 			}
412 		}
413 		input.next_token();
414 	} while (input.consume(','));
415 	if (!input.consume(';'))
416 	{
417 		input.parse_error("Expected ; at end of property");
418 		valid = false;
419 	}
420 }
421 
422 property*
423 property::parse_dtb(input_buffer &structs, input_buffer &strings)
424 {
425 	property *p = new property(structs, strings);
426 	if (!p->valid)
427 	{
428 		delete p;
429 		p = 0;
430 	}
431 	return p;
432 }
433 
434 property*
435 property::parse(input_buffer &input, string key, string label)
436 {
437 	property *p = new property(input, key, label);
438 	if (!p->valid)
439 	{
440 		delete p;
441 		p = 0;
442 	}
443 	return p;
444 }
445 
446 void
447 property::write(dtb::output_writer &writer, dtb::string_table &strings)
448 {
449 	writer.write_token(dtb::FDT_PROP);
450 	byte_buffer value_buffer;
451 	for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
452 	{
453 		i->push_to_buffer(value_buffer);
454 	}
455 	writer.write_data((uint32_t)value_buffer.size());
456 	writer.write_comment(key);
457 	writer.write_data(strings.add_string(key));
458 	writer.write_data(value_buffer);
459 }
460 
461 void
462 property::write_dts(FILE *file, int indent)
463 {
464 	for (int i=0 ; i<indent ; i++)
465 	{
466 		putc('\t', file);
467 	}
468 	if (label != string())
469 	{
470 		label.print(file);
471 		fputs(": ", file);
472 	}
473 	if (key != string())
474 	{
475 		key.print(file);
476 	}
477 	if (!values.empty())
478 	{
479 		fputs(" = ", file);
480 		for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
481 		{
482 			i->write_dts(file);
483 			if (i+1 != e)
484 			{
485 				putc(',', file);
486 				putc(' ', file);
487 			}
488 		}
489 	}
490 	fputs(";\n", file);
491 }
492 
493 string
494 node::parse_name(input_buffer &input, bool &is_property, const char *error)
495 {
496 	if (!valid)
497 	{
498 		return string();
499 	}
500 	input.next_token();
501 	if (is_property)
502 	{
503 		return string::parse_property_name(input);
504 	}
505 	string n = string::parse_node_or_property_name(input, is_property);
506 	if (n.empty())
507 	{
508 		if (n.empty())
509 		{
510 			input.parse_error(error);
511 			valid = false;
512 		}
513 	}
514 	return n;
515 }
516 
517 node::node(input_buffer &structs, input_buffer &strings) : valid(true)
518 {
519 	const char *name_start = (const char*)structs;
520 	int name_length = 0;
521 	while (structs[0] != '\0' && structs[0] != '@')
522 	{
523 		name_length++;
524 		++structs;
525 	}
526 	name = string(name_start, name_length);
527 	if (structs[0] == '@')
528 	{
529 		++structs;
530 		name_start = (const char*)structs;
531 		name_length = 0;
532 		while (structs[0] != '\0')
533 		{
534 			name_length++;
535 			++structs;
536 		}
537 		unit_address = string(name_start, name_length);
538 	}
539 	++structs;
540 	uint32_t token;
541 	while (structs.consume_binary(token))
542 	{
543 		switch (token)
544 		{
545 			default:
546 				fprintf(stderr, "Unexpected token 0x%" PRIx32
547 					" while parsing node.\n", token);
548 				valid = false;
549 				return;
550 			// Child node, parse it.
551 			case dtb::FDT_BEGIN_NODE:
552 			{
553 				node *child = node::parse_dtb(structs, strings);
554 				if (child == 0)
555 				{
556 					valid = false;
557 					return;
558 				}
559 				children.push_back(child);
560 				break;
561 			}
562 			// End of this node, no errors.
563 			case dtb::FDT_END_NODE:
564 				return;
565 			// Property, parse it.
566 			case dtb::FDT_PROP:
567 			{
568 				property *prop = property::parse_dtb(structs, strings);
569 				if (prop == 0)
570 				{
571 					valid = false;
572 					return;
573 				}
574 				properties.push_back(prop);
575 				break;
576 			}
577 				break;
578 			// End of structs table.  Should appear after
579 			// the end of the last node.
580 			case dtb::FDT_END:
581 				fprintf(stderr, "Unexpected FDT_END token while parsing node.\n");
582 				valid = false;
583 				return;
584 			// NOPs are padding.  Ignore them.
585 			case dtb::FDT_NOP:
586 				break;
587 		}
588 	}
589 	fprintf(stderr, "Failed to read token from structs table while parsing node.\n");
590 	valid = false;
591 	return;
592 }
593 
594 node::node(input_buffer &input, string n, string l, string a) :
595 	label(l), name(n), unit_address(a), valid(true)
596 {
597 	if (!input.consume('{'))
598 	{
599 		input.parse_error("Expected { to start new device tree node.\n");
600 	}
601 	input.next_token();
602 	while (valid && !input.consume('}'))
603 	{
604 		// flag set if we find any characters that are only in
605 		// the property name character set, not the node
606 		bool is_property = false;
607 		string child_name, child_label, child_address;
608 		child_name = parse_name(input, is_property,
609 				"Expected property or node name");
610 		if (input.consume(':'))
611 		{
612 			// Node labels can contain any characters?  The
613 			// spec doesn't say, so we guess so...
614 			is_property = false;
615 			child_label = child_name;
616 			child_name = parse_name(input, is_property, "Expected property or node name");
617 		}
618 		if (input.consume('@'))
619 		{
620 			child_address = parse_name(input, is_property, "Expected unit address");
621 		}
622 		if (!valid)
623 		{
624 			return;
625 		}
626 		input.next_token();
627 		// If we're parsing a property, then we must actually do that.
628 		if (input.consume('='))
629 		{
630 			property *p= property::parse(input, child_name,
631 					child_label);
632 			if (p == 0)
633 			{
634 				valid = false;
635 			}
636 			else
637 			{
638 				properties.push_back(p);
639 			}
640 		}
641 		else if (!is_property && input[0] == ('{'))
642 		{
643 			node *child = node::parse(input, child_name,
644 					child_label, child_address);
645 			if (child)
646 			{
647 				children.push_back(child);
648 			}
649 			else
650 			{
651 				valid = false;
652 			}
653 		}
654 		else if (input.consume(';'))
655 		{
656 			properties.push_back(new property(child_name, child_label));
657 		}
658 		else
659 		{
660 			input.parse_error("Error parsing property.");
661 			valid = false;
662 		}
663 		input.next_token();
664 	}
665 	input.consume(';');
666 }
667 
668 bool
669 node::cmp_properties(property *p1, property *p2)
670 {
671 	return p1->get_key() < p2->get_key();
672 }
673 
674 bool
675 node::cmp_children(node *c1, node *c2)
676 {
677 	if (c1->name == c2->name)
678 	{
679 		return c1->unit_address < c2->unit_address;
680 	}
681 	return c1->name < c2->name;
682 }
683 
684 void
685 node::sort()
686 {
687 	std::sort(property_begin(), property_end(), cmp_properties);
688 	std::sort(child_begin(), child_end(), cmp_children);
689 	for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
690 	{
691 		(*i)->sort();
692 	}
693 }
694 
695 node*
696 node::parse(input_buffer &input, string name, string label, string address)
697 {
698 	node *n = new node(input, name, label, address);
699 	if (!n->valid)
700 	{
701 		delete n;
702 		n = 0;
703 	}
704 	return n;
705 }
706 
707 node*
708 node::parse_dtb(input_buffer &structs, input_buffer &strings)
709 {
710 	node *n = new node(structs, strings);
711 	if (!n->valid)
712 	{
713 		delete n;
714 		n = 0;
715 	}
716 	return n;
717 }
718 
719 node::~node()
720 {
721 	while (!children.empty())
722 	{
723 		delete children.back();
724 		children.pop_back();
725 	}
726 	while (!properties.empty())
727 	{
728 		delete properties.back();
729 		properties.pop_back();
730 	}
731 }
732 
733 property*
734 node::get_property(string key)
735 {
736 	for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
737 	{
738 		if ((*i)->get_key() == key)
739 		{
740 			return *i;
741 		}
742 	}
743 	return 0;
744 }
745 
746 void
747 node::merge_node(node *other)
748 {
749 	if (!other->label.empty())
750 	{
751 		label = other->label;
752 	}
753 	// Note: this is an O(n*m) operation.  It might be sensible to
754 	// optimise this if we find that there are nodes with very
755 	// large numbers of properties, but for typical usage the
756 	// entire vector will fit (easily) into cache, so iterating
757 	// over it repeatedly isn't that expensive.
758 	while (!other->properties.empty())
759 	{
760 		property *p = other->properties.front();
761 		for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
762 		{
763 			if ((*i)->get_key() == p->get_key())
764 			{
765 				delete *i;
766 				properties.erase(i);
767 				break;
768 			}
769 		}
770 		add_property(p);
771 		other->properties.erase(other->properties.begin());
772 	}
773 	while (!other->children.empty())
774 	{
775 		node *c = other->children.front();
776 		bool found = false;
777 		for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
778 		{
779 			if ((*i)->name == c->name && (*i)->unit_address == c->unit_address)
780 			{
781 				(*i)->merge_node(c);
782 				delete c;
783 				found = true;
784 				break;
785 			}
786 		}
787 		if (!found)
788 		{
789 			children.push_back(c);
790 		}
791 		other->children.erase(other->children.begin());
792 	}
793 }
794 
795 void
796 node::write(dtb::output_writer &writer, dtb::string_table &strings)
797 {
798 	writer.write_token(dtb::FDT_BEGIN_NODE);
799 	byte_buffer name_buffer;
800 	name.push_to_buffer(name_buffer);
801 	if (unit_address != string())
802 	{
803 		name_buffer.push_back('@');
804 		unit_address.push_to_buffer(name_buffer);
805 	}
806 	writer.write_comment(name);
807 	writer.write_data(name_buffer);
808 	writer.write_data((uint8_t)0);
809 	for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
810 	{
811 		(*i)->write(writer, strings);
812 	}
813 	for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
814 	{
815 		(*i)->write(writer, strings);
816 	}
817 	writer.write_token(dtb::FDT_END_NODE);
818 }
819 
820 void
821 node::write_dts(FILE *file, int indent)
822 {
823 	for (int i=0 ; i<indent ; i++)
824 	{
825 		putc('\t', file);
826 	}
827 	if (label != string())
828 	{
829 		label.print(file);
830 		fputs(": ", file);
831 	}
832 	if (name != string())
833 	{
834 		name.print(file);
835 	}
836 	if (unit_address != string())
837 	{
838 		putc('@', file);
839 		unit_address.print(file);
840 	}
841 	fputs(" {\n\n", file);
842 	for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
843 	{
844 		(*i)->write_dts(file, indent+1);
845 	}
846 	for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
847 	{
848 		(*i)->write_dts(file, indent+1);
849 	}
850 	for (int i=0 ; i<indent ; i++)
851 	{
852 		putc('\t', file);
853 	}
854 	fputs("};\n", file);
855 }
856 
857 void
858 device_tree::collect_names_recursive(node* n, node_path &path)
859 {
860 	string name = n->label;
861 	path.push_back(std::make_pair(n->name, n->unit_address));
862 	if (name != string())
863 	{
864 		if (node_names.find(name) == node_names.end())
865 		{
866 			node_names.insert(std::make_pair(name, n));
867 			node_paths.insert(std::make_pair(name, path));
868 		}
869 		else
870 		{
871 			node_names[name] = (node*)-1;
872 			std::map<string, node_path>::iterator i = node_paths.find(name);
873 			if (i != node_paths.end())
874 			{
875 				node_paths.erase(name);
876 			}
877 			fprintf(stderr, "Label not unique: ");
878 			name.dump();
879 			fprintf(stderr, ".  References to this label will not be resolved.");
880 		}
881 	}
882 	for (node::child_iterator i=n->child_begin(), e=n->child_end() ; i!=e ; ++i)
883 	{
884 		collect_names_recursive(*i, path);
885 	}
886 	path.pop_back();
887 	// Now we collect the phandles and properties that reference
888 	// other nodes.
889 	for (node::property_iterator i=n->property_begin(), e=n->property_end() ; i!=e ; ++i)
890 	{
891 		for (property::value_iterator p=(*i)->begin(),pe=(*i)->end() ; p!=pe ; ++p)
892 		{
893 			if (p->is_phandle())
894 			{
895 				phandles.push_back(&*p);
896 			}
897 			if (p->is_cross_reference())
898 			{
899 				cross_references.push_back(&*p);
900 			}
901 		}
902 		if ((*i)->get_key() == string("phandle") ||
903 		    (*i)->get_key() == string("linux,phandle"))
904 		{
905 			if ((*i)->begin()->byte_data.size() != 4)
906 			{
907 				fprintf(stderr, "Invalid phandle value for node ");
908 				n->name.dump();
909 				fprintf(stderr, ".  Should be a 4-byte value.\n");
910 				valid = false;
911 			}
912 			else
913 			{
914 				uint32_t phandle = (*i)->begin()->get_as_uint32();
915 				used_phandles.insert(std::make_pair(phandle, n));
916 			}
917 		}
918 	}
919 }
920 
921 void
922 device_tree::collect_names()
923 {
924 	node_path p;
925 	collect_names_recursive(root, p);
926 }
927 
928 void
929 device_tree::resolve_cross_references()
930 {
931 	for (std::vector<property_value*>::iterator i=cross_references.begin(), e=cross_references.end() ; i!=e ; ++i)
932 	{
933 		property_value* pv = *i;
934 		node_path path = node_paths[pv->string_data];
935 		// Skip the first name in the path.  It's always "", and implicitly /
936 		for (node_path::iterator p=path.begin()+1, pe=path.end() ; p!=pe ; ++p)
937 		{
938 			pv->byte_data.push_back('/');
939 			p->first.push_to_buffer(pv->byte_data);
940 			if (!(p->second.empty()))
941 			{
942 				pv->byte_data.push_back('@');
943 				p->second.push_to_buffer(pv->byte_data);
944 			}
945 		}
946 		pv->byte_data.push_back(0);
947 	}
948 	uint32_t phandle = 1;
949 	for (std::vector<property_value*>::iterator i=phandles.begin(), e=phandles.end() ; i!=e ; ++i)
950 	{
951 		string target_name = (*i)->string_data;
952 		node *target = node_names[target_name];
953 		if (target == 0)
954 		{
955 			fprintf(stderr, "Failed to find node with label:");
956 			target_name.dump();
957 			fprintf(stderr, "\n");
958 			valid = 0;
959 			return;
960 		}
961 		// If there is an existing phandle, use it
962 		property *p = target->get_property("phandle");
963 		if (p == 0)
964 		{
965 			p = target->get_property("linux,phandle");
966 		}
967 		if (p == 0)
968 		{
969 			// Otherwise insert a new phandle node
970 			property_value v;
971 			while (used_phandles.find(phandle) != used_phandles.end())
972 			{
973 				// Note that we only don't need to
974 				// store this phandle in the set,
975 				// because we are monotonically
976 				// increasing the value of phandle and
977 				// so will only ever revisit this value
978 				// if we have used 2^32 phandles, at
979 				// which point our blob won't fit in
980 				// any 32-bit system and we've done
981 				// something badly wrong elsewhere
982 				// already.
983 				phandle++;
984 			}
985 			push_big_endian(v.byte_data, phandle++);
986 			if (phandle_node_name == BOTH || phandle_node_name == LINUX)
987 			{
988 				p = new property(string("linux,phandle"));
989 				p->add_value(v);
990 				target->add_property(p);
991 			}
992 			if (phandle_node_name == BOTH || phandle_node_name == EPAPR)
993 			{
994 				p = new property(string("phandle"));
995 				p->add_value(v);
996 				target->add_property(p);
997 			}
998 		}
999 		p->begin()->push_to_buffer((*i)->byte_data);
1000 		assert((*i)->byte_data.size() == 4);
1001 	}
1002 }
1003 
1004 void
1005 device_tree::parse_roots(input_buffer &input, std::vector<node*> &roots)
1006 {
1007 	input.next_token();
1008 	while (valid && input.consume('/'))
1009 	{
1010 		input.next_token();
1011 		node *n = node::parse(input, string("", 1));
1012 		if (n)
1013 		{
1014 			roots.push_back(n);
1015 		}
1016 		else
1017 		{
1018 			valid = false;
1019 		}
1020 	}
1021 }
1022 
1023 input_buffer*
1024 device_tree::buffer_for_file(const char *path)
1025 {
1026 	if (string(path) == string("-"))
1027 	{
1028 		input_buffer *b = new stream_input_buffer();
1029 		buffers.push_back(b);
1030 		return b;
1031 	}
1032 	int source = open(path, O_RDONLY);
1033 	if (source == -1)
1034 	{
1035 		fprintf(stderr, "Unable to open file %s\n", path);
1036 		return 0;
1037 	}
1038 	input_buffer *b = new mmap_input_buffer(source);
1039 	// Keep the buffer that owns the memory around for the lifetime
1040 	// of this FDT.  Ones simply referring to it may have shorter
1041 	// lifetimes.
1042 	buffers.push_back(b);
1043 	close(source);
1044 	return b;
1045 }
1046 
1047 template<class writer> void
1048 device_tree::write(int fd)
1049 {
1050 	dtb::string_table st;
1051 	dtb::header head;
1052 	writer head_writer;
1053 	writer reservation_writer;
1054 	writer struct_writer;
1055 	writer strings_writer;
1056 
1057 	// Build the reservation table
1058 	reservation_writer.write_comment(string("Memory reservations"));
1059 	reservation_writer.write_label(string("dt_reserve_map"));
1060 	for (std::vector<reservation>::iterator i=reservations.begin(),
1061 	     e=reservations.end() ; i!=e ; ++i)
1062 	{
1063 		reservation_writer.write_comment(string("Reservation start"));
1064 		reservation_writer.write_data(i->first);
1065 		reservation_writer.write_comment(string("Reservation length"));
1066 		reservation_writer.write_data(i->first);
1067 	}
1068 	// Write n spare reserve map entries, plus the trailing 0.
1069 	for (uint32_t i=0 ; i<=spare_reserve_map_entries ; i++)
1070 	{
1071 		reservation_writer.write_data((uint64_t)0);
1072 		reservation_writer.write_data((uint64_t)0);
1073 	}
1074 
1075 
1076 	struct_writer.write_comment(string("Device tree"));
1077 	struct_writer.write_label(string("dt_struct_start"));
1078 	root->write(struct_writer, st);
1079 	struct_writer.write_token(dtb::FDT_END);
1080 	struct_writer.write_label(string("dt_struct_end"));
1081 
1082 	st.write(strings_writer);
1083 	// Find the strings size before we stick padding on the end.
1084 	// Note: We should possibly use a new writer for the padding.
1085 	head.size_dt_strings = strings_writer.size();
1086 
1087 	// Stick the padding in the strings writer, but after the
1088 	// marker indicating that it's the end.
1089 	// Note: We probably should add a padding call to the writer so
1090 	// that the asm back end can write padding directives instead
1091 	// of a load of 0 bytes.
1092 	for (uint32_t i=0 ; i<blob_padding ; i++)
1093 	{
1094 		strings_writer.write_data((uint8_t)0);
1095 	}
1096 	head.totalsize = sizeof(head) + strings_writer.size() +
1097 		struct_writer.size() + reservation_writer.size();
1098 	while (head.totalsize < minimum_blob_size)
1099 	{
1100 		head.totalsize++;
1101 		strings_writer.write_data((uint8_t)0);
1102 	}
1103 	head.off_dt_struct = sizeof(head) + reservation_writer.size();;
1104 	head.off_dt_strings = head.off_dt_struct + struct_writer.size();
1105 	head.off_mem_rsvmap = sizeof(head);
1106 	head.boot_cpuid_phys = boot_cpu;
1107 	head.size_dt_struct = struct_writer.size();
1108 	head.write(head_writer);
1109 
1110 	head_writer.write_to_file(fd);
1111 	reservation_writer.write_to_file(fd);
1112 	struct_writer.write_to_file(fd);
1113 	strings_writer.write_label(string("dt_blob_end"));
1114 	strings_writer.write_to_file(fd);
1115 }
1116 
1117 node*
1118 device_tree::referenced_node(property_value &v)
1119 {
1120 	if (v.is_phandle())
1121 	{
1122 		return node_names[v.string_data];
1123 	}
1124 	if (v.is_binary())
1125 	{
1126 		return used_phandles[v.get_as_uint32()];
1127 	}
1128 	return 0;
1129 }
1130 
1131 void
1132 device_tree::write_binary(int fd)
1133 {
1134 	write<dtb::binary_writer>(fd);
1135 }
1136 
1137 void
1138 device_tree::write_asm(int fd)
1139 {
1140 	write<dtb::asm_writer>(fd);
1141 }
1142 
1143 void
1144 device_tree::write_dts(int fd)
1145 {
1146 	FILE *file = fdopen(fd, "w");
1147 	fputs("/dtc-v1/;\n\n", file);
1148 
1149 	if (!reservations.empty())
1150 	{
1151 		const char msg[] = "/memreserve/";
1152 		fwrite(msg, sizeof(msg), 1, file);
1153 		for (std::vector<reservation>::iterator i=reservations.begin(),
1154 		     e=reservations.end() ; i!=e ; ++i)
1155 		{
1156 			fprintf(stderr, " %" PRIx64 " %" PRIx64, i->first, i->second);
1157 		}
1158 		fputs(";\n\n", file);
1159 	}
1160 	putc('/', file);
1161 	putc(' ', file);
1162 	root->write_dts(file, 0);
1163 	fclose(file);
1164 }
1165 
1166 void
1167 device_tree::parse_dtb(const char *fn, FILE *depfile)
1168 {
1169 	input_buffer *in = buffer_for_file(fn);
1170 	if (in == 0)
1171 	{
1172 		valid = false;
1173 		return;
1174 	}
1175 	input_buffer &input = *in;
1176 	dtb::header h;
1177 	valid = h.read_dtb(input);
1178 	boot_cpu = h.boot_cpuid_phys;
1179 	if (h.last_comp_version > 17)
1180 	{
1181 		fprintf(stderr, "Don't know how to read this version of the device tree blob");
1182 		valid = false;
1183 	}
1184 	if (!valid)
1185 	{
1186 		return;
1187 	}
1188 	input_buffer reservation_map =
1189 		input.buffer_from_offset(h.off_mem_rsvmap, 0);
1190 	uint64_t start, length;
1191 	do
1192 	{
1193 		if (!(reservation_map.consume_binary(start) &&
1194 		      reservation_map.consume_binary(length)))
1195 		{
1196 			fprintf(stderr, "Failed to read memory reservation table\n");
1197 			valid = false;
1198 			return;
1199 		}
1200 	} while (!((start == 0) && (length == 0)));
1201 	input_buffer struct_table =
1202 		input.buffer_from_offset(h.off_dt_struct, h.size_dt_struct);
1203 	input_buffer strings_table =
1204 		input.buffer_from_offset(h.off_dt_strings, h.size_dt_strings);
1205 	uint32_t token;
1206 	if (!(struct_table.consume_binary(token) &&
1207 		(token == dtb::FDT_BEGIN_NODE)))
1208 	{
1209 		fprintf(stderr, "Expected FDT_BEGIN_NODE token.\n");
1210 		valid = false;
1211 		return;
1212 	}
1213 	root = node::parse_dtb(struct_table, strings_table);
1214 	if (!(struct_table.consume_binary(token) && (token == dtb::FDT_END)))
1215 	{
1216 		fprintf(stderr, "Expected FDT_END token after parsing root node.\n");
1217 		valid = false;
1218 		return;
1219 	}
1220 	valid = (root != 0);
1221 }
1222 
1223 void
1224 device_tree::parse_dts(const char *fn, FILE *depfile)
1225 {
1226 	input_buffer *in = buffer_for_file(fn);
1227 	if (in == 0)
1228 	{
1229 		valid = false;
1230 		return;
1231 	}
1232 	std::vector<node*> roots;
1233 	input_buffer &input = *in;
1234 	input.next_token();
1235 	bool read_header = false;
1236 	// Read the header
1237 	if (input.consume("/dts-v1/;"))
1238 	{
1239 		read_header = true;
1240 	}
1241 	input.next_token();
1242 	while(input.consume("/include/"))
1243 	{
1244 		input.next_token();
1245 		if (!input.consume('"'))
1246 		{
1247 			input.parse_error("Expected quoted filename");
1248 			valid = false;
1249 			return;
1250 		}
1251 		int length = 0;
1252 		while (input[length] != '"') length++;
1253 
1254 		const char *file = (const char*)input;
1255 		const char *dir = dirname(fn);
1256 		int dir_length = strlen(dir);
1257 		char *include_file = (char*)malloc(strlen(dir) + length + 2);
1258 		memcpy(include_file, dir, dir_length);
1259 		include_file[dir_length] = '/';
1260 		memcpy(include_file+dir_length+1, file, length);
1261 		include_file[dir_length+length+1] = 0;
1262 		input_buffer *include_buffer = buffer_for_file(include_file);
1263 
1264 		if (include_buffer == 0)
1265 		{
1266 			for (std::vector<const char*>::iterator i=include_paths.begin(), e=include_paths.end() ; e!=i ; ++i)
1267 			{
1268 				free(include_file);
1269 				dir = *i;
1270 				dir_length = strlen(dir);
1271 				include_file = (char*)malloc(strlen(dir) +
1272 						length + 2);
1273 				memcpy(include_file, dir, dir_length);
1274 				include_file[dir_length] = '/';
1275 				memcpy(include_file+dir_length+1, file, length);
1276 				include_file[dir_length+length+1] = 0;
1277 				include_buffer = buffer_for_file(include_file);
1278 				if (include_buffer != 0)
1279 				{
1280 					break;
1281 				}
1282 			}
1283 		}
1284 		if (depfile != 0)
1285 		{
1286 			putc(' ', depfile);
1287 			fputs(include_file, depfile);
1288 		}
1289 		if (include_buffer == 0)
1290 		{
1291 			valid = false;
1292 			return;
1293 		}
1294 		input_buffer &include = *include_buffer;
1295 		input.consume(include_file+dir_length+1);
1296 		input.consume('"');
1297 		free((void*)include_file);
1298 
1299 		if (!read_header)
1300 		{
1301 			include.next_token();
1302 			read_header = include.consume("/dts-v1/;");
1303 		}
1304 		parse_roots(include, roots);
1305 	}
1306 	input.next_token();
1307 	if (!read_header)
1308 	{
1309 		input.parse_error("Expected /dts-v1/; version string");
1310 	}
1311 	// Read any memory reservations
1312 	while(input.consume("/memreserve/"))
1313 	{
1314 		long long start, len;
1315 		input.next_token();
1316 		// Read the start and length.
1317 		if (!(input.consume_integer(start) &&
1318 		    (input.next_token(),
1319 		    input.consume_integer(len))))
1320 		{
1321 			input.parse_error("Expected /dts-v1/; version string");
1322 		}
1323 		input.next_token();
1324 		input.consume(';');
1325 		reservations.push_back(reservation(start, len));
1326 	}
1327 	parse_roots(input, roots);
1328 	switch (roots.size())
1329 	{
1330 		case 0:
1331 			valid = false;
1332 			input.parse_error("Failed to find root node /.");
1333 			return;
1334 		case 1:
1335 			root = roots[0];
1336 			break;
1337 		default:
1338 		{
1339 			root = roots[0];
1340 			for (std::vector<node*>::iterator i=roots.begin()+1,
1341 			     e=roots.end() ; i!=e ; ++i)
1342 			{
1343 				root->merge_node(*i);
1344 				delete *i;
1345 			}
1346 			roots.resize(1);
1347 		}
1348 	}
1349 	collect_names();
1350 	resolve_cross_references();
1351 }
1352 
1353 device_tree::~device_tree()
1354 {
1355 	if (root != 0)
1356 	{
1357 		delete root;
1358 	}
1359 	while (!buffers.empty())
1360 	{
1361 		delete buffers.back();
1362 		buffers.pop_back();
1363 	}
1364 }
1365 
1366 } // namespace fdt
1367 
1368 } // namespace dtc
1369 
1370