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