fdt.cc (009e81b16465ea457c0e63fd49fe77f47cc27a5a) fdt.cc (bbe31b709a653884e18995a1c97cdafd7392999a)
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 *

--- 22 unchanged lines hidden (view full) ---

31 */
32
33#define __STDC_LIMIT_MACROS 1
34
35#include "fdt.hh"
36#include "dtb.hh"
37
38#include <algorithm>
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 *

--- 22 unchanged lines hidden (view full) ---

31 */
32
33#define __STDC_LIMIT_MACROS 1
34
35#include "fdt.hh"
36#include "dtb.hh"
37
38#include <algorithm>
39#include <sstream>
39
40#include <ctype.h>
41#include <fcntl.h>
42#include <inttypes.h>
43#include <libgen.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <unistd.h>
47#include <sys/types.h>
48#include <sys/stat.h>
49#include <errno.h>
50
40
41#include <ctype.h>
42#include <fcntl.h>
43#include <inttypes.h>
44#include <libgen.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <unistd.h>
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <errno.h>
51
52using std::string;
53
51namespace dtc
52{
53
54namespace fdt
55{
56
57uint32_t
58property_value::get_as_uint32()

--- 14 unchanged lines hidden (view full) ---

73property_value::push_to_buffer(byte_buffer &buffer)
74{
75 if (!byte_data.empty())
76 {
77 buffer.insert(buffer.end(), byte_data.begin(), byte_data.end());
78 }
79 else
80 {
54namespace dtc
55{
56
57namespace fdt
58{
59
60uint32_t
61property_value::get_as_uint32()

--- 14 unchanged lines hidden (view full) ---

76property_value::push_to_buffer(byte_buffer &buffer)
77{
78 if (!byte_data.empty())
79 {
80 buffer.insert(buffer.end(), byte_data.begin(), byte_data.end());
81 }
82 else
83 {
81 string_data.push_to_buffer(buffer, true);
84 push_string(buffer, string_data, true);
82 // Trailing nul
83 buffer.push_back(0);
84 }
85}
86
87void
88property_value::write_dts(FILE *file)
89{

--- 77 unchanged lines hidden (view full) ---

167}
168
169void
170property_value::write_as_string(FILE *file)
171{
172 putc('"', file);
173 if (byte_data.empty())
174 {
85 // Trailing nul
86 buffer.push_back(0);
87 }
88}
89
90void
91property_value::write_dts(FILE *file)
92{

--- 77 unchanged lines hidden (view full) ---

170}
171
172void
173property_value::write_as_string(FILE *file)
174{
175 putc('"', file);
176 if (byte_data.empty())
177 {
175 string_data.print(file);
178 fputs(string_data.c_str(), file);
176 }
177 else
178 {
179 bool hasNull = (byte_data.back() == '\0');
180 // Remove trailing null bytes from the string before printing as dts.
181 if (hasNull)
182 {
183 byte_data.pop_back();

--- 51 unchanged lines hidden (view full) ---

235 {
236 putc(' ', file);
237 }
238 }
239 putc(']', file);
240}
241
242void
179 }
180 else
181 {
182 bool hasNull = (byte_data.back() == '\0');
183 // Remove trailing null bytes from the string before printing as dts.
184 if (hasNull)
185 {
186 byte_data.pop_back();

--- 51 unchanged lines hidden (view full) ---

238 {
239 putc(' ', file);
240 }
241 }
242 putc(']', file);
243}
244
245void
243property::parse_string(input_buffer &input)
246property::parse_string(text_input_buffer &input)
244{
245 property_value v;
247{
248 property_value v;
246 assert(input[0] == '"');
249 assert(*input == '"');
247 ++input;
250 ++input;
248 const char *start = (const char*)input;
249 int length = 0;
250 while (char c = input[0])
251 std::vector<char> bytes;
252 bool isEscaped = false;
253 while (char c = *input)
251 {
254 {
252 if (c == '"' && input[-1] != '\\')
255 if (c == '"' && !isEscaped)
253 {
254 input.consume('"');
255 break;
256 }
256 {
257 input.consume('"');
258 break;
259 }
260 isEscaped = (c == '\\');
261 bytes.push_back(c);
257 ++input;
262 ++input;
258 ++length;
259 }
263 }
260 v.string_data = string(start, length);
264 v.string_data = string(bytes.begin(), bytes.end());
261 values.push_back(v);
262}
263
264void
265 values.push_back(v);
266}
267
268void
265property::parse_cells(input_buffer &input, int cell_size)
269property::parse_cells(text_input_buffer &input, int cell_size)
266{
270{
267 assert(input[0] == '<');
271 assert(*input == '<');
268 ++input;
269 property_value v;
270 input.next_token();
271 while (!input.consume('>'))
272 {
273 input.next_token();
274 // If this is a phandle then we need to get the name of the
275 // referenced node
276 if (input.consume('&'))
277 {
278 if (cell_size != 32)
279 {
280 input.parse_error("reference only permitted in 32-bit arrays");
281 valid = false;
282 return;
283 }
284 input.next_token();
272 ++input;
273 property_value v;
274 input.next_token();
275 while (!input.consume('>'))
276 {
277 input.next_token();
278 // If this is a phandle then we need to get the name of the
279 // referenced node
280 if (input.consume('&'))
281 {
282 if (cell_size != 32)
283 {
284 input.parse_error("reference only permitted in 32-bit arrays");
285 valid = false;
286 return;
287 }
288 input.next_token();
285 // FIXME: We should support full paths here, but we
286 // don't.
287 string referenced = string::parse_node_name(input);
289 bool isPath = false;
290 string referenced;
291 if (!input.consume('{'))
292 {
293 referenced = input.parse_node_name();
294 }
295 else
296 {
297 referenced = input.parse_to('}');
298 input.consume('}');
299 isPath = true;
300 }
288 if (referenced.empty())
289 {
290 input.parse_error("Expected node name");
291 valid = false;
292 return;
293 }
294 input.next_token();
295 // If we already have some bytes, make the phandle a

--- 42 unchanged lines hidden (view full) ---

338 // Don't store an empty string value here.
339 if (v.byte_data.size() > 0)
340 {
341 values.push_back(v);
342 }
343}
344
345void
301 if (referenced.empty())
302 {
303 input.parse_error("Expected node name");
304 valid = false;
305 return;
306 }
307 input.next_token();
308 // If we already have some bytes, make the phandle a

--- 42 unchanged lines hidden (view full) ---

351 // Don't store an empty string value here.
352 if (v.byte_data.size() > 0)
353 {
354 values.push_back(v);
355 }
356}
357
358void
346property::parse_bytes(input_buffer &input)
359property::parse_bytes(text_input_buffer &input)
347{
360{
348 assert(input[0] == '[');
361 assert(*input == '[');
349 ++input;
350 property_value v;
351 input.next_token();
352 while (!input.consume(']'))
353 {
354 {
355 //FIXME: We should support
356 //labels in the middle of

--- 8 unchanged lines hidden (view full) ---

365 v.byte_data.push_back(val);
366 input.next_token();
367 }
368 }
369 values.push_back(v);
370}
371
372void
362 ++input;
363 property_value v;
364 input.next_token();
365 while (!input.consume(']'))
366 {
367 {
368 //FIXME: We should support
369 //labels in the middle of

--- 8 unchanged lines hidden (view full) ---

378 v.byte_data.push_back(val);
379 input.next_token();
380 }
381 }
382 values.push_back(v);
383}
384
385void
373property::parse_reference(input_buffer &input)
386property::parse_reference(text_input_buffer &input)
374{
387{
375 assert(input[0] == '&');
388 assert(*input == '&');
376 ++input;
377 input.next_token();
378 property_value v;
389 ++input;
390 input.next_token();
391 property_value v;
379 v.string_data = string::parse_node_name(input);
392 v.string_data = input.parse_node_name();
380 if (v.string_data.empty())
381 {
382 input.parse_error("Expected node name");
383 valid = false;
384 return;
385 }
386 v.type = property_value::CROSS_REFERENCE;
387 values.push_back(v);

--- 7 unchanged lines hidden (view full) ---

395 structs.consume_binary(name_offset);
396 if (!valid)
397 {
398 fprintf(stderr, "Failed to read property\n");
399 return;
400 }
401 // Find the name
402 input_buffer name_buffer = strings.buffer_from_offset(name_offset);
393 if (v.string_data.empty())
394 {
395 input.parse_error("Expected node name");
396 valid = false;
397 return;
398 }
399 v.type = property_value::CROSS_REFERENCE;
400 values.push_back(v);

--- 7 unchanged lines hidden (view full) ---

408 structs.consume_binary(name_offset);
409 if (!valid)
410 {
411 fprintf(stderr, "Failed to read property\n");
412 return;
413 }
414 // Find the name
415 input_buffer name_buffer = strings.buffer_from_offset(name_offset);
403 if (name_buffer.empty())
416 if (name_buffer.finished())
404 {
405 fprintf(stderr, "Property name offset %" PRIu32
406 " is past the end of the strings table\n",
407 name_offset);
408 valid = false;
409 return;
410 }
417 {
418 fprintf(stderr, "Property name offset %" PRIu32
419 " is past the end of the strings table\n",
420 name_offset);
421 valid = false;
422 return;
423 }
411 key = string(name_buffer);
424 key = name_buffer.parse_to(0);
412
413 // If we're empty, do not push anything as value.
414 if (!length)
415 return;
416
417 // Read the value
418 uint8_t byte;
419 property_value v;

--- 4 unchanged lines hidden (view full) ---

424 fprintf(stderr, "Failed to read property value\n");
425 return;
426 }
427 v.byte_data.push_back(byte);
428 }
429 values.push_back(v);
430}
431
425
426 // If we're empty, do not push anything as value.
427 if (!length)
428 return;
429
430 // Read the value
431 uint8_t byte;
432 property_value v;

--- 4 unchanged lines hidden (view full) ---

437 fprintf(stderr, "Failed to read property value\n");
438 return;
439 }
440 v.byte_data.push_back(byte);
441 }
442 values.push_back(v);
443}
444
432void property::parse_define(input_buffer &input, define_map *defines)
445void property::parse_define(text_input_buffer &input, define_map *defines)
433{
434 input.consume('$');
435 if (!defines)
436 {
437 input.parse_error("No predefined properties to match name\n");
438 valid = false;
439 return;
440 }
446{
447 input.consume('$');
448 if (!defines)
449 {
450 input.parse_error("No predefined properties to match name\n");
451 valid = false;
452 return;
453 }
441 string name = string::parse_property_name(input);
454 string name = input.parse_property_name();
442 define_map::iterator found;
443 if ((name == string()) ||
444 ((found = defines->find(name)) == defines->end()))
445 {
446 input.parse_error("Undefined property name\n");
447 valid = false;
448 return;
449 }
450 values.push_back((*found).second->values[0]);
451}
452
455 define_map::iterator found;
456 if ((name == string()) ||
457 ((found = defines->find(name)) == defines->end()))
458 {
459 input.parse_error("Undefined property name\n");
460 valid = false;
461 return;
462 }
463 values.push_back((*found).second->values[0]);
464}
465
453property::property(input_buffer &input,
454 string k,
455 string l,
466property::property(text_input_buffer &input,
467 string &&k,
468 string_set &&l,
456 bool semicolonTerminated,
469 bool semicolonTerminated,
457 define_map *defines) : key(k), label(l), valid(true)
470 define_map *defines) : key(k), labels(l), valid(true)
458{
459 do {
460 input.next_token();
471{
472 do {
473 input.next_token();
461 switch (input[0])
474 switch (*input)
462 {
463 case '$':
464 {
465 parse_define(input, defines);
466 if (valid)
467 {
468 break;
469 }

--- 12 unchanged lines hidden (view full) ---

482 (bits != 16) &&
483 (bits != 32) &&
484 (bits != 64)) {
485 input.parse_error("Invalid size for elements");
486 valid = false;
487 }
488 if (!valid) return;
489 input.next_token();
475 {
476 case '$':
477 {
478 parse_define(input, defines);
479 if (valid)
480 {
481 break;
482 }

--- 12 unchanged lines hidden (view full) ---

495 (bits != 16) &&
496 (bits != 32) &&
497 (bits != 64)) {
498 input.parse_error("Invalid size for elements");
499 valid = false;
500 }
501 if (!valid) return;
502 input.next_token();
490 if (input[0] != '<')
503 if (*input != '<')
491 {
492 input.parse_error("/bits/ directive is only valid on arrays");
493 valid = false;
494 return;
495 }
496 parse_cells(input, bits);
497 break;
498 }

--- 30 unchanged lines hidden (view full) ---

529 if (!p->valid)
530 {
531 p = nullptr;
532 }
533 return p;
534}
535
536property_ptr
504 {
505 input.parse_error("/bits/ directive is only valid on arrays");
506 valid = false;
507 return;
508 }
509 parse_cells(input, bits);
510 break;
511 }

--- 30 unchanged lines hidden (view full) ---

542 if (!p->valid)
543 {
544 p = nullptr;
545 }
546 return p;
547}
548
549property_ptr
537property::parse(input_buffer &input, string key, string label,
550property::parse(text_input_buffer &input, string &&key, string_set &&label,
538 bool semicolonTerminated, define_map *defines)
539{
551 bool semicolonTerminated, define_map *defines)
552{
540 property_ptr p(new property(input, key, label, semicolonTerminated, defines));
553 property_ptr p(new property(input,
554 std::move(key),
555 std::move(label),
556 semicolonTerminated,
557 defines));
541 if (!p->valid)
542 {
543 p = nullptr;
544 }
545 return p;
546}
547
548void

--- 42 unchanged lines hidden (view full) ---

591
592void
593property::write_dts(FILE *file, int indent)
594{
595 for (int i=0 ; i<indent ; i++)
596 {
597 putc('\t', file);
598 }
558 if (!p->valid)
559 {
560 p = nullptr;
561 }
562 return p;
563}
564
565void

--- 42 unchanged lines hidden (view full) ---

608
609void
610property::write_dts(FILE *file, int indent)
611{
612 for (int i=0 ; i<indent ; i++)
613 {
614 putc('\t', file);
615 }
599 if (label != string())
616#ifdef PRINT_LABELS
617 for (auto &l : labels)
600 {
618 {
601 label.print(file);
619 fputs(l.c_str(), file);
602 fputs(": ", file);
603 }
620 fputs(": ", file);
621 }
622#endif
604 if (key != string())
605 {
623 if (key != string())
624 {
606 key.print(file);
625 fputs(key.c_str(), file);
607 }
608 if (!values.empty())
609 {
610 std::vector<property_value> *vals = &values;
611 std::vector<property_value> v;
612 // If we've got multiple values then try to merge them all together.
613 if (values.size() > 1)
614 {

--- 17 unchanged lines hidden (view full) ---

632 putc(' ', file);
633 }
634 }
635 }
636 fputs(";\n", file);
637}
638
639string
626 }
627 if (!values.empty())
628 {
629 std::vector<property_value> *vals = &values;
630 std::vector<property_value> v;
631 // If we've got multiple values then try to merge them all together.
632 if (values.size() > 1)
633 {

--- 17 unchanged lines hidden (view full) ---

651 putc(' ', file);
652 }
653 }
654 }
655 fputs(";\n", file);
656}
657
658string
640node::parse_name(input_buffer &input, bool &is_property, const char *error)
659node::parse_name(text_input_buffer &input, bool &is_property, const char *error)
641{
642 if (!valid)
643 {
644 return string();
645 }
646 input.next_token();
647 if (is_property)
648 {
660{
661 if (!valid)
662 {
663 return string();
664 }
665 input.next_token();
666 if (is_property)
667 {
649 return string::parse_property_name(input);
668 return input.parse_property_name();
650 }
669 }
651 string n = string::parse_node_or_property_name(input, is_property);
670 string n = input.parse_node_or_property_name(is_property);
652 if (n.empty())
653 {
654 if (n.empty())
655 {
656 input.parse_error(error);
657 valid = false;
658 }
659 }

--- 7 unchanged lines hidden (view full) ---

667 for (auto &&c : children)
668 {
669 c->visit(fn);
670 }
671}
672
673node::node(input_buffer &structs, input_buffer &strings) : valid(true)
674{
671 if (n.empty())
672 {
673 if (n.empty())
674 {
675 input.parse_error(error);
676 valid = false;
677 }
678 }

--- 7 unchanged lines hidden (view full) ---

686 for (auto &&c : children)
687 {
688 c->visit(fn);
689 }
690}
691
692node::node(input_buffer &structs, input_buffer &strings) : valid(true)
693{
675 const char *name_start = (const char*)structs;
676 int name_length = 0;
694 std::vector<char> bytes;
677 while (structs[0] != '\0' && structs[0] != '@')
678 {
695 while (structs[0] != '\0' && structs[0] != '@')
696 {
679 name_length++;
697 bytes.push_back(structs[0]);
680 ++structs;
681 }
698 ++structs;
699 }
682 name = string(name_start, name_length);
700 name = string(bytes.begin(), bytes.end());
701 bytes.clear();
683 if (structs[0] == '@')
684 {
685 ++structs;
702 if (structs[0] == '@')
703 {
704 ++structs;
686 name_start = (const char*)structs;
687 name_length = 0;
688 while (structs[0] != '\0')
689 {
705 while (structs[0] != '\0')
706 {
690 name_length++;
707 bytes.push_back(structs[0]);
691 ++structs;
692 }
708 ++structs;
709 }
693 unit_address = string(name_start, name_length);
710 unit_address = string(bytes.begin(), bytes.end());
694 }
695 ++structs;
696 uint32_t token;
697 while (structs.consume_binary(token))
698 {
699 switch (token)
700 {
701 default:

--- 40 unchanged lines hidden (view full) ---

742 break;
743 }
744 }
745 fprintf(stderr, "Failed to read token from structs table while parsing node.\n");
746 valid = false;
747 return;
748}
749
711 }
712 ++structs;
713 uint32_t token;
714 while (structs.consume_binary(token))
715 {
716 switch (token)
717 {
718 default:

--- 40 unchanged lines hidden (view full) ---

759 break;
760 }
761 }
762 fprintf(stderr, "Failed to read token from structs table while parsing node.\n");
763 valid = false;
764 return;
765}
766
750node::node(input_buffer &input, string n, string l, string a, define_map *defines) :
751 label(l), name(n), unit_address(a), valid(true)
767node::node(text_input_buffer &input,
768 string &&n,
769 std::unordered_set<string> &&l,
770 string &&a,
771 define_map *defines)
772 : labels(l), name(n), unit_address(a), valid(true)
752{
753 if (!input.consume('{'))
754 {
755 input.parse_error("Expected { to start new device tree node.\n");
756 }
757 input.next_token();
758 while (valid && !input.consume('}'))
759 {
760 // flag set if we find any characters that are only in
761 // the property name character set, not the node
762 bool is_property = false;
773{
774 if (!input.consume('{'))
775 {
776 input.parse_error("Expected { to start new device tree node.\n");
777 }
778 input.next_token();
779 while (valid && !input.consume('}'))
780 {
781 // flag set if we find any characters that are only in
782 // the property name character set, not the node
783 bool is_property = false;
763 string child_name, child_label, child_address;
784 string child_name, child_address;
785 std::unordered_set<string> child_labels;
786 auto parse_delete = [&](const char *expected, bool at)
787 {
788 if (child_name == string())
789 {
790 input.parse_error(expected);
791 valid = false;
792 return;
793 }
794 input.next_token();
795 if (at && input.consume('@'))
796 {
797 child_name += '@';
798 child_name += parse_name(input, is_property, "Expected unit address");
799 }
800 if (!input.consume(';'))
801 {
802 input.parse_error("Expected semicolon");
803 valid = false;
804 return;
805 }
806 input.next_token();
807 };
808 if (input.consume("/delete-node/"))
809 {
810 input.next_token();
811 child_name = input.parse_node_name();
812 parse_delete("Expected node name", true);
813 if (valid)
814 {
815 deleted_children.insert(child_name);
816 }
817 continue;
818 }
819 if (input.consume("/delete-property/"))
820 {
821 input.next_token();
822 child_name = input.parse_property_name();
823 parse_delete("Expected property name", false);
824 if (valid)
825 {
826 deleted_props.insert(child_name);
827 }
828 continue;
829 }
764 child_name = parse_name(input, is_property,
765 "Expected property or node name");
830 child_name = parse_name(input, is_property,
831 "Expected property or node name");
766 if (input.consume(':'))
832 while (input.consume(':'))
767 {
768 // Node labels can contain any characters? The
769 // spec doesn't say, so we guess so...
770 is_property = false;
833 {
834 // Node labels can contain any characters? The
835 // spec doesn't say, so we guess so...
836 is_property = false;
771 child_label = child_name;
837 child_labels.insert(std::move(child_name));
772 child_name = parse_name(input, is_property, "Expected property or node name");
773 }
774 if (input.consume('@'))
775 {
776 child_address = parse_name(input, is_property, "Expected unit address");
777 }
778 if (!valid)
779 {
780 return;
781 }
782 input.next_token();
783 // If we're parsing a property, then we must actually do that.
784 if (input.consume('='))
785 {
838 child_name = parse_name(input, is_property, "Expected property or node name");
839 }
840 if (input.consume('@'))
841 {
842 child_address = parse_name(input, is_property, "Expected unit address");
843 }
844 if (!valid)
845 {
846 return;
847 }
848 input.next_token();
849 // If we're parsing a property, then we must actually do that.
850 if (input.consume('='))
851 {
786 property_ptr p = property::parse(input, child_name,
787 child_label, true, defines);
852 property_ptr p = property::parse(input, std::move(child_name),
853 std::move(child_labels), true, defines);
788 if (p == 0)
789 {
790 valid = false;
791 }
792 else
793 {
794 props.push_back(p);
795 }
796 }
854 if (p == 0)
855 {
856 valid = false;
857 }
858 else
859 {
860 props.push_back(p);
861 }
862 }
797 else if (!is_property && input[0] == ('{'))
863 else if (!is_property && *input == ('{'))
798 {
864 {
799 node_ptr child = node::parse(input, child_name,
800 child_label, child_address, defines);
865 node_ptr child = node::parse(input, std::move(child_name),
866 std::move(child_labels), std::move(child_address), defines);
801 if (child)
802 {
803 children.push_back(std::move(child));
804 }
805 else
806 {
807 valid = false;
808 }
809 }
810 else if (input.consume(';'))
811 {
867 if (child)
868 {
869 children.push_back(std::move(child));
870 }
871 else
872 {
873 valid = false;
874 }
875 }
876 else if (input.consume(';'))
877 {
812 props.push_back(property_ptr(new property(child_name, child_label)));
878 props.push_back(property_ptr(new property(std::move(child_name), std::move(child_labels))));
813 }
814 else
815 {
879 }
880 else
881 {
816 input.parse_error("Error parsing property.");
882 input.parse_error("Error parsing property. Expected property value");
817 valid = false;
818 }
819 input.next_token();
820 }
883 valid = false;
884 }
885 input.next_token();
886 }
887 input.next_token();
821 input.consume(';');
822}
823
824bool
825node::cmp_properties(property_ptr &p1, property_ptr &p2)
826{
827 return p1->get_key() < p2->get_key();
828}

--- 15 unchanged lines hidden (view full) ---

844 std::sort(child_begin(), child_end(), cmp_children);
845 for (auto &c : child_nodes())
846 {
847 c->sort();
848 }
849}
850
851node_ptr
888 input.consume(';');
889}
890
891bool
892node::cmp_properties(property_ptr &p1, property_ptr &p2)
893{
894 return p1->get_key() < p2->get_key();
895}

--- 15 unchanged lines hidden (view full) ---

911 std::sort(child_begin(), child_end(), cmp_children);
912 for (auto &c : child_nodes())
913 {
914 c->sort();
915 }
916}
917
918node_ptr
852node::parse(input_buffer &input,
853 string name,
854 string label,
855 string address,
919node::parse(text_input_buffer &input,
920 string &&name,
921 string_set &&label,
922 string &&address,
856 define_map *defines)
857{
923 define_map *defines)
924{
858 node_ptr n(new node(input, name, label, address, defines));
925 node_ptr n(new node(input,
926 std::move(name),
927 std::move(label),
928 std::move(address),
929 defines));
859 if (!n->valid)
860 {
861 n = 0;
862 }
863 return n;
864}
865
866node_ptr
867node::parse_dtb(input_buffer &structs, input_buffer &strings)
868{
869 node_ptr n(new node(structs, strings));
870 if (!n->valid)
871 {
872 n = 0;
873 }
874 return n;
875}
876
877property_ptr
930 if (!n->valid)
931 {
932 n = 0;
933 }
934 return n;
935}
936
937node_ptr
938node::parse_dtb(input_buffer &structs, input_buffer &strings)
939{
940 node_ptr n(new node(structs, strings));
941 if (!n->valid)
942 {
943 n = 0;
944 }
945 return n;
946}
947
948property_ptr
878node::get_property(string key)
949node::get_property(const string &key)
879{
880 for (auto &i : props)
881 {
882 if (i->get_key() == key)
883 {
884 return i;
885 }
886 }
887 return 0;
888}
889
890void
891node::merge_node(node_ptr other)
892{
950{
951 for (auto &i : props)
952 {
953 if (i->get_key() == key)
954 {
955 return i;
956 }
957 }
958 return 0;
959}
960
961void
962node::merge_node(node_ptr other)
963{
893 if (!other->label.empty())
964 for (auto &l : other->labels)
894 {
965 {
895 label = other->label;
966 labels.insert(l);
896 }
897 // Note: this is an O(n*m) operation. It might be sensible to
898 // optimise this if we find that there are nodes with very
899 // large numbers of properties, but for typical usage the
900 // entire vector will fit (easily) into cache, so iterating
901 // over it repeatedly isn't that expensive.
902 for (auto &p : other->properties())
903 {

--- 24 unchanged lines hidden (view full) ---

928 break;
929 }
930 }
931 if (!found)
932 {
933 children.push_back(std::move(c));
934 }
935 }
967 }
968 // Note: this is an O(n*m) operation. It might be sensible to
969 // optimise this if we find that there are nodes with very
970 // large numbers of properties, but for typical usage the
971 // entire vector will fit (easily) into cache, so iterating
972 // over it repeatedly isn't that expensive.
973 for (auto &p : other->properties())
974 {

--- 24 unchanged lines hidden (view full) ---

999 break;
1000 }
1001 }
1002 if (!found)
1003 {
1004 children.push_back(std::move(c));
1005 }
1006 }
1007 children.erase(std::remove_if(children.begin(), children.end(),
1008 [&](const node_ptr &p) {
1009 string full_name = p->name;
1010 if (p->unit_address != string())
1011 {
1012 full_name += '@';
1013 full_name += p->unit_address;
1014 }
1015 if (other->deleted_children.count(full_name) > 0)
1016 {
1017 other->deleted_children.erase(full_name);
1018 return true;
1019 }
1020 return false;
1021 }), children.end());
1022 props.erase(std::remove_if(props.begin(), props.end(),
1023 [&](const property_ptr &p) {
1024 if (other->deleted_props.count(p->get_key()) > 0)
1025 {
1026 other->deleted_props.erase(p->get_key());
1027 return true;
1028 }
1029 return false;
1030 }), props.end());
936}
937
938void
939node::write(dtb::output_writer &writer, dtb::string_table &strings)
940{
941 writer.write_token(dtb::FDT_BEGIN_NODE);
942 byte_buffer name_buffer;
1031}
1032
1033void
1034node::write(dtb::output_writer &writer, dtb::string_table &strings)
1035{
1036 writer.write_token(dtb::FDT_BEGIN_NODE);
1037 byte_buffer name_buffer;
943 name.push_to_buffer(name_buffer);
1038 push_string(name_buffer, name);
944 if (unit_address != string())
945 {
946 name_buffer.push_back('@');
1039 if (unit_address != string())
1040 {
1041 name_buffer.push_back('@');
947 unit_address.push_to_buffer(name_buffer);
1042 push_string(name_buffer, unit_address);
948 }
949 writer.write_comment(name);
950 writer.write_data(name_buffer);
951 writer.write_data((uint8_t)0);
952 for (auto p : properties())
953 {
954 p->write(writer, strings);
955 }

--- 7 unchanged lines hidden (view full) ---

963void
964node::write_dts(FILE *file, int indent)
965{
966 for (int i=0 ; i<indent ; i++)
967 {
968 putc('\t', file);
969 }
970#ifdef PRINT_LABELS
1043 }
1044 writer.write_comment(name);
1045 writer.write_data(name_buffer);
1046 writer.write_data((uint8_t)0);
1047 for (auto p : properties())
1048 {
1049 p->write(writer, strings);
1050 }

--- 7 unchanged lines hidden (view full) ---

1058void
1059node::write_dts(FILE *file, int indent)
1060{
1061 for (int i=0 ; i<indent ; i++)
1062 {
1063 putc('\t', file);
1064 }
1065#ifdef PRINT_LABELS
971 if (label != string())
1066 for (auto &label : labels)
972 {
1067 {
973 label.print(file);
974 fputs(": ", file);
1068 fprintf(file, "%s: ", label.c_str());
975 }
976#endif
977 if (name != string())
978 {
1069 }
1070#endif
1071 if (name != string())
1072 {
979 name.print(file);
1073 fputs(name.c_str(), file);
980 }
981 if (unit_address != string())
982 {
983 putc('@', file);
1074 }
1075 if (unit_address != string())
1076 {
1077 putc('@', file);
984 unit_address.print(file);
1078 fputs(unit_address.c_str(), file);
985 }
986 fputs(" {\n\n", file);
987 for (auto p : properties())
988 {
989 p->write_dts(file, indent+1);
990 }
991 for (auto &c : child_nodes())
992 {

--- 4 unchanged lines hidden (view full) ---

997 putc('\t', file);
998 }
999 fputs("};\n", file);
1000}
1001
1002void
1003device_tree::collect_names_recursive(node_ptr &n, node_path &path)
1004{
1079 }
1080 fputs(" {\n\n", file);
1081 for (auto p : properties())
1082 {
1083 p->write_dts(file, indent+1);
1084 }
1085 for (auto &c : child_nodes())
1086 {

--- 4 unchanged lines hidden (view full) ---

1091 putc('\t', file);
1092 }
1093 fputs("};\n", file);
1094}
1095
1096void
1097device_tree::collect_names_recursive(node_ptr &n, node_path &path)
1098{
1005 string name = n->label;
1006 path.push_back(std::make_pair(n->name, n->unit_address));
1099 path.push_back(std::make_pair(n->name, n->unit_address));
1007 if (name != string())
1100 for (const string &name : n->labels)
1008 {
1101 {
1009 if (node_names.find(name) == node_names.end())
1102 if (name != string())
1010 {
1103 {
1011 node_names.insert(std::make_pair(name, n.get()));
1012 node_paths.insert(std::make_pair(name, path));
1013 }
1014 else
1015 {
1016 node_names[name] = (node*)-1;
1017 auto i = node_paths.find(name);
1018 if (i != node_paths.end())
1104 auto iter = node_names.find(name);
1105 if (iter == node_names.end())
1019 {
1106 {
1020 node_paths.erase(name);
1107 node_names.insert(std::make_pair(name, n.get()));
1108 node_paths.insert(std::make_pair(name, path));
1021 }
1109 }
1022 fprintf(stderr, "Label not unique: ");
1023 name.dump();
1024 fprintf(stderr, ". References to this label will not be resolved.");
1110 else
1111 {
1112 node_names.erase(iter);
1113 auto i = node_paths.find(name);
1114 if (i != node_paths.end())
1115 {
1116 node_paths.erase(name);
1117 }
1118 fprintf(stderr, "Label not unique: %s. References to this label will not be resolved.\n", name.c_str());
1119 }
1025 }
1026 }
1027 for (auto &c : n->child_nodes())
1028 {
1029 collect_names_recursive(c, path);
1030 }
1031 path.pop_back();
1032 // Now we collect the phandles and properties that reference

--- 6 unchanged lines hidden (view full) ---

1039 {
1040 phandles.push_back(&v);
1041 }
1042 if (v.is_cross_reference())
1043 {
1044 cross_references.push_back(&v);
1045 }
1046 }
1120 }
1121 }
1122 for (auto &c : n->child_nodes())
1123 {
1124 collect_names_recursive(c, path);
1125 }
1126 path.pop_back();
1127 // Now we collect the phandles and properties that reference

--- 6 unchanged lines hidden (view full) ---

1134 {
1135 phandles.push_back(&v);
1136 }
1137 if (v.is_cross_reference())
1138 {
1139 cross_references.push_back(&v);
1140 }
1141 }
1047 if (p->get_key() == string("phandle") ||
1048 p->get_key() == string("linux,phandle"))
1142 if ((p->get_key() == "phandle") ||
1143 (p->get_key() == "linux,phandle"))
1049 {
1050 if (p->begin()->byte_data.size() != 4)
1051 {
1144 {
1145 if (p->begin()->byte_data.size() != 4)
1146 {
1052 fprintf(stderr, "Invalid phandle value for node ");
1053 n->name.dump();
1054 fprintf(stderr, ". Should be a 4-byte value.\n");
1147 fprintf(stderr, "Invalid phandle value for node %s. Should be a 4-byte value.\n", n->name.c_str());
1055 valid = false;
1056 }
1057 else
1058 {
1059 uint32_t phandle = p->begin()->get_as_uint32();
1060 used_phandles.insert(std::make_pair(phandle, n.get()));
1061 }
1062 }

--- 12 unchanged lines hidden (view full) ---

1075}
1076
1077void
1078device_tree::resolve_cross_references()
1079{
1080 for (auto *pv : cross_references)
1081 {
1082 node_path path = node_paths[pv->string_data];
1148 valid = false;
1149 }
1150 else
1151 {
1152 uint32_t phandle = p->begin()->get_as_uint32();
1153 used_phandles.insert(std::make_pair(phandle, n.get()));
1154 }
1155 }

--- 12 unchanged lines hidden (view full) ---

1168}
1169
1170void
1171device_tree::resolve_cross_references()
1172{
1173 for (auto *pv : cross_references)
1174 {
1175 node_path path = node_paths[pv->string_data];
1083 // Skip the first name in the path. It's always "", and implicitly /
1084 for (auto p=path.begin()+1, pe=path.end() ; p!=pe ; ++p)
1176 auto p = path.begin();
1177 auto pe = path.end();
1178 if (p != pe)
1085 {
1179 {
1086 pv->byte_data.push_back('/');
1087 p->first.push_to_buffer(pv->byte_data);
1088 if (!(p->second.empty()))
1180 // Skip the first name in the path. It's always "", and implicitly /
1181 for (++p ; p!=pe ; ++p)
1089 {
1182 {
1090 pv->byte_data.push_back('@');
1091 p->second.push_to_buffer(pv->byte_data);
1092 pv->byte_data.push_back(0);
1183 pv->byte_data.push_back('/');
1184 push_string(pv->byte_data, p->first);
1185 if (!(p->second.empty()))
1186 {
1187 pv->byte_data.push_back('@');
1188 push_string(pv->byte_data, p->second);
1189 pv->byte_data.push_back(0);
1190 }
1093 }
1094 }
1095 }
1096 std::unordered_set<property_value*> phandle_set;
1097 for (auto &i : phandles)
1098 {
1099 phandle_set.insert(i);
1100 }

--- 11 unchanged lines hidden (view full) ---

1112 }
1113 });
1114 assert(sorted_phandles.size() == phandles.size());
1115
1116 uint32_t phandle = 1;
1117 for (auto &i : sorted_phandles)
1118 {
1119 string target_name = i->string_data;
1191 }
1192 }
1193 }
1194 std::unordered_set<property_value*> phandle_set;
1195 for (auto &i : phandles)
1196 {
1197 phandle_set.insert(i);
1198 }

--- 11 unchanged lines hidden (view full) ---

1210 }
1211 });
1212 assert(sorted_phandles.size() == phandles.size());
1213
1214 uint32_t phandle = 1;
1215 for (auto &i : sorted_phandles)
1216 {
1217 string target_name = i->string_data;
1120 node *target = node_names[target_name];
1121 if (target == 0)
1218 node *target = nullptr;
1219 string possible;
1220 // If the node name is a path, then look it up by following the path,
1221 // otherwise jump directly to the named node.
1222 if (target_name[0] == '/')
1122 {
1223 {
1123 fprintf(stderr, "Failed to find node with label: ");
1124 target_name.dump();
1125 fprintf(stderr, "\n");
1224 std::string path;
1225 target = root.get();
1226 std::istringstream ss(target_name);
1227 string path_element;
1228 // Read the leading /
1229 std::getline(ss, path_element, '/');
1230 // Iterate over path elements
1231 while (!ss.eof())
1232 {
1233 path += '/';
1234 std::getline(ss, path_element, '/');
1235 std::istringstream nss(path_element);
1236 string node_name, node_address;
1237 std::getline(nss, node_name, '@');
1238 std::getline(nss, node_address, '@');
1239 node *next = nullptr;
1240 for (auto &c : target->child_nodes())
1241 {
1242 if (c->name == node_name)
1243 {
1244 if (c->unit_address == node_address)
1245 {
1246 next = c.get();
1247 break;
1248 }
1249 else
1250 {
1251 possible = path + c->name;
1252 if (c->unit_address != string())
1253 {
1254 possible += '@';
1255 possible += c->unit_address;
1256 }
1257 }
1258 }
1259 }
1260 path += node_name;
1261 if (node_address != string())
1262 {
1263 path += '@';
1264 path += node_address;
1265 }
1266 target = next;
1267 if (target == nullptr)
1268 {
1269 break;
1270 }
1271 }
1272 }
1273 else
1274 {
1275 target = node_names[target_name];
1276 }
1277 if (target == nullptr)
1278 {
1279 fprintf(stderr, "Failed to find node with label: %s\n", target_name.c_str());
1280 if (possible != string())
1281 {
1282 fprintf(stderr, "Possible intended match: %s\n", possible.c_str());
1283 }
1126 valid = 0;
1127 return;
1128 }
1129 // If there is an existing phandle, use it
1130 property_ptr p = target->get_property("phandle");
1131 if (p == 0)
1132 {
1133 p = target->get_property("linux,phandle");

--- 14 unchanged lines hidden (view full) ---

1148 // any 32-bit system and we've done
1149 // something badly wrong elsewhere
1150 // already.
1151 phandle++;
1152 }
1153 push_big_endian(v.byte_data, phandle++);
1154 if (phandle_node_name == BOTH || phandle_node_name == LINUX)
1155 {
1284 valid = 0;
1285 return;
1286 }
1287 // If there is an existing phandle, use it
1288 property_ptr p = target->get_property("phandle");
1289 if (p == 0)
1290 {
1291 p = target->get_property("linux,phandle");

--- 14 unchanged lines hidden (view full) ---

1306 // any 32-bit system and we've done
1307 // something badly wrong elsewhere
1308 // already.
1309 phandle++;
1310 }
1311 push_big_endian(v.byte_data, phandle++);
1312 if (phandle_node_name == BOTH || phandle_node_name == LINUX)
1313 {
1156 p.reset(new property(string("linux,phandle")));
1314 p.reset(new property("linux,phandle"));
1157 p->add_value(v);
1158 target->add_property(p);
1159 }
1160 if (phandle_node_name == BOTH || phandle_node_name == EPAPR)
1161 {
1315 p->add_value(v);
1316 target->add_property(p);
1317 }
1318 if (phandle_node_name == BOTH || phandle_node_name == EPAPR)
1319 {
1162 p.reset(new property(string("phandle")));
1320 p.reset(new property("phandle"));
1163 p->add_value(v);
1164 target->add_property(p);
1165 }
1166 }
1167 p->begin()->push_to_buffer(i->byte_data);
1168 assert(i->byte_data.size() == 4);
1169 }
1170}
1171
1321 p->add_value(v);
1322 target->add_property(p);
1323 }
1324 }
1325 p->begin()->push_to_buffer(i->byte_data);
1326 assert(i->byte_data.size() == 4);
1327 }
1328}
1329
1172bool
1173device_tree::parse_include(input_buffer &input,
1174 const std::string &dir,
1175 std::vector<node_ptr> &roots,
1176 FILE *depfile,
1177 bool &read_header)
1178{
1179 if (!input.consume("/include/"))
1180 {
1181 return false;
1182 }
1183 bool reallyInclude = true;
1184 if (input.consume("if "))
1185 {
1186 input.next_token();
1187 string name = string::parse_property_name(input);
1188 // XXX: Error handling
1189 if (defines.find(name) == defines.end())
1190 {
1191 reallyInclude = false;
1192 }
1193 input.consume('/');
1194 }
1195 input.next_token();
1196 if (!input.consume('"'))
1197 {
1198 input.parse_error("Expected quoted filename");
1199 valid = false;
1200 return false;
1201 }
1202 int length = 0;
1203 while (input[length] != '"') length++;
1204
1330
1205 std::string file((const char*)input, length);
1206 std::string include_file = dir + '/' + file;
1207 input.consume(file.c_str());
1208 if (!reallyInclude)
1209 {
1210 input.consume('"');
1211 input.next_token();
1212 return true;
1213 }
1214
1215 input_buffer *include_buffer = buffer_for_file(include_file.c_str(), false);
1216
1217 if (include_buffer == 0)
1218 {
1219 for (auto i : include_paths)
1220 {
1221 include_file = i + '/' + file;
1222 include_buffer = buffer_for_file(include_file.c_str());
1223 if (include_buffer != 0)
1224 {
1225 break;
1226 }
1227 }
1228 }
1229 if (depfile != 0)
1230 {
1231 putc(' ', depfile);
1232 fputs(include_file.c_str(), depfile);
1233 }
1234 if (include_buffer == 0)
1235 {
1236 input.parse_error("Unable to locate input file");
1237 input.consume('"');
1238 input.next_token();
1239 valid = false;
1240 return true;
1241 }
1242 input.consume('"');
1243 input.next_token();
1244 parse_file(*include_buffer, dir, roots, depfile, read_header);
1245 return true;
1246}
1247
1248void
1331void
1249device_tree::parse_file(input_buffer &input,
1250 const std::string &dir,
1332device_tree::parse_file(text_input_buffer &input,
1251 std::vector<node_ptr> &roots,
1333 std::vector<node_ptr> &roots,
1252 FILE *depfile,
1253 bool &read_header)
1254{
1255 input.next_token();
1256 // Read the header
1257 if (input.consume("/dts-v1/;"))
1258 {
1259 read_header = true;
1260 }
1261 input.next_token();
1262 input.next_token();
1263 if (!read_header)
1264 {
1265 input.parse_error("Expected /dts-v1/; version string");
1266 }
1334 bool &read_header)
1335{
1336 input.next_token();
1337 // Read the header
1338 if (input.consume("/dts-v1/;"))
1339 {
1340 read_header = true;
1341 }
1342 input.next_token();
1343 input.next_token();
1344 if (!read_header)
1345 {
1346 input.parse_error("Expected /dts-v1/; version string");
1347 }
1267 while(parse_include(input, dir, roots, depfile, read_header)) {}
1268 // Read any memory reservations
1348 // Read any memory reservations
1269 while(input.consume("/memreserve/"))
1349 while (input.consume("/memreserve/"))
1270 {
1271 unsigned long long start, len;
1272 input.next_token();
1273 // Read the start and length.
1274 if (!(input.consume_integer_expression(start) &&
1275 (input.next_token(),
1276 input.consume_integer_expression(len))))
1277 {
1278 input.parse_error("Expected size on /memreserve/ node.");
1279 }
1280 input.next_token();
1281 input.consume(';');
1282 reservations.push_back(reservation(start, len));
1350 {
1351 unsigned long long start, len;
1352 input.next_token();
1353 // Read the start and length.
1354 if (!(input.consume_integer_expression(start) &&
1355 (input.next_token(),
1356 input.consume_integer_expression(len))))
1357 {
1358 input.parse_error("Expected size on /memreserve/ node.");
1359 }
1360 input.next_token();
1361 input.consume(';');
1362 reservations.push_back(reservation(start, len));
1363 input.next_token();
1283 }
1364 }
1284 input.next_token();
1285 while(parse_include(input, dir, roots, depfile, read_header)) {}
1286 while (valid && !input.finished())
1287 {
1288 node_ptr n;
1289 if (input.consume('/'))
1290 {
1291 input.next_token();
1365 while (valid && !input.finished())
1366 {
1367 node_ptr n;
1368 if (input.consume('/'))
1369 {
1370 input.next_token();
1292 n = node::parse(input, string(), string(), string(), &defines);
1371 n = node::parse(input, string(), string_set(), string(), &defines);
1293 }
1294 else if (input.consume('&'))
1295 {
1296 input.next_token();
1372 }
1373 else if (input.consume('&'))
1374 {
1375 input.next_token();
1297 string name = string::parse_node_name(input);
1376 string name = input.parse_node_name();
1298 input.next_token();
1377 input.next_token();
1299 n = node::parse(input, name, string(), string(), &defines);
1378 n = node::parse(input, std::move(name), string_set(), string(), &defines);
1300 }
1301 else
1302 {
1303 input.parse_error("Failed to find root node /.");
1304 }
1305 if (n)
1306 {
1307 roots.push_back(std::move(n));
1308 }
1309 else
1310 {
1311 valid = false;
1312 }
1313 input.next_token();
1379 }
1380 else
1381 {
1382 input.parse_error("Failed to find root node /.");
1383 }
1384 if (n)
1385 {
1386 roots.push_back(std::move(n));
1387 }
1388 else
1389 {
1390 valid = false;
1391 }
1392 input.next_token();
1314 while(parse_include(input, dir, roots, depfile, read_header)) {}
1315 }
1316}
1317
1393 }
1394}
1395
1318input_buffer*
1319device_tree::buffer_for_file(const char *path, bool warn)
1320{
1321 if (string(path) == string("-"))
1322 {
1323 input_buffer *b = new stream_input_buffer();
1324 if (b)
1325 {
1326 std::unique_ptr<input_buffer> ptr(b);
1327 buffers.push_back(std::move(ptr));
1328 }
1329 return b;
1330 }
1331 int source = open(path, O_RDONLY);
1332 if (source == -1)
1333 {
1334 if (warn)
1335 {
1336 fprintf(stderr, "Unable to open file '%s'. %s\n", path, strerror(errno));
1337 }
1338 return 0;
1339 }
1340 struct stat st;
1341 if (fstat(source, &st) == 0 && S_ISDIR(st.st_mode))
1342 {
1343 fprintf(stderr, "File %s is a directory\n", path);
1344 close(source);
1345 return 0;
1346 }
1347 input_buffer *b = new mmap_input_buffer(source);
1348 // Keep the buffer that owns the memory around for the lifetime
1349 // of this FDT. Ones simply referring to it may have shorter
1350 // lifetimes.
1351 if (b)
1352 {
1353 std::unique_ptr<input_buffer> ptr(b);
1354 buffers.push_back(std::move(ptr));
1355 }
1356 close(source);
1357 return b;
1358}
1359
1360template<class writer> void
1361device_tree::write(int fd)
1362{
1363 dtb::string_table st;
1364 dtb::header head;
1365 writer head_writer;
1366 writer reservation_writer;
1367 writer struct_writer;

--- 102 unchanged lines hidden (view full) ---

1470 }
1471 putc('/', file);
1472 putc(' ', file);
1473 root->write_dts(file, 0);
1474 fclose(file);
1475}
1476
1477void
1396template<class writer> void
1397device_tree::write(int fd)
1398{
1399 dtb::string_table st;
1400 dtb::header head;
1401 writer head_writer;
1402 writer reservation_writer;
1403 writer struct_writer;

--- 102 unchanged lines hidden (view full) ---

1506 }
1507 putc('/', file);
1508 putc(' ', file);
1509 root->write_dts(file, 0);
1510 fclose(file);
1511}
1512
1513void
1478device_tree::parse_dtb(const char *fn, FILE *)
1514device_tree::parse_dtb(const string &fn, FILE *)
1479{
1515{
1480 input_buffer *in = buffer_for_file(fn);
1516 auto in = input_buffer::buffer_for_file(fn);
1481 if (in == 0)
1482 {
1483 valid = false;
1484 return;
1485 }
1486 input_buffer &input = *in;
1487 dtb::header h;
1488 valid = h.read_dtb(input);

--- 38 unchanged lines hidden (view full) ---

1527 fprintf(stderr, "Expected FDT_END token after parsing root node.\n");
1528 valid = false;
1529 return;
1530 }
1531 valid = (root != 0);
1532}
1533
1534void
1517 if (in == 0)
1518 {
1519 valid = false;
1520 return;
1521 }
1522 input_buffer &input = *in;
1523 dtb::header h;
1524 valid = h.read_dtb(input);

--- 38 unchanged lines hidden (view full) ---

1563 fprintf(stderr, "Expected FDT_END token after parsing root node.\n");
1564 valid = false;
1565 return;
1566 }
1567 valid = (root != 0);
1568}
1569
1570void
1535device_tree::parse_dts(const char *fn, FILE *depfile)
1571device_tree::parse_dts(const string &fn, FILE *depfile)
1536{
1572{
1537 input_buffer *in = buffer_for_file(fn);
1538 std::string dir(dirname((char*)fn));
1539 if (in == 0)
1573 auto in = input_buffer::buffer_for_file(fn);
1574 if (!in)
1540 {
1541 valid = false;
1542 return;
1543 }
1544 std::vector<node_ptr> roots;
1575 {
1576 valid = false;
1577 return;
1578 }
1579 std::vector<node_ptr> roots;
1545 input_buffer &input = *in;
1580 std::unordered_set<string> defnames;
1581 for (auto &i : defines)
1582 {
1583 defnames.insert(i.first);
1584 }
1585 text_input_buffer input(std::move(in),
1586 std::move(defnames),
1587 std::vector<string>(include_paths),
1588 dirname(fn),
1589 depfile);
1546 bool read_header = false;
1590 bool read_header = false;
1547 parse_file(input, dir, roots, depfile, read_header);
1591 parse_file(input, roots, read_header);
1548 switch (roots.size())
1549 {
1550 case 0:
1551 valid = false;
1552 input.parse_error("Failed to find root node /.");
1553 return;
1554 case 1:
1555 root = std::move(roots[0]);

--- 14 unchanged lines hidden (view full) ---

1570 auto existing = node_names.find(name);
1571 if (existing == node_names.end())
1572 {
1573 collect_names();
1574 existing = node_names.find(name);
1575 }
1576 if (existing == node_names.end())
1577 {
1592 switch (roots.size())
1593 {
1594 case 0:
1595 valid = false;
1596 input.parse_error("Failed to find root node /.");
1597 return;
1598 case 1:
1599 root = std::move(roots[0]);

--- 14 unchanged lines hidden (view full) ---

1614 auto existing = node_names.find(name);
1615 if (existing == node_names.end())
1616 {
1617 collect_names();
1618 existing = node_names.find(name);
1619 }
1620 if (existing == node_names.end())
1621 {
1578 fprintf(stderr, "Unable to merge node: ");
1579 name.dump();
1580 fprintf(stderr, "\n");
1622 fprintf(stderr, "Unable to merge node: %s\n", name.c_str());
1581 }
1623 }
1582 existing->second->merge_node(std::move(node));
1624 else
1625 {
1626 existing->second->merge_node(std::move(node));
1627 }
1583 }
1584 }
1585 }
1586 }
1587 collect_names();
1588 resolve_cross_references();
1589}
1590

--- 6 unchanged lines hidden (view full) ---

1597 {
1598 string name(def);
1599 defines[name];
1600 return true;
1601 }
1602 return false;
1603 }
1604 string name(def, val-def);
1628 }
1629 }
1630 }
1631 }
1632 collect_names();
1633 resolve_cross_references();
1634}
1635

--- 6 unchanged lines hidden (view full) ---

1642 {
1643 string name(def);
1644 defines[name];
1645 return true;
1646 }
1647 return false;
1648 }
1649 string name(def, val-def);
1650 string name_copy = name;
1605 val++;
1651 val++;
1606 input_buffer in = input_buffer(val, strlen(val));
1607 property_ptr p = property::parse(in, name, string(), false);
1652 std::unique_ptr<input_buffer> raw(new input_buffer(val, strlen(val)));
1653 text_input_buffer in(std::move(raw),
1654 std::unordered_set<string>(),
1655 std::vector<string>(),
1656 std::string(),
1657 nullptr);
1658 property_ptr p = property::parse(in, std::move(name_copy), string_set(), false);
1608 if (p)
1609 defines[name] = p;
1610 return (bool)p;
1611}
1612
1613} // namespace fdt
1614
1615} // namespace dtc
1616
1659 if (p)
1660 defines[name] = p;
1661 return (bool)p;
1662}
1663
1664} // namespace fdt
1665
1666} // namespace dtc
1667