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