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