xref: /freebsd/usr.bin/dtc/fdt.cc (revision 190cef3d)
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 node::visit_behavior
731 node::visit(std::function<visit_behavior(node&, node*)> fn, node *parent)
732 {
733 	visit_behavior behavior;
734 	behavior = fn(*this, parent);
735 	if (behavior == VISIT_BREAK)
736 	{
737 		return VISIT_BREAK;
738 	}
739 	else if (behavior != VISIT_CONTINUE)
740 	{
741 		for (auto &&c : children)
742 		{
743 			behavior = c->visit(fn, this);
744 			// Any status other than VISIT_RECURSE stops our execution and
745 			// bubbles up to our caller.  The caller may then either continue
746 			// visiting nodes that are siblings to this one or completely halt
747 			// visiting.
748 			if (behavior != VISIT_RECURSE)
749 			{
750 				return behavior;
751 			}
752 		}
753 	}
754 	// Continue recursion by default
755 	return VISIT_RECURSE;
756 }
757 
758 node::node(input_buffer &structs, input_buffer &strings) : valid(true)
759 {
760 	std::vector<char> bytes;
761 	while (structs[0] != '\0' && structs[0] != '@')
762 	{
763 		bytes.push_back(structs[0]);
764 		++structs;
765 	}
766 	name = string(bytes.begin(), bytes.end());
767 	bytes.clear();
768 	if (structs[0] == '@')
769 	{
770 		++structs;
771 		while (structs[0] != '\0')
772 		{
773 			bytes.push_back(structs[0]);
774 			++structs;
775 		}
776 		unit_address = string(bytes.begin(), bytes.end());
777 	}
778 	++structs;
779 	uint32_t token;
780 	while (structs.consume_binary(token))
781 	{
782 		switch (token)
783 		{
784 			default:
785 				fprintf(stderr, "Unexpected token 0x%" PRIx32
786 					" while parsing node.\n", token);
787 				valid = false;
788 				return;
789 			// Child node, parse it.
790 			case dtb::FDT_BEGIN_NODE:
791 			{
792 				node_ptr child = node::parse_dtb(structs, strings);
793 				if (child == 0)
794 				{
795 					valid = false;
796 					return;
797 				}
798 				children.push_back(std::move(child));
799 				break;
800 			}
801 			// End of this node, no errors.
802 			case dtb::FDT_END_NODE:
803 				return;
804 			// Property, parse it.
805 			case dtb::FDT_PROP:
806 			{
807 				property_ptr prop = property::parse_dtb(structs, strings);
808 				if (prop == 0)
809 				{
810 					valid = false;
811 					return;
812 				}
813 				props.push_back(prop);
814 				break;
815 			}
816 				break;
817 			// End of structs table.  Should appear after
818 			// the end of the last node.
819 			case dtb::FDT_END:
820 				fprintf(stderr, "Unexpected FDT_END token while parsing node.\n");
821 				valid = false;
822 				return;
823 			// NOPs are padding.  Ignore them.
824 			case dtb::FDT_NOP:
825 				break;
826 		}
827 	}
828 	fprintf(stderr, "Failed to read token from structs table while parsing node.\n");
829 	valid = false;
830 	return;
831 }
832 
833 
834 node::node(const string &n,
835            const std::vector<property_ptr> &p)
836 	: name(n)
837 {
838 	props.insert(props.begin(), p.begin(), p.end());
839 }
840 
841 node_ptr node::create_special_node(const string &name,
842                                    const std::vector<property_ptr> &props)
843 {
844 	node_ptr n(new node(name, props));
845 	return n;
846 }
847 
848 node::node(text_input_buffer &input,
849            string &&n,
850            std::unordered_set<string> &&l,
851            string &&a,
852            define_map *defines)
853 	: labels(l), name(n), unit_address(a), valid(true)
854 {
855 	if (!input.consume('{'))
856 	{
857 		input.parse_error("Expected { to start new device tree node.\n");
858 	}
859 	input.next_token();
860 	while (valid && !input.consume('}'))
861 	{
862 		// flag set if we find any characters that are only in
863 		// the property name character set, not the node
864 		bool is_property = false;
865 		string child_name, child_address;
866 		std::unordered_set<string> child_labels;
867 		auto parse_delete = [&](const char *expected, bool at)
868 		{
869 			if (child_name == string())
870 			{
871 				input.parse_error(expected);
872 				valid = false;
873 				return;
874 			}
875 			input.next_token();
876 			if (at && input.consume('@'))
877 			{
878 				child_name += '@';
879 				child_name += parse_name(input, is_property, "Expected unit address");
880 			}
881 			if (!input.consume(';'))
882 			{
883 				input.parse_error("Expected semicolon");
884 				valid = false;
885 				return;
886 			}
887 			input.next_token();
888 		};
889 		if (input.consume("/delete-node/"))
890 		{
891 			input.next_token();
892 			child_name = input.parse_node_name();
893 			parse_delete("Expected node name", true);
894 			if (valid)
895 			{
896 				deleted_children.insert(child_name);
897 			}
898 			continue;
899 		}
900 		if (input.consume("/delete-property/"))
901 		{
902 			input.next_token();
903 			child_name = input.parse_property_name();
904 			parse_delete("Expected property name", false);
905 			if (valid)
906 			{
907 				deleted_props.insert(child_name);
908 			}
909 			continue;
910 		}
911 		child_name = parse_name(input, is_property,
912 				"Expected property or node name");
913 		while (input.consume(':'))
914 		{
915 			// Node labels can contain any characters?  The
916 			// spec doesn't say, so we guess so...
917 			is_property = false;
918 			child_labels.insert(std::move(child_name));
919 			child_name = parse_name(input, is_property, "Expected property or node name");
920 		}
921 		if (input.consume('@'))
922 		{
923 			child_address = parse_name(input, is_property, "Expected unit address");
924 		}
925 		if (!valid)
926 		{
927 			return;
928 		}
929 		input.next_token();
930 		// If we're parsing a property, then we must actually do that.
931 		if (input.consume('='))
932 		{
933 			property_ptr p = property::parse(input, std::move(child_name),
934 					std::move(child_labels), true, defines);
935 			if (p == 0)
936 			{
937 				valid = false;
938 			}
939 			else
940 			{
941 				props.push_back(p);
942 			}
943 		}
944 		else if (!is_property && *input == ('{'))
945 		{
946 			node_ptr child = node::parse(input, std::move(child_name),
947 					std::move(child_labels), std::move(child_address), defines);
948 			if (child)
949 			{
950 				children.push_back(std::move(child));
951 			}
952 			else
953 			{
954 				valid = false;
955 			}
956 		}
957 		else if (input.consume(';'))
958 		{
959 			props.push_back(property_ptr(new property(std::move(child_name), std::move(child_labels))));
960 		}
961 		else
962 		{
963 			input.parse_error("Error parsing property.  Expected property value");
964 			valid = false;
965 		}
966 		input.next_token();
967 	}
968 	input.next_token();
969 	input.consume(';');
970 }
971 
972 bool
973 node::cmp_properties(property_ptr &p1, property_ptr &p2)
974 {
975 	return p1->get_key() < p2->get_key();
976 }
977 
978 bool
979 node::cmp_children(node_ptr &c1, node_ptr &c2)
980 {
981 	if (c1->name == c2->name)
982 	{
983 		return c1->unit_address < c2->unit_address;
984 	}
985 	return c1->name < c2->name;
986 }
987 
988 void
989 node::sort()
990 {
991 	std::sort(property_begin(), property_end(), cmp_properties);
992 	std::sort(child_begin(), child_end(), cmp_children);
993 	for (auto &c : child_nodes())
994 	{
995 		c->sort();
996 	}
997 }
998 
999 node_ptr
1000 node::parse(text_input_buffer &input,
1001             string &&name,
1002             string_set &&label,
1003             string &&address,
1004             define_map *defines)
1005 {
1006 	node_ptr n(new node(input,
1007 	                    std::move(name),
1008 	                    std::move(label),
1009 	                    std::move(address),
1010 	                    defines));
1011 	if (!n->valid)
1012 	{
1013 		n = 0;
1014 	}
1015 	return n;
1016 }
1017 
1018 node_ptr
1019 node::parse_dtb(input_buffer &structs, input_buffer &strings)
1020 {
1021 	node_ptr n(new node(structs, strings));
1022 	if (!n->valid)
1023 	{
1024 		n = 0;
1025 	}
1026 	return n;
1027 }
1028 
1029 property_ptr
1030 node::get_property(const string &key)
1031 {
1032 	for (auto &i : props)
1033 	{
1034 		if (i->get_key() == key)
1035 		{
1036 			return i;
1037 		}
1038 	}
1039 	return 0;
1040 }
1041 
1042 void
1043 node::merge_node(node_ptr &other)
1044 {
1045 	for (auto &l : other->labels)
1046 	{
1047 		labels.insert(l);
1048 	}
1049 	// Note: this is an O(n*m) operation.  It might be sensible to
1050 	// optimise this if we find that there are nodes with very
1051 	// large numbers of properties, but for typical usage the
1052 	// entire vector will fit (easily) into cache, so iterating
1053 	// over it repeatedly isn't that expensive.
1054 	for (auto &p : other->properties())
1055 	{
1056 		bool found = false;
1057 		for (auto &mp : properties())
1058 		{
1059 			if (mp->get_key() == p->get_key())
1060 			{
1061 				mp = p;
1062 				found = true;
1063 				break;
1064 			}
1065 		}
1066 		if (!found)
1067 		{
1068 			add_property(p);
1069 		}
1070 	}
1071 	for (auto &c : other->children)
1072 	{
1073 		bool found = false;
1074 		for (auto &i : children)
1075 		{
1076 			if (i->name == c->name && i->unit_address == c->unit_address)
1077 			{
1078 				i->merge_node(c);
1079 				found = true;
1080 				break;
1081 			}
1082 		}
1083 		if (!found)
1084 		{
1085 			children.push_back(std::move(c));
1086 		}
1087 	}
1088 	children.erase(std::remove_if(children.begin(), children.end(),
1089 			[&](const node_ptr &p) {
1090 				string full_name = p->name;
1091 				if (p->unit_address != string())
1092 				{
1093 					full_name += '@';
1094 					full_name += p->unit_address;
1095 				}
1096 				if (other->deleted_children.count(full_name) > 0)
1097 				{
1098 					other->deleted_children.erase(full_name);
1099 					return true;
1100 				}
1101 				return false;
1102 			}), children.end());
1103 	props.erase(std::remove_if(props.begin(), props.end(),
1104 			[&](const property_ptr &p) {
1105 				if (other->deleted_props.count(p->get_key()) > 0)
1106 				{
1107 					other->deleted_props.erase(p->get_key());
1108 					return true;
1109 				}
1110 				return false;
1111 			}), props.end());
1112 }
1113 
1114 void
1115 node::write(dtb::output_writer &writer, dtb::string_table &strings)
1116 {
1117 	writer.write_token(dtb::FDT_BEGIN_NODE);
1118 	byte_buffer name_buffer;
1119 	push_string(name_buffer, name);
1120 	if (unit_address != string())
1121 	{
1122 		name_buffer.push_back('@');
1123 		push_string(name_buffer, unit_address);
1124 	}
1125 	writer.write_comment(name);
1126 	writer.write_data(name_buffer);
1127 	writer.write_data((uint8_t)0);
1128 	for (auto p : properties())
1129 	{
1130 		p->write(writer, strings);
1131 	}
1132 	for (auto &c : child_nodes())
1133 	{
1134 		c->write(writer, strings);
1135 	}
1136 	writer.write_token(dtb::FDT_END_NODE);
1137 }
1138 
1139 void
1140 node::write_dts(FILE *file, int indent)
1141 {
1142 	for (int i=0 ; i<indent ; i++)
1143 	{
1144 		putc('\t', file);
1145 	}
1146 #ifdef PRINT_LABELS
1147 	for (auto &label : labels)
1148 	{
1149 		fprintf(file, "%s: ", label.c_str());
1150 	}
1151 #endif
1152 	if (name != string())
1153 	{
1154 		fputs(name.c_str(), file);
1155 	}
1156 	if (unit_address != string())
1157 	{
1158 		putc('@', file);
1159 		fputs(unit_address.c_str(), file);
1160 	}
1161 	fputs(" {\n\n", file);
1162 	for (auto p : properties())
1163 	{
1164 		p->write_dts(file, indent+1);
1165 	}
1166 	for (auto &c : child_nodes())
1167 	{
1168 		c->write_dts(file, indent+1);
1169 	}
1170 	for (int i=0 ; i<indent ; i++)
1171 	{
1172 		putc('\t', file);
1173 	}
1174 	fputs("};\n", file);
1175 }
1176 
1177 void
1178 device_tree::collect_names_recursive(node_ptr &n, node_path &path)
1179 {
1180 	path.push_back(std::make_pair(n->name, n->unit_address));
1181 	for (const string &name : n->labels)
1182 	{
1183 		if (name != string())
1184 		{
1185 			auto iter = node_names.find(name);
1186 			if (iter == node_names.end())
1187 			{
1188 				node_names.insert(std::make_pair(name, n.get()));
1189 				node_paths.insert(std::make_pair(name, path));
1190 			}
1191 			else
1192 			{
1193 				node_names.erase(iter);
1194 				auto i = node_paths.find(name);
1195 				if (i != node_paths.end())
1196 				{
1197 					node_paths.erase(name);
1198 				}
1199 				fprintf(stderr, "Label not unique: %s.  References to this label will not be resolved.\n", name.c_str());
1200 			}
1201 		}
1202 	}
1203 	for (auto &c : n->child_nodes())
1204 	{
1205 		collect_names_recursive(c, path);
1206 	}
1207 	// Now we collect the phandles and properties that reference
1208 	// other nodes.
1209 	for (auto &p : n->properties())
1210 	{
1211 		for (auto &v : *p)
1212 		{
1213 			if (v.is_phandle())
1214 			{
1215 				fixups.push_back({path, p, v});
1216 			}
1217 			if (v.is_cross_reference())
1218 			{
1219 				cross_references.push_back(&v);
1220 			}
1221 		}
1222 		if ((p->get_key() == "phandle") ||
1223 		    (p->get_key() == "linux,phandle"))
1224 		{
1225 			if (p->begin()->byte_data.size() != 4)
1226 			{
1227 				fprintf(stderr, "Invalid phandle value for node %s.  Should be a 4-byte value.\n", n->name.c_str());
1228 				valid = false;
1229 			}
1230 			else
1231 			{
1232 				uint32_t phandle = p->begin()->get_as_uint32();
1233 				used_phandles.insert(std::make_pair(phandle, n.get()));
1234 			}
1235 		}
1236 	}
1237 	path.pop_back();
1238 }
1239 
1240 void
1241 device_tree::collect_names()
1242 {
1243 	node_path p;
1244 	node_names.clear();
1245 	node_paths.clear();
1246 	cross_references.clear();
1247 	fixups.clear();
1248 	collect_names_recursive(root, p);
1249 }
1250 
1251 property_ptr
1252 device_tree::assign_phandle(node *n, uint32_t &phandle)
1253 {
1254 	// If there is an existing phandle, use it
1255 	property_ptr p = n->get_property("phandle");
1256 	if (p == 0)
1257 	{
1258 		p = n->get_property("linux,phandle");
1259 	}
1260 	if (p == 0)
1261 	{
1262 		// Otherwise insert a new phandle node
1263 		property_value v;
1264 		while (used_phandles.find(phandle) != used_phandles.end())
1265 		{
1266 			// Note that we only don't need to
1267 			// store this phandle in the set,
1268 			// because we are monotonically
1269 			// increasing the value of phandle and
1270 			// so will only ever revisit this value
1271 			// if we have used 2^32 phandles, at
1272 			// which point our blob won't fit in
1273 			// any 32-bit system and we've done
1274 			// something badly wrong elsewhere
1275 			// already.
1276 			phandle++;
1277 		}
1278 		push_big_endian(v.byte_data, phandle++);
1279 		if (phandle_node_name == BOTH || phandle_node_name == LINUX)
1280 		{
1281 			p.reset(new property("linux,phandle"));
1282 			p->add_value(v);
1283 			n->add_property(p);
1284 		}
1285 		if (phandle_node_name == BOTH || phandle_node_name == EPAPR)
1286 		{
1287 			p.reset(new property("phandle"));
1288 			p->add_value(v);
1289 			n->add_property(p);
1290 		}
1291 	}
1292 
1293 	return (p);
1294 }
1295 
1296 void
1297 device_tree::assign_phandles(node_ptr &n, uint32_t &next)
1298 {
1299 	if (!n->labels.empty())
1300 	{
1301 		assign_phandle(n.get(), next);
1302 	}
1303 
1304 	for (auto &c : n->child_nodes())
1305 	{
1306 		assign_phandles(c, next);
1307 	}
1308 }
1309 
1310 void
1311 device_tree::resolve_cross_references(uint32_t &phandle)
1312 {
1313 	for (auto *pv : cross_references)
1314 	{
1315 		node_path path = node_paths[pv->string_data];
1316 		auto p = path.begin();
1317 		auto pe = path.end();
1318 		if (p != pe)
1319 		{
1320 			// Skip the first name in the path.  It's always "", and implicitly /
1321 			for (++p ; p!=pe ; ++p)
1322 			{
1323 				pv->byte_data.push_back('/');
1324 				push_string(pv->byte_data, p->first);
1325 				if (!(p->second.empty()))
1326 				{
1327 					pv->byte_data.push_back('@');
1328 					push_string(pv->byte_data, p->second);
1329 				}
1330 			}
1331 			pv->byte_data.push_back(0);
1332 		}
1333 	}
1334 	std::unordered_map<property_value*, fixup&> phandle_set;
1335 	for (auto &i : fixups)
1336 	{
1337 		phandle_set.insert({&i.val, i});
1338 	}
1339 	std::vector<std::reference_wrapper<fixup>> sorted_phandles;
1340 	root->visit([&](node &n, node *) {
1341 		for (auto &p : n.properties())
1342 		{
1343 			for (auto &v : *p)
1344 			{
1345 				auto i = phandle_set.find(&v);
1346 				if (i != phandle_set.end())
1347 				{
1348 					sorted_phandles.push_back(i->second);
1349 				}
1350 			}
1351 		}
1352 		// Allow recursion
1353 		return node::VISIT_RECURSE;
1354 	}, nullptr);
1355 	assert(sorted_phandles.size() == fixups.size());
1356 
1357 	for (auto &i : sorted_phandles)
1358 	{
1359 		string target_name = i.get().val.string_data;
1360 		node *target = nullptr;
1361 		string possible;
1362 		// If the node name is a path, then look it up by following the path,
1363 		// otherwise jump directly to the named node.
1364 		if (target_name[0] == '/')
1365 		{
1366 			string path;
1367 			target = root.get();
1368 			std::istringstream ss(target_name);
1369 			string path_element;
1370 			// Read the leading /
1371 			std::getline(ss, path_element, '/');
1372 			// Iterate over path elements
1373 			while (!ss.eof())
1374 			{
1375 				path += '/';
1376 				std::getline(ss, path_element, '/');
1377 				std::istringstream nss(path_element);
1378 				string node_name, node_address;
1379 				std::getline(nss, node_name, '@');
1380 				std::getline(nss, node_address, '@');
1381 				node *next = nullptr;
1382 				for (auto &c : target->child_nodes())
1383 				{
1384 					if (c->name == node_name)
1385 					{
1386 						if (c->unit_address == node_address)
1387 						{
1388 							next = c.get();
1389 							break;
1390 						}
1391 						else
1392 						{
1393 							possible = path + c->name;
1394 							if (c->unit_address != string())
1395 							{
1396 								possible += '@';
1397 								possible += c->unit_address;
1398 							}
1399 						}
1400 					}
1401 				}
1402 				path += node_name;
1403 				if (node_address != string())
1404 				{
1405 					path += '@';
1406 					path += node_address;
1407 				}
1408 				target = next;
1409 				if (target == nullptr)
1410 				{
1411 					break;
1412 				}
1413 			}
1414 		}
1415 		else
1416 		{
1417 			target = node_names[target_name];
1418 		}
1419 		if (target == nullptr)
1420 		{
1421 			if (is_plugin)
1422 			{
1423 				unresolved_fixups.push_back(i);
1424 				continue;
1425 			}
1426 			else
1427 			{
1428 				fprintf(stderr, "Failed to find node with label: %s\n", target_name.c_str());
1429 				if (possible != string())
1430 				{
1431 					fprintf(stderr, "Possible intended match: %s\n", possible.c_str());
1432 				}
1433 				valid = 0;
1434 				return;
1435 			}
1436 		}
1437 		// If there is an existing phandle, use it
1438 		property_ptr p = assign_phandle(target, phandle);
1439 		p->begin()->push_to_buffer(i.get().val.byte_data);
1440 		assert(i.get().val.byte_data.size() == 4);
1441 	}
1442 }
1443 
1444 
1445 void
1446 device_tree::parse_file(text_input_buffer &input,
1447                         std::vector<node_ptr> &roots,
1448                         bool &read_header)
1449 {
1450 	input.next_token();
1451 	// Read the header
1452 	if (input.consume("/dts-v1/;"))
1453 	{
1454 		read_header = true;
1455 	}
1456 	input.next_token();
1457 	if (input.consume("/plugin/;"))
1458 	{
1459 		is_plugin = true;
1460 	}
1461 	input.next_token();
1462 	if (!read_header)
1463 	{
1464 		input.parse_error("Expected /dts-v1/; version string");
1465 	}
1466 	// Read any memory reservations
1467 	while (input.consume("/memreserve/"))
1468 	{
1469 		unsigned long long start, len;
1470 		input.next_token();
1471 		// Read the start and length.
1472 		if (!(input.consume_integer_expression(start) &&
1473 		    (input.next_token(),
1474 		    input.consume_integer_expression(len))))
1475 		{
1476 			input.parse_error("Expected size on /memreserve/ node.");
1477 		}
1478 		input.next_token();
1479 		input.consume(';');
1480 		reservations.push_back(reservation(start, len));
1481 		input.next_token();
1482 	}
1483 	while (valid && !input.finished())
1484 	{
1485 		node_ptr n;
1486 		if (input.consume('/'))
1487 		{
1488 			input.next_token();
1489 			n = node::parse(input, string(), string_set(), string(), &defines);
1490 		}
1491 		else if (input.consume('&'))
1492 		{
1493 			input.next_token();
1494 			string name;
1495 			bool name_is_path_reference = false;
1496 			// This is to deal with names intended as path references, e.g. &{/path}.
1497 			// While it may make sense in a non-plugin context, we don't support such
1498 			// usage at this time.
1499 			if (input.consume('{') && is_plugin)
1500 			{
1501 				name = input.parse_to('}');
1502 				input.consume('}');
1503 				name_is_path_reference = true;
1504 			}
1505 			else
1506 			{
1507 				name = input.parse_node_name();
1508 			}
1509 			input.next_token();
1510 			n = node::parse(input, std::move(name), string_set(), string(), &defines);
1511 			n->name_is_path_reference = name_is_path_reference;
1512 		}
1513 		else
1514 		{
1515 			input.parse_error("Failed to find root node /.");
1516 		}
1517 		if (n)
1518 		{
1519 			roots.push_back(std::move(n));
1520 		}
1521 		else
1522 		{
1523 			valid = false;
1524 		}
1525 		input.next_token();
1526 	}
1527 }
1528 
1529 template<class writer> void
1530 device_tree::write(int fd)
1531 {
1532 	dtb::string_table st;
1533 	dtb::header head;
1534 	writer head_writer;
1535 	writer reservation_writer;
1536 	writer struct_writer;
1537 	writer strings_writer;
1538 
1539 	// Build the reservation table
1540 	reservation_writer.write_comment(string("Memory reservations"));
1541 	reservation_writer.write_label(string("dt_reserve_map"));
1542 	for (auto &i : reservations)
1543 	{
1544 		reservation_writer.write_comment(string("Reservation start"));
1545 		reservation_writer.write_data(i.first);
1546 		reservation_writer.write_comment(string("Reservation length"));
1547 		reservation_writer.write_data(i.first);
1548 	}
1549 	// Write n spare reserve map entries, plus the trailing 0.
1550 	for (uint32_t i=0 ; i<=spare_reserve_map_entries ; i++)
1551 	{
1552 		reservation_writer.write_data((uint64_t)0);
1553 		reservation_writer.write_data((uint64_t)0);
1554 	}
1555 
1556 
1557 	struct_writer.write_comment(string("Device tree"));
1558 	struct_writer.write_label(string("dt_struct_start"));
1559 	root->write(struct_writer, st);
1560 	struct_writer.write_token(dtb::FDT_END);
1561 	struct_writer.write_label(string("dt_struct_end"));
1562 
1563 	st.write(strings_writer);
1564 	// Find the strings size before we stick padding on the end.
1565 	// Note: We should possibly use a new writer for the padding.
1566 	head.size_dt_strings = strings_writer.size();
1567 
1568 	// Stick the padding in the strings writer, but after the
1569 	// marker indicating that it's the end.
1570 	// Note: We probably should add a padding call to the writer so
1571 	// that the asm back end can write padding directives instead
1572 	// of a load of 0 bytes.
1573 	for (uint32_t i=0 ; i<blob_padding ; i++)
1574 	{
1575 		strings_writer.write_data((uint8_t)0);
1576 	}
1577 	head.totalsize = sizeof(head) + strings_writer.size() +
1578 		struct_writer.size() + reservation_writer.size();
1579 	while (head.totalsize < minimum_blob_size)
1580 	{
1581 		head.totalsize++;
1582 		strings_writer.write_data((uint8_t)0);
1583 	}
1584 	head.off_dt_struct = sizeof(head) + reservation_writer.size();;
1585 	head.off_dt_strings = head.off_dt_struct + struct_writer.size();
1586 	head.off_mem_rsvmap = sizeof(head);
1587 	head.boot_cpuid_phys = boot_cpu;
1588 	head.size_dt_struct = struct_writer.size();
1589 	head.write(head_writer);
1590 
1591 	head_writer.write_to_file(fd);
1592 	reservation_writer.write_to_file(fd);
1593 	struct_writer.write_to_file(fd);
1594 	strings_writer.write_label(string("dt_blob_end"));
1595 	strings_writer.write_to_file(fd);
1596 }
1597 
1598 node*
1599 device_tree::referenced_node(property_value &v)
1600 {
1601 	if (v.is_phandle())
1602 	{
1603 		return node_names[v.string_data];
1604 	}
1605 	if (v.is_binary())
1606 	{
1607 		return used_phandles[v.get_as_uint32()];
1608 	}
1609 	return 0;
1610 }
1611 
1612 void
1613 device_tree::write_binary(int fd)
1614 {
1615 	write<dtb::binary_writer>(fd);
1616 }
1617 
1618 void
1619 device_tree::write_asm(int fd)
1620 {
1621 	write<dtb::asm_writer>(fd);
1622 }
1623 
1624 void
1625 device_tree::write_dts(int fd)
1626 {
1627 	FILE *file = fdopen(fd, "w");
1628 	fputs("/dts-v1/;\n\n", file);
1629 
1630 	if (!reservations.empty())
1631 	{
1632 		const char msg[] = "/memreserve/";
1633 		fwrite(msg, sizeof(msg), 1, file);
1634 		for (auto &i : reservations)
1635 		{
1636 			fprintf(file, " %" PRIx64 " %" PRIx64, i.first, i.second);
1637 		}
1638 		fputs(";\n\n", file);
1639 	}
1640 	putc('/', file);
1641 	putc(' ', file);
1642 	root->write_dts(file, 0);
1643 	fclose(file);
1644 }
1645 
1646 void
1647 device_tree::parse_dtb(const string &fn, FILE *)
1648 {
1649 	auto in = input_buffer::buffer_for_file(fn);
1650 	if (in == 0)
1651 	{
1652 		valid = false;
1653 		return;
1654 	}
1655 	input_buffer &input = *in;
1656 	dtb::header h;
1657 	valid = h.read_dtb(input);
1658 	boot_cpu = h.boot_cpuid_phys;
1659 	if (h.last_comp_version > 17)
1660 	{
1661 		fprintf(stderr, "Don't know how to read this version of the device tree blob");
1662 		valid = false;
1663 	}
1664 	if (!valid)
1665 	{
1666 		return;
1667 	}
1668 	input_buffer reservation_map =
1669 		input.buffer_from_offset(h.off_mem_rsvmap, 0);
1670 	uint64_t start, length;
1671 	do
1672 	{
1673 		if (!(reservation_map.consume_binary(start) &&
1674 		      reservation_map.consume_binary(length)))
1675 		{
1676 			fprintf(stderr, "Failed to read memory reservation table\n");
1677 			valid = false;
1678 			return;
1679 		}
1680 	} while (!((start == 0) && (length == 0)));
1681 	input_buffer struct_table =
1682 		input.buffer_from_offset(h.off_dt_struct, h.size_dt_struct);
1683 	input_buffer strings_table =
1684 		input.buffer_from_offset(h.off_dt_strings, h.size_dt_strings);
1685 	uint32_t token;
1686 	if (!(struct_table.consume_binary(token) &&
1687 		(token == dtb::FDT_BEGIN_NODE)))
1688 	{
1689 		fprintf(stderr, "Expected FDT_BEGIN_NODE token.\n");
1690 		valid = false;
1691 		return;
1692 	}
1693 	root = node::parse_dtb(struct_table, strings_table);
1694 	if (!(struct_table.consume_binary(token) && (token == dtb::FDT_END)))
1695 	{
1696 		fprintf(stderr, "Expected FDT_END token after parsing root node.\n");
1697 		valid = false;
1698 		return;
1699 	}
1700 	valid = (root != 0);
1701 }
1702 
1703 string
1704 device_tree::node_path::to_string() const
1705 {
1706 	string path;
1707 	auto p = begin();
1708 	auto pe = end();
1709 	if ((p == pe) || (p+1 == pe))
1710 	{
1711 		return string("/");
1712 	}
1713 	// Skip the first name in the path.  It's always "", and implicitly /
1714 	for (++p ; p!=pe ; ++p)
1715 	{
1716 		path += '/';
1717 		path += p->first;
1718 		if (!(p->second.empty()))
1719 		{
1720 			path += '@';
1721 			path += p->second;
1722 		}
1723 	}
1724 	return path;
1725 }
1726 
1727 node_ptr
1728 device_tree::create_fragment_wrapper(node_ptr &node, int &fragnum)
1729 {
1730 	// In a plugin, we can massage these non-/ root nodes into into a fragment
1731 	std::string fragment_address = "fragment@" + std::to_string(fragnum);
1732 	++fragnum;
1733 
1734 	std::vector<property_ptr> symbols;
1735 
1736 	// Intentionally left empty
1737 	node_ptr newroot = node::create_special_node("", symbols);
1738 	node_ptr wrapper = node::create_special_node("__overlay__", symbols);
1739 
1740 	// Generate the fragment with $propname = <&name>
1741 	property_value v;
1742 	std::string propname;
1743 	v.string_data = node->name;
1744 	if (!node->name_is_path_reference)
1745 	{
1746 		propname = "target";
1747 		v.type = property_value::PHANDLE;
1748 	}
1749 	else
1750 	{
1751 		propname = "target-path";
1752 		v.type = property_value::STRING;
1753 	}
1754 	auto prop = std::make_shared<property>(std::string(propname));
1755 	prop->add_value(v);
1756 	symbols.push_back(prop);
1757 
1758 	node_ptr fragment = node::create_special_node(fragment_address, symbols);
1759 
1760 	wrapper->merge_node(node);
1761 	fragment->add_child(std::move(wrapper));
1762 	newroot->add_child(std::move(fragment));
1763 	return newroot;
1764 }
1765 
1766 node_ptr
1767 device_tree::generate_root(node_ptr &node, int &fragnum)
1768 {
1769 
1770 	string name = node->name;
1771 	if (name == string())
1772 	{
1773 		return std::move(node);
1774 	}
1775 	else if (!is_plugin)
1776 	{
1777 		return nullptr;
1778 	}
1779 
1780 	return create_fragment_wrapper(node, fragnum);
1781 }
1782 
1783 void
1784 device_tree::reassign_fragment_numbers(node_ptr &node, int &delta)
1785 {
1786 
1787 	for (auto &c : node->child_nodes())
1788 	{
1789 		if (c->name == std::string("fragment"))
1790 		{
1791 			int current_address = std::stoi(c->unit_address, nullptr, 16);
1792 			std::ostringstream new_address;
1793 			current_address += delta;
1794 			// It's possible that we hopped more than one somewhere, so just reset
1795 			// delta to the next in sequence.
1796 			delta = current_address + 1;
1797 			new_address << std::hex << current_address;
1798 			c->unit_address = new_address.str();
1799 		}
1800 	}
1801 }
1802 
1803 void
1804 device_tree::parse_dts(const string &fn, FILE *depfile)
1805 {
1806 	auto in = input_buffer::buffer_for_file(fn);
1807 	if (!in)
1808 	{
1809 		valid = false;
1810 		return;
1811 	}
1812 	std::vector<node_ptr> roots;
1813 	std::unordered_set<string> defnames;
1814 	for (auto &i : defines)
1815 	{
1816 		defnames.insert(i.first);
1817 	}
1818 	text_input_buffer input(std::move(in),
1819 	                        std::move(defnames),
1820 	                        std::vector<string>(include_paths),
1821 	                        dirname(fn),
1822 	                        depfile);
1823 	bool read_header = false;
1824 	int fragnum = 0;
1825 	parse_file(input, roots, read_header);
1826 	switch (roots.size())
1827 	{
1828 		case 0:
1829 			valid = false;
1830 			input.parse_error("Failed to find root node /.");
1831 			return;
1832 		case 1:
1833 			root = generate_root(roots[0], fragnum);
1834 			if (!root)
1835 			{
1836 				valid = false;
1837 				input.parse_error("Failed to find root node /.");
1838 				return;
1839 			}
1840 			break;
1841 		default:
1842 		{
1843 			root = generate_root(roots[0], fragnum);
1844 			if (!root)
1845 			{
1846 				valid = false;
1847 				input.parse_error("Failed to find root node /.");
1848 				return;
1849 			}
1850 			for (auto i=++(roots.begin()), e=roots.end() ; i!=e ; ++i)
1851 			{
1852 				auto &node = *i;
1853 				string name = node->name;
1854 				if (name == string())
1855 				{
1856 					if (is_plugin)
1857 					{
1858 						// Re-assign any fragment numbers based on a delta of
1859 						// fragnum before we merge it
1860 						reassign_fragment_numbers(node, fragnum);
1861 					}
1862 					root->merge_node(node);
1863 				}
1864 				else
1865 				{
1866 					auto existing = node_names.find(name);
1867 					if (existing == node_names.end())
1868 					{
1869 						collect_names();
1870 						existing = node_names.find(name);
1871 					}
1872 					if (existing == node_names.end())
1873 					{
1874 						if (is_plugin)
1875 						{
1876 							auto fragment = create_fragment_wrapper(node, fragnum);
1877 							root->merge_node(fragment);
1878 						}
1879 						else
1880 						{
1881 							fprintf(stderr, "Unable to merge node: %s\n", name.c_str());
1882 						}
1883 					}
1884 					else
1885 					{
1886 						existing->second->merge_node(node);
1887 					}
1888 				}
1889 			}
1890 		}
1891 	}
1892 	collect_names();
1893 	uint32_t phandle = 1;
1894 	// If we're writing symbols, go ahead and assign phandles to the entire
1895 	// tree. We'll do this before we resolve cross references, just to keep
1896 	// order semi-predictable and stable.
1897 	if (write_symbols)
1898 	{
1899 		assign_phandles(root, phandle);
1900 	}
1901 	resolve_cross_references(phandle);
1902 	if (write_symbols)
1903 	{
1904 		std::vector<property_ptr> symbols;
1905 		// Create a symbol table.  Each label  in this device tree may be
1906 		// referenced by other plugins, so we create a __symbols__ node inside
1907 		// the root that contains mappings (properties) from label names to
1908 		// paths.
1909 		for (auto &s : node_paths)
1910 		{
1911 			property_value v;
1912 			v.string_data = s.second.to_string();
1913 			v.type = property_value::STRING;
1914 			string name = s.first;
1915 			auto prop = std::make_shared<property>(std::move(name));
1916 			prop->add_value(v);
1917 			symbols.push_back(prop);
1918 		}
1919 		root->add_child(node::create_special_node("__symbols__", symbols));
1920 	}
1921 	// If this is a plugin, then we also need to create two extra nodes.
1922 	// Internal phandles will need to be renumbered to avoid conflicts with
1923 	// already-loaded nodes and external references will need to be
1924 	// resolved.
1925 	if (is_plugin)
1926 	{
1927 		std::vector<property_ptr> symbols;
1928 		// Create the fixups entry.  This is of the form:
1929 		// {target} = {path}:{property name}:{offset}
1930 		auto create_fixup_entry = [&](fixup &i, string target)
1931 			{
1932 				string value = i.path.to_string();
1933 				value += ':';
1934 				value += i.prop->get_key();
1935 				value += ':';
1936 				value += std::to_string(i.prop->offset_of_value(i.val));
1937 				property_value v;
1938 				v.string_data = value;
1939 				v.type = property_value::STRING;
1940 				auto prop = std::make_shared<property>(std::move(target));
1941 				prop->add_value(v);
1942 				return prop;
1943 			};
1944 		// If we have any unresolved phandle references in this plugin,
1945 		// then we must update them to 0xdeadbeef and leave a property in
1946 		// the /__fixups__ node whose key is the label and whose value is
1947 		// as described above.
1948 		if (!unresolved_fixups.empty())
1949 		{
1950 			for (auto &i : unresolved_fixups)
1951 			{
1952 				auto &val = i.get().val;
1953 				symbols.push_back(create_fixup_entry(i, val.string_data));
1954 				val.byte_data.push_back(0xde);
1955 				val.byte_data.push_back(0xad);
1956 				val.byte_data.push_back(0xbe);
1957 				val.byte_data.push_back(0xef);
1958 				val.type = property_value::BINARY;
1959 			}
1960 			root->add_child(node::create_special_node("__fixups__", symbols));
1961 		}
1962 		symbols.clear();
1963 		// If we have any resolved phandle references in this plugin, then
1964 		// we must create a child in the __local_fixups__ node whose path
1965 		// matches the node path from the root and whose value contains the
1966 		// location of the reference within a property.
1967 
1968 		// Create a local_fixups node that is initially empty.
1969 		node_ptr local_fixups = node::create_special_node("__local_fixups__", symbols);
1970 		for (auto &i : fixups)
1971 		{
1972 			if (!i.val.is_phandle())
1973 			{
1974 				continue;
1975 			}
1976 			node *n = local_fixups.get();
1977 			for (auto &p : i.path)
1978 			{
1979 				// Skip the implicit root
1980 				if (p.first.empty())
1981 				{
1982 					continue;
1983 				}
1984 				bool found = false;
1985 				for (auto &c : n->child_nodes())
1986 				{
1987 					if (c->name == p.first)
1988 					{
1989 						string path = p.first;
1990 						if (!(p.second.empty()))
1991 						{
1992 							path += '@';
1993 							path += p.second;
1994 						}
1995 						n->add_child(node::create_special_node(path, symbols));
1996 						n = (--n->child_end())->get();
1997 					}
1998 				}
1999 				if (!found)
2000 				{
2001 					n->add_child(node::create_special_node(p.first, symbols));
2002 					n = (--n->child_end())->get();
2003 				}
2004 			}
2005 			assert(n);
2006 			property_value pv;
2007 			push_big_endian(pv.byte_data, static_cast<uint32_t>(i.prop->offset_of_value(i.val)));
2008 			pv.type = property_value::BINARY;
2009 			auto key = i.prop->get_key();
2010 			property_ptr prop = n->get_property(key);
2011 			// If we don't have an existing property then create one and
2012 			// use this property value
2013 			if (!prop)
2014 			{
2015 				prop = std::make_shared<property>(std::move(key));
2016 				n->add_property(prop);
2017 				prop->add_value(pv);
2018 			}
2019 			else
2020 			{
2021 				// If we do have an existing property value, try to append
2022 				// this value.
2023 				property_value &old_val = *(--prop->end());
2024 				if (!old_val.try_to_merge(pv))
2025 				{
2026 					prop->add_value(pv);
2027 				}
2028 			}
2029 		}
2030 		// We've iterated over all fixups, but only emit the
2031 		// __local_fixups__ if we found some that were resolved internally.
2032 		if (local_fixups->child_begin() != local_fixups->child_end())
2033 		{
2034 			root->add_child(std::move(local_fixups));
2035 		}
2036 	}
2037 }
2038 
2039 bool device_tree::parse_define(const char *def)
2040 {
2041 	const char *val = strchr(def, '=');
2042 	if (!val)
2043 	{
2044 		if (strlen(def) != 0)
2045 		{
2046 			string name(def);
2047 			defines[name];
2048 			return true;
2049 		}
2050 		return false;
2051 	}
2052 	string name(def, val-def);
2053 	string name_copy = name;
2054 	val++;
2055 	std::unique_ptr<input_buffer> raw(new input_buffer(val, strlen(val)));
2056 	text_input_buffer in(std::move(raw),
2057 	                     std::unordered_set<string>(),
2058 	                     std::vector<string>(),
2059 	                     string(),
2060 	                     nullptr);
2061 	property_ptr p = property::parse(in, std::move(name_copy), string_set(), false);
2062 	if (p)
2063 		defines[name] = p;
2064 	return (bool)p;
2065 }
2066 
2067 } // namespace fdt
2068 
2069 } // namespace dtc
2070 
2071