2 * Copyright (c) 2013 David Chisnall
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.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
33 #define __STDC_LIMIT_MACROS 1
45 #include <sys/types.h>
56 property_value::get_as_uint32()
58 if (byte_data.size() != 4)
63 v &= byte_data[0] << 24;
64 v &= byte_data[1] << 16;
65 v &= byte_data[2] << 8;
66 v &= byte_data[3] << 0;
71 property_value::push_to_buffer(byte_buffer &buffer)
73 if (!byte_data.empty())
75 buffer.insert(buffer.end(), byte_data.begin(), byte_data.end());
79 string_data.push_to_buffer(buffer, true);
86 property_value::write_dts(FILE *file)
92 assert(0 && "Invalid type");
96 write_as_string(file);
102 if (byte_data.size() % 4 == 0)
104 write_as_cells(file);
107 write_as_bytes(file);
113 property_value::resolve_type()
119 if (byte_data.empty())
124 if (byte_data.back() == 0)
126 bool is_all_printable = true;
129 for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i<e ; i++)
132 is_all_printable &= (*i == '\0') || isprint(*i);
137 if (!is_all_printable)
142 if ((is_all_printable && (bytes > nuls)) || bytes == 0)
156 property_value::write_as_string(FILE *file)
159 if (byte_data.empty())
161 string_data.print(file);
165 for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i!=e ; ++i)
167 // FIXME Escape tabs, newlines, and so on.
170 fputs("\", \"", file);
180 property_value::write_as_cells(FILE *file)
183 assert((byte_data.size() % 4) == 0);
184 for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; ++i)
194 fprintf(file, "0x%" PRIx32, v);
204 property_value::write_as_bytes(FILE *file)
207 for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; i++)
209 fprintf(file, "%02hhx", *i);
219 property::parse_string(input_buffer &input)
222 assert(input[0] == '"');
224 const char *start = (const char*)input;
226 while (char c = input[0])
228 if (c == '"' && input[-1] != '\\')
236 v.string_data = string(start, length);
241 property::parse_cells(input_buffer &input)
243 assert(input[0] == '<');
247 while (!input.consume('>'))
250 // If this is a phandle then we need to get the name of the
252 if (input.consume('&'))
255 // FIXME: We should support full paths here, but we
257 string referenced = string::parse_node_name(input);
258 if (referenced.empty())
260 input.parse_error("Expected node name");
265 // If we already have some bytes, make the phandle a
266 // separate component.
267 if (!v.byte_data.empty())
270 v = property_value();
272 v.string_data = referenced;
273 v.type = property_value::PHANDLE;
275 v = property_value();
279 //FIXME: We should support labels in the middle
280 //of these, but we don't.
282 if (!input.consume_integer(val))
284 input.parse_error("Expected numbers in array of cells");
288 if ((val < 0) || (val > UINT32_MAX))
290 input.parse_error("Value out of range");
294 push_big_endian(v.byte_data, (uint32_t)val);
298 // Don't store an empty string value here.
299 if (v.byte_data.size() > 0)
306 property::parse_bytes(input_buffer &input)
308 assert(input[0] == '[');
312 while (!input.consume(']'))
315 //FIXME: We should support
316 //labels in the middle of
317 //these, but we don't.
319 if (!input.consume_hex_byte(val))
321 input.parse_error("Expected hex bytes in array of bytes");
325 v.byte_data.push_back(val);
333 property::parse_reference(input_buffer &input)
335 assert(input[0] == '&');
339 v.string_data = string::parse_node_name(input);
340 if (v.string_data.empty())
342 input.parse_error("Expected node name");
346 v.type = property_value::CROSS_REFERENCE;
350 property::property(input_buffer &structs, input_buffer &strings)
352 uint32_t name_offset;
354 valid = structs.consume_binary(length) &&
355 structs.consume_binary(name_offset);
358 fprintf(stderr, "Failed to read property\n");
362 input_buffer name_buffer = strings.buffer_from_offset(name_offset);
363 if (name_buffer.empty())
365 fprintf(stderr, "Property name offset %" PRIu32
366 " is past the end of the strings table\n",
371 key = string(name_buffer);
373 // If we're empty, do not push anything as value.
380 for (uint32_t i=0 ; i<length ; i++)
382 if (!(valid = structs.consume_binary(byte)))
384 fprintf(stderr, "Failed to read property value\n");
387 v.byte_data.push_back(byte);
392 void property::parse_define(input_buffer &input, define_map *defines)
397 input.parse_error("No predefined properties to match name\n");
401 string name = string::parse_property_name(input);
402 define_map::iterator found;
403 if ((name == string()) ||
404 ((found = defines->find(name)) == defines->end()))
406 input.parse_error("Undefined property name\n");
410 values.push_back((*found).second->values[0]);
413 property::property(input_buffer &input,
416 bool semicolonTerminated,
417 define_map *defines) : key(k), label(l), valid(true)
425 parse_define(input, defines);
432 input.parse_error("Invalid property value.");
445 parse_reference(input);
453 } while (input.consume(','));
454 if (semicolonTerminated && !input.consume(';'))
456 input.parse_error("Expected ; at end of property");
462 property::parse_dtb(input_buffer &structs, input_buffer &strings)
464 property *p = new property(structs, strings);
474 property::parse(input_buffer &input, string key, string label,
475 bool semicolonTerminated, define_map *defines)
477 property *p = new property(input, key, label, semicolonTerminated, defines);
487 property::write(dtb::output_writer &writer, dtb::string_table &strings)
489 writer.write_token(dtb::FDT_PROP);
490 byte_buffer value_buffer;
491 for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
493 i->push_to_buffer(value_buffer);
495 writer.write_data((uint32_t)value_buffer.size());
496 writer.write_comment(key);
497 writer.write_data(strings.add_string(key));
498 writer.write_data(value_buffer);
502 property::write_dts(FILE *file, int indent)
504 for (int i=0 ; i<indent ; i++)
508 if (label != string())
520 for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
534 node::parse_name(input_buffer &input, bool &is_property, const char *error)
543 return string::parse_property_name(input);
545 string n = string::parse_node_or_property_name(input, is_property);
550 input.parse_error(error);
557 node::node(input_buffer &structs, input_buffer &strings) : valid(true)
559 const char *name_start = (const char*)structs;
561 while (structs[0] != '\0' && structs[0] != '@')
566 name = string(name_start, name_length);
567 if (structs[0] == '@')
570 name_start = (const char*)structs;
572 while (structs[0] != '\0')
577 unit_address = string(name_start, name_length);
581 while (structs.consume_binary(token))
586 fprintf(stderr, "Unexpected token 0x%" PRIx32
587 " while parsing node.\n", token);
590 // Child node, parse it.
591 case dtb::FDT_BEGIN_NODE:
593 node *child = node::parse_dtb(structs, strings);
599 children.push_back(child);
602 // End of this node, no errors.
603 case dtb::FDT_END_NODE:
605 // Property, parse it.
608 property *prop = property::parse_dtb(structs, strings);
614 properties.push_back(prop);
618 // End of structs table. Should appear after
619 // the end of the last node.
621 fprintf(stderr, "Unexpected FDT_END token while parsing node.\n");
624 // NOPs are padding. Ignore them.
629 fprintf(stderr, "Failed to read token from structs table while parsing node.\n");
634 node::node(input_buffer &input, string n, string l, string a, define_map *defines) :
635 label(l), name(n), unit_address(a), valid(true)
637 if (!input.consume('{'))
639 input.parse_error("Expected { to start new device tree node.\n");
642 while (valid && !input.consume('}'))
644 // flag set if we find any characters that are only in
645 // the property name character set, not the node
646 bool is_property = false;
647 string child_name, child_label, child_address;
648 child_name = parse_name(input, is_property,
649 "Expected property or node name");
650 if (input.consume(':'))
652 // Node labels can contain any characters? The
653 // spec doesn't say, so we guess so...
655 child_label = child_name;
656 child_name = parse_name(input, is_property, "Expected property or node name");
658 if (input.consume('@'))
660 child_address = parse_name(input, is_property, "Expected unit address");
667 // If we're parsing a property, then we must actually do that.
668 if (input.consume('='))
670 property *p= property::parse(input, child_name,
671 child_label, true, defines);
678 properties.push_back(p);
681 else if (!is_property && input[0] == ('{'))
683 node *child = node::parse(input, child_name,
684 child_label, child_address, defines);
687 children.push_back(child);
694 else if (input.consume(';'))
696 properties.push_back(new property(child_name, child_label));
700 input.parse_error("Error parsing property.");
709 node::cmp_properties(property *p1, property *p2)
711 return p1->get_key() < p2->get_key();
715 node::cmp_children(node *c1, node *c2)
717 if (c1->name == c2->name)
719 return c1->unit_address < c2->unit_address;
721 return c1->name < c2->name;
727 std::sort(property_begin(), property_end(), cmp_properties);
728 std::sort(child_begin(), child_end(), cmp_children);
729 for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
736 node::parse(input_buffer &input,
742 node *n = new node(input, name, label, address, defines);
752 node::parse_dtb(input_buffer &structs, input_buffer &strings)
754 node *n = new node(structs, strings);
765 while (!children.empty())
767 delete children.back();
770 while (!properties.empty())
772 delete properties.back();
773 properties.pop_back();
778 node::get_property(string key)
780 for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
782 if ((*i)->get_key() == key)
791 node::merge_node(node *other)
793 if (!other->label.empty())
795 label = other->label;
797 // Note: this is an O(n*m) operation. It might be sensible to
798 // optimise this if we find that there are nodes with very
799 // large numbers of properties, but for typical usage the
800 // entire vector will fit (easily) into cache, so iterating
801 // over it repeatedly isn't that expensive.
802 while (!other->properties.empty())
804 property *p = other->properties.front();
805 for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
807 if ((*i)->get_key() == p->get_key())
815 other->properties.erase(other->properties.begin());
817 while (!other->children.empty())
819 node *c = other->children.front();
821 for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
823 if ((*i)->name == c->name && (*i)->unit_address == c->unit_address)
833 children.push_back(c);
835 other->children.erase(other->children.begin());
840 node::write(dtb::output_writer &writer, dtb::string_table &strings)
842 writer.write_token(dtb::FDT_BEGIN_NODE);
843 byte_buffer name_buffer;
844 name.push_to_buffer(name_buffer);
845 if (unit_address != string())
847 name_buffer.push_back('@');
848 unit_address.push_to_buffer(name_buffer);
850 writer.write_comment(name);
851 writer.write_data(name_buffer);
852 writer.write_data((uint8_t)0);
853 for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
855 (*i)->write(writer, strings);
857 for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
859 (*i)->write(writer, strings);
861 writer.write_token(dtb::FDT_END_NODE);
865 node::write_dts(FILE *file, int indent)
867 for (int i=0 ; i<indent ; i++)
871 if (label != string())
876 if (name != string())
880 if (unit_address != string())
883 unit_address.print(file);
885 fputs(" {\n\n", file);
886 for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
888 (*i)->write_dts(file, indent+1);
890 for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
892 (*i)->write_dts(file, indent+1);
894 for (int i=0 ; i<indent ; i++)
902 device_tree::collect_names_recursive(node* n, node_path &path)
904 string name = n->label;
905 path.push_back(std::make_pair(n->name, n->unit_address));
906 if (name != string())
908 if (node_names.find(name) == node_names.end())
910 node_names.insert(std::make_pair(name, n));
911 node_paths.insert(std::make_pair(name, path));
915 node_names[name] = (node*)-1;
916 std::map<string, node_path>::iterator i = node_paths.find(name);
917 if (i != node_paths.end())
919 node_paths.erase(name);
921 fprintf(stderr, "Label not unique: ");
923 fprintf(stderr, ". References to this label will not be resolved.");
926 for (node::child_iterator i=n->child_begin(), e=n->child_end() ; i!=e ; ++i)
928 collect_names_recursive(*i, path);
931 // Now we collect the phandles and properties that reference
933 for (node::property_iterator i=n->property_begin(), e=n->property_end() ; i!=e ; ++i)
935 for (property::value_iterator p=(*i)->begin(),pe=(*i)->end() ; p!=pe ; ++p)
939 phandles.push_back(&*p);
941 if (p->is_cross_reference())
943 cross_references.push_back(&*p);
946 if ((*i)->get_key() == string("phandle") ||
947 (*i)->get_key() == string("linux,phandle"))
949 if ((*i)->begin()->byte_data.size() != 4)
951 fprintf(stderr, "Invalid phandle value for node ");
953 fprintf(stderr, ". Should be a 4-byte value.\n");
958 uint32_t phandle = (*i)->begin()->get_as_uint32();
959 used_phandles.insert(std::make_pair(phandle, n));
966 device_tree::collect_names()
969 collect_names_recursive(root, p);
973 device_tree::resolve_cross_references()
975 for (std::vector<property_value*>::iterator i=cross_references.begin(), e=cross_references.end() ; i!=e ; ++i)
977 property_value* pv = *i;
978 node_path path = node_paths[pv->string_data];
979 // Skip the first name in the path. It's always "", and implicitly /
980 for (node_path::iterator p=path.begin()+1, pe=path.end() ; p!=pe ; ++p)
982 pv->byte_data.push_back('/');
983 p->first.push_to_buffer(pv->byte_data);
984 if (!(p->second.empty()))
986 pv->byte_data.push_back('@');
987 p->second.push_to_buffer(pv->byte_data);
990 pv->byte_data.push_back(0);
992 uint32_t phandle = 1;
993 for (std::vector<property_value*>::iterator i=phandles.begin(), e=phandles.end() ; i!=e ; ++i)
995 string target_name = (*i)->string_data;
996 node *target = node_names[target_name];
999 fprintf(stderr, "Failed to find node with label:");
1001 fprintf(stderr, "\n");
1005 // If there is an existing phandle, use it
1006 property *p = target->get_property("phandle");
1009 p = target->get_property("linux,phandle");
1013 // Otherwise insert a new phandle node
1015 while (used_phandles.find(phandle) != used_phandles.end())
1017 // Note that we only don't need to
1018 // store this phandle in the set,
1019 // because we are monotonically
1020 // increasing the value of phandle and
1021 // so will only ever revisit this value
1022 // if we have used 2^32 phandles, at
1023 // which point our blob won't fit in
1024 // any 32-bit system and we've done
1025 // something badly wrong elsewhere
1029 push_big_endian(v.byte_data, phandle++);
1030 if (phandle_node_name == BOTH || phandle_node_name == LINUX)
1032 p = new property(string("linux,phandle"));
1034 target->add_property(p);
1036 if (phandle_node_name == BOTH || phandle_node_name == EPAPR)
1038 p = new property(string("phandle"));
1040 target->add_property(p);
1043 p->begin()->push_to_buffer((*i)->byte_data);
1044 assert((*i)->byte_data.size() == 4);
1049 device_tree::parse_roots(input_buffer &input, std::vector<node*> &roots)
1052 while (valid && input.consume('/'))
1055 node *n = node::parse(input, string("", 1), string(), string(), &defines);
1069 device_tree::buffer_for_file(const char *path)
1071 if (string(path) == string("-"))
1073 input_buffer *b = new stream_input_buffer();
1074 buffers.push_back(b);
1077 int source = open(path, O_RDONLY);
1080 fprintf(stderr, "Unable to open file %s\n", path);
1084 if (fstat(source, &st) == 0 && S_ISDIR(st.st_mode))
1086 fprintf(stderr, "File %s is a directory\n", path);
1090 input_buffer *b = new mmap_input_buffer(source);
1091 // Keep the buffer that owns the memory around for the lifetime
1092 // of this FDT. Ones simply referring to it may have shorter
1094 buffers.push_back(b);
1099 template<class writer> void
1100 device_tree::write(int fd)
1102 dtb::string_table st;
1105 writer reservation_writer;
1106 writer struct_writer;
1107 writer strings_writer;
1109 // Build the reservation table
1110 reservation_writer.write_comment(string("Memory reservations"));
1111 reservation_writer.write_label(string("dt_reserve_map"));
1112 for (std::vector<reservation>::iterator i=reservations.begin(),
1113 e=reservations.end() ; i!=e ; ++i)
1115 reservation_writer.write_comment(string("Reservation start"));
1116 reservation_writer.write_data(i->first);
1117 reservation_writer.write_comment(string("Reservation length"));
1118 reservation_writer.write_data(i->first);
1120 // Write n spare reserve map entries, plus the trailing 0.
1121 for (uint32_t i=0 ; i<=spare_reserve_map_entries ; i++)
1123 reservation_writer.write_data((uint64_t)0);
1124 reservation_writer.write_data((uint64_t)0);
1128 struct_writer.write_comment(string("Device tree"));
1129 struct_writer.write_label(string("dt_struct_start"));
1130 root->write(struct_writer, st);
1131 struct_writer.write_token(dtb::FDT_END);
1132 struct_writer.write_label(string("dt_struct_end"));
1134 st.write(strings_writer);
1135 // Find the strings size before we stick padding on the end.
1136 // Note: We should possibly use a new writer for the padding.
1137 head.size_dt_strings = strings_writer.size();
1139 // Stick the padding in the strings writer, but after the
1140 // marker indicating that it's the end.
1141 // Note: We probably should add a padding call to the writer so
1142 // that the asm back end can write padding directives instead
1143 // of a load of 0 bytes.
1144 for (uint32_t i=0 ; i<blob_padding ; i++)
1146 strings_writer.write_data((uint8_t)0);
1148 head.totalsize = sizeof(head) + strings_writer.size() +
1149 struct_writer.size() + reservation_writer.size();
1150 while (head.totalsize < minimum_blob_size)
1153 strings_writer.write_data((uint8_t)0);
1155 head.off_dt_struct = sizeof(head) + reservation_writer.size();;
1156 head.off_dt_strings = head.off_dt_struct + struct_writer.size();
1157 head.off_mem_rsvmap = sizeof(head);
1158 head.boot_cpuid_phys = boot_cpu;
1159 head.size_dt_struct = struct_writer.size();
1160 head.write(head_writer);
1162 head_writer.write_to_file(fd);
1163 reservation_writer.write_to_file(fd);
1164 struct_writer.write_to_file(fd);
1165 strings_writer.write_label(string("dt_blob_end"));
1166 strings_writer.write_to_file(fd);
1170 device_tree::referenced_node(property_value &v)
1174 return node_names[v.string_data];
1178 return used_phandles[v.get_as_uint32()];
1184 device_tree::write_binary(int fd)
1186 write<dtb::binary_writer>(fd);
1190 device_tree::write_asm(int fd)
1192 write<dtb::asm_writer>(fd);
1196 device_tree::write_dts(int fd)
1198 FILE *file = fdopen(fd, "w");
1199 fputs("/dts-v1/;\n\n", file);
1201 if (!reservations.empty())
1203 const char msg[] = "/memreserve/";
1204 fwrite(msg, sizeof(msg), 1, file);
1205 for (std::vector<reservation>::iterator i=reservations.begin(),
1206 e=reservations.end() ; i!=e ; ++i)
1208 fprintf(file, " %" PRIx64 " %" PRIx64, i->first, i->second);
1210 fputs(";\n\n", file);
1214 root->write_dts(file, 0);
1219 device_tree::parse_dtb(const char *fn, FILE *depfile)
1221 input_buffer *in = buffer_for_file(fn);
1227 input_buffer &input = *in;
1229 valid = h.read_dtb(input);
1230 boot_cpu = h.boot_cpuid_phys;
1231 if (h.last_comp_version > 17)
1233 fprintf(stderr, "Don't know how to read this version of the device tree blob");
1240 input_buffer reservation_map =
1241 input.buffer_from_offset(h.off_mem_rsvmap, 0);
1242 uint64_t start, length;
1245 if (!(reservation_map.consume_binary(start) &&
1246 reservation_map.consume_binary(length)))
1248 fprintf(stderr, "Failed to read memory reservation table\n");
1252 } while (!((start == 0) && (length == 0)));
1253 input_buffer struct_table =
1254 input.buffer_from_offset(h.off_dt_struct, h.size_dt_struct);
1255 input_buffer strings_table =
1256 input.buffer_from_offset(h.off_dt_strings, h.size_dt_strings);
1258 if (!(struct_table.consume_binary(token) &&
1259 (token == dtb::FDT_BEGIN_NODE)))
1261 fprintf(stderr, "Expected FDT_BEGIN_NODE token.\n");
1265 root = node::parse_dtb(struct_table, strings_table);
1266 if (!(struct_table.consume_binary(token) && (token == dtb::FDT_END)))
1268 fprintf(stderr, "Expected FDT_END token after parsing root node.\n");
1272 valid = (root != 0);
1276 device_tree::parse_dts(const char *fn, FILE *depfile)
1278 input_buffer *in = buffer_for_file(fn);
1284 std::vector<node*> roots;
1285 input_buffer &input = *in;
1287 bool read_header = false;
1289 if (input.consume("/dts-v1/;"))
1294 while(input.consume("/include/"))
1296 bool reallyInclude = true;
1297 if (input.consume("if "))
1300 string name = string::parse_property_name(input);
1301 // XXX: Error handling
1302 if (defines.find(name) == defines.end())
1304 reallyInclude = false;
1309 if (!input.consume('"'))
1311 input.parse_error("Expected quoted filename");
1316 while (input[length] != '"') length++;
1318 const char *file = (const char*)input;
1319 const char *dir = dirname(fn);
1320 int dir_length = strlen(dir);
1321 char *include_file = (char*)malloc(strlen(dir) + length + 2);
1322 memcpy(include_file, dir, dir_length);
1323 include_file[dir_length] = '/';
1324 memcpy(include_file+dir_length+1, file, length);
1325 include_file[dir_length+length+1] = 0;
1327 input.consume(include_file+dir_length+1);
1334 input_buffer *include_buffer = buffer_for_file(include_file);
1336 if (include_buffer == 0)
1338 for (std::vector<const char*>::iterator i=include_paths.begin(), e=include_paths.end() ; e!=i ; ++i)
1342 dir_length = strlen(dir);
1343 include_file = (char*)malloc(strlen(dir) +
1345 memcpy(include_file, dir, dir_length);
1346 include_file[dir_length] = '/';
1347 memcpy(include_file+dir_length+1, file, length);
1348 include_file[dir_length+length+1] = 0;
1349 include_buffer = buffer_for_file(include_file);
1350 if (include_buffer != 0)
1359 fputs(include_file, depfile);
1361 if (include_buffer == 0)
1366 input_buffer &include = *include_buffer;
1367 free((void*)include_file);
1371 include.next_token();
1372 read_header = include.consume("/dts-v1/;");
1374 parse_roots(include, roots);
1379 input.parse_error("Expected /dts-v1/; version string");
1381 // Read any memory reservations
1382 while(input.consume("/memreserve/"))
1384 long long start, len;
1386 // Read the start and length.
1387 if (!(input.consume_integer(start) &&
1388 (input.next_token(),
1389 input.consume_integer(len))))
1391 input.parse_error("Expected size on /memreserve/ node.");
1395 reservations.push_back(reservation(start, len));
1397 parse_roots(input, roots);
1398 switch (roots.size())
1402 input.parse_error("Failed to find root node /.");
1410 for (std::vector<node*>::iterator i=roots.begin()+1,
1411 e=roots.end() ; i!=e ; ++i)
1413 root->merge_node(*i);
1420 resolve_cross_references();
1423 device_tree::~device_tree()
1429 while (!buffers.empty())
1431 delete buffers.back();
1434 for (define_map::iterator i=defines.begin(), e=defines.end() ;
1441 bool device_tree::parse_define(const char *def)
1443 char *val = strchr(def, '=');
1446 if (strlen(def) != 0)
1454 string name(def, val-def);
1456 input_buffer in = input_buffer(val, strlen(val));
1457 property *p = property::parse(in, name, string(), false);