1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 <sstream> 42 43 #include <ctype.h> 44 #include <fcntl.h> 45 #include <inttypes.h> 46 #include <libgen.h> 47 #include <stdio.h> 48 #include <stdlib.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 input.parse_error("Expected numbers in array of cells"); 338 valid = false; 339 return; 340 } 341 switch (cell_size) 342 { 343 case 8: 344 v.byte_data.push_back(val); 345 break; 346 case 16: 347 push_big_endian(v.byte_data, (uint16_t)val); 348 break; 349 case 32: 350 push_big_endian(v.byte_data, (uint32_t)val); 351 break; 352 case 64: 353 push_big_endian(v.byte_data, (uint64_t)val); 354 break; 355 default: 356 assert(0 && "Invalid cell size!"); 357 } 358 input.next_token(); 359 } 360 } 361 // Don't store an empty string value here. 362 if (v.byte_data.size() > 0) 363 { 364 values.push_back(v); 365 } 366 } 367 368 void 369 property::parse_bytes(text_input_buffer &input) 370 { 371 assert(*input == '['); 372 ++input; 373 property_value v; 374 input.next_token(); 375 while (!input.consume(']')) 376 { 377 { 378 //FIXME: We should support 379 //labels in the middle of 380 //these, but we don't. 381 uint8_t val; 382 if (!input.consume_hex_byte(val)) 383 { 384 input.parse_error("Expected hex bytes in array of bytes"); 385 valid = false; 386 return; 387 } 388 v.byte_data.push_back(val); 389 input.next_token(); 390 } 391 } 392 values.push_back(v); 393 } 394 395 void 396 property::parse_reference(text_input_buffer &input) 397 { 398 assert(*input == '&'); 399 ++input; 400 input.next_token(); 401 property_value v; 402 v.string_data = input.parse_node_name(); 403 if (v.string_data.empty()) 404 { 405 input.parse_error("Expected node name"); 406 valid = false; 407 return; 408 } 409 v.type = property_value::CROSS_REFERENCE; 410 values.push_back(v); 411 } 412 413 property::property(input_buffer &structs, input_buffer &strings) 414 { 415 uint32_t name_offset; 416 uint32_t length; 417 valid = structs.consume_binary(length) && 418 structs.consume_binary(name_offset); 419 if (!valid) 420 { 421 fprintf(stderr, "Failed to read property\n"); 422 return; 423 } 424 // Find the name 425 input_buffer name_buffer = strings.buffer_from_offset(name_offset); 426 if (name_buffer.finished()) 427 { 428 fprintf(stderr, "Property name offset %" PRIu32 429 " is past the end of the strings table\n", 430 name_offset); 431 valid = false; 432 return; 433 } 434 key = name_buffer.parse_to(0); 435 436 // If we're empty, do not push anything as value. 437 if (!length) 438 return; 439 440 // Read the value 441 uint8_t byte; 442 property_value v; 443 for (uint32_t i=0 ; i<length ; i++) 444 { 445 if (!(valid = structs.consume_binary(byte))) 446 { 447 fprintf(stderr, "Failed to read property value\n"); 448 return; 449 } 450 v.byte_data.push_back(byte); 451 } 452 values.push_back(v); 453 } 454 455 void property::parse_define(text_input_buffer &input, define_map *defines) 456 { 457 input.consume('$'); 458 if (!defines) 459 { 460 input.parse_error("No predefined properties to match name\n"); 461 valid = false; 462 return; 463 } 464 string name = input.parse_property_name(); 465 define_map::iterator found; 466 if ((name == string()) || 467 ((found = defines->find(name)) == defines->end())) 468 { 469 input.parse_error("Undefined property name\n"); 470 valid = false; 471 return; 472 } 473 values.push_back((*found).second->values[0]); 474 } 475 476 property::property(text_input_buffer &input, 477 string &&k, 478 string_set &&l, 479 bool semicolonTerminated, 480 define_map *defines) : key(k), labels(l), valid(true) 481 { 482 do { 483 input.next_token(); 484 switch (*input) 485 { 486 case '$': 487 { 488 parse_define(input, defines); 489 if (valid) 490 { 491 break; 492 } 493 } 494 default: 495 input.parse_error("Invalid property value."); 496 valid = false; 497 return; 498 case '/': 499 { 500 if (input.consume("/incbin/(\"")) 501 { 502 auto loc = input.location(); 503 std::string filename = input.parse_to('"'); 504 if (!(valid = input.consume('"'))) 505 { 506 loc.report_error("Syntax error, expected '\"' to terminate /incbin/("); 507 return; 508 } 509 property_value v; 510 if (!(valid = input.read_binary_file(filename, v.byte_data))) 511 { 512 input.parse_error("Cannot open binary include file"); 513 return; 514 } 515 if (!(valid &= input.consume(')'))) 516 { 517 input.parse_error("Syntax error, expected ')' to terminate /incbin/("); 518 return; 519 } 520 values.push_back(v); 521 break; 522 } 523 unsigned long long bits = 0; 524 valid = input.consume("/bits/"); 525 input.next_token(); 526 valid &= input.consume_integer(bits); 527 if ((bits != 8) && 528 (bits != 16) && 529 (bits != 32) && 530 (bits != 64)) { 531 input.parse_error("Invalid size for elements"); 532 valid = false; 533 } 534 if (!valid) return; 535 input.next_token(); 536 if (*input != '<') 537 { 538 input.parse_error("/bits/ directive is only valid on arrays"); 539 valid = false; 540 return; 541 } 542 parse_cells(input, bits); 543 break; 544 } 545 case '"': 546 parse_string(input); 547 break; 548 case '<': 549 parse_cells(input, 32); 550 break; 551 case '[': 552 parse_bytes(input); 553 break; 554 case '&': 555 parse_reference(input); 556 break; 557 case ';': 558 { 559 break; 560 } 561 } 562 input.next_token(); 563 } while (input.consume(',')); 564 if (semicolonTerminated && !input.consume(';')) 565 { 566 input.parse_error("Expected ; at end of property"); 567 valid = false; 568 } 569 } 570 571 property_ptr 572 property::parse_dtb(input_buffer &structs, input_buffer &strings) 573 { 574 property_ptr p(new property(structs, strings)); 575 if (!p->valid) 576 { 577 p = nullptr; 578 } 579 return p; 580 } 581 582 property_ptr 583 property::parse(text_input_buffer &input, string &&key, string_set &&label, 584 bool semicolonTerminated, define_map *defines) 585 { 586 property_ptr p(new property(input, 587 std::move(key), 588 std::move(label), 589 semicolonTerminated, 590 defines)); 591 if (!p->valid) 592 { 593 p = nullptr; 594 } 595 return p; 596 } 597 598 void 599 property::write(dtb::output_writer &writer, dtb::string_table &strings) 600 { 601 writer.write_token(dtb::FDT_PROP); 602 byte_buffer value_buffer; 603 for (value_iterator i=begin(), e=end() ; i!=e ; ++i) 604 { 605 i->push_to_buffer(value_buffer); 606 } 607 writer.write_data((uint32_t)value_buffer.size()); 608 writer.write_comment(key); 609 writer.write_data(strings.add_string(key)); 610 writer.write_data(value_buffer); 611 } 612 613 bool 614 property_value::try_to_merge(property_value &other) 615 { 616 resolve_type(); 617 switch (type) 618 { 619 case UNKNOWN: 620 __builtin_unreachable(); 621 assert(0); 622 return false; 623 case EMPTY: 624 *this = other; 625 case STRING: 626 case STRING_LIST: 627 case CROSS_REFERENCE: 628 return false; 629 case PHANDLE: 630 case BINARY: 631 if (other.type == PHANDLE || other.type == BINARY) 632 { 633 type = BINARY; 634 byte_data.insert(byte_data.end(), other.byte_data.begin(), 635 other.byte_data.end()); 636 return true; 637 } 638 } 639 return false; 640 } 641 642 void 643 property::write_dts(FILE *file, int indent) 644 { 645 for (int i=0 ; i<indent ; i++) 646 { 647 putc('\t', file); 648 } 649 #ifdef PRINT_LABELS 650 for (auto &l : labels) 651 { 652 fputs(l.c_str(), file); 653 fputs(": ", file); 654 } 655 #endif 656 if (key != string()) 657 { 658 fputs(key.c_str(), file); 659 } 660 if (!values.empty()) 661 { 662 std::vector<property_value> *vals = &values; 663 std::vector<property_value> v; 664 // If we've got multiple values then try to merge them all together. 665 if (values.size() > 1) 666 { 667 vals = &v; 668 v.push_back(values.front()); 669 for (auto i=(++begin()), e=end() ; i!=e ; ++i) 670 { 671 if (!v.back().try_to_merge(*i)) 672 { 673 v.push_back(*i); 674 } 675 } 676 } 677 fputs(" = ", file); 678 for (auto i=vals->begin(), e=vals->end() ; i!=e ; ++i) 679 { 680 i->write_dts(file); 681 if (i+1 != e) 682 { 683 putc(',', file); 684 putc(' ', file); 685 } 686 } 687 } 688 fputs(";\n", file); 689 } 690 691 size_t 692 property::offset_of_value(property_value &val) 693 { 694 size_t off = 0; 695 for (auto &v : values) 696 { 697 if (&v == &val) 698 { 699 return off; 700 } 701 off += v.size(); 702 } 703 return -1; 704 } 705 706 string 707 node::parse_name(text_input_buffer &input, bool &is_property, const char *error) 708 { 709 if (!valid) 710 { 711 return string(); 712 } 713 input.next_token(); 714 if (is_property) 715 { 716 return input.parse_property_name(); 717 } 718 string n = input.parse_node_or_property_name(is_property); 719 if (n.empty()) 720 { 721 if (n.empty()) 722 { 723 input.parse_error(error); 724 valid = false; 725 } 726 } 727 return n; 728 } 729 730 void 731 node::visit(std::function<void(node&)> fn) 732 { 733 fn(*this); 734 for (auto &&c : children) 735 { 736 c->visit(fn); 737 } 738 } 739 740 node::node(input_buffer &structs, input_buffer &strings) : valid(true) 741 { 742 std::vector<char> bytes; 743 while (structs[0] != '\0' && structs[0] != '@') 744 { 745 bytes.push_back(structs[0]); 746 ++structs; 747 } 748 name = string(bytes.begin(), bytes.end()); 749 bytes.clear(); 750 if (structs[0] == '@') 751 { 752 ++structs; 753 while (structs[0] != '\0') 754 { 755 bytes.push_back(structs[0]); 756 ++structs; 757 } 758 unit_address = string(bytes.begin(), bytes.end()); 759 } 760 ++structs; 761 uint32_t token; 762 while (structs.consume_binary(token)) 763 { 764 switch (token) 765 { 766 default: 767 fprintf(stderr, "Unexpected token 0x%" PRIx32 768 " while parsing node.\n", token); 769 valid = false; 770 return; 771 // Child node, parse it. 772 case dtb::FDT_BEGIN_NODE: 773 { 774 node_ptr child = node::parse_dtb(structs, strings); 775 if (child == 0) 776 { 777 valid = false; 778 return; 779 } 780 children.push_back(std::move(child)); 781 break; 782 } 783 // End of this node, no errors. 784 case dtb::FDT_END_NODE: 785 return; 786 // Property, parse it. 787 case dtb::FDT_PROP: 788 { 789 property_ptr prop = property::parse_dtb(structs, strings); 790 if (prop == 0) 791 { 792 valid = false; 793 return; 794 } 795 props.push_back(prop); 796 break; 797 } 798 break; 799 // End of structs table. Should appear after 800 // the end of the last node. 801 case dtb::FDT_END: 802 fprintf(stderr, "Unexpected FDT_END token while parsing node.\n"); 803 valid = false; 804 return; 805 // NOPs are padding. Ignore them. 806 case dtb::FDT_NOP: 807 break; 808 } 809 } 810 fprintf(stderr, "Failed to read token from structs table while parsing node.\n"); 811 valid = false; 812 return; 813 } 814 815 816 node::node(const string &n, 817 const std::vector<property_ptr> &p) 818 : name(n) 819 { 820 props.insert(props.begin(), p.begin(), p.end()); 821 } 822 823 node_ptr node::create_special_node(const string &name, 824 const std::vector<property_ptr> &props) 825 { 826 node_ptr n(new node(name, props)); 827 return n; 828 } 829 830 node::node(text_input_buffer &input, 831 string &&n, 832 std::unordered_set<string> &&l, 833 string &&a, 834 define_map *defines) 835 : labels(l), name(n), unit_address(a), valid(true) 836 { 837 if (!input.consume('{')) 838 { 839 input.parse_error("Expected { to start new device tree node.\n"); 840 } 841 input.next_token(); 842 while (valid && !input.consume('}')) 843 { 844 // flag set if we find any characters that are only in 845 // the property name character set, not the node 846 bool is_property = false; 847 string child_name, child_address; 848 std::unordered_set<string> child_labels; 849 auto parse_delete = [&](const char *expected, bool at) 850 { 851 if (child_name == string()) 852 { 853 input.parse_error(expected); 854 valid = false; 855 return; 856 } 857 input.next_token(); 858 if (at && input.consume('@')) 859 { 860 child_name += '@'; 861 child_name += parse_name(input, is_property, "Expected unit address"); 862 } 863 if (!input.consume(';')) 864 { 865 input.parse_error("Expected semicolon"); 866 valid = false; 867 return; 868 } 869 input.next_token(); 870 }; 871 if (input.consume("/delete-node/")) 872 { 873 input.next_token(); 874 child_name = input.parse_node_name(); 875 parse_delete("Expected node name", true); 876 if (valid) 877 { 878 deleted_children.insert(child_name); 879 } 880 continue; 881 } 882 if (input.consume("/delete-property/")) 883 { 884 input.next_token(); 885 child_name = input.parse_property_name(); 886 parse_delete("Expected property name", false); 887 if (valid) 888 { 889 deleted_props.insert(child_name); 890 } 891 continue; 892 } 893 child_name = parse_name(input, is_property, 894 "Expected property or node name"); 895 while (input.consume(':')) 896 { 897 // Node labels can contain any characters? The 898 // spec doesn't say, so we guess so... 899 is_property = false; 900 child_labels.insert(std::move(child_name)); 901 child_name = parse_name(input, is_property, "Expected property or node name"); 902 } 903 if (input.consume('@')) 904 { 905 child_address = parse_name(input, is_property, "Expected unit address"); 906 } 907 if (!valid) 908 { 909 return; 910 } 911 input.next_token(); 912 // If we're parsing a property, then we must actually do that. 913 if (input.consume('=')) 914 { 915 property_ptr p = property::parse(input, std::move(child_name), 916 std::move(child_labels), true, defines); 917 if (p == 0) 918 { 919 valid = false; 920 } 921 else 922 { 923 props.push_back(p); 924 } 925 } 926 else if (!is_property && *input == ('{')) 927 { 928 node_ptr child = node::parse(input, std::move(child_name), 929 std::move(child_labels), std::move(child_address), defines); 930 if (child) 931 { 932 children.push_back(std::move(child)); 933 } 934 else 935 { 936 valid = false; 937 } 938 } 939 else if (input.consume(';')) 940 { 941 props.push_back(property_ptr(new property(std::move(child_name), std::move(child_labels)))); 942 } 943 else 944 { 945 input.parse_error("Error parsing property. Expected property value"); 946 valid = false; 947 } 948 input.next_token(); 949 } 950 input.next_token(); 951 input.consume(';'); 952 } 953 954 bool 955 node::cmp_properties(property_ptr &p1, property_ptr &p2) 956 { 957 return p1->get_key() < p2->get_key(); 958 } 959 960 bool 961 node::cmp_children(node_ptr &c1, node_ptr &c2) 962 { 963 if (c1->name == c2->name) 964 { 965 return c1->unit_address < c2->unit_address; 966 } 967 return c1->name < c2->name; 968 } 969 970 void 971 node::sort() 972 { 973 std::sort(property_begin(), property_end(), cmp_properties); 974 std::sort(child_begin(), child_end(), cmp_children); 975 for (auto &c : child_nodes()) 976 { 977 c->sort(); 978 } 979 } 980 981 node_ptr 982 node::parse(text_input_buffer &input, 983 string &&name, 984 string_set &&label, 985 string &&address, 986 define_map *defines) 987 { 988 node_ptr n(new node(input, 989 std::move(name), 990 std::move(label), 991 std::move(address), 992 defines)); 993 if (!n->valid) 994 { 995 n = 0; 996 } 997 return n; 998 } 999 1000 node_ptr 1001 node::parse_dtb(input_buffer &structs, input_buffer &strings) 1002 { 1003 node_ptr n(new node(structs, strings)); 1004 if (!n->valid) 1005 { 1006 n = 0; 1007 } 1008 return n; 1009 } 1010 1011 property_ptr 1012 node::get_property(const string &key) 1013 { 1014 for (auto &i : props) 1015 { 1016 if (i->get_key() == key) 1017 { 1018 return i; 1019 } 1020 } 1021 return 0; 1022 } 1023 1024 void 1025 node::merge_node(node_ptr &other) 1026 { 1027 for (auto &l : other->labels) 1028 { 1029 labels.insert(l); 1030 } 1031 // Note: this is an O(n*m) operation. It might be sensible to 1032 // optimise this if we find that there are nodes with very 1033 // large numbers of properties, but for typical usage the 1034 // entire vector will fit (easily) into cache, so iterating 1035 // over it repeatedly isn't that expensive. 1036 for (auto &p : other->properties()) 1037 { 1038 bool found = false; 1039 for (auto &mp : properties()) 1040 { 1041 if (mp->get_key() == p->get_key()) 1042 { 1043 mp = p; 1044 found = true; 1045 break; 1046 } 1047 } 1048 if (!found) 1049 { 1050 add_property(p); 1051 } 1052 } 1053 for (auto &c : other->children) 1054 { 1055 bool found = false; 1056 for (auto &i : children) 1057 { 1058 if (i->name == c->name && i->unit_address == c->unit_address) 1059 { 1060 i->merge_node(c); 1061 found = true; 1062 break; 1063 } 1064 } 1065 if (!found) 1066 { 1067 children.push_back(std::move(c)); 1068 } 1069 } 1070 children.erase(std::remove_if(children.begin(), children.end(), 1071 [&](const node_ptr &p) { 1072 string full_name = p->name; 1073 if (p->unit_address != string()) 1074 { 1075 full_name += '@'; 1076 full_name += p->unit_address; 1077 } 1078 if (other->deleted_children.count(full_name) > 0) 1079 { 1080 other->deleted_children.erase(full_name); 1081 return true; 1082 } 1083 return false; 1084 }), children.end()); 1085 props.erase(std::remove_if(props.begin(), props.end(), 1086 [&](const property_ptr &p) { 1087 if (other->deleted_props.count(p->get_key()) > 0) 1088 { 1089 other->deleted_props.erase(p->get_key()); 1090 return true; 1091 } 1092 return false; 1093 }), props.end()); 1094 } 1095 1096 void 1097 node::write(dtb::output_writer &writer, dtb::string_table &strings) 1098 { 1099 writer.write_token(dtb::FDT_BEGIN_NODE); 1100 byte_buffer name_buffer; 1101 push_string(name_buffer, name); 1102 if (unit_address != string()) 1103 { 1104 name_buffer.push_back('@'); 1105 push_string(name_buffer, unit_address); 1106 } 1107 writer.write_comment(name); 1108 writer.write_data(name_buffer); 1109 writer.write_data((uint8_t)0); 1110 for (auto p : properties()) 1111 { 1112 p->write(writer, strings); 1113 } 1114 for (auto &c : child_nodes()) 1115 { 1116 c->write(writer, strings); 1117 } 1118 writer.write_token(dtb::FDT_END_NODE); 1119 } 1120 1121 void 1122 node::write_dts(FILE *file, int indent) 1123 { 1124 for (int i=0 ; i<indent ; i++) 1125 { 1126 putc('\t', file); 1127 } 1128 #ifdef PRINT_LABELS 1129 for (auto &label : labels) 1130 { 1131 fprintf(file, "%s: ", label.c_str()); 1132 } 1133 #endif 1134 if (name != string()) 1135 { 1136 fputs(name.c_str(), file); 1137 } 1138 if (unit_address != string()) 1139 { 1140 putc('@', file); 1141 fputs(unit_address.c_str(), file); 1142 } 1143 fputs(" {\n\n", file); 1144 for (auto p : properties()) 1145 { 1146 p->write_dts(file, indent+1); 1147 } 1148 for (auto &c : child_nodes()) 1149 { 1150 c->write_dts(file, indent+1); 1151 } 1152 for (int i=0 ; i<indent ; i++) 1153 { 1154 putc('\t', file); 1155 } 1156 fputs("};\n", file); 1157 } 1158 1159 void 1160 device_tree::collect_names_recursive(node_ptr &n, node_path &path) 1161 { 1162 path.push_back(std::make_pair(n->name, n->unit_address)); 1163 for (const string &name : n->labels) 1164 { 1165 if (name != string()) 1166 { 1167 auto iter = node_names.find(name); 1168 if (iter == node_names.end()) 1169 { 1170 node_names.insert(std::make_pair(name, n.get())); 1171 node_paths.insert(std::make_pair(name, path)); 1172 } 1173 else 1174 { 1175 node_names.erase(iter); 1176 auto i = node_paths.find(name); 1177 if (i != node_paths.end()) 1178 { 1179 node_paths.erase(name); 1180 } 1181 fprintf(stderr, "Label not unique: %s. References to this label will not be resolved.\n", name.c_str()); 1182 } 1183 } 1184 } 1185 for (auto &c : n->child_nodes()) 1186 { 1187 collect_names_recursive(c, path); 1188 } 1189 // Now we collect the phandles and properties that reference 1190 // other nodes. 1191 for (auto &p : n->properties()) 1192 { 1193 for (auto &v : *p) 1194 { 1195 if (v.is_phandle()) 1196 { 1197 fixups.push_back({path, p, v}); 1198 } 1199 if (v.is_cross_reference()) 1200 { 1201 cross_references.push_back(&v); 1202 } 1203 } 1204 if ((p->get_key() == "phandle") || 1205 (p->get_key() == "linux,phandle")) 1206 { 1207 if (p->begin()->byte_data.size() != 4) 1208 { 1209 fprintf(stderr, "Invalid phandle value for node %s. Should be a 4-byte value.\n", n->name.c_str()); 1210 valid = false; 1211 } 1212 else 1213 { 1214 uint32_t phandle = p->begin()->get_as_uint32(); 1215 used_phandles.insert(std::make_pair(phandle, n.get())); 1216 } 1217 } 1218 } 1219 path.pop_back(); 1220 } 1221 1222 void 1223 device_tree::collect_names() 1224 { 1225 node_path p; 1226 node_names.clear(); 1227 node_paths.clear(); 1228 cross_references.clear(); 1229 fixups.clear(); 1230 collect_names_recursive(root, p); 1231 } 1232 1233 property_ptr 1234 device_tree::assign_phandle(node *n, uint32_t &phandle) 1235 { 1236 // If there is an existing phandle, use it 1237 property_ptr p = n->get_property("phandle"); 1238 if (p == 0) 1239 { 1240 p = n->get_property("linux,phandle"); 1241 } 1242 if (p == 0) 1243 { 1244 // Otherwise insert a new phandle node 1245 property_value v; 1246 while (used_phandles.find(phandle) != used_phandles.end()) 1247 { 1248 // Note that we only don't need to 1249 // store this phandle in the set, 1250 // because we are monotonically 1251 // increasing the value of phandle and 1252 // so will only ever revisit this value 1253 // if we have used 2^32 phandles, at 1254 // which point our blob won't fit in 1255 // any 32-bit system and we've done 1256 // something badly wrong elsewhere 1257 // already. 1258 phandle++; 1259 } 1260 push_big_endian(v.byte_data, phandle++); 1261 if (phandle_node_name == BOTH || phandle_node_name == LINUX) 1262 { 1263 p.reset(new property("linux,phandle")); 1264 p->add_value(v); 1265 n->add_property(p); 1266 } 1267 if (phandle_node_name == BOTH || phandle_node_name == EPAPR) 1268 { 1269 p.reset(new property("phandle")); 1270 p->add_value(v); 1271 n->add_property(p); 1272 } 1273 } 1274 1275 return (p); 1276 } 1277 1278 void 1279 device_tree::assign_phandles(node_ptr &n, uint32_t &next) 1280 { 1281 if (!n->labels.empty()) 1282 { 1283 assign_phandle(n.get(), next); 1284 } 1285 1286 for (auto &c : n->child_nodes()) 1287 { 1288 assign_phandles(c, next); 1289 } 1290 } 1291 1292 void 1293 device_tree::resolve_cross_references(uint32_t &phandle) 1294 { 1295 for (auto *pv : cross_references) 1296 { 1297 node_path path = node_paths[pv->string_data]; 1298 auto p = path.begin(); 1299 auto pe = path.end(); 1300 if (p != pe) 1301 { 1302 // Skip the first name in the path. It's always "", and implicitly / 1303 for (++p ; p!=pe ; ++p) 1304 { 1305 pv->byte_data.push_back('/'); 1306 push_string(pv->byte_data, p->first); 1307 if (!(p->second.empty())) 1308 { 1309 pv->byte_data.push_back('@'); 1310 push_string(pv->byte_data, p->second); 1311 } 1312 } 1313 pv->byte_data.push_back(0); 1314 } 1315 } 1316 std::unordered_map<property_value*, fixup&> phandle_set; 1317 for (auto &i : fixups) 1318 { 1319 phandle_set.insert({&i.val, i}); 1320 } 1321 std::vector<std::reference_wrapper<fixup>> sorted_phandles; 1322 root->visit([&](node &n) { 1323 for (auto &p : n.properties()) 1324 { 1325 for (auto &v : *p) 1326 { 1327 auto i = phandle_set.find(&v); 1328 if (i != phandle_set.end()) 1329 { 1330 sorted_phandles.push_back(i->second); 1331 } 1332 } 1333 } 1334 }); 1335 assert(sorted_phandles.size() == fixups.size()); 1336 1337 for (auto &i : sorted_phandles) 1338 { 1339 string target_name = i.get().val.string_data; 1340 node *target = nullptr; 1341 string possible; 1342 // If the node name is a path, then look it up by following the path, 1343 // otherwise jump directly to the named node. 1344 if (target_name[0] == '/') 1345 { 1346 string path; 1347 target = root.get(); 1348 std::istringstream ss(target_name); 1349 string path_element; 1350 // Read the leading / 1351 std::getline(ss, path_element, '/'); 1352 // Iterate over path elements 1353 while (!ss.eof()) 1354 { 1355 path += '/'; 1356 std::getline(ss, path_element, '/'); 1357 std::istringstream nss(path_element); 1358 string node_name, node_address; 1359 std::getline(nss, node_name, '@'); 1360 std::getline(nss, node_address, '@'); 1361 node *next = nullptr; 1362 for (auto &c : target->child_nodes()) 1363 { 1364 if (c->name == node_name) 1365 { 1366 if (c->unit_address == node_address) 1367 { 1368 next = c.get(); 1369 break; 1370 } 1371 else 1372 { 1373 possible = path + c->name; 1374 if (c->unit_address != string()) 1375 { 1376 possible += '@'; 1377 possible += c->unit_address; 1378 } 1379 } 1380 } 1381 } 1382 path += node_name; 1383 if (node_address != string()) 1384 { 1385 path += '@'; 1386 path += node_address; 1387 } 1388 target = next; 1389 if (target == nullptr) 1390 { 1391 break; 1392 } 1393 } 1394 } 1395 else 1396 { 1397 target = node_names[target_name]; 1398 } 1399 if (target == nullptr) 1400 { 1401 if (is_plugin) 1402 { 1403 unresolved_fixups.push_back(i); 1404 continue; 1405 } 1406 else 1407 { 1408 fprintf(stderr, "Failed to find node with label: %s\n", target_name.c_str()); 1409 if (possible != string()) 1410 { 1411 fprintf(stderr, "Possible intended match: %s\n", possible.c_str()); 1412 } 1413 valid = 0; 1414 return; 1415 } 1416 } 1417 // If there is an existing phandle, use it 1418 property_ptr p = assign_phandle(target, phandle); 1419 p->begin()->push_to_buffer(i.get().val.byte_data); 1420 assert(i.get().val.byte_data.size() == 4); 1421 } 1422 } 1423 1424 1425 void 1426 device_tree::parse_file(text_input_buffer &input, 1427 std::vector<node_ptr> &roots, 1428 bool &read_header) 1429 { 1430 input.next_token(); 1431 // Read the header 1432 if (input.consume("/dts-v1/;")) 1433 { 1434 read_header = true; 1435 } 1436 input.next_token(); 1437 if (input.consume("/plugin/;")) 1438 { 1439 is_plugin = true; 1440 } 1441 input.next_token(); 1442 if (!read_header) 1443 { 1444 input.parse_error("Expected /dts-v1/; version string"); 1445 } 1446 // Read any memory reservations 1447 while (input.consume("/memreserve/")) 1448 { 1449 unsigned long long start, len; 1450 input.next_token(); 1451 // Read the start and length. 1452 if (!(input.consume_integer_expression(start) && 1453 (input.next_token(), 1454 input.consume_integer_expression(len)))) 1455 { 1456 input.parse_error("Expected size on /memreserve/ node."); 1457 } 1458 input.next_token(); 1459 input.consume(';'); 1460 reservations.push_back(reservation(start, len)); 1461 input.next_token(); 1462 } 1463 while (valid && !input.finished()) 1464 { 1465 node_ptr n; 1466 if (input.consume('/')) 1467 { 1468 input.next_token(); 1469 n = node::parse(input, string(), string_set(), string(), &defines); 1470 } 1471 else if (input.consume('&')) 1472 { 1473 input.next_token(); 1474 string name = input.parse_node_name(); 1475 input.next_token(); 1476 n = node::parse(input, std::move(name), string_set(), string(), &defines); 1477 } 1478 else 1479 { 1480 input.parse_error("Failed to find root node /."); 1481 } 1482 if (n) 1483 { 1484 roots.push_back(std::move(n)); 1485 } 1486 else 1487 { 1488 valid = false; 1489 } 1490 input.next_token(); 1491 } 1492 } 1493 1494 template<class writer> void 1495 device_tree::write(int fd) 1496 { 1497 dtb::string_table st; 1498 dtb::header head; 1499 writer head_writer; 1500 writer reservation_writer; 1501 writer struct_writer; 1502 writer strings_writer; 1503 1504 // Build the reservation table 1505 reservation_writer.write_comment(string("Memory reservations")); 1506 reservation_writer.write_label(string("dt_reserve_map")); 1507 for (auto &i : reservations) 1508 { 1509 reservation_writer.write_comment(string("Reservation start")); 1510 reservation_writer.write_data(i.first); 1511 reservation_writer.write_comment(string("Reservation length")); 1512 reservation_writer.write_data(i.first); 1513 } 1514 // Write n spare reserve map entries, plus the trailing 0. 1515 for (uint32_t i=0 ; i<=spare_reserve_map_entries ; i++) 1516 { 1517 reservation_writer.write_data((uint64_t)0); 1518 reservation_writer.write_data((uint64_t)0); 1519 } 1520 1521 1522 struct_writer.write_comment(string("Device tree")); 1523 struct_writer.write_label(string("dt_struct_start")); 1524 root->write(struct_writer, st); 1525 struct_writer.write_token(dtb::FDT_END); 1526 struct_writer.write_label(string("dt_struct_end")); 1527 1528 st.write(strings_writer); 1529 // Find the strings size before we stick padding on the end. 1530 // Note: We should possibly use a new writer for the padding. 1531 head.size_dt_strings = strings_writer.size(); 1532 1533 // Stick the padding in the strings writer, but after the 1534 // marker indicating that it's the end. 1535 // Note: We probably should add a padding call to the writer so 1536 // that the asm back end can write padding directives instead 1537 // of a load of 0 bytes. 1538 for (uint32_t i=0 ; i<blob_padding ; i++) 1539 { 1540 strings_writer.write_data((uint8_t)0); 1541 } 1542 head.totalsize = sizeof(head) + strings_writer.size() + 1543 struct_writer.size() + reservation_writer.size(); 1544 while (head.totalsize < minimum_blob_size) 1545 { 1546 head.totalsize++; 1547 strings_writer.write_data((uint8_t)0); 1548 } 1549 head.off_dt_struct = sizeof(head) + reservation_writer.size();; 1550 head.off_dt_strings = head.off_dt_struct + struct_writer.size(); 1551 head.off_mem_rsvmap = sizeof(head); 1552 head.boot_cpuid_phys = boot_cpu; 1553 head.size_dt_struct = struct_writer.size(); 1554 head.write(head_writer); 1555 1556 head_writer.write_to_file(fd); 1557 reservation_writer.write_to_file(fd); 1558 struct_writer.write_to_file(fd); 1559 strings_writer.write_label(string("dt_blob_end")); 1560 strings_writer.write_to_file(fd); 1561 } 1562 1563 node* 1564 device_tree::referenced_node(property_value &v) 1565 { 1566 if (v.is_phandle()) 1567 { 1568 return node_names[v.string_data]; 1569 } 1570 if (v.is_binary()) 1571 { 1572 return used_phandles[v.get_as_uint32()]; 1573 } 1574 return 0; 1575 } 1576 1577 void 1578 device_tree::write_binary(int fd) 1579 { 1580 write<dtb::binary_writer>(fd); 1581 } 1582 1583 void 1584 device_tree::write_asm(int fd) 1585 { 1586 write<dtb::asm_writer>(fd); 1587 } 1588 1589 void 1590 device_tree::write_dts(int fd) 1591 { 1592 FILE *file = fdopen(fd, "w"); 1593 fputs("/dts-v1/;\n\n", file); 1594 1595 if (!reservations.empty()) 1596 { 1597 const char msg[] = "/memreserve/"; 1598 fwrite(msg, sizeof(msg), 1, file); 1599 for (auto &i : reservations) 1600 { 1601 fprintf(file, " %" PRIx64 " %" PRIx64, i.first, i.second); 1602 } 1603 fputs(";\n\n", file); 1604 } 1605 putc('/', file); 1606 putc(' ', file); 1607 root->write_dts(file, 0); 1608 fclose(file); 1609 } 1610 1611 void 1612 device_tree::parse_dtb(const string &fn, FILE *) 1613 { 1614 auto in = input_buffer::buffer_for_file(fn); 1615 if (in == 0) 1616 { 1617 valid = false; 1618 return; 1619 } 1620 input_buffer &input = *in; 1621 dtb::header h; 1622 valid = h.read_dtb(input); 1623 boot_cpu = h.boot_cpuid_phys; 1624 if (h.last_comp_version > 17) 1625 { 1626 fprintf(stderr, "Don't know how to read this version of the device tree blob"); 1627 valid = false; 1628 } 1629 if (!valid) 1630 { 1631 return; 1632 } 1633 input_buffer reservation_map = 1634 input.buffer_from_offset(h.off_mem_rsvmap, 0); 1635 uint64_t start, length; 1636 do 1637 { 1638 if (!(reservation_map.consume_binary(start) && 1639 reservation_map.consume_binary(length))) 1640 { 1641 fprintf(stderr, "Failed to read memory reservation table\n"); 1642 valid = false; 1643 return; 1644 } 1645 } while (!((start == 0) && (length == 0))); 1646 input_buffer struct_table = 1647 input.buffer_from_offset(h.off_dt_struct, h.size_dt_struct); 1648 input_buffer strings_table = 1649 input.buffer_from_offset(h.off_dt_strings, h.size_dt_strings); 1650 uint32_t token; 1651 if (!(struct_table.consume_binary(token) && 1652 (token == dtb::FDT_BEGIN_NODE))) 1653 { 1654 fprintf(stderr, "Expected FDT_BEGIN_NODE token.\n"); 1655 valid = false; 1656 return; 1657 } 1658 root = node::parse_dtb(struct_table, strings_table); 1659 if (!(struct_table.consume_binary(token) && (token == dtb::FDT_END))) 1660 { 1661 fprintf(stderr, "Expected FDT_END token after parsing root node.\n"); 1662 valid = false; 1663 return; 1664 } 1665 valid = (root != 0); 1666 } 1667 1668 string 1669 device_tree::node_path::to_string() const 1670 { 1671 string path; 1672 auto p = begin(); 1673 auto pe = end(); 1674 if ((p == pe) || (p+1 == pe)) 1675 { 1676 return string("/"); 1677 } 1678 // Skip the first name in the path. It's always "", and implicitly / 1679 for (++p ; p!=pe ; ++p) 1680 { 1681 path += '/'; 1682 path += p->first; 1683 if (!(p->second.empty())) 1684 { 1685 path += '@'; 1686 path += p->second; 1687 } 1688 } 1689 return path; 1690 } 1691 1692 node_ptr 1693 device_tree::create_fragment_wrapper(node_ptr &node, int &fragnum) 1694 { 1695 // In a plugin, we can massage these non-/ root nodes into into a fragment 1696 std::string fragment_address = "fragment@" + std::to_string(fragnum); 1697 ++fragnum; 1698 1699 std::vector<property_ptr> symbols; 1700 1701 // Intentionally left empty 1702 node_ptr newroot = node::create_special_node("", symbols); 1703 node_ptr wrapper = node::create_special_node("__overlay__", symbols); 1704 1705 // Generate the fragment with target = <&name> 1706 property_value v; 1707 v.string_data = node->name; 1708 v.type = property_value::PHANDLE; 1709 auto prop = std::make_shared<property>(std::string("target")); 1710 prop->add_value(v); 1711 symbols.push_back(prop); 1712 1713 node_ptr fragment = node::create_special_node(fragment_address, symbols); 1714 1715 wrapper->merge_node(node); 1716 fragment->add_child(std::move(wrapper)); 1717 newroot->add_child(std::move(fragment)); 1718 return newroot; 1719 } 1720 1721 node_ptr 1722 device_tree::generate_root(node_ptr &node, int &fragnum) 1723 { 1724 1725 string name = node->name; 1726 if (name == string()) 1727 { 1728 return std::move(node); 1729 } 1730 else if (!is_plugin) 1731 { 1732 return nullptr; 1733 } 1734 1735 return create_fragment_wrapper(node, fragnum); 1736 } 1737 1738 void 1739 device_tree::reassign_fragment_numbers(node_ptr &node, int &delta) 1740 { 1741 1742 for (auto &c : node->child_nodes()) 1743 { 1744 if (c->name == std::string("fragment")) 1745 { 1746 int current_address = std::stoi(c->unit_address, nullptr, 16); 1747 std::ostringstream new_address; 1748 current_address += delta; 1749 // It's possible that we hopped more than one somewhere, so just reset 1750 // delta to the next in sequence. 1751 delta = current_address + 1; 1752 new_address << std::hex << current_address; 1753 c->unit_address = new_address.str(); 1754 } 1755 } 1756 } 1757 1758 void 1759 device_tree::parse_dts(const string &fn, FILE *depfile) 1760 { 1761 auto in = input_buffer::buffer_for_file(fn); 1762 if (!in) 1763 { 1764 valid = false; 1765 return; 1766 } 1767 std::vector<node_ptr> roots; 1768 std::unordered_set<string> defnames; 1769 for (auto &i : defines) 1770 { 1771 defnames.insert(i.first); 1772 } 1773 text_input_buffer input(std::move(in), 1774 std::move(defnames), 1775 std::vector<string>(include_paths), 1776 dirname(fn), 1777 depfile); 1778 bool read_header = false; 1779 int fragnum = 0; 1780 parse_file(input, roots, read_header); 1781 switch (roots.size()) 1782 { 1783 case 0: 1784 valid = false; 1785 input.parse_error("Failed to find root node /."); 1786 return; 1787 case 1: 1788 root = generate_root(roots[0], fragnum); 1789 if (!root) 1790 { 1791 valid = false; 1792 input.parse_error("Failed to find root node /."); 1793 return; 1794 } 1795 break; 1796 default: 1797 { 1798 root = generate_root(roots[0], fragnum); 1799 if (!root) 1800 { 1801 valid = false; 1802 input.parse_error("Failed to find root node /."); 1803 return; 1804 } 1805 for (auto i=++(roots.begin()), e=roots.end() ; i!=e ; ++i) 1806 { 1807 auto &node = *i; 1808 string name = node->name; 1809 if (name == string()) 1810 { 1811 if (is_plugin) 1812 { 1813 // Re-assign any fragment numbers based on a delta of 1814 // fragnum before we merge it 1815 reassign_fragment_numbers(node, fragnum); 1816 } 1817 root->merge_node(node); 1818 } 1819 else 1820 { 1821 auto existing = node_names.find(name); 1822 if (existing == node_names.end()) 1823 { 1824 collect_names(); 1825 existing = node_names.find(name); 1826 } 1827 if (existing == node_names.end()) 1828 { 1829 if (is_plugin) 1830 { 1831 auto fragment = create_fragment_wrapper(node, fragnum); 1832 root->merge_node(fragment); 1833 } 1834 else 1835 { 1836 fprintf(stderr, "Unable to merge node: %s\n", name.c_str()); 1837 } 1838 } 1839 else 1840 { 1841 existing->second->merge_node(node); 1842 } 1843 } 1844 } 1845 } 1846 } 1847 collect_names(); 1848 uint32_t phandle = 1; 1849 // If we're writing symbols, go ahead and assign phandles to the entire 1850 // tree. We'll do this before we resolve cross references, just to keep 1851 // order semi-predictable and stable. 1852 if (write_symbols) 1853 { 1854 assign_phandles(root, phandle); 1855 } 1856 resolve_cross_references(phandle); 1857 if (write_symbols) 1858 { 1859 std::vector<property_ptr> symbols; 1860 // Create a symbol table. Each label in this device tree may be 1861 // referenced by other plugins, so we create a __symbols__ node inside 1862 // the root that contains mappings (properties) from label names to 1863 // paths. 1864 for (auto &s : node_paths) 1865 { 1866 property_value v; 1867 v.string_data = s.second.to_string(); 1868 v.type = property_value::STRING; 1869 string name = s.first; 1870 auto prop = std::make_shared<property>(std::move(name)); 1871 prop->add_value(v); 1872 symbols.push_back(prop); 1873 } 1874 root->add_child(node::create_special_node("__symbols__", symbols)); 1875 // If this is a plugin, then we also need to create two extra nodes. 1876 // Internal phandles will need to be renumbered to avoid conflicts with 1877 // already-loaded nodes and external references will need to be 1878 // resolved. 1879 if (is_plugin) 1880 { 1881 // Create the fixups entry. This is of the form: 1882 // {target} = {path}:{property name}:{offset} 1883 auto create_fixup_entry = [&](fixup &i, string target) 1884 { 1885 string value = i.path.to_string(); 1886 value += ':'; 1887 value += i.prop->get_key(); 1888 value += ':'; 1889 value += std::to_string(i.prop->offset_of_value(i.val)); 1890 property_value v; 1891 v.string_data = value; 1892 v.type = property_value::STRING; 1893 auto prop = std::make_shared<property>(std::move(target)); 1894 prop->add_value(v); 1895 return prop; 1896 }; 1897 // If we have any unresolved phandle references in this plugin, 1898 // then we must update them to 0xdeadbeef and leave a property in 1899 // the /__fixups__ node whose key is the label and whose value is 1900 // as described above. 1901 if (!unresolved_fixups.empty()) 1902 { 1903 symbols.clear(); 1904 for (auto &i : unresolved_fixups) 1905 { 1906 auto &val = i.get().val; 1907 symbols.push_back(create_fixup_entry(i, val.string_data)); 1908 val.byte_data.push_back(0xde); 1909 val.byte_data.push_back(0xad); 1910 val.byte_data.push_back(0xbe); 1911 val.byte_data.push_back(0xef); 1912 val.type = property_value::BINARY; 1913 } 1914 root->add_child(node::create_special_node("__fixups__", symbols)); 1915 } 1916 symbols.clear(); 1917 // If we have any resolved phandle references in this plugin, then 1918 // we must create a child in the __local_fixups__ node whose path 1919 // matches the node path from the root and whose value contains the 1920 // location of the reference within a property. 1921 1922 // Create a local_fixups node that is initially empty. 1923 node_ptr local_fixups = node::create_special_node("__local_fixups__", symbols); 1924 for (auto &i : fixups) 1925 { 1926 if (!i.val.is_phandle()) 1927 { 1928 continue; 1929 } 1930 node *n = local_fixups.get(); 1931 for (auto &p : i.path) 1932 { 1933 // Skip the implicit root 1934 if (p.first.empty()) 1935 { 1936 continue; 1937 } 1938 bool found = false; 1939 for (auto &c : n->child_nodes()) 1940 { 1941 if (c->name == p.first) 1942 { 1943 n = c.get(); 1944 found = true; 1945 break; 1946 } 1947 } 1948 if (!found) 1949 { 1950 n->add_child(node::create_special_node(p.first, symbols)); 1951 n = (--n->child_end())->get(); 1952 } 1953 } 1954 assert(n); 1955 property_value pv; 1956 push_big_endian(pv.byte_data, static_cast<uint32_t>(i.prop->offset_of_value(i.val))); 1957 pv.type = property_value::BINARY; 1958 auto key = i.prop->get_key(); 1959 property_ptr prop = n->get_property(key); 1960 // If we don't have an existing property then create one and 1961 // use this property value 1962 if (!prop) 1963 { 1964 prop = std::make_shared<property>(std::move(key)); 1965 n->add_property(prop); 1966 prop->add_value(pv); 1967 } 1968 else 1969 { 1970 // If we do have an existing property value, try to append 1971 // this value. 1972 property_value &old_val = *(--prop->end()); 1973 if (!old_val.try_to_merge(pv)) 1974 { 1975 prop->add_value(pv); 1976 } 1977 } 1978 } 1979 // We've iterated over all fixups, but only emit the 1980 // __local_fixups__ if we found some that were resolved internally. 1981 if (local_fixups->child_begin() != local_fixups->child_end()) 1982 { 1983 root->add_child(std::move(local_fixups)); 1984 } 1985 } 1986 } 1987 } 1988 1989 bool device_tree::parse_define(const char *def) 1990 { 1991 const char *val = strchr(def, '='); 1992 if (!val) 1993 { 1994 if (strlen(def) != 0) 1995 { 1996 string name(def); 1997 defines[name]; 1998 return true; 1999 } 2000 return false; 2001 } 2002 string name(def, val-def); 2003 string name_copy = name; 2004 val++; 2005 std::unique_ptr<input_buffer> raw(new input_buffer(val, strlen(val))); 2006 text_input_buffer in(std::move(raw), 2007 std::unordered_set<string>(), 2008 std::vector<string>(), 2009 string(), 2010 nullptr); 2011 property_ptr p = property::parse(in, std::move(name_copy), string_set(), false); 2012 if (p) 2013 defines[name] = p; 2014 return (bool)p; 2015 } 2016 2017 } // namespace fdt 2018 2019 } // namespace dtc 2020 2021