fdt.cc revision 266202
1/*-
2 * Copyright (c) 2013 David Chisnall
3 * All rights reserved.
4 *
5 * This software was developed by SRI International and the University of
6 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7 * ("CTSRD"), as part of the DARPA CRASH research programme.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $FreeBSD: stable/10/usr.bin/dtc/fdt.cc 266202 2014-05-15 22:51:14Z ian $
31 */
32
33#define __STDC_LIMIT_MACROS 1
34
35#include "fdt.hh"
36
37#include <algorithm>
38#include <ctype.h>
39#include <fcntl.h>
40#include <inttypes.h>
41#include <libgen.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <unistd.h>
45#include "dtb.hh"
46
47namespace dtc
48{
49
50namespace fdt
51{
52
53uint32_t
54property_value::get_as_uint32()
55{
56	if (byte_data.size() != 4)
57	{
58		return 0;
59	}
60	uint32_t v = 0;
61	v &= byte_data[0] << 24;
62	v &= byte_data[1] << 16;
63	v &= byte_data[2] << 8;
64	v &= byte_data[3] << 0;
65	return v;
66}
67
68void
69property_value::push_to_buffer(byte_buffer &buffer)
70{
71	if (!byte_data.empty())
72	{
73		buffer.insert(buffer.end(), byte_data.begin(), byte_data.end());
74	}
75	else
76	{
77		string_data.push_to_buffer(buffer, true);
78		// Trailing nul
79		buffer.push_back(0);
80	}
81}
82
83void
84property_value::write_dts(FILE *file)
85{
86	resolve_type();
87	switch (type)
88	{
89		default:
90			assert(0 && "Invalid type");
91		case STRING:
92		case STRING_LIST:
93		case CROSS_REFERENCE:
94			write_as_string(file);
95			break;
96		case PHANDLE:
97			write_as_cells(file);
98			break;
99		case BINARY:
100			if (byte_data.size() % 4 == 0)
101			{
102				write_as_cells(file);
103				break;
104			}
105			write_as_bytes(file);
106			break;
107	}
108}
109
110void
111property_value::resolve_type()
112{
113	if (type != UNKNOWN)
114	{
115		return;
116	}
117	if (byte_data.empty())
118	{
119		type = STRING;
120		return;
121	}
122	if (byte_data.back() == 0)
123	{
124		bool is_all_printable = true;
125		int nuls = 0;
126		int bytes = 0;
127		for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i<e ; i++)
128		{
129			bytes++;
130			is_all_printable &= (*i == '\0') || isprint(*i);
131			if (*i == '\0')
132			{
133				nuls++;
134			}
135			if (!is_all_printable)
136			{
137				break;
138			}
139		}
140		if (is_all_printable && (bytes > nuls))
141		{
142			type = STRING;
143			if (nuls > 0)
144			{
145				type = STRING_LIST;
146			}
147			return;
148		}
149	}
150	type = BINARY;
151}
152
153void
154property_value::write_as_string(FILE *file)
155{
156	putc('"', file);
157	if (byte_data.empty())
158	{
159		string_data.print(file);
160	}
161	else
162	{
163		for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i!=e ; ++i)
164		{
165			// FIXME Escape tabs, newlines, and so on.
166			if (*i == '\0')
167			{
168				fputs("\", \"", file);
169				continue;
170			}
171			putc(*i, file);
172		}
173	}
174	putc('"', file);
175}
176
177void
178property_value::write_as_cells(FILE *file)
179{
180	putc('<', file);
181	assert((byte_data.size() % 4) == 0);
182	for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; ++i)
183	{
184		uint32_t v = 0;
185		v = (v << 8) | *i;
186		++i;
187		v = (v << 8) | *i;
188		++i;
189		v = (v << 8) | *i;
190		++i;
191		v = (v << 8) | *i;
192		fprintf(file, "0x%" PRIx32, v);
193		if (i+1 != e)
194		{
195			putc(' ', file);
196		}
197	}
198	putc('>', file);
199}
200
201void
202property_value::write_as_bytes(FILE *file)
203{
204	putc('[', file);
205	for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; i++)
206	{
207		fprintf(file, "%hhx", *i);
208		if (i+1 != e)
209		{
210			putc(' ', file);
211		}
212	}
213	putc(']', file);
214}
215
216void
217property::parse_string(input_buffer &input)
218{
219	property_value v;
220	assert(input[0] == '"');
221	++input;
222	const char *start = (const char*)input;
223	int length = 0;
224	while (char c = input[0])
225	{
226		if (c == '"' && input[-1] != '\\')
227		{
228			input.consume('"');
229			break;
230		}
231		++input;
232		++length;
233	}
234	v.string_data = string(start, length);
235	values.push_back(v);
236}
237
238void
239property::parse_cells(input_buffer &input)
240{
241	assert(input[0] == '<');
242	++input;
243	property_value v;
244	input.next_token();
245	while (!input.consume('>'))
246	{
247		input.next_token();
248		// If this is a phandle then we need to get the name of the
249		// referenced node
250		if (input.consume('&'))
251		{
252			input.next_token();
253			// FIXME: We should support full paths here, but we
254			// don't.
255			string referenced = string::parse_node_name(input);
256			if (referenced.empty())
257			{
258				input.parse_error("Expected node name");
259				valid = false;
260				return;
261			}
262			input.next_token();
263			// If we already have some bytes, make the phandle a
264			// separate component.
265			if (!v.byte_data.empty())
266			{
267				values.push_back(v);
268				v = property_value();
269			}
270			v.string_data = referenced;
271			v.type = property_value::PHANDLE;
272			values.push_back(v);
273			v = property_value();
274		}
275		else
276		{
277			//FIXME: We should support labels in the middle
278			//of these, but we don't.
279			long long val;
280			if (!input.consume_integer(val))
281			{
282				input.parse_error("Expected numbers in array of cells");
283				valid = false;
284				return;
285			}
286			if ((val < 0) || (val > UINT32_MAX))
287			{
288				input.parse_error("Value out of range");
289				valid = false;
290				return;
291			}
292			push_big_endian(v.byte_data, (uint32_t)val);
293			input.next_token();
294		}
295	}
296	// Don't store an empty string value here.
297	if (v.byte_data.size() > 0)
298	{
299		values.push_back(v);
300	}
301}
302
303void
304property::parse_bytes(input_buffer &input)
305{
306	assert(input[0] == '[');
307	++input;
308	property_value v;
309	input.next_token();
310	while (!input.consume(']'))
311	{
312		{
313			//FIXME: We should support
314			//labels in the middle of
315			//these, but we don't.
316			uint8_t val;
317			if (!input.consume_hex_byte(val))
318			{
319				input.parse_error("Expected hex bytes in array of bytes");
320				valid = false;
321				return;
322			}
323			v.byte_data.push_back(val);
324			input.next_token();
325		}
326	}
327	values.push_back(v);
328}
329
330void
331property::parse_reference(input_buffer &input)
332{
333	assert(input[0] == '&');
334	++input;
335	input.next_token();
336	property_value v;
337	v.string_data = string::parse_node_name(input);
338	if (v.string_data.empty())
339	{
340		input.parse_error("Expected node name");
341		valid = false;
342		return;
343	}
344	v.type = property_value::CROSS_REFERENCE;
345	values.push_back(v);
346}
347
348property::property(input_buffer &structs, input_buffer &strings)
349{
350	uint32_t name_offset;
351	uint32_t length;
352	valid = structs.consume_binary(length) &&
353		structs.consume_binary(name_offset);
354	if (!valid)
355	{
356		fprintf(stderr, "Failed to read property\n");
357		return;
358	}
359	// Find the name
360	input_buffer name_buffer = strings.buffer_from_offset(name_offset);
361	if (name_buffer.empty())
362	{
363		fprintf(stderr, "Property name offset %" PRIu32
364			" is past the end of the strings table\n",
365			name_offset);
366		valid = false;
367		return;
368	}
369	key = string(name_buffer);
370	// Read the value
371	uint8_t byte;
372	property_value v;
373	for (uint32_t i=0 ; i<length ; i++)
374	{
375		if (!(valid = structs.consume_binary(byte)))
376		{
377			fprintf(stderr, "Failed to read property value\n");
378			return;
379		}
380		v.byte_data.push_back(byte);
381	}
382	values.push_back(v);
383}
384
385void property::parse_define(input_buffer &input, define_map *defines)
386{
387	input.consume('$');
388	if (!defines)
389	{
390		input.parse_error("No predefined properties to match name\n");
391		valid = false;
392		return;
393	}
394	string name = string::parse_property_name(input);
395	define_map::iterator found;
396	if ((name == string()) ||
397	    ((found = defines->find(name)) == defines->end()))
398	{
399		input.parse_error("Undefined property name\n");
400		valid = false;
401		return;
402	}
403	values.push_back((*found).second->values[0]);
404}
405
406property::property(input_buffer &input,
407                   string k,
408                   string l,
409                   bool semicolonTerminated,
410                   define_map *defines) : key(k), label(l), valid(true)
411{
412	do {
413		input.next_token();
414		switch (input[0])
415		{
416			case '$':
417			{
418				parse_define(input, defines);
419				if (valid)
420				{
421					break;
422				}
423			}
424			default:
425				input.parse_error("Invalid property value.");
426				valid = false;
427				return;
428			case '"':
429				parse_string(input);
430				break;
431			case '<':
432				parse_cells(input);
433				break;
434			case '[':
435				parse_bytes(input);
436				break;
437			case '&':
438				parse_reference(input);
439				break;
440			case ';':
441			{
442				break;
443			}
444		}
445		input.next_token();
446	} while (input.consume(','));
447	if (semicolonTerminated && !input.consume(';'))
448	{
449		input.parse_error("Expected ; at end of property");
450		valid = false;
451	}
452}
453
454property*
455property::parse_dtb(input_buffer &structs, input_buffer &strings)
456{
457	property *p = new property(structs, strings);
458	if (!p->valid)
459	{
460		delete p;
461		p = 0;
462	}
463	return p;
464}
465
466property*
467property::parse(input_buffer &input, string key, string label,
468                bool semicolonTerminated, define_map *defines)
469{
470	property *p = new property(input, key, label, semicolonTerminated, defines);
471	if (!p->valid)
472	{
473		delete p;
474		p = 0;
475	}
476	return p;
477}
478
479void
480property::write(dtb::output_writer &writer, dtb::string_table &strings)
481{
482	writer.write_token(dtb::FDT_PROP);
483	byte_buffer value_buffer;
484	for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
485	{
486		i->push_to_buffer(value_buffer);
487	}
488	writer.write_data((uint32_t)value_buffer.size());
489	writer.write_comment(key);
490	writer.write_data(strings.add_string(key));
491	writer.write_data(value_buffer);
492}
493
494void
495property::write_dts(FILE *file, int indent)
496{
497	for (int i=0 ; i<indent ; i++)
498	{
499		putc('\t', file);
500	}
501	if (label != string())
502	{
503		label.print(file);
504		fputs(": ", file);
505	}
506	if (key != string())
507	{
508		key.print(file);
509	}
510	if (!values.empty())
511	{
512		fputs(" = ", file);
513		for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
514		{
515			i->write_dts(file);
516			if (i+1 != e)
517			{
518				putc(',', file);
519				putc(' ', file);
520			}
521		}
522	}
523	fputs(";\n", file);
524}
525
526string
527node::parse_name(input_buffer &input, bool &is_property, const char *error)
528{
529	if (!valid)
530	{
531		return string();
532	}
533	input.next_token();
534	if (is_property)
535	{
536		return string::parse_property_name(input);
537	}
538	string n = string::parse_node_or_property_name(input, is_property);
539	if (n.empty())
540	{
541		if (n.empty())
542		{
543			input.parse_error(error);
544			valid = false;
545		}
546	}
547	return n;
548}
549
550node::node(input_buffer &structs, input_buffer &strings) : valid(true)
551{
552	const char *name_start = (const char*)structs;
553	int name_length = 0;
554	while (structs[0] != '\0' && structs[0] != '@')
555	{
556		name_length++;
557		++structs;
558	}
559	name = string(name_start, name_length);
560	if (structs[0] == '@')
561	{
562		++structs;
563		name_start = (const char*)structs;
564		name_length = 0;
565		while (structs[0] != '\0')
566		{
567			name_length++;
568			++structs;
569		}
570		unit_address = string(name_start, name_length);
571	}
572	++structs;
573	uint32_t token;
574	while (structs.consume_binary(token))
575	{
576		switch (token)
577		{
578			default:
579				fprintf(stderr, "Unexpected token 0x%" PRIx32
580					" while parsing node.\n", token);
581				valid = false;
582				return;
583			// Child node, parse it.
584			case dtb::FDT_BEGIN_NODE:
585			{
586				node *child = node::parse_dtb(structs, strings);
587				if (child == 0)
588				{
589					valid = false;
590					return;
591				}
592				children.push_back(child);
593				break;
594			}
595			// End of this node, no errors.
596			case dtb::FDT_END_NODE:
597				return;
598			// Property, parse it.
599			case dtb::FDT_PROP:
600			{
601				property *prop = property::parse_dtb(structs, strings);
602				if (prop == 0)
603				{
604					valid = false;
605					return;
606				}
607				properties.push_back(prop);
608				break;
609			}
610				break;
611			// End of structs table.  Should appear after
612			// the end of the last node.
613			case dtb::FDT_END:
614				fprintf(stderr, "Unexpected FDT_END token while parsing node.\n");
615				valid = false;
616				return;
617			// NOPs are padding.  Ignore them.
618			case dtb::FDT_NOP:
619				break;
620		}
621	}
622	fprintf(stderr, "Failed to read token from structs table while parsing node.\n");
623	valid = false;
624	return;
625}
626
627node::node(input_buffer &input, string n, string l, string a, define_map *defines) :
628	label(l), name(n), unit_address(a), valid(true)
629{
630	if (!input.consume('{'))
631	{
632		input.parse_error("Expected { to start new device tree node.\n");
633	}
634	input.next_token();
635	while (valid && !input.consume('}'))
636	{
637		// flag set if we find any characters that are only in
638		// the property name character set, not the node
639		bool is_property = false;
640		string child_name, child_label, child_address;
641		child_name = parse_name(input, is_property,
642				"Expected property or node name");
643		if (input.consume(':'))
644		{
645			// Node labels can contain any characters?  The
646			// spec doesn't say, so we guess so...
647			is_property = false;
648			child_label = child_name;
649			child_name = parse_name(input, is_property, "Expected property or node name");
650		}
651		if (input.consume('@'))
652		{
653			child_address = parse_name(input, is_property, "Expected unit address");
654		}
655		if (!valid)
656		{
657			return;
658		}
659		input.next_token();
660		// If we're parsing a property, then we must actually do that.
661		if (input.consume('='))
662		{
663			property *p= property::parse(input, child_name,
664					child_label, true, defines);
665			if (p == 0)
666			{
667				valid = false;
668			}
669			else
670			{
671				properties.push_back(p);
672			}
673		}
674		else if (!is_property && input[0] == ('{'))
675		{
676			node *child = node::parse(input, child_name,
677					child_label, child_address, defines);
678			if (child)
679			{
680				children.push_back(child);
681			}
682			else
683			{
684				valid = false;
685			}
686		}
687		else if (input.consume(';'))
688		{
689			properties.push_back(new property(child_name, child_label));
690		}
691		else
692		{
693			input.parse_error("Error parsing property.");
694			valid = false;
695		}
696		input.next_token();
697	}
698	input.consume(';');
699}
700
701bool
702node::cmp_properties(property *p1, property *p2)
703{
704	return p1->get_key() < p2->get_key();
705}
706
707bool
708node::cmp_children(node *c1, node *c2)
709{
710	if (c1->name == c2->name)
711	{
712		return c1->unit_address < c2->unit_address;
713	}
714	return c1->name < c2->name;
715}
716
717void
718node::sort()
719{
720	std::sort(property_begin(), property_end(), cmp_properties);
721	std::sort(child_begin(), child_end(), cmp_children);
722	for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
723	{
724		(*i)->sort();
725	}
726}
727
728node*
729node::parse(input_buffer &input,
730            string name,
731            string label,
732            string address,
733            define_map *defines)
734{
735	node *n = new node(input, name, label, address, defines);
736	if (!n->valid)
737	{
738		delete n;
739		n = 0;
740	}
741	return n;
742}
743
744node*
745node::parse_dtb(input_buffer &structs, input_buffer &strings)
746{
747	node *n = new node(structs, strings);
748	if (!n->valid)
749	{
750		delete n;
751		n = 0;
752	}
753	return n;
754}
755
756node::~node()
757{
758	while (!children.empty())
759	{
760		delete children.back();
761		children.pop_back();
762	}
763	while (!properties.empty())
764	{
765		delete properties.back();
766		properties.pop_back();
767	}
768}
769
770property*
771node::get_property(string key)
772{
773	for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
774	{
775		if ((*i)->get_key() == key)
776		{
777			return *i;
778		}
779	}
780	return 0;
781}
782
783void
784node::merge_node(node *other)
785{
786	if (!other->label.empty())
787	{
788		label = other->label;
789	}
790	// Note: this is an O(n*m) operation.  It might be sensible to
791	// optimise this if we find that there are nodes with very
792	// large numbers of properties, but for typical usage the
793	// entire vector will fit (easily) into cache, so iterating
794	// over it repeatedly isn't that expensive.
795	while (!other->properties.empty())
796	{
797		property *p = other->properties.front();
798		for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
799		{
800			if ((*i)->get_key() == p->get_key())
801			{
802				delete *i;
803				properties.erase(i);
804				break;
805			}
806		}
807		add_property(p);
808		other->properties.erase(other->properties.begin());
809	}
810	while (!other->children.empty())
811	{
812		node *c = other->children.front();
813		bool found = false;
814		for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
815		{
816			if ((*i)->name == c->name && (*i)->unit_address == c->unit_address)
817			{
818				(*i)->merge_node(c);
819				delete c;
820				found = true;
821				break;
822			}
823		}
824		if (!found)
825		{
826			children.push_back(c);
827		}
828		other->children.erase(other->children.begin());
829	}
830}
831
832void
833node::write(dtb::output_writer &writer, dtb::string_table &strings)
834{
835	writer.write_token(dtb::FDT_BEGIN_NODE);
836	byte_buffer name_buffer;
837	name.push_to_buffer(name_buffer);
838	if (unit_address != string())
839	{
840		name_buffer.push_back('@');
841		unit_address.push_to_buffer(name_buffer);
842	}
843	writer.write_comment(name);
844	writer.write_data(name_buffer);
845	writer.write_data((uint8_t)0);
846	for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
847	{
848		(*i)->write(writer, strings);
849	}
850	for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
851	{
852		(*i)->write(writer, strings);
853	}
854	writer.write_token(dtb::FDT_END_NODE);
855}
856
857void
858node::write_dts(FILE *file, int indent)
859{
860	for (int i=0 ; i<indent ; i++)
861	{
862		putc('\t', file);
863	}
864	if (label != string())
865	{
866		label.print(file);
867		fputs(": ", file);
868	}
869	if (name != string())
870	{
871		name.print(file);
872	}
873	if (unit_address != string())
874	{
875		putc('@', file);
876		unit_address.print(file);
877	}
878	fputs(" {\n\n", file);
879	for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
880	{
881		(*i)->write_dts(file, indent+1);
882	}
883	for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
884	{
885		(*i)->write_dts(file, indent+1);
886	}
887	for (int i=0 ; i<indent ; i++)
888	{
889		putc('\t', file);
890	}
891	fputs("};\n", file);
892}
893
894void
895device_tree::collect_names_recursive(node* n, node_path &path)
896{
897	string name = n->label;
898	path.push_back(std::make_pair(n->name, n->unit_address));
899	if (name != string())
900	{
901		if (node_names.find(name) == node_names.end())
902		{
903			node_names.insert(std::make_pair(name, n));
904			node_paths.insert(std::make_pair(name, path));
905		}
906		else
907		{
908			node_names[name] = (node*)-1;
909			std::map<string, node_path>::iterator i = node_paths.find(name);
910			if (i != node_paths.end())
911			{
912				node_paths.erase(name);
913			}
914			fprintf(stderr, "Label not unique: ");
915			name.dump();
916			fprintf(stderr, ".  References to this label will not be resolved.");
917		}
918	}
919	for (node::child_iterator i=n->child_begin(), e=n->child_end() ; i!=e ; ++i)
920	{
921		collect_names_recursive(*i, path);
922	}
923	path.pop_back();
924	// Now we collect the phandles and properties that reference
925	// other nodes.
926	for (node::property_iterator i=n->property_begin(), e=n->property_end() ; i!=e ; ++i)
927	{
928		for (property::value_iterator p=(*i)->begin(),pe=(*i)->end() ; p!=pe ; ++p)
929		{
930			if (p->is_phandle())
931			{
932				phandles.push_back(&*p);
933			}
934			if (p->is_cross_reference())
935			{
936				cross_references.push_back(&*p);
937			}
938		}
939		if ((*i)->get_key() == string("phandle") ||
940		    (*i)->get_key() == string("linux,phandle"))
941		{
942			if ((*i)->begin()->byte_data.size() != 4)
943			{
944				fprintf(stderr, "Invalid phandle value for node ");
945				n->name.dump();
946				fprintf(stderr, ".  Should be a 4-byte value.\n");
947				valid = false;
948			}
949			else
950			{
951				uint32_t phandle = (*i)->begin()->get_as_uint32();
952				used_phandles.insert(std::make_pair(phandle, n));
953			}
954		}
955	}
956}
957
958void
959device_tree::collect_names()
960{
961	node_path p;
962	collect_names_recursive(root, p);
963}
964
965void
966device_tree::resolve_cross_references()
967{
968	for (std::vector<property_value*>::iterator i=cross_references.begin(), e=cross_references.end() ; i!=e ; ++i)
969	{
970		property_value* pv = *i;
971		node_path path = node_paths[pv->string_data];
972		// Skip the first name in the path.  It's always "", and implicitly /
973		for (node_path::iterator p=path.begin()+1, pe=path.end() ; p!=pe ; ++p)
974		{
975			pv->byte_data.push_back('/');
976			p->first.push_to_buffer(pv->byte_data);
977			if (!(p->second.empty()))
978			{
979				pv->byte_data.push_back('@');
980				p->second.push_to_buffer(pv->byte_data);
981			}
982		}
983		pv->byte_data.push_back(0);
984	}
985	uint32_t phandle = 1;
986	for (std::vector<property_value*>::iterator i=phandles.begin(), e=phandles.end() ; i!=e ; ++i)
987	{
988		string target_name = (*i)->string_data;
989		node *target = node_names[target_name];
990		if (target == 0)
991		{
992			fprintf(stderr, "Failed to find node with label:");
993			target_name.dump();
994			fprintf(stderr, "\n");
995			valid = 0;
996			return;
997		}
998		// If there is an existing phandle, use it
999		property *p = target->get_property("phandle");
1000		if (p == 0)
1001		{
1002			p = target->get_property("linux,phandle");
1003		}
1004		if (p == 0)
1005		{
1006			// Otherwise insert a new phandle node
1007			property_value v;
1008			while (used_phandles.find(phandle) != used_phandles.end())
1009			{
1010				// Note that we only don't need to
1011				// store this phandle in the set,
1012				// because we are monotonically
1013				// increasing the value of phandle and
1014				// so will only ever revisit this value
1015				// if we have used 2^32 phandles, at
1016				// which point our blob won't fit in
1017				// any 32-bit system and we've done
1018				// something badly wrong elsewhere
1019				// already.
1020				phandle++;
1021			}
1022			push_big_endian(v.byte_data, phandle++);
1023			if (phandle_node_name == BOTH || phandle_node_name == LINUX)
1024			{
1025				p = new property(string("linux,phandle"));
1026				p->add_value(v);
1027				target->add_property(p);
1028			}
1029			if (phandle_node_name == BOTH || phandle_node_name == EPAPR)
1030			{
1031				p = new property(string("phandle"));
1032				p->add_value(v);
1033				target->add_property(p);
1034			}
1035		}
1036		p->begin()->push_to_buffer((*i)->byte_data);
1037		assert((*i)->byte_data.size() == 4);
1038	}
1039}
1040
1041void
1042device_tree::parse_roots(input_buffer &input, std::vector<node*> &roots)
1043{
1044	input.next_token();
1045	while (valid && input.consume('/'))
1046	{
1047		input.next_token();
1048		node *n = node::parse(input, string("", 1), string(), string(), &defines);
1049		if (n)
1050		{
1051			roots.push_back(n);
1052		}
1053		else
1054		{
1055			valid = false;
1056		}
1057		input.next_token();
1058	}
1059}
1060
1061input_buffer*
1062device_tree::buffer_for_file(const char *path)
1063{
1064	if (string(path) == string("-"))
1065	{
1066		input_buffer *b = new stream_input_buffer();
1067		buffers.push_back(b);
1068		return b;
1069	}
1070	int source = open(path, O_RDONLY);
1071	if (source == -1)
1072	{
1073		fprintf(stderr, "Unable to open file %s\n", path);
1074		return 0;
1075	}
1076	input_buffer *b = new mmap_input_buffer(source);
1077	// Keep the buffer that owns the memory around for the lifetime
1078	// of this FDT.  Ones simply referring to it may have shorter
1079	// lifetimes.
1080	buffers.push_back(b);
1081	close(source);
1082	return b;
1083}
1084
1085template<class writer> void
1086device_tree::write(int fd)
1087{
1088	dtb::string_table st;
1089	dtb::header head;
1090	writer head_writer;
1091	writer reservation_writer;
1092	writer struct_writer;
1093	writer strings_writer;
1094
1095	// Build the reservation table
1096	reservation_writer.write_comment(string("Memory reservations"));
1097	reservation_writer.write_label(string("dt_reserve_map"));
1098	for (std::vector<reservation>::iterator i=reservations.begin(),
1099	     e=reservations.end() ; i!=e ; ++i)
1100	{
1101		reservation_writer.write_comment(string("Reservation start"));
1102		reservation_writer.write_data(i->first);
1103		reservation_writer.write_comment(string("Reservation length"));
1104		reservation_writer.write_data(i->first);
1105	}
1106	// Write n spare reserve map entries, plus the trailing 0.
1107	for (uint32_t i=0 ; i<=spare_reserve_map_entries ; i++)
1108	{
1109		reservation_writer.write_data((uint64_t)0);
1110		reservation_writer.write_data((uint64_t)0);
1111	}
1112
1113
1114	struct_writer.write_comment(string("Device tree"));
1115	struct_writer.write_label(string("dt_struct_start"));
1116	root->write(struct_writer, st);
1117	struct_writer.write_token(dtb::FDT_END);
1118	struct_writer.write_label(string("dt_struct_end"));
1119
1120	st.write(strings_writer);
1121	// Find the strings size before we stick padding on the end.
1122	// Note: We should possibly use a new writer for the padding.
1123	head.size_dt_strings = strings_writer.size();
1124
1125	// Stick the padding in the strings writer, but after the
1126	// marker indicating that it's the end.
1127	// Note: We probably should add a padding call to the writer so
1128	// that the asm back end can write padding directives instead
1129	// of a load of 0 bytes.
1130	for (uint32_t i=0 ; i<blob_padding ; i++)
1131	{
1132		strings_writer.write_data((uint8_t)0);
1133	}
1134	head.totalsize = sizeof(head) + strings_writer.size() +
1135		struct_writer.size() + reservation_writer.size();
1136	while (head.totalsize < minimum_blob_size)
1137	{
1138		head.totalsize++;
1139		strings_writer.write_data((uint8_t)0);
1140	}
1141	head.off_dt_struct = sizeof(head) + reservation_writer.size();;
1142	head.off_dt_strings = head.off_dt_struct + struct_writer.size();
1143	head.off_mem_rsvmap = sizeof(head);
1144	head.boot_cpuid_phys = boot_cpu;
1145	head.size_dt_struct = struct_writer.size();
1146	head.write(head_writer);
1147
1148	head_writer.write_to_file(fd);
1149	reservation_writer.write_to_file(fd);
1150	struct_writer.write_to_file(fd);
1151	strings_writer.write_label(string("dt_blob_end"));
1152	strings_writer.write_to_file(fd);
1153}
1154
1155node*
1156device_tree::referenced_node(property_value &v)
1157{
1158	if (v.is_phandle())
1159	{
1160		return node_names[v.string_data];
1161	}
1162	if (v.is_binary())
1163	{
1164		return used_phandles[v.get_as_uint32()];
1165	}
1166	return 0;
1167}
1168
1169void
1170device_tree::write_binary(int fd)
1171{
1172	write<dtb::binary_writer>(fd);
1173}
1174
1175void
1176device_tree::write_asm(int fd)
1177{
1178	write<dtb::asm_writer>(fd);
1179}
1180
1181void
1182device_tree::write_dts(int fd)
1183{
1184	FILE *file = fdopen(fd, "w");
1185	fputs("/dtc-v1/;\n\n", file);
1186
1187	if (!reservations.empty())
1188	{
1189		const char msg[] = "/memreserve/";
1190		fwrite(msg, sizeof(msg), 1, file);
1191		for (std::vector<reservation>::iterator i=reservations.begin(),
1192		     e=reservations.end() ; i!=e ; ++i)
1193		{
1194			fprintf(stderr, " %" PRIx64 " %" PRIx64, i->first, i->second);
1195		}
1196		fputs(";\n\n", file);
1197	}
1198	putc('/', file);
1199	putc(' ', file);
1200	root->write_dts(file, 0);
1201	fclose(file);
1202}
1203
1204void
1205device_tree::parse_dtb(const char *fn, FILE *depfile)
1206{
1207	input_buffer *in = buffer_for_file(fn);
1208	if (in == 0)
1209	{
1210		valid = false;
1211		return;
1212	}
1213	input_buffer &input = *in;
1214	dtb::header h;
1215	valid = h.read_dtb(input);
1216	boot_cpu = h.boot_cpuid_phys;
1217	if (h.last_comp_version > 17)
1218	{
1219		fprintf(stderr, "Don't know how to read this version of the device tree blob");
1220		valid = false;
1221	}
1222	if (!valid)
1223	{
1224		return;
1225	}
1226	input_buffer reservation_map =
1227		input.buffer_from_offset(h.off_mem_rsvmap, 0);
1228	uint64_t start, length;
1229	do
1230	{
1231		if (!(reservation_map.consume_binary(start) &&
1232		      reservation_map.consume_binary(length)))
1233		{
1234			fprintf(stderr, "Failed to read memory reservation table\n");
1235			valid = false;
1236			return;
1237		}
1238	} while (!((start == 0) && (length == 0)));
1239	input_buffer struct_table =
1240		input.buffer_from_offset(h.off_dt_struct, h.size_dt_struct);
1241	input_buffer strings_table =
1242		input.buffer_from_offset(h.off_dt_strings, h.size_dt_strings);
1243	uint32_t token;
1244	if (!(struct_table.consume_binary(token) &&
1245		(token == dtb::FDT_BEGIN_NODE)))
1246	{
1247		fprintf(stderr, "Expected FDT_BEGIN_NODE token.\n");
1248		valid = false;
1249		return;
1250	}
1251	root = node::parse_dtb(struct_table, strings_table);
1252	if (!(struct_table.consume_binary(token) && (token == dtb::FDT_END)))
1253	{
1254		fprintf(stderr, "Expected FDT_END token after parsing root node.\n");
1255		valid = false;
1256		return;
1257	}
1258	valid = (root != 0);
1259}
1260
1261void
1262device_tree::parse_dts(const char *fn, FILE *depfile)
1263{
1264	input_buffer *in = buffer_for_file(fn);
1265	if (in == 0)
1266	{
1267		valid = false;
1268		return;
1269	}
1270	std::vector<node*> roots;
1271	input_buffer &input = *in;
1272	input.next_token();
1273	bool read_header = false;
1274	// Read the header
1275	if (input.consume("/dts-v1/;"))
1276	{
1277		read_header = true;
1278	}
1279	input.next_token();
1280	while(input.consume("/include/"))
1281	{
1282		bool reallyInclude = true;
1283		if (input.consume("if "))
1284		{
1285			input.next_token();
1286			string name = string::parse_property_name(input);
1287			// XXX: Error handling
1288			if (defines.find(name) == defines.end())
1289			{
1290				reallyInclude = false;
1291			}
1292			input.consume('/');
1293		}
1294		input.next_token();
1295		if (!input.consume('"'))
1296		{
1297			input.parse_error("Expected quoted filename");
1298			valid = false;
1299			return;
1300		}
1301		int length = 0;
1302		while (input[length] != '"') length++;
1303
1304		const char *file = (const char*)input;
1305		const char *dir = dirname(fn);
1306		int dir_length = strlen(dir);
1307		char *include_file = (char*)malloc(strlen(dir) + length + 2);
1308		memcpy(include_file, dir, dir_length);
1309		include_file[dir_length] = '/';
1310		memcpy(include_file+dir_length+1, file, length);
1311		include_file[dir_length+length+1] = 0;
1312
1313		input.consume(include_file+dir_length+1);
1314		input.consume('"');
1315		if (!reallyInclude)
1316		{
1317			continue;
1318		}
1319
1320		input_buffer *include_buffer = buffer_for_file(include_file);
1321
1322		if (include_buffer == 0)
1323		{
1324			for (std::vector<const char*>::iterator i=include_paths.begin(), e=include_paths.end() ; e!=i ; ++i)
1325			{
1326				free(include_file);
1327				dir = *i;
1328				dir_length = strlen(dir);
1329				include_file = (char*)malloc(strlen(dir) +
1330						length + 2);
1331				memcpy(include_file, dir, dir_length);
1332				include_file[dir_length] = '/';
1333				memcpy(include_file+dir_length+1, file, length);
1334				include_file[dir_length+length+1] = 0;
1335				include_buffer = buffer_for_file(include_file);
1336				if (include_buffer != 0)
1337				{
1338					break;
1339				}
1340			}
1341		}
1342		if (depfile != 0)
1343		{
1344			putc(' ', depfile);
1345			fputs(include_file, depfile);
1346		}
1347		if (include_buffer == 0)
1348		{
1349			valid = false;
1350			return;
1351		}
1352		input_buffer &include = *include_buffer;
1353		free((void*)include_file);
1354
1355		if (!read_header)
1356		{
1357			include.next_token();
1358			read_header = include.consume("/dts-v1/;");
1359		}
1360		parse_roots(include, roots);
1361	}
1362	input.next_token();
1363	if (!read_header)
1364	{
1365		input.parse_error("Expected /dts-v1/; version string");
1366	}
1367	// Read any memory reservations
1368	while(input.consume("/memreserve/"))
1369	{
1370		long long start, len;
1371		input.next_token();
1372		// Read the start and length.
1373		if (!(input.consume_integer(start) &&
1374		    (input.next_token(),
1375		    input.consume_integer(len))))
1376		{
1377			input.parse_error("Expected /dts-v1/; version string");
1378		}
1379		input.next_token();
1380		input.consume(';');
1381		reservations.push_back(reservation(start, len));
1382	}
1383	parse_roots(input, roots);
1384	switch (roots.size())
1385	{
1386		case 0:
1387			valid = false;
1388			input.parse_error("Failed to find root node /.");
1389			return;
1390		case 1:
1391			root = roots[0];
1392			break;
1393		default:
1394		{
1395			root = roots[0];
1396			for (std::vector<node*>::iterator i=roots.begin()+1,
1397			     e=roots.end() ; i!=e ; ++i)
1398			{
1399				root->merge_node(*i);
1400				delete *i;
1401			}
1402			roots.resize(1);
1403		}
1404	}
1405	collect_names();
1406	resolve_cross_references();
1407}
1408
1409device_tree::~device_tree()
1410{
1411	if (root != 0)
1412	{
1413		delete root;
1414	}
1415	while (!buffers.empty())
1416	{
1417		delete buffers.back();
1418		buffers.pop_back();
1419	}
1420	for (define_map::iterator i=defines.begin(), e=defines.end() ;
1421	     i!=e ; ++i)
1422	{
1423		delete i->second;
1424	}
1425}
1426
1427bool device_tree::parse_define(const char *def)
1428{
1429	char *val = strchr(def, '=');
1430	if (!val)
1431	{
1432		if (strlen(def) != 0)
1433		{
1434			string name(def);
1435			defines[name];
1436			return true;
1437		}
1438		return false;
1439	}
1440	string name(def, val-def);
1441	val++;
1442	input_buffer in = input_buffer(val, strlen(val));
1443	property *p = property::parse(in, name, string(), false);
1444	if (p)
1445		defines[name] = p;
1446	return p;
1447}
1448
1449} // namespace fdt
1450
1451} // namespace dtc
1452
1453