xref: /freebsd/usr.bin/dtc/fdt.cc (revision 643ac419fafba89f5adda0e0ea75b538727453fb)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2013 David Chisnall
5  * All rights reserved.
6  *
7  * This software was developed by SRI International and the University of
8  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
9  * ("CTSRD"), as part of the DARPA CRASH research programme.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $FreeBSD$
33  */
34 
35 #define __STDC_LIMIT_MACROS 1
36 
37 #include "fdt.hh"
38 #include "dtb.hh"
39 
40 #include <algorithm>
41 #include <limits>
42 #include <sstream>
43 
44 #include <ctype.h>
45 #include <fcntl.h>
46 #include <inttypes.h>
47 #include <libgen.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <errno.h>
55 
56 using std::string;
57 
58 namespace dtc
59 {
60 
61 namespace fdt
62 {
63 
64 uint32_t
65 property_value::get_as_uint32()
66 {
67 	if (byte_data.size() != 4)
68 	{
69 		return 0;
70 	}
71 	uint32_t v = 0;
72 	v &= byte_data[0] << 24;
73 	v &= byte_data[1] << 16;
74 	v &= byte_data[2] << 8;
75 	v &= byte_data[3] << 0;
76 	return v;
77 }
78 
79 void
80 property_value::push_to_buffer(byte_buffer &buffer)
81 {
82 	if (!byte_data.empty())
83 	{
84 		buffer.insert(buffer.end(), byte_data.begin(), byte_data.end());
85 	}
86 	else
87 	{
88 		push_string(buffer, string_data, true);
89 		// Trailing nul
90 		buffer.push_back(0);
91 	}
92 }
93 
94 void
95 property_value::write_dts(FILE *file)
96 {
97 	resolve_type();
98 	switch (type)
99 	{
100 		default:
101 			assert(0 && "Invalid type");
102 		case STRING:
103 		case STRING_LIST:
104 		case CROSS_REFERENCE:
105 			write_as_string(file);
106 			break;
107 		case PHANDLE:
108 			write_as_cells(file);
109 			break;
110 		case BINARY:
111 			if (byte_data.size() % 4 == 0)
112 			{
113 				write_as_cells(file);
114 				break;
115 			}
116 			write_as_bytes(file);
117 			break;
118 	}
119 }
120 
121 void
122 property_value::resolve_type()
123 {
124 	if (type != UNKNOWN)
125 	{
126 		return;
127 	}
128 	if (byte_data.empty())
129 	{
130 		type = STRING;
131 		return;
132 	}
133 	if (byte_data.back() == 0)
134 	{
135 		bool is_all_printable = true;
136 		int nuls = 0;
137 		int bytes = 0;
138 		bool lastWasNull = false;
139 		for (auto i : byte_data)
140 		{
141 			bytes++;
142 			is_all_printable &= (i == '\0') || isprint(i);
143 			if (i == '\0')
144 			{
145 				// If there are two nulls in a row, then we're probably binary.
146 				if (lastWasNull)
147 				{
148 					type = BINARY;
149 					return;
150 				}
151 				nuls++;
152 				lastWasNull = true;
153 			}
154 			else
155 			{
156 				lastWasNull = false;
157 			}
158 			if (!is_all_printable)
159 			{
160 				break;
161 			}
162 		}
163 		if ((is_all_printable && (bytes > nuls)) || bytes == 0)
164 		{
165 			type = STRING;
166 			if (nuls > 1)
167 			{
168 				type = STRING_LIST;
169 			}
170 			return;
171 		}
172 	}
173 	type = BINARY;
174 }
175 
176 size_t
177 property_value::size()
178 {
179 	if (!byte_data.empty())
180 	{
181 		return byte_data.size();
182 	}
183 	return string_data.size() + 1;
184 }
185 
186 void
187 property_value::write_as_string(FILE *file)
188 {
189 	putc('"', file);
190 	if (byte_data.empty())
191 	{
192 		fputs(string_data.c_str(), file);
193 	}
194 	else
195 	{
196 		bool hasNull = (byte_data.back() == '\0');
197 		// Remove trailing null bytes from the string before printing as dts.
198 		if (hasNull)
199 		{
200 			byte_data.pop_back();
201 		}
202 		for (auto i : byte_data)
203 		{
204 			// FIXME Escape tabs, newlines, and so on.
205 			if (i == '\0')
206 			{
207 				fputs("\", \"", file);
208 				continue;
209 			}
210 			putc(i, file);
211 		}
212 		if (hasNull)
213 		{
214 			byte_data.push_back('\0');
215 		}
216 	}
217 	putc('"', file);
218 }
219 
220 void
221 property_value::write_as_cells(FILE *file)
222 {
223 	putc('<', file);
224 	assert((byte_data.size() % 4) == 0);
225 	for (auto i=byte_data.begin(), e=byte_data.end(); i!=e ; ++i)
226 	{
227 		uint32_t v = 0;
228 		v = (v << 8) | *i;
229 		++i;
230 		v = (v << 8) | *i;
231 		++i;
232 		v = (v << 8) | *i;
233 		++i;
234 		v = (v << 8) | *i;
235 		fprintf(file, "0x%" PRIx32, v);
236 		if (i+1 != e)
237 		{
238 			putc(' ', file);
239 		}
240 	}
241 	putc('>', file);
242 }
243 
244 void
245 property_value::write_as_bytes(FILE *file)
246 {
247 	putc('[', file);
248 	for (auto i=byte_data.begin(), e=byte_data.end(); i!=e ; i++)
249 	{
250 		fprintf(file, "%02hhx", *i);
251 		if (i+1 != e)
252 		{
253 			putc(' ', file);
254 		}
255 	}
256 	putc(']', file);
257 }
258 
259 void
260 property::parse_string(text_input_buffer &input)
261 {
262 	property_value v;
263 	assert(*input == '"');
264 	++input;
265 	std::vector<char> bytes;
266 	bool isEscaped = false;
267 	while (char c = *input)
268 	{
269 		if (c == '"' && !isEscaped)
270 		{
271 			input.consume('"');
272 			break;
273 		}
274 		isEscaped = (c == '\\');
275 		bytes.push_back(c);
276 		++input;
277 	}
278 	v.string_data = string(bytes.begin(), bytes.end());
279 	values.push_back(v);
280 }
281 
282 void
283 property::parse_cells(text_input_buffer &input, int cell_size)
284 {
285 	assert(*input == '<');
286 	++input;
287 	property_value v;
288 	input.next_token();
289 	while (!input.consume('>'))
290 	{
291 		input.next_token();
292 		// If this is a phandle then we need to get the name of the
293 		// referenced node
294 		if (input.consume('&'))
295 		{
296 			if (cell_size != 32)
297 			{
298 				input.parse_error("reference only permitted in 32-bit arrays");
299 				valid = false;
300 				return;
301 			}
302 			input.next_token();
303 			string referenced;
304 			if (!input.consume('{'))
305 			{
306 				referenced = input.parse_node_name();
307 			}
308 			else
309 			{
310 				referenced = input.parse_to('}');
311 				input.consume('}');
312 			}
313 			if (referenced.empty())
314 			{
315 				input.parse_error("Expected node name");
316 				valid = false;
317 				return;
318 			}
319 			input.next_token();
320 			// If we already have some bytes, make the phandle a
321 			// separate component.
322 			if (!v.byte_data.empty())
323 			{
324 				values.push_back(v);
325 				v = property_value();
326 			}
327 			v.string_data = referenced;
328 			v.type = property_value::PHANDLE;
329 			values.push_back(v);
330 			v = property_value();
331 		}
332 		else
333 		{
334 			//FIXME: We should support labels in the middle
335 			//of these, but we don't.
336 			unsigned long long val;
337 			if (!input.consume_integer_expression(val))
338 			{
339 				// FIXME: Distinguish invalid syntax from a
340 				// number that cannot be represented in an
341 				// unsigned long long.
342 				input.parse_error("Expected numbers in array of cells");
343 				valid = false;
344 				return;
345 			}
346 			// FIXME: No sign information available, so cannot
347 			// distinguish small negative values from large
348 			// positive ones, and thus we have to conservatively
349 			// permit anything that looks like a sign-extended
350 			// negative integer.
351 			if (cell_size < 64 && val >= (1ull << cell_size) &&
352 			    (val | ((1ull << (cell_size - 1)) - 1)) !=
353 			    std::numeric_limits<unsigned long long>::max())
354 			{
355 				std::string msg = "Value does not fit in a " +
356 					std::to_string(cell_size) + "-bit cell";
357 				input.parse_error(msg.c_str());
358 				valid = false;
359 				return;
360 			}
361 			switch (cell_size)
362 			{
363 				case 8:
364 					v.byte_data.push_back(val);
365 					break;
366 				case 16:
367 					push_big_endian(v.byte_data, (uint16_t)val);
368 					break;
369 				case 32:
370 					push_big_endian(v.byte_data, (uint32_t)val);
371 					break;
372 				case 64:
373 					push_big_endian(v.byte_data, (uint64_t)val);
374 					break;
375 				default:
376 					assert(0 && "Invalid cell size!");
377 			}
378 			input.next_token();
379 		}
380 	}
381 	// Don't store an empty string value here.
382 	if (v.byte_data.size() > 0)
383 	{
384 		values.push_back(v);
385 	}
386 }
387 
388 void
389 property::parse_bytes(text_input_buffer &input)
390 {
391 	assert(*input == '[');
392 	++input;
393 	property_value v;
394 	input.next_token();
395 	while (!input.consume(']'))
396 	{
397 		{
398 			//FIXME: We should support
399 			//labels in the middle of
400 			//these, but we don't.
401 			uint8_t val;
402 			if (!input.consume_hex_byte(val))
403 			{
404 				input.parse_error("Expected hex bytes in array of bytes");
405 				valid = false;
406 				return;
407 			}
408 			v.byte_data.push_back(val);
409 			input.next_token();
410 		}
411 	}
412 	values.push_back(v);
413 }
414 
415 void
416 property::parse_reference(text_input_buffer &input)
417 {
418 	assert(*input == '&');
419 	++input;
420 	input.next_token();
421 	property_value v;
422 	v.string_data = input.parse_node_name();
423 	if (v.string_data.empty())
424 	{
425 		input.parse_error("Expected node name");
426 		valid = false;
427 		return;
428 	}
429 	v.type = property_value::CROSS_REFERENCE;
430 	values.push_back(v);
431 }
432 
433 property::property(input_buffer &structs, input_buffer &strings)
434 {
435 	uint32_t name_offset;
436 	uint32_t length;
437 	valid = structs.consume_binary(length) &&
438 		structs.consume_binary(name_offset);
439 	if (!valid)
440 	{
441 		fprintf(stderr, "Failed to read property\n");
442 		return;
443 	}
444 	// Find the name
445 	input_buffer name_buffer = strings.buffer_from_offset(name_offset);
446 	if (name_buffer.finished())
447 	{
448 		fprintf(stderr, "Property name offset %" PRIu32
449 			" is past the end of the strings table\n",
450 			name_offset);
451 		valid = false;
452 		return;
453 	}
454 	key = name_buffer.parse_to(0);
455 
456 	// If we're empty, do not push anything as value.
457 	if (!length)
458 		return;
459 
460 	// Read the value
461 	uint8_t byte;
462 	property_value v;
463 	for (uint32_t i=0 ; i<length ; i++)
464 	{
465 		if (!(valid = structs.consume_binary(byte)))
466 		{
467 			fprintf(stderr, "Failed to read property value\n");
468 			return;
469 		}
470 		v.byte_data.push_back(byte);
471 	}
472 	values.push_back(v);
473 }
474 
475 void property::parse_define(text_input_buffer &input, define_map *defines)
476 {
477 	input.consume('$');
478 	if (!defines)
479 	{
480 		input.parse_error("No predefined properties to match name\n");
481 		valid = false;
482 		return;
483 	}
484 	string name = input.parse_property_name();
485 	define_map::iterator found;
486 	if ((name == string()) ||
487 	    ((found = defines->find(name)) == defines->end()))
488 	{
489 		input.parse_error("Undefined property name\n");
490 		valid = false;
491 		return;
492 	}
493 	values.push_back((*found).second->values[0]);
494 }
495 
496 property::property(text_input_buffer &input,
497                    string &&k,
498                    string_set &&l,
499                    bool semicolonTerminated,
500                    define_map *defines) : key(k), labels(l), valid(true)
501 {
502 	do {
503 		input.next_token();
504 		switch (*input)
505 		{
506 			case '$':
507 			{
508 				parse_define(input, defines);
509 				if (valid)
510 				{
511 					break;
512 				}
513 			}
514 			[[fallthrough]];
515 			default:
516 				input.parse_error("Invalid property value.");
517 				valid = false;
518 				return;
519 			case '/':
520 			{
521 				if (input.consume("/incbin/(\""))
522 				{
523 					auto loc = input.location();
524 					std::string filename = input.parse_to('"');
525 					if (!(valid = input.consume('"')))
526 					{
527 						loc.report_error("Syntax error, expected '\"' to terminate /incbin/(");
528 						return;
529 					}
530 					property_value v;
531 					if (!(valid = input.read_binary_file(filename, v.byte_data)))
532 					{
533 						input.parse_error("Cannot open binary include file");
534 						return;
535 					}
536 					if (!(valid &= input.consume(')')))
537 					{
538 						input.parse_error("Syntax error, expected ')' to terminate /incbin/(");
539 						return;
540 					}
541 					values.push_back(v);
542 					break;
543 				}
544 				unsigned long long bits = 0;
545 				valid = input.consume("/bits/");
546 				input.next_token();
547 				valid &= input.consume_integer(bits);
548 				if ((bits != 8) &&
549 				    (bits != 16) &&
550 				    (bits != 32) &&
551 				    (bits != 64)) {
552 					input.parse_error("Invalid size for elements");
553 					valid = false;
554 				}
555 				if (!valid) return;
556 				input.next_token();
557 				if (*input != '<')
558 				{
559 					input.parse_error("/bits/ directive is only valid on arrays");
560 					valid = false;
561 					return;
562 				}
563 				parse_cells(input, bits);
564 				break;
565 			}
566 			case '"':
567 				parse_string(input);
568 				break;
569 			case '<':
570 				parse_cells(input, 32);
571 				break;
572 			case '[':
573 				parse_bytes(input);
574 				break;
575 			case '&':
576 				parse_reference(input);
577 				break;
578 			case ';':
579 			{
580 				break;
581 			}
582 		}
583 		input.next_token();
584 	} while (input.consume(','));
585 	if (semicolonTerminated && !input.consume(';'))
586 	{
587 		input.parse_error("Expected ; at end of property");
588 		valid = false;
589 	}
590 }
591 
592 property_ptr
593 property::parse_dtb(input_buffer &structs, input_buffer &strings)
594 {
595 	property_ptr p(new property(structs, strings));
596 	if (!p->valid)
597 	{
598 		p = nullptr;
599 	}
600 	return p;
601 }
602 
603 property_ptr
604 property::parse(text_input_buffer &input, string &&key, string_set &&label,
605                 bool semicolonTerminated, define_map *defines)
606 {
607 	property_ptr p(new property(input,
608 	                            std::move(key),
609 	                            std::move(label),
610 	                            semicolonTerminated,
611 	                            defines));
612 	if (!p->valid)
613 	{
614 		p = nullptr;
615 	}
616 	return p;
617 }
618 
619 void
620 property::write(dtb::output_writer &writer, dtb::string_table &strings)
621 {
622 	writer.write_token(dtb::FDT_PROP);
623 	byte_buffer value_buffer;
624 	for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
625 	{
626 		i->push_to_buffer(value_buffer);
627 	}
628 	writer.write_data((uint32_t)value_buffer.size());
629 	writer.write_comment(key);
630 	writer.write_data(strings.add_string(key));
631 	writer.write_data(value_buffer);
632 }
633 
634 bool
635 property_value::try_to_merge(property_value &other)
636 {
637 	resolve_type();
638 	switch (type)
639 	{
640 		case UNKNOWN:
641 			__builtin_unreachable();
642 			assert(0);
643 			return false;
644 		case EMPTY:
645 			*this = other;
646 			[[fallthrough]];
647 		case STRING:
648 		case STRING_LIST:
649 		case CROSS_REFERENCE:
650 			return false;
651 		case PHANDLE:
652 		case BINARY:
653 			if (other.type == PHANDLE || other.type == BINARY)
654 			{
655 				type = BINARY;
656 				byte_data.insert(byte_data.end(), other.byte_data.begin(),
657 				                 other.byte_data.end());
658 				return true;
659 			}
660 	}
661 	return false;
662 }
663 
664 void
665 property::write_dts(FILE *file, int indent)
666 {
667 	for (int i=0 ; i<indent ; i++)
668 	{
669 		putc('\t', file);
670 	}
671 #ifdef PRINT_LABELS
672 	for (auto &l : labels)
673 	{
674 		fputs(l.c_str(), file);
675 		fputs(": ", file);
676 	}
677 #endif
678 	if (key != string())
679 	{
680 		fputs(key.c_str(), file);
681 	}
682 	if (!values.empty())
683 	{
684 		std::vector<property_value> *vals = &values;
685 		std::vector<property_value> v;
686 		// If we've got multiple values then try to merge them all together.
687 		if (values.size() > 1)
688 		{
689 			vals = &v;
690 			v.push_back(values.front());
691 			for (auto i=(++begin()), e=end() ; i!=e ; ++i)
692 			{
693 				if (!v.back().try_to_merge(*i))
694 				{
695 					v.push_back(*i);
696 				}
697 			}
698 		}
699 		fputs(" = ", file);
700 		for (auto i=vals->begin(), e=vals->end() ; i!=e ; ++i)
701 		{
702 			i->write_dts(file);
703 			if (i+1 != e)
704 			{
705 				putc(',', file);
706 				putc(' ', file);
707 			}
708 		}
709 	}
710 	fputs(";\n", file);
711 }
712 
713 size_t
714 property::offset_of_value(property_value &val)
715 {
716 	size_t off = 0;
717 	for (auto &v : values)
718 	{
719 		if (&v == &val)
720 		{
721 			return off;
722 		}
723 		off += v.size();
724 	}
725 	return -1;
726 }
727 
728 string
729 node::parse_name(text_input_buffer &input, bool &is_property, const char *error)
730 {
731 	if (!valid)
732 	{
733 		return string();
734 	}
735 	input.next_token();
736 	if (is_property)
737 	{
738 		return input.parse_property_name();
739 	}
740 	string n = input.parse_node_or_property_name(is_property);
741 	if (n.empty())
742 	{
743 		if (n.empty())
744 		{
745 			input.parse_error(error);
746 			valid = false;
747 		}
748 	}
749 	return n;
750 }
751 
752 node::visit_behavior
753 node::visit(std::function<visit_behavior(node&, node*)> fn, node *parent)
754 {
755 	visit_behavior behavior;
756 	behavior = fn(*this, parent);
757 	if (behavior == VISIT_BREAK)
758 	{
759 		return VISIT_BREAK;
760 	}
761 	else if (behavior != VISIT_CONTINUE)
762 	{
763 		for (auto &&c : children)
764 		{
765 			behavior = c->visit(fn, this);
766 			// Any status other than VISIT_RECURSE stops our execution and
767 			// bubbles up to our caller.  The caller may then either continue
768 			// visiting nodes that are siblings to this one or completely halt
769 			// visiting.
770 			if (behavior != VISIT_RECURSE)
771 			{
772 				return behavior;
773 			}
774 		}
775 	}
776 	// Continue recursion by default
777 	return VISIT_RECURSE;
778 }
779 
780 node::node(input_buffer &structs, input_buffer &strings) : valid(true)
781 {
782 	std::vector<char> bytes;
783 	while (structs[0] != '\0' && structs[0] != '@')
784 	{
785 		bytes.push_back(structs[0]);
786 		++structs;
787 	}
788 	name = string(bytes.begin(), bytes.end());
789 	bytes.clear();
790 	if (structs[0] == '@')
791 	{
792 		++structs;
793 		while (structs[0] != '\0')
794 		{
795 			bytes.push_back(structs[0]);
796 			++structs;
797 		}
798 		unit_address = string(bytes.begin(), bytes.end());
799 	}
800 	++structs;
801 	uint32_t token;
802 	while (structs.consume_binary(token))
803 	{
804 		switch (token)
805 		{
806 			default:
807 				fprintf(stderr, "Unexpected token 0x%" PRIx32
808 					" while parsing node.\n", token);
809 				valid = false;
810 				return;
811 			// Child node, parse it.
812 			case dtb::FDT_BEGIN_NODE:
813 			{
814 				node_ptr child = node::parse_dtb(structs, strings);
815 				if (child == 0)
816 				{
817 					valid = false;
818 					return;
819 				}
820 				children.push_back(std::move(child));
821 				break;
822 			}
823 			// End of this node, no errors.
824 			case dtb::FDT_END_NODE:
825 				return;
826 			// Property, parse it.
827 			case dtb::FDT_PROP:
828 			{
829 				property_ptr prop = property::parse_dtb(structs, strings);
830 				if (prop == 0)
831 				{
832 					valid = false;
833 					return;
834 				}
835 				props.push_back(prop);
836 				break;
837 			}
838 				break;
839 			// End of structs table.  Should appear after
840 			// the end of the last node.
841 			case dtb::FDT_END:
842 				fprintf(stderr, "Unexpected FDT_END token while parsing node.\n");
843 				valid = false;
844 				return;
845 			// NOPs are padding.  Ignore them.
846 			case dtb::FDT_NOP:
847 				break;
848 		}
849 	}
850 	fprintf(stderr, "Failed to read token from structs table while parsing node.\n");
851 	valid = false;
852 	return;
853 }
854 
855 
856 node::node(const string &n,
857            const std::vector<property_ptr> &p)
858 	: name(n)
859 {
860 	props.insert(props.begin(), p.begin(), p.end());
861 }
862 
863 node_ptr node::create_special_node(const string &name,
864                                    const std::vector<property_ptr> &props)
865 {
866 	node_ptr n(new node(name, props));
867 	return n;
868 }
869 
870 node::node(text_input_buffer &input,
871            device_tree &tree,
872            string &&n,
873            std::unordered_set<string> &&l,
874            string &&a,
875            define_map *defines)
876 	: labels(l), name(n), unit_address(a), valid(true)
877 {
878 	if (!input.consume('{'))
879 	{
880 		input.parse_error("Expected { to start new device tree node.\n");
881 	}
882 	input.next_token();
883 	while (valid && !input.consume('}'))
884 	{
885 		// flag set if we find any characters that are only in
886 		// the property name character set, not the node
887 		bool is_property = false;
888 		// flag set if our node is marked as /omit-if-no-ref/ to be
889 		// garbage collected later if nothing references it
890 		bool marked_omit_if_no_ref = false;
891 		string child_name, child_address;
892 		std::unordered_set<string> child_labels;
893 		auto parse_delete = [&](const char *expected, bool at)
894 		{
895 			if (child_name == string())
896 			{
897 				input.parse_error(expected);
898 				valid = false;
899 				return;
900 			}
901 			input.next_token();
902 			if (at && input.consume('@'))
903 			{
904 				child_name += '@';
905 				child_name += parse_name(input, is_property, "Expected unit address");
906 			}
907 			if (!input.consume(';'))
908 			{
909 				input.parse_error("Expected semicolon");
910 				valid = false;
911 				return;
912 			}
913 			input.next_token();
914 		};
915 		if (input.consume("/delete-node/"))
916 		{
917 			input.next_token();
918 			child_name = input.parse_node_name();
919 			parse_delete("Expected node name", true);
920 			if (valid)
921 			{
922 				deleted_children.insert(child_name);
923 			}
924 			continue;
925 		}
926 		if (input.consume("/delete-property/"))
927 		{
928 			input.next_token();
929 			child_name = input.parse_property_name();
930 			parse_delete("Expected property name", false);
931 			if (valid)
932 			{
933 				deleted_props.insert(child_name);
934 			}
935 			continue;
936 		}
937 		if (input.consume("/omit-if-no-ref/"))
938 		{
939 			input.next_token();
940 			marked_omit_if_no_ref = true;
941 			tree.set_needs_garbage_collection();
942 		}
943 		child_name = parse_name(input, is_property,
944 				"Expected property or node name");
945 		while (input.consume(':'))
946 		{
947 			// Node labels can contain any characters?  The
948 			// spec doesn't say, so we guess so...
949 			is_property = false;
950 			child_labels.insert(std::move(child_name));
951 			child_name = parse_name(input, is_property, "Expected property or node name");
952 		}
953 		if (input.consume('@'))
954 		{
955 			child_address = parse_name(input, is_property, "Expected unit address");
956 		}
957 		if (!valid)
958 		{
959 			return;
960 		}
961 		input.next_token();
962 		// If we're parsing a property, then we must actually do that.
963 		if (input.consume('='))
964 		{
965 			property_ptr p = property::parse(input, std::move(child_name),
966 					std::move(child_labels), true, defines);
967 			if (p == 0)
968 			{
969 				valid = false;
970 			}
971 			else
972 			{
973 				props.push_back(p);
974 			}
975 		}
976 		else if (!is_property && *input == ('{'))
977 		{
978 			node_ptr child = node::parse(input, tree, std::move(child_name),
979 					std::move(child_labels), std::move(child_address), defines);
980 			if (child)
981 			{
982 				child->omit_if_no_ref = marked_omit_if_no_ref;
983 				children.push_back(std::move(child));
984 			}
985 			else
986 			{
987 				valid = false;
988 			}
989 		}
990 		else if (input.consume(';'))
991 		{
992 			props.push_back(property_ptr(new property(std::move(child_name), std::move(child_labels))));
993 		}
994 		else
995 		{
996 			input.parse_error("Error parsing property.  Expected property value");
997 			valid = false;
998 		}
999 		input.next_token();
1000 	}
1001 	input.next_token();
1002 	input.consume(';');
1003 }
1004 
1005 bool
1006 node::cmp_properties(property_ptr &p1, property_ptr &p2)
1007 {
1008 	return p1->get_key() < p2->get_key();
1009 }
1010 
1011 bool
1012 node::cmp_children(node_ptr &c1, node_ptr &c2)
1013 {
1014 	if (c1->name == c2->name)
1015 	{
1016 		return c1->unit_address < c2->unit_address;
1017 	}
1018 	return c1->name < c2->name;
1019 }
1020 
1021 void
1022 node::sort()
1023 {
1024 	std::sort(property_begin(), property_end(), cmp_properties);
1025 	std::sort(child_begin(), child_end(), cmp_children);
1026 	for (auto &c : child_nodes())
1027 	{
1028 		c->sort();
1029 	}
1030 }
1031 
1032 node_ptr
1033 node::parse(text_input_buffer &input,
1034             device_tree &tree,
1035             string &&name,
1036             string_set &&label,
1037             string &&address,
1038             define_map *defines)
1039 {
1040 	node_ptr n(new node(input,
1041 	                    tree,
1042 	                    std::move(name),
1043 	                    std::move(label),
1044 	                    std::move(address),
1045 	                    defines));
1046 	if (!n->valid)
1047 	{
1048 		n = 0;
1049 	}
1050 	return n;
1051 }
1052 
1053 node_ptr
1054 node::parse_dtb(input_buffer &structs, input_buffer &strings)
1055 {
1056 	node_ptr n(new node(structs, strings));
1057 	if (!n->valid)
1058 	{
1059 		n = 0;
1060 	}
1061 	return n;
1062 }
1063 
1064 property_ptr
1065 node::get_property(const string &key)
1066 {
1067 	for (auto &i : props)
1068 	{
1069 		if (i->get_key() == key)
1070 		{
1071 			return i;
1072 		}
1073 	}
1074 	return 0;
1075 }
1076 
1077 void
1078 node::merge_node(node_ptr &other)
1079 {
1080 	for (auto &l : other->labels)
1081 	{
1082 		labels.insert(l);
1083 	}
1084 	children.erase(std::remove_if(children.begin(), children.end(),
1085 			[&](const node_ptr &p) {
1086 				string full_name = p->name;
1087 				if (p->unit_address != string())
1088 				{
1089 					full_name += '@';
1090 					full_name += p->unit_address;
1091 				}
1092 				if (other->deleted_children.count(full_name) > 0)
1093 				{
1094 					other->deleted_children.erase(full_name);
1095 					return true;
1096 				}
1097 				return false;
1098 			}), children.end());
1099 	props.erase(std::remove_if(props.begin(), props.end(),
1100 			[&](const property_ptr &p) {
1101 				if (other->deleted_props.count(p->get_key()) > 0)
1102 				{
1103 					other->deleted_props.erase(p->get_key());
1104 					return true;
1105 				}
1106 				return false;
1107 			}), props.end());
1108 	// Note: this is an O(n*m) operation.  It might be sensible to
1109 	// optimise this if we find that there are nodes with very
1110 	// large numbers of properties, but for typical usage the
1111 	// entire vector will fit (easily) into cache, so iterating
1112 	// over it repeatedly isn't that expensive.
1113 	for (auto &p : other->properties())
1114 	{
1115 		bool found = false;
1116 		for (auto &mp : properties())
1117 		{
1118 			if (mp->get_key() == p->get_key())
1119 			{
1120 				mp = p;
1121 				found = true;
1122 				break;
1123 			}
1124 		}
1125 		if (!found)
1126 		{
1127 			add_property(p);
1128 		}
1129 	}
1130 	for (auto &c : other->children)
1131 	{
1132 		bool found = false;
1133 		for (auto &i : children)
1134 		{
1135 			if (i->name == c->name && i->unit_address == c->unit_address)
1136 			{
1137 				i->merge_node(c);
1138 				found = true;
1139 				break;
1140 			}
1141 		}
1142 		if (!found)
1143 		{
1144 			children.push_back(std::move(c));
1145 		}
1146 	}
1147 }
1148 
1149 void
1150 node::write(dtb::output_writer &writer, dtb::string_table &strings)
1151 {
1152 	writer.write_token(dtb::FDT_BEGIN_NODE);
1153 	byte_buffer name_buffer;
1154 	push_string(name_buffer, name);
1155 	if (unit_address != string())
1156 	{
1157 		name_buffer.push_back('@');
1158 		push_string(name_buffer, unit_address);
1159 	}
1160 	writer.write_comment(name);
1161 	writer.write_data(name_buffer);
1162 	writer.write_data((uint8_t)0);
1163 	for (auto p : properties())
1164 	{
1165 		p->write(writer, strings);
1166 	}
1167 	for (auto &c : child_nodes())
1168 	{
1169 		c->write(writer, strings);
1170 	}
1171 	writer.write_token(dtb::FDT_END_NODE);
1172 }
1173 
1174 void
1175 node::write_dts(FILE *file, int indent)
1176 {
1177 	for (int i=0 ; i<indent ; i++)
1178 	{
1179 		putc('\t', file);
1180 	}
1181 #ifdef PRINT_LABELS
1182 	for (auto &label : labels)
1183 	{
1184 		fprintf(file, "%s: ", label.c_str());
1185 	}
1186 #endif
1187 	if (name != string())
1188 	{
1189 		fputs(name.c_str(), file);
1190 	}
1191 	if (unit_address != string())
1192 	{
1193 		putc('@', file);
1194 		fputs(unit_address.c_str(), file);
1195 	}
1196 	fputs(" {\n\n", file);
1197 	for (auto p : properties())
1198 	{
1199 		p->write_dts(file, indent+1);
1200 	}
1201 	for (auto &c : child_nodes())
1202 	{
1203 		c->write_dts(file, indent+1);
1204 	}
1205 	for (int i=0 ; i<indent ; i++)
1206 	{
1207 		putc('\t', file);
1208 	}
1209 	fputs("};\n", file);
1210 }
1211 
1212 void
1213 device_tree::collect_names_recursive(node_ptr &n, node_path &path)
1214 {
1215 	path.push_back(std::make_pair(n->name, n->unit_address));
1216 	for (const string &name : n->labels)
1217 	{
1218 		if (name != string())
1219 		{
1220 			auto iter = node_names.find(name);
1221 			if (iter == node_names.end())
1222 			{
1223 				node_names.insert(std::make_pair(name, n.get()));
1224 				node_paths.insert(std::make_pair(name, path));
1225 				ordered_node_paths.push_back({name, path});
1226 			}
1227 			else
1228 			{
1229 				node_names.erase(iter);
1230 				auto i = node_paths.find(name);
1231 				if (i != node_paths.end())
1232 				{
1233 					node_paths.erase(name);
1234 				}
1235 				fprintf(stderr, "Label not unique: %s.  References to this label will not be resolved.\n", name.c_str());
1236 			}
1237 		}
1238 	}
1239 	for (auto &c : n->child_nodes())
1240 	{
1241 		collect_names_recursive(c, path);
1242 	}
1243 	// Now we collect the phandles and properties that reference
1244 	// other nodes.
1245 	for (auto &p : n->properties())
1246 	{
1247 		for (auto &v : *p)
1248 		{
1249 			if (v.is_phandle())
1250 			{
1251 				fixups.push_back({path, p, v});
1252 			}
1253 			if (v.is_cross_reference())
1254 			{
1255 				cross_references.push_back(&v);
1256 			}
1257 		}
1258 		if ((p->get_key() == "phandle") ||
1259 		    (p->get_key() == "linux,phandle"))
1260 		{
1261 			if (p->begin()->byte_data.size() != 4)
1262 			{
1263 				fprintf(stderr, "Invalid phandle value for node %s.  Should be a 4-byte value.\n", n->name.c_str());
1264 				valid = false;
1265 			}
1266 			else
1267 			{
1268 				uint32_t phandle = p->begin()->get_as_uint32();
1269 				used_phandles.insert(std::make_pair(phandle, n.get()));
1270 			}
1271 		}
1272 	}
1273 	path.pop_back();
1274 }
1275 
1276 void
1277 device_tree::collect_names()
1278 {
1279 	node_path p;
1280 	node_names.clear();
1281 	node_paths.clear();
1282 	ordered_node_paths.clear();
1283 	cross_references.clear();
1284 	fixups.clear();
1285 	collect_names_recursive(root, p);
1286 }
1287 
1288 property_ptr
1289 device_tree::assign_phandle(node *n, uint32_t &phandle)
1290 {
1291 	// If there is an existing phandle, use it
1292 	property_ptr p = n->get_property("phandle");
1293 	if (p == 0)
1294 	{
1295 		p = n->get_property("linux,phandle");
1296 	}
1297 	if (p == 0)
1298 	{
1299 		// Otherwise insert a new phandle node
1300 		property_value v;
1301 		while (used_phandles.find(phandle) != used_phandles.end())
1302 		{
1303 			// Note that we only don't need to
1304 			// store this phandle in the set,
1305 			// because we are monotonically
1306 			// increasing the value of phandle and
1307 			// so will only ever revisit this value
1308 			// if we have used 2^32 phandles, at
1309 			// which point our blob won't fit in
1310 			// any 32-bit system and we've done
1311 			// something badly wrong elsewhere
1312 			// already.
1313 			phandle++;
1314 		}
1315 		push_big_endian(v.byte_data, phandle++);
1316 		if (phandle_node_name == BOTH || phandle_node_name == LINUX)
1317 		{
1318 			p.reset(new property("linux,phandle"));
1319 			p->add_value(v);
1320 			n->add_property(p);
1321 		}
1322 		if (phandle_node_name == BOTH || phandle_node_name == EPAPR)
1323 		{
1324 			p.reset(new property("phandle"));
1325 			p->add_value(v);
1326 			n->add_property(p);
1327 		}
1328 	}
1329 
1330 	return (p);
1331 }
1332 
1333 void
1334 device_tree::assign_phandles(node_ptr &n, uint32_t &next)
1335 {
1336 	if (!n->labels.empty())
1337 	{
1338 		assign_phandle(n.get(), next);
1339 	}
1340 
1341 	for (auto &c : n->child_nodes())
1342 	{
1343 		assign_phandles(c, next);
1344 	}
1345 }
1346 
1347 void
1348 device_tree::resolve_cross_references(uint32_t &phandle)
1349 {
1350 	for (auto *pv : cross_references)
1351 	{
1352 		node_path path = node_paths[pv->string_data];
1353 		auto p = path.begin();
1354 		auto pe = path.end();
1355 		if (p != pe)
1356 		{
1357 			// Skip the first name in the path.  It's always "", and implicitly /
1358 			for (++p ; p!=pe ; ++p)
1359 			{
1360 				pv->byte_data.push_back('/');
1361 				push_string(pv->byte_data, p->first);
1362 				if (!(p->second.empty()))
1363 				{
1364 					pv->byte_data.push_back('@');
1365 					push_string(pv->byte_data, p->second);
1366 				}
1367 			}
1368 			pv->byte_data.push_back(0);
1369 		}
1370 	}
1371 	std::unordered_map<property_value*, fixup&> phandle_set;
1372 	for (auto &i : fixups)
1373 	{
1374 		phandle_set.insert({&i.val, i});
1375 	}
1376 	std::vector<std::reference_wrapper<fixup>> sorted_phandles;
1377 	root->visit([&](node &n, node *) {
1378 		for (auto &p : n.properties())
1379 		{
1380 			for (auto &v : *p)
1381 			{
1382 				auto i = phandle_set.find(&v);
1383 				if (i != phandle_set.end())
1384 				{
1385 					sorted_phandles.push_back(i->second);
1386 				}
1387 			}
1388 		}
1389 		// Allow recursion
1390 		return node::VISIT_RECURSE;
1391 	}, nullptr);
1392 	assert(sorted_phandles.size() == fixups.size());
1393 	for (auto &i : sorted_phandles)
1394 	{
1395 		string target_name = i.get().val.string_data;
1396 		node *target = nullptr;
1397 		string possible;
1398 		// If the node name is a path, then look it up by following the path,
1399 		// otherwise jump directly to the named node.
1400 		if (target_name[0] == '/')
1401 		{
1402 			string path;
1403 			target = root.get();
1404 			std::istringstream ss(target_name);
1405 			string path_element;
1406 			// Read the leading /
1407 			std::getline(ss, path_element, '/');
1408 			// Iterate over path elements
1409 			while (!ss.eof())
1410 			{
1411 				path += '/';
1412 				std::getline(ss, path_element, '/');
1413 				std::istringstream nss(path_element);
1414 				string node_name, node_address;
1415 				std::getline(nss, node_name, '@');
1416 				std::getline(nss, node_address, '@');
1417 				node *next = nullptr;
1418 				for (auto &c : target->child_nodes())
1419 				{
1420 					if (c->name == node_name)
1421 					{
1422 						if (c->unit_address == node_address)
1423 						{
1424 							next = c.get();
1425 							break;
1426 						}
1427 						else
1428 						{
1429 							possible = path + c->name;
1430 							if (c->unit_address != string())
1431 							{
1432 								possible += '@';
1433 								possible += c->unit_address;
1434 							}
1435 						}
1436 					}
1437 				}
1438 				path += node_name;
1439 				if (node_address != string())
1440 				{
1441 					path += '@';
1442 					path += node_address;
1443 				}
1444 				target = next;
1445 				if (target == nullptr)
1446 				{
1447 					break;
1448 				}
1449 			}
1450 		}
1451 		else
1452 		{
1453 			target = node_names[target_name];
1454 		}
1455 		if (target == nullptr)
1456 		{
1457 			if (is_plugin)
1458 			{
1459 				unresolved_fixups.push_back(i);
1460 				continue;
1461 			}
1462 			else
1463 			{
1464 				fprintf(stderr, "Failed to find node with label: %s\n", target_name.c_str());
1465 				if (possible != string())
1466 				{
1467 					fprintf(stderr, "Possible intended match: %s\n", possible.c_str());
1468 				}
1469 				valid = 0;
1470 				return;
1471 			}
1472 		}
1473 		// If there is an existing phandle, use it
1474 		property_ptr p = assign_phandle(target, phandle);
1475 		p->begin()->push_to_buffer(i.get().val.byte_data);
1476 		assert(i.get().val.byte_data.size() == 4);
1477 	}
1478 }
1479 
1480 bool
1481 device_tree::garbage_collect_marked_nodes()
1482 {
1483 	std::unordered_set<node*> previously_referenced_nodes;
1484 	std::unordered_set<node*> newly_referenced_nodes;
1485 
1486 	auto mark_referenced_nodes_used = [&](node &n)
1487 	{
1488 		for (auto &p : n.properties())
1489 		{
1490 			for (auto &v : *p)
1491 			{
1492 				if (v.is_phandle())
1493 				{
1494 					node *nx = node_names[v.string_data];
1495 					if (nx == nullptr)
1496 					{
1497 						// Try it again, but as a path
1498 						for (auto &s : node_paths)
1499 						{
1500 							if (v.string_data == s.second.to_string())
1501 							{
1502 								nx = node_names[s.first];
1503 								break;
1504 							}
1505 						}
1506 					}
1507 					if (nx == nullptr)
1508 					{
1509 						// Couldn't resolve this one?
1510 						continue;
1511 					}
1512 					// Only mark those currently unmarked
1513 					if (!nx->used)
1514 					{
1515 							nx->used = 1;
1516 							newly_referenced_nodes.insert(nx);
1517 					}
1518 				}
1519 			}
1520 		}
1521 	};
1522 
1523 	// Seed our referenced nodes with those that have been seen by a node that
1524 	// either will not be omitted if it's unreferenced or has a symbol.
1525 	// Nodes with symbols are explicitly not garbage collected because they may
1526 	// be expected for referencing by an overlay, and we do not want surprises
1527 	// there.
1528 	root->visit([&](node &n, node *) {
1529 		if (!n.omit_if_no_ref || (write_symbols && !n.labels.empty()))
1530 		{
1531 			mark_referenced_nodes_used(n);
1532 		}
1533 		// Recurse as normal
1534 		return node::VISIT_RECURSE;
1535 	}, nullptr);
1536 
1537 	while (!newly_referenced_nodes.empty())
1538 	{
1539 			previously_referenced_nodes = std::move(newly_referenced_nodes);
1540 			for (auto *n : previously_referenced_nodes)
1541 			{
1542 				mark_referenced_nodes_used(*n);
1543 			}
1544 	}
1545 
1546 	previously_referenced_nodes.clear();
1547 	bool children_deleted = false;
1548 
1549 	// Delete
1550 	root->visit([&](node &n, node *) {
1551 		bool gc_children = false;
1552 
1553 		for (auto &cn : n.child_nodes())
1554 		{
1555 				if (cn->omit_if_no_ref && !cn->used)
1556 				{
1557 					gc_children = true;
1558 					break;
1559 				}
1560 		}
1561 
1562 		if (gc_children)
1563 		{
1564 			children_deleted = true;
1565 			n.delete_children_if([](node_ptr &nx) {
1566 				return (nx->omit_if_no_ref && !nx->used);
1567 			});
1568 
1569 			return node::VISIT_CONTINUE;
1570 		}
1571 
1572 		return node::VISIT_RECURSE;
1573 	}, nullptr);
1574 
1575 	return children_deleted;
1576 }
1577 
1578 void
1579 device_tree::parse_file(text_input_buffer &input,
1580                         std::vector<node_ptr> &roots,
1581                         bool &read_header)
1582 {
1583 	input.next_token();
1584 	// Read the header
1585 	while (input.consume("/dts-v1/;"))
1586 	{
1587 		read_header = true;
1588 		input.next_token();
1589 	}
1590 	if (input.consume("/plugin/;"))
1591 	{
1592 		is_plugin = true;
1593 	}
1594 	input.next_token();
1595 	if (!read_header)
1596 	{
1597 		input.parse_error("Expected /dts-v1/; version string");
1598 	}
1599 	// Read any memory reservations
1600 	while (input.consume("/memreserve/"))
1601 	{
1602 		unsigned long long start, len;
1603 		input.next_token();
1604 		// Read the start and length.
1605 		if (!(input.consume_integer_expression(start) &&
1606 		    (input.next_token(),
1607 		    input.consume_integer_expression(len))))
1608 		{
1609 			input.parse_error("Expected size on /memreserve/ node.");
1610 		}
1611 		else
1612 		{
1613 			reservations.push_back(reservation(start, len));
1614 		}
1615 		input.next_token();
1616 		input.consume(';');
1617 		input.next_token();
1618 	}
1619 	while (valid && !input.finished())
1620 	{
1621 		node_ptr n;
1622 		if (input.consume('/'))
1623 		{
1624 			input.next_token();
1625 			n = node::parse(input, *this, string(), string_set(), string(), &defines);
1626 		}
1627 		else if (input.consume('&'))
1628 		{
1629 			input.next_token();
1630 			string name;
1631 			bool name_is_path_reference = false;
1632 			// This is to deal with names intended as path references, e.g. &{/path}.
1633 			// While it may make sense in a non-plugin context, we don't support such
1634 			// usage at this time.
1635 			if (input.consume('{') && is_plugin)
1636 			{
1637 				name = input.parse_to('}');
1638 				input.consume('}');
1639 				name_is_path_reference = true;
1640 			}
1641 			else
1642 			{
1643 				name = input.parse_node_name();
1644 			}
1645 			input.next_token();
1646 			n = node::parse(input, *this, std::move(name), string_set(), string(), &defines);
1647 			if (n)
1648 			{
1649 				n->name_is_path_reference = name_is_path_reference;
1650 			}
1651 		}
1652 		else
1653 		{
1654 			input.parse_error("Failed to find root node /.");
1655 		}
1656 		if (n)
1657 		{
1658 			roots.push_back(std::move(n));
1659 		}
1660 		else
1661 		{
1662 			valid = false;
1663 		}
1664 		input.next_token();
1665 	}
1666 }
1667 
1668 template<class writer> void
1669 device_tree::write(int fd)
1670 {
1671 	dtb::string_table st;
1672 	dtb::header head;
1673 	writer head_writer;
1674 	writer reservation_writer;
1675 	writer struct_writer;
1676 	writer strings_writer;
1677 
1678 	// Build the reservation table
1679 	reservation_writer.write_comment(string("Memory reservations"));
1680 	reservation_writer.write_label(string("dt_reserve_map"));
1681 	for (auto &i : reservations)
1682 	{
1683 		reservation_writer.write_comment(string("Reservation start"));
1684 		reservation_writer.write_data(i.first);
1685 		reservation_writer.write_comment(string("Reservation length"));
1686 		reservation_writer.write_data(i.second);
1687 	}
1688 	// Write n spare reserve map entries, plus the trailing 0.
1689 	for (uint32_t i=0 ; i<=spare_reserve_map_entries ; i++)
1690 	{
1691 		reservation_writer.write_data((uint64_t)0);
1692 		reservation_writer.write_data((uint64_t)0);
1693 	}
1694 
1695 
1696 	struct_writer.write_comment(string("Device tree"));
1697 	struct_writer.write_label(string("dt_struct_start"));
1698 	root->write(struct_writer, st);
1699 	struct_writer.write_token(dtb::FDT_END);
1700 	struct_writer.write_label(string("dt_struct_end"));
1701 
1702 	st.write(strings_writer);
1703 	// Find the strings size before we stick padding on the end.
1704 	// Note: We should possibly use a new writer for the padding.
1705 	head.size_dt_strings = strings_writer.size();
1706 
1707 	// Stick the padding in the strings writer, but after the
1708 	// marker indicating that it's the end.
1709 	// Note: We probably should add a padding call to the writer so
1710 	// that the asm back end can write padding directives instead
1711 	// of a load of 0 bytes.
1712 	for (uint32_t i=0 ; i<blob_padding ; i++)
1713 	{
1714 		strings_writer.write_data((uint8_t)0);
1715 	}
1716 	head.totalsize = sizeof(head) + strings_writer.size() +
1717 		struct_writer.size() + reservation_writer.size();
1718 	while (head.totalsize < minimum_blob_size)
1719 	{
1720 		head.totalsize++;
1721 		strings_writer.write_data((uint8_t)0);
1722 	}
1723 	head.off_dt_struct = sizeof(head) + reservation_writer.size();;
1724 	head.off_dt_strings = head.off_dt_struct + struct_writer.size();
1725 	head.off_mem_rsvmap = sizeof(head);
1726 	head.boot_cpuid_phys = boot_cpu;
1727 	head.size_dt_struct = struct_writer.size();
1728 	head.write(head_writer);
1729 
1730 	head_writer.write_to_file(fd);
1731 	reservation_writer.write_to_file(fd);
1732 	struct_writer.write_to_file(fd);
1733 	strings_writer.write_label(string("dt_blob_end"));
1734 	strings_writer.write_to_file(fd);
1735 }
1736 
1737 node*
1738 device_tree::referenced_node(property_value &v)
1739 {
1740 	if (v.is_phandle())
1741 	{
1742 		return node_names[v.string_data];
1743 	}
1744 	if (v.is_binary())
1745 	{
1746 		return used_phandles[v.get_as_uint32()];
1747 	}
1748 	return 0;
1749 }
1750 
1751 void
1752 device_tree::write_binary(int fd)
1753 {
1754 	write<dtb::binary_writer>(fd);
1755 }
1756 
1757 void
1758 device_tree::write_asm(int fd)
1759 {
1760 	write<dtb::asm_writer>(fd);
1761 }
1762 
1763 void
1764 device_tree::write_dts(int fd)
1765 {
1766 	FILE *file = fdopen(fd, "w");
1767 	fputs("/dts-v1/;\n\n", file);
1768 
1769 	if (!reservations.empty())
1770 	{
1771 		const char msg[] = "/memreserve/";
1772 		// Exclude the null byte when we're writing it out to the file.
1773 		fwrite(msg, sizeof(msg) - 1, 1, file);
1774 		for (auto &i : reservations)
1775 		{
1776 			fprintf(file, " 0x%" PRIx64 " 0x%" PRIx64, i.first, i.second);
1777 		}
1778 		fputs(";\n\n", file);
1779 	}
1780 	putc('/', file);
1781 	putc(' ', file);
1782 	root->write_dts(file, 0);
1783 	fclose(file);
1784 }
1785 
1786 void
1787 device_tree::parse_dtb(const string &fn, FILE *)
1788 {
1789 	auto in = input_buffer::buffer_for_file(fn);
1790 	if (in == 0)
1791 	{
1792 		valid = false;
1793 		return;
1794 	}
1795 	input_buffer &input = *in;
1796 	dtb::header h;
1797 	valid = h.read_dtb(input);
1798 	boot_cpu = h.boot_cpuid_phys;
1799 	if (h.last_comp_version > 17)
1800 	{
1801 		fprintf(stderr, "Don't know how to read this version of the device tree blob");
1802 		valid = false;
1803 	}
1804 	if (!valid)
1805 	{
1806 		return;
1807 	}
1808 	input_buffer reservation_map =
1809 		input.buffer_from_offset(h.off_mem_rsvmap, 0);
1810 	uint64_t start, length;
1811 	do
1812 	{
1813 		if (!(reservation_map.consume_binary(start) &&
1814 		      reservation_map.consume_binary(length)))
1815 		{
1816 			fprintf(stderr, "Failed to read memory reservation table\n");
1817 			valid = false;
1818 			return;
1819 		}
1820 		if (start != 0 || length != 0)
1821 		{
1822 			reservations.push_back(reservation(start, length));
1823 		}
1824 	} while (!((start == 0) && (length == 0)));
1825 	input_buffer struct_table =
1826 		input.buffer_from_offset(h.off_dt_struct, h.size_dt_struct);
1827 	input_buffer strings_table =
1828 		input.buffer_from_offset(h.off_dt_strings, h.size_dt_strings);
1829 	uint32_t token;
1830 	if (!(struct_table.consume_binary(token) &&
1831 		(token == dtb::FDT_BEGIN_NODE)))
1832 	{
1833 		fprintf(stderr, "Expected FDT_BEGIN_NODE token.\n");
1834 		valid = false;
1835 		return;
1836 	}
1837 	root = node::parse_dtb(struct_table, strings_table);
1838 	if (!(struct_table.consume_binary(token) && (token == dtb::FDT_END)))
1839 	{
1840 		fprintf(stderr, "Expected FDT_END token after parsing root node.\n");
1841 		valid = false;
1842 		return;
1843 	}
1844 	valid = (root != 0);
1845 }
1846 
1847 string
1848 device_tree::node_path::to_string() const
1849 {
1850 	string path;
1851 	auto p = begin();
1852 	auto pe = end();
1853 	if ((p == pe) || (p+1 == pe))
1854 	{
1855 		return string("/");
1856 	}
1857 	// Skip the first name in the path.  It's always "", and implicitly /
1858 	for (++p ; p!=pe ; ++p)
1859 	{
1860 		path += '/';
1861 		path += p->first;
1862 		if (!(p->second.empty()))
1863 		{
1864 			path += '@';
1865 			path += p->second;
1866 		}
1867 	}
1868 	return path;
1869 }
1870 
1871 node_ptr
1872 device_tree::create_fragment_wrapper(node_ptr &node, int &fragnum)
1873 {
1874 	// In a plugin, we can massage these non-/ root nodes into into a fragment
1875 	std::string fragment_address = "fragment@" + std::to_string(fragnum);
1876 	++fragnum;
1877 
1878 	std::vector<property_ptr> symbols;
1879 
1880 	// Intentionally left empty
1881 	node_ptr newroot = node::create_special_node("", symbols);
1882 	node_ptr wrapper = node::create_special_node("__overlay__", symbols);
1883 
1884 	// Generate the fragment with $propname = <&name>
1885 	property_value v;
1886 	std::string propname;
1887 	v.string_data = node->name;
1888 	if (!node->name_is_path_reference)
1889 	{
1890 		propname = "target";
1891 		v.type = property_value::PHANDLE;
1892 	}
1893 	else
1894 	{
1895 		propname = "target-path";
1896 		v.type = property_value::STRING;
1897 	}
1898 	auto prop = std::make_shared<property>(std::string(propname));
1899 	prop->add_value(v);
1900 	symbols.push_back(prop);
1901 
1902 	node_ptr fragment = node::create_special_node(fragment_address, symbols);
1903 
1904 	wrapper->merge_node(node);
1905 	fragment->add_child(std::move(wrapper));
1906 	newroot->add_child(std::move(fragment));
1907 	return newroot;
1908 }
1909 
1910 node_ptr
1911 device_tree::generate_root(node_ptr &node, int &fragnum)
1912 {
1913 
1914 	string name = node->name;
1915 	if (name == string())
1916 	{
1917 		return std::move(node);
1918 	}
1919 	else if (!is_plugin)
1920 	{
1921 		return nullptr;
1922 	}
1923 
1924 	return create_fragment_wrapper(node, fragnum);
1925 }
1926 
1927 void
1928 device_tree::reassign_fragment_numbers(node_ptr &node, int &delta)
1929 {
1930 
1931 	for (auto &c : node->child_nodes())
1932 	{
1933 		if (c->name == std::string("fragment"))
1934 		{
1935 			int current_address = std::stoi(c->unit_address, nullptr, 16);
1936 			std::ostringstream new_address;
1937 			current_address += delta;
1938 			// It's possible that we hopped more than one somewhere, so just reset
1939 			// delta to the next in sequence.
1940 			delta = current_address + 1;
1941 			new_address << std::hex << current_address;
1942 			c->unit_address = new_address.str();
1943 		}
1944 	}
1945 }
1946 
1947 void
1948 device_tree::parse_dts(const string &fn, FILE *depfile)
1949 {
1950 	auto in = input_buffer::buffer_for_file(fn);
1951 	if (!in)
1952 	{
1953 		valid = false;
1954 		return;
1955 	}
1956 	std::vector<node_ptr> roots;
1957 	std::unordered_set<string> defnames;
1958 	for (auto &i : defines)
1959 	{
1960 		defnames.insert(i.first);
1961 	}
1962 	text_input_buffer input(std::move(in),
1963 	                        std::move(defnames),
1964 	                        std::vector<string>(include_paths),
1965 	                        dirname(fn),
1966 	                        depfile);
1967 	bool read_header = false;
1968 	int fragnum = 0;
1969 	parse_file(input, roots, read_header);
1970 	switch (roots.size())
1971 	{
1972 		case 0:
1973 			valid = false;
1974 			input.parse_error("Failed to find root node /.");
1975 			return;
1976 		case 1:
1977 			root = generate_root(roots[0], fragnum);
1978 			if (!root)
1979 			{
1980 				valid = false;
1981 				input.parse_error("Failed to find root node /.");
1982 				return;
1983 			}
1984 			break;
1985 		default:
1986 		{
1987 			root = generate_root(roots[0], fragnum);
1988 			if (!root)
1989 			{
1990 				valid = false;
1991 				input.parse_error("Failed to find root node /.");
1992 				return;
1993 			}
1994 			for (auto i=++(roots.begin()), e=roots.end() ; i!=e ; ++i)
1995 			{
1996 				auto &node = *i;
1997 				string name = node->name;
1998 				if (name == string())
1999 				{
2000 					if (is_plugin)
2001 					{
2002 						// Re-assign any fragment numbers based on a delta of
2003 						// fragnum before we merge it
2004 						reassign_fragment_numbers(node, fragnum);
2005 					}
2006 					root->merge_node(node);
2007 				}
2008 				else
2009 				{
2010 					auto existing = node_names.find(name);
2011 					if (existing == node_names.end())
2012 					{
2013 						collect_names();
2014 						existing = node_names.find(name);
2015 					}
2016 					if (existing == node_names.end())
2017 					{
2018 						if (is_plugin)
2019 						{
2020 							auto fragment = create_fragment_wrapper(node, fragnum);
2021 							root->merge_node(fragment);
2022 						}
2023 						else
2024 						{
2025 							fprintf(stderr, "Unable to merge node: %s\n", name.c_str());
2026 						}
2027 					}
2028 					else
2029 					{
2030 						existing->second->merge_node(node);
2031 					}
2032 				}
2033 			}
2034 		}
2035 	}
2036 	collect_names();
2037 	// Return value indicates whether we've dirtied the tree or not and need to
2038 	// recollect names
2039 	if (garbage_collect && garbage_collect_marked_nodes())
2040 	{
2041 		collect_names();
2042 	}
2043 	uint32_t phandle = 1;
2044 	// If we're writing symbols, go ahead and assign phandles to the entire
2045 	// tree. We'll do this before we resolve cross references, just to keep
2046 	// order semi-predictable and stable.
2047 	if (write_symbols)
2048 	{
2049 		assign_phandles(root, phandle);
2050 	}
2051 	resolve_cross_references(phandle);
2052 	if (write_symbols)
2053 	{
2054 		std::vector<property_ptr> symbols;
2055 		// Create a symbol table.  Each label  in this device tree may be
2056 		// referenced by other plugins, so we create a __symbols__ node inside
2057 		// the root that contains mappings (properties) from label names to
2058 		// paths.
2059 		for (auto i=ordered_node_paths.rbegin(), e=ordered_node_paths.rend() ; i!=e ; ++i)
2060 		{
2061 			auto &s = *i;
2062 			if (node_paths.find(s.first) == node_paths.end())
2063 			{
2064 				// Erased node, skip it.
2065 				continue;
2066 			}
2067 			property_value v;
2068 			v.string_data = s.second.to_string();
2069 			v.type = property_value::STRING;
2070 			string name = s.first;
2071 			auto prop = std::make_shared<property>(std::move(name));
2072 			prop->add_value(v);
2073 			symbols.push_back(prop);
2074 		}
2075 		root->add_child(node::create_special_node("__symbols__", symbols));
2076 	}
2077 	// If this is a plugin, then we also need to create two extra nodes.
2078 	// Internal phandles will need to be renumbered to avoid conflicts with
2079 	// already-loaded nodes and external references will need to be
2080 	// resolved.
2081 	if (is_plugin)
2082 	{
2083 		std::vector<property_ptr> symbols;
2084 		// Create the fixups entry.  This is of the form:
2085 		// {target} = {path}:{property name}:{offset}
2086 		auto create_fixup_entry = [&](fixup &i, string target)
2087 			{
2088 				string value = i.path.to_string();
2089 				value += ':';
2090 				value += i.prop->get_key();
2091 				value += ':';
2092 				value += std::to_string(i.prop->offset_of_value(i.val));
2093 				property_value v;
2094 				v.string_data = value;
2095 				v.type = property_value::STRING;
2096 				auto prop = std::make_shared<property>(std::move(target));
2097 				prop->add_value(v);
2098 				return prop;
2099 			};
2100 		// If we have any unresolved phandle references in this plugin,
2101 		// then we must update them to 0xdeadbeef and leave a property in
2102 		// the /__fixups__ node whose key is the label and whose value is
2103 		// as described above.
2104 		if (!unresolved_fixups.empty())
2105 		{
2106 			for (auto &i : unresolved_fixups)
2107 			{
2108 				auto &val = i.get().val;
2109 				symbols.push_back(create_fixup_entry(i, val.string_data));
2110 				val.byte_data.push_back(0xde);
2111 				val.byte_data.push_back(0xad);
2112 				val.byte_data.push_back(0xbe);
2113 				val.byte_data.push_back(0xef);
2114 				val.type = property_value::BINARY;
2115 			}
2116 			root->add_child(node::create_special_node("__fixups__", symbols));
2117 		}
2118 		symbols.clear();
2119 		// If we have any resolved phandle references in this plugin, then
2120 		// we must create a child in the __local_fixups__ node whose path
2121 		// matches the node path from the root and whose value contains the
2122 		// location of the reference within a property.
2123 
2124 		// Create a local_fixups node that is initially empty.
2125 		node_ptr local_fixups = node::create_special_node("__local_fixups__", symbols);
2126 		for (auto &i : fixups)
2127 		{
2128 			if (!i.val.is_phandle())
2129 			{
2130 				continue;
2131 			}
2132 			node *n = local_fixups.get();
2133 			for (auto &p : i.path)
2134 			{
2135 				// Skip the implicit root
2136 				if (p.first.empty())
2137 				{
2138 					continue;
2139 				}
2140 				bool found = false;
2141 				for (auto &c : n->child_nodes())
2142 				{
2143 					if (c->name == p.first)
2144 					{
2145 						if (c->unit_address == p.second)
2146 						{
2147 							n = c.get();
2148 							found = true;
2149 							break;
2150 						}
2151 					}
2152 				}
2153 				if (!found)
2154 				{
2155 					string path = p.first;
2156 					if (!(p.second.empty()))
2157 					{
2158 						path += '@';
2159 						path += p.second;
2160 					}
2161 					n->add_child(node::create_special_node(path, symbols));
2162 					n = (--n->child_end())->get();
2163 				}
2164 			}
2165 			assert(n);
2166 			property_value pv;
2167 			push_big_endian(pv.byte_data, static_cast<uint32_t>(i.prop->offset_of_value(i.val)));
2168 			pv.type = property_value::BINARY;
2169 			auto key = i.prop->get_key();
2170 			property_ptr prop = n->get_property(key);
2171 			// If we don't have an existing property then create one and
2172 			// use this property value
2173 			if (!prop)
2174 			{
2175 				prop = std::make_shared<property>(std::move(key));
2176 				n->add_property(prop);
2177 				prop->add_value(pv);
2178 			}
2179 			else
2180 			{
2181 				// If we do have an existing property value, try to append
2182 				// this value.
2183 				property_value &old_val = *(--prop->end());
2184 				if (!old_val.try_to_merge(pv))
2185 				{
2186 					prop->add_value(pv);
2187 				}
2188 			}
2189 		}
2190 		// We've iterated over all fixups, but only emit the
2191 		// __local_fixups__ if we found some that were resolved internally.
2192 		if (local_fixups->child_begin() != local_fixups->child_end())
2193 		{
2194 			root->add_child(std::move(local_fixups));
2195 		}
2196 	}
2197 }
2198 
2199 bool device_tree::parse_define(const char *def)
2200 {
2201 	const char *val = strchr(def, '=');
2202 	if (!val)
2203 	{
2204 		if (strlen(def) != 0)
2205 		{
2206 			string name(def);
2207 			defines[name];
2208 			return true;
2209 		}
2210 		return false;
2211 	}
2212 	string name(def, val-def);
2213 	string name_copy = name;
2214 	val++;
2215 	std::unique_ptr<input_buffer> raw(new input_buffer(val, strlen(val)));
2216 	text_input_buffer in(std::move(raw),
2217 	                     std::unordered_set<string>(),
2218 	                     std::vector<string>(),
2219 	                     string(),
2220 	                     nullptr);
2221 	property_ptr p = property::parse(in, std::move(name_copy), string_set(), false);
2222 	if (p)
2223 		defines[name] = p;
2224 	return (bool)p;
2225 }
2226 
2227 } // namespace fdt
2228 
2229 } // namespace dtc
2230 
2231