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