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