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