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 |