1 /*- 2 * Copyright (c) 2013 David Chisnall 3 * All rights reserved. 4 * 5 * This software was developed by SRI International and the University of 6 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 7 * ("CTSRD"), as part of the DARPA CRASH research programme. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $FreeBSD$ 31 */ 32 33 #define __STDC_LIMIT_MACROS 1 34 35 #include "fdt.hh" 36 37 #include <algorithm> 38 #include <ctype.h> 39 #include <fcntl.h> 40 #include <inttypes.h> 41 #include <libgen.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <unistd.h> 45 #include <sys/types.h> 46 #include <sys/stat.h> 47 #include "dtb.hh" 48 49 namespace dtc 50 { 51 52 namespace fdt 53 { 54 55 uint32_t 56 property_value::get_as_uint32() 57 { 58 if (byte_data.size() != 4) 59 { 60 return 0; 61 } 62 uint32_t v = 0; 63 v &= byte_data[0] << 24; 64 v &= byte_data[1] << 16; 65 v &= byte_data[2] << 8; 66 v &= byte_data[3] << 0; 67 return v; 68 } 69 70 void 71 property_value::push_to_buffer(byte_buffer &buffer) 72 { 73 if (!byte_data.empty()) 74 { 75 buffer.insert(buffer.end(), byte_data.begin(), byte_data.end()); 76 } 77 else 78 { 79 string_data.push_to_buffer(buffer, true); 80 // Trailing nul 81 buffer.push_back(0); 82 } 83 } 84 85 void 86 property_value::write_dts(FILE *file) 87 { 88 resolve_type(); 89 switch (type) 90 { 91 default: 92 assert(0 && "Invalid type"); 93 case STRING: 94 case STRING_LIST: 95 case CROSS_REFERENCE: 96 write_as_string(file); 97 break; 98 case PHANDLE: 99 write_as_cells(file); 100 break; 101 case BINARY: 102 if (byte_data.size() % 4 == 0) 103 { 104 write_as_cells(file); 105 break; 106 } 107 write_as_bytes(file); 108 break; 109 } 110 } 111 112 void 113 property_value::resolve_type() 114 { 115 if (type != UNKNOWN) 116 { 117 return; 118 } 119 if (byte_data.empty()) 120 { 121 type = STRING; 122 return; 123 } 124 if (byte_data.back() == 0) 125 { 126 bool is_all_printable = true; 127 int nuls = 0; 128 int bytes = 0; 129 for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i<e ; i++) 130 { 131 bytes++; 132 is_all_printable &= (*i == '\0') || isprint(*i); 133 if (*i == '\0') 134 { 135 nuls++; 136 } 137 if (!is_all_printable) 138 { 139 break; 140 } 141 } 142 if ((is_all_printable && (bytes > nuls)) || bytes == 0) 143 { 144 type = STRING; 145 if (nuls > 0) 146 { 147 type = STRING_LIST; 148 } 149 return; 150 } 151 } 152 type = BINARY; 153 } 154 155 void 156 property_value::write_as_string(FILE *file) 157 { 158 putc('"', file); 159 if (byte_data.empty()) 160 { 161 string_data.print(file); 162 } 163 else 164 { 165 for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i!=e ; ++i) 166 { 167 // FIXME Escape tabs, newlines, and so on. 168 if (*i == '\0') 169 { 170 fputs("\", \"", file); 171 continue; 172 } 173 putc(*i, file); 174 } 175 } 176 putc('"', file); 177 } 178 179 void 180 property_value::write_as_cells(FILE *file) 181 { 182 putc('<', file); 183 assert((byte_data.size() % 4) == 0); 184 for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; ++i) 185 { 186 uint32_t v = 0; 187 v = (v << 8) | *i; 188 ++i; 189 v = (v << 8) | *i; 190 ++i; 191 v = (v << 8) | *i; 192 ++i; 193 v = (v << 8) | *i; 194 fprintf(file, "0x%" PRIx32, v); 195 if (i+1 != e) 196 { 197 putc(' ', file); 198 } 199 } 200 putc('>', file); 201 } 202 203 void 204 property_value::write_as_bytes(FILE *file) 205 { 206 putc('[', file); 207 for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; i++) 208 { 209 fprintf(file, "%02hhx", *i); 210 if (i+1 != e) 211 { 212 putc(' ', file); 213 } 214 } 215 putc(']', file); 216 } 217 218 void 219 property::parse_string(input_buffer &input) 220 { 221 property_value v; 222 assert(input[0] == '"'); 223 ++input; 224 const char *start = (const char*)input; 225 int length = 0; 226 while (char c = input[0]) 227 { 228 if (c == '"' && input[-1] != '\\') 229 { 230 input.consume('"'); 231 break; 232 } 233 ++input; 234 ++length; 235 } 236 v.string_data = string(start, length); 237 values.push_back(v); 238 } 239 240 void 241 property::parse_cells(input_buffer &input) 242 { 243 assert(input[0] == '<'); 244 ++input; 245 property_value v; 246 input.next_token(); 247 while (!input.consume('>')) 248 { 249 input.next_token(); 250 // If this is a phandle then we need to get the name of the 251 // referenced node 252 if (input.consume('&')) 253 { 254 input.next_token(); 255 // FIXME: We should support full paths here, but we 256 // don't. 257 string referenced = string::parse_node_name(input); 258 if (referenced.empty()) 259 { 260 input.parse_error("Expected node name"); 261 valid = false; 262 return; 263 } 264 input.next_token(); 265 // If we already have some bytes, make the phandle a 266 // separate component. 267 if (!v.byte_data.empty()) 268 { 269 values.push_back(v); 270 v = property_value(); 271 } 272 v.string_data = referenced; 273 v.type = property_value::PHANDLE; 274 values.push_back(v); 275 v = property_value(); 276 } 277 else 278 { 279 //FIXME: We should support labels in the middle 280 //of these, but we don't. 281 long long val; 282 if (!input.consume_integer(val)) 283 { 284 input.parse_error("Expected numbers in array of cells"); 285 valid = false; 286 return; 287 } 288 if ((val < 0) || (val > UINT32_MAX)) 289 { 290 input.parse_error("Value out of range"); 291 valid = false; 292 return; 293 } 294 push_big_endian(v.byte_data, (uint32_t)val); 295 input.next_token(); 296 } 297 } 298 // Don't store an empty string value here. 299 if (v.byte_data.size() > 0) 300 { 301 values.push_back(v); 302 } 303 } 304 305 void 306 property::parse_bytes(input_buffer &input) 307 { 308 assert(input[0] == '['); 309 ++input; 310 property_value v; 311 input.next_token(); 312 while (!input.consume(']')) 313 { 314 { 315 //FIXME: We should support 316 //labels in the middle of 317 //these, but we don't. 318 uint8_t val; 319 if (!input.consume_hex_byte(val)) 320 { 321 input.parse_error("Expected hex bytes in array of bytes"); 322 valid = false; 323 return; 324 } 325 v.byte_data.push_back(val); 326 input.next_token(); 327 } 328 } 329 values.push_back(v); 330 } 331 332 void 333 property::parse_reference(input_buffer &input) 334 { 335 assert(input[0] == '&'); 336 ++input; 337 input.next_token(); 338 property_value v; 339 v.string_data = string::parse_node_name(input); 340 if (v.string_data.empty()) 341 { 342 input.parse_error("Expected node name"); 343 valid = false; 344 return; 345 } 346 v.type = property_value::CROSS_REFERENCE; 347 values.push_back(v); 348 } 349 350 property::property(input_buffer &structs, input_buffer &strings) 351 { 352 uint32_t name_offset; 353 uint32_t length; 354 valid = structs.consume_binary(length) && 355 structs.consume_binary(name_offset); 356 if (!valid) 357 { 358 fprintf(stderr, "Failed to read property\n"); 359 return; 360 } 361 // Find the name 362 input_buffer name_buffer = strings.buffer_from_offset(name_offset); 363 if (name_buffer.empty()) 364 { 365 fprintf(stderr, "Property name offset %" PRIu32 366 " is past the end of the strings table\n", 367 name_offset); 368 valid = false; 369 return; 370 } 371 key = string(name_buffer); 372 373 // If we're empty, do not push anything as value. 374 if (!length) 375 return; 376 377 // Read the value 378 uint8_t byte; 379 property_value v; 380 for (uint32_t i=0 ; i<length ; i++) 381 { 382 if (!(valid = structs.consume_binary(byte))) 383 { 384 fprintf(stderr, "Failed to read property value\n"); 385 return; 386 } 387 v.byte_data.push_back(byte); 388 } 389 values.push_back(v); 390 } 391 392 void property::parse_define(input_buffer &input, define_map *defines) 393 { 394 input.consume('$'); 395 if (!defines) 396 { 397 input.parse_error("No predefined properties to match name\n"); 398 valid = false; 399 return; 400 } 401 string name = string::parse_property_name(input); 402 define_map::iterator found; 403 if ((name == string()) || 404 ((found = defines->find(name)) == defines->end())) 405 { 406 input.parse_error("Undefined property name\n"); 407 valid = false; 408 return; 409 } 410 values.push_back((*found).second->values[0]); 411 } 412 413 property::property(input_buffer &input, 414 string k, 415 string l, 416 bool semicolonTerminated, 417 define_map *defines) : key(k), label(l), valid(true) 418 { 419 do { 420 input.next_token(); 421 switch (input[0]) 422 { 423 case '$': 424 { 425 parse_define(input, defines); 426 if (valid) 427 { 428 break; 429 } 430 } 431 default: 432 input.parse_error("Invalid property value."); 433 valid = false; 434 return; 435 case '"': 436 parse_string(input); 437 break; 438 case '<': 439 parse_cells(input); 440 break; 441 case '[': 442 parse_bytes(input); 443 break; 444 case '&': 445 parse_reference(input); 446 break; 447 case ';': 448 { 449 break; 450 } 451 } 452 input.next_token(); 453 } while (input.consume(',')); 454 if (semicolonTerminated && !input.consume(';')) 455 { 456 input.parse_error("Expected ; at end of property"); 457 valid = false; 458 } 459 } 460 461 property* 462 property::parse_dtb(input_buffer &structs, input_buffer &strings) 463 { 464 property *p = new property(structs, strings); 465 if (!p->valid) 466 { 467 delete p; 468 p = 0; 469 } 470 return p; 471 } 472 473 property* 474 property::parse(input_buffer &input, string key, string label, 475 bool semicolonTerminated, define_map *defines) 476 { 477 property *p = new property(input, key, label, semicolonTerminated, defines); 478 if (!p->valid) 479 { 480 delete p; 481 p = 0; 482 } 483 return p; 484 } 485 486 void 487 property::write(dtb::output_writer &writer, dtb::string_table &strings) 488 { 489 writer.write_token(dtb::FDT_PROP); 490 byte_buffer value_buffer; 491 for (value_iterator i=begin(), e=end() ; i!=e ; ++i) 492 { 493 i->push_to_buffer(value_buffer); 494 } 495 writer.write_data((uint32_t)value_buffer.size()); 496 writer.write_comment(key); 497 writer.write_data(strings.add_string(key)); 498 writer.write_data(value_buffer); 499 } 500 501 void 502 property::write_dts(FILE *file, int indent) 503 { 504 for (int i=0 ; i<indent ; i++) 505 { 506 putc('\t', file); 507 } 508 if (label != string()) 509 { 510 label.print(file); 511 fputs(": ", file); 512 } 513 if (key != string()) 514 { 515 key.print(file); 516 } 517 if (!values.empty()) 518 { 519 fputs(" = ", file); 520 for (value_iterator i=begin(), e=end() ; i!=e ; ++i) 521 { 522 i->write_dts(file); 523 if (i+1 != e) 524 { 525 putc(',', file); 526 putc(' ', file); 527 } 528 } 529 } 530 fputs(";\n", file); 531 } 532 533 string 534 node::parse_name(input_buffer &input, bool &is_property, const char *error) 535 { 536 if (!valid) 537 { 538 return string(); 539 } 540 input.next_token(); 541 if (is_property) 542 { 543 return string::parse_property_name(input); 544 } 545 string n = string::parse_node_or_property_name(input, is_property); 546 if (n.empty()) 547 { 548 if (n.empty()) 549 { 550 input.parse_error(error); 551 valid = false; 552 } 553 } 554 return n; 555 } 556 557 node::node(input_buffer &structs, input_buffer &strings) : valid(true) 558 { 559 const char *name_start = (const char*)structs; 560 int name_length = 0; 561 while (structs[0] != '\0' && structs[0] != '@') 562 { 563 name_length++; 564 ++structs; 565 } 566 name = string(name_start, name_length); 567 if (structs[0] == '@') 568 { 569 ++structs; 570 name_start = (const char*)structs; 571 name_length = 0; 572 while (structs[0] != '\0') 573 { 574 name_length++; 575 ++structs; 576 } 577 unit_address = string(name_start, name_length); 578 } 579 ++structs; 580 uint32_t token; 581 while (structs.consume_binary(token)) 582 { 583 switch (token) 584 { 585 default: 586 fprintf(stderr, "Unexpected token 0x%" PRIx32 587 " while parsing node.\n", token); 588 valid = false; 589 return; 590 // Child node, parse it. 591 case dtb::FDT_BEGIN_NODE: 592 { 593 node *child = node::parse_dtb(structs, strings); 594 if (child == 0) 595 { 596 valid = false; 597 return; 598 } 599 children.push_back(child); 600 break; 601 } 602 // End of this node, no errors. 603 case dtb::FDT_END_NODE: 604 return; 605 // Property, parse it. 606 case dtb::FDT_PROP: 607 { 608 property *prop = property::parse_dtb(structs, strings); 609 if (prop == 0) 610 { 611 valid = false; 612 return; 613 } 614 properties.push_back(prop); 615 break; 616 } 617 break; 618 // End of structs table. Should appear after 619 // the end of the last node. 620 case dtb::FDT_END: 621 fprintf(stderr, "Unexpected FDT_END token while parsing node.\n"); 622 valid = false; 623 return; 624 // NOPs are padding. Ignore them. 625 case dtb::FDT_NOP: 626 break; 627 } 628 } 629 fprintf(stderr, "Failed to read token from structs table while parsing node.\n"); 630 valid = false; 631 return; 632 } 633 634 node::node(input_buffer &input, string n, string l, string a, define_map *defines) : 635 label(l), name(n), unit_address(a), valid(true) 636 { 637 if (!input.consume('{')) 638 { 639 input.parse_error("Expected { to start new device tree node.\n"); 640 } 641 input.next_token(); 642 while (valid && !input.consume('}')) 643 { 644 // flag set if we find any characters that are only in 645 // the property name character set, not the node 646 bool is_property = false; 647 string child_name, child_label, child_address; 648 child_name = parse_name(input, is_property, 649 "Expected property or node name"); 650 if (input.consume(':')) 651 { 652 // Node labels can contain any characters? The 653 // spec doesn't say, so we guess so... 654 is_property = false; 655 child_label = child_name; 656 child_name = parse_name(input, is_property, "Expected property or node name"); 657 } 658 if (input.consume('@')) 659 { 660 child_address = parse_name(input, is_property, "Expected unit address"); 661 } 662 if (!valid) 663 { 664 return; 665 } 666 input.next_token(); 667 // If we're parsing a property, then we must actually do that. 668 if (input.consume('=')) 669 { 670 property *p= property::parse(input, child_name, 671 child_label, true, defines); 672 if (p == 0) 673 { 674 valid = false; 675 } 676 else 677 { 678 properties.push_back(p); 679 } 680 } 681 else if (!is_property && input[0] == ('{')) 682 { 683 node *child = node::parse(input, child_name, 684 child_label, child_address, defines); 685 if (child) 686 { 687 children.push_back(child); 688 } 689 else 690 { 691 valid = false; 692 } 693 } 694 else if (input.consume(';')) 695 { 696 properties.push_back(new property(child_name, child_label)); 697 } 698 else 699 { 700 input.parse_error("Error parsing property."); 701 valid = false; 702 } 703 input.next_token(); 704 } 705 input.consume(';'); 706 } 707 708 bool 709 node::cmp_properties(property *p1, property *p2) 710 { 711 return p1->get_key() < p2->get_key(); 712 } 713 714 bool 715 node::cmp_children(node *c1, node *c2) 716 { 717 if (c1->name == c2->name) 718 { 719 return c1->unit_address < c2->unit_address; 720 } 721 return c1->name < c2->name; 722 } 723 724 void 725 node::sort() 726 { 727 std::sort(property_begin(), property_end(), cmp_properties); 728 std::sort(child_begin(), child_end(), cmp_children); 729 for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i) 730 { 731 (*i)->sort(); 732 } 733 } 734 735 node* 736 node::parse(input_buffer &input, 737 string name, 738 string label, 739 string address, 740 define_map *defines) 741 { 742 node *n = new node(input, name, label, address, defines); 743 if (!n->valid) 744 { 745 delete n; 746 n = 0; 747 } 748 return n; 749 } 750 751 node* 752 node::parse_dtb(input_buffer &structs, input_buffer &strings) 753 { 754 node *n = new node(structs, strings); 755 if (!n->valid) 756 { 757 delete n; 758 n = 0; 759 } 760 return n; 761 } 762 763 node::~node() 764 { 765 while (!children.empty()) 766 { 767 delete children.back(); 768 children.pop_back(); 769 } 770 while (!properties.empty()) 771 { 772 delete properties.back(); 773 properties.pop_back(); 774 } 775 } 776 777 property* 778 node::get_property(string key) 779 { 780 for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i) 781 { 782 if ((*i)->get_key() == key) 783 { 784 return *i; 785 } 786 } 787 return 0; 788 } 789 790 void 791 node::merge_node(node *other) 792 { 793 if (!other->label.empty()) 794 { 795 label = other->label; 796 } 797 // Note: this is an O(n*m) operation. It might be sensible to 798 // optimise this if we find that there are nodes with very 799 // large numbers of properties, but for typical usage the 800 // entire vector will fit (easily) into cache, so iterating 801 // over it repeatedly isn't that expensive. 802 while (!other->properties.empty()) 803 { 804 property *p = other->properties.front(); 805 for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i) 806 { 807 if ((*i)->get_key() == p->get_key()) 808 { 809 delete *i; 810 properties.erase(i); 811 break; 812 } 813 } 814 add_property(p); 815 other->properties.erase(other->properties.begin()); 816 } 817 while (!other->children.empty()) 818 { 819 node *c = other->children.front(); 820 bool found = false; 821 for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i) 822 { 823 if ((*i)->name == c->name && (*i)->unit_address == c->unit_address) 824 { 825 (*i)->merge_node(c); 826 delete c; 827 found = true; 828 break; 829 } 830 } 831 if (!found) 832 { 833 children.push_back(c); 834 } 835 other->children.erase(other->children.begin()); 836 } 837 } 838 839 void 840 node::write(dtb::output_writer &writer, dtb::string_table &strings) 841 { 842 writer.write_token(dtb::FDT_BEGIN_NODE); 843 byte_buffer name_buffer; 844 name.push_to_buffer(name_buffer); 845 if (unit_address != string()) 846 { 847 name_buffer.push_back('@'); 848 unit_address.push_to_buffer(name_buffer); 849 } 850 writer.write_comment(name); 851 writer.write_data(name_buffer); 852 writer.write_data((uint8_t)0); 853 for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i) 854 { 855 (*i)->write(writer, strings); 856 } 857 for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i) 858 { 859 (*i)->write(writer, strings); 860 } 861 writer.write_token(dtb::FDT_END_NODE); 862 } 863 864 void 865 node::write_dts(FILE *file, int indent) 866 { 867 for (int i=0 ; i<indent ; i++) 868 { 869 putc('\t', file); 870 } 871 if (label != string()) 872 { 873 label.print(file); 874 fputs(": ", file); 875 } 876 if (name != string()) 877 { 878 name.print(file); 879 } 880 if (unit_address != string()) 881 { 882 putc('@', file); 883 unit_address.print(file); 884 } 885 fputs(" {\n\n", file); 886 for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i) 887 { 888 (*i)->write_dts(file, indent+1); 889 } 890 for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i) 891 { 892 (*i)->write_dts(file, indent+1); 893 } 894 for (int i=0 ; i<indent ; i++) 895 { 896 putc('\t', file); 897 } 898 fputs("};\n", file); 899 } 900 901 void 902 device_tree::collect_names_recursive(node* n, node_path &path) 903 { 904 string name = n->label; 905 path.push_back(std::make_pair(n->name, n->unit_address)); 906 if (name != string()) 907 { 908 if (node_names.find(name) == node_names.end()) 909 { 910 node_names.insert(std::make_pair(name, n)); 911 node_paths.insert(std::make_pair(name, path)); 912 } 913 else 914 { 915 node_names[name] = (node*)-1; 916 std::map<string, node_path>::iterator i = node_paths.find(name); 917 if (i != node_paths.end()) 918 { 919 node_paths.erase(name); 920 } 921 fprintf(stderr, "Label not unique: "); 922 name.dump(); 923 fprintf(stderr, ". References to this label will not be resolved."); 924 } 925 } 926 for (node::child_iterator i=n->child_begin(), e=n->child_end() ; i!=e ; ++i) 927 { 928 collect_names_recursive(*i, path); 929 } 930 path.pop_back(); 931 // Now we collect the phandles and properties that reference 932 // other nodes. 933 for (node::property_iterator i=n->property_begin(), e=n->property_end() ; i!=e ; ++i) 934 { 935 for (property::value_iterator p=(*i)->begin(),pe=(*i)->end() ; p!=pe ; ++p) 936 { 937 if (p->is_phandle()) 938 { 939 phandles.push_back(&*p); 940 } 941 if (p->is_cross_reference()) 942 { 943 cross_references.push_back(&*p); 944 } 945 } 946 if ((*i)->get_key() == string("phandle") || 947 (*i)->get_key() == string("linux,phandle")) 948 { 949 if ((*i)->begin()->byte_data.size() != 4) 950 { 951 fprintf(stderr, "Invalid phandle value for node "); 952 n->name.dump(); 953 fprintf(stderr, ". Should be a 4-byte value.\n"); 954 valid = false; 955 } 956 else 957 { 958 uint32_t phandle = (*i)->begin()->get_as_uint32(); 959 used_phandles.insert(std::make_pair(phandle, n)); 960 } 961 } 962 } 963 } 964 965 void 966 device_tree::collect_names() 967 { 968 node_path p; 969 collect_names_recursive(root, p); 970 } 971 972 void 973 device_tree::resolve_cross_references() 974 { 975 for (std::vector<property_value*>::iterator i=cross_references.begin(), e=cross_references.end() ; i!=e ; ++i) 976 { 977 property_value* pv = *i; 978 node_path path = node_paths[pv->string_data]; 979 // Skip the first name in the path. It's always "", and implicitly / 980 for (node_path::iterator p=path.begin()+1, pe=path.end() ; p!=pe ; ++p) 981 { 982 pv->byte_data.push_back('/'); 983 p->first.push_to_buffer(pv->byte_data); 984 if (!(p->second.empty())) 985 { 986 pv->byte_data.push_back('@'); 987 p->second.push_to_buffer(pv->byte_data); 988 } 989 } 990 pv->byte_data.push_back(0); 991 } 992 uint32_t phandle = 1; 993 for (std::vector<property_value*>::iterator i=phandles.begin(), e=phandles.end() ; i!=e ; ++i) 994 { 995 string target_name = (*i)->string_data; 996 node *target = node_names[target_name]; 997 if (target == 0) 998 { 999 fprintf(stderr, "Failed to find node with label:"); 1000 target_name.dump(); 1001 fprintf(stderr, "\n"); 1002 valid = 0; 1003 return; 1004 } 1005 // If there is an existing phandle, use it 1006 property *p = target->get_property("phandle"); 1007 if (p == 0) 1008 { 1009 p = target->get_property("linux,phandle"); 1010 } 1011 if (p == 0) 1012 { 1013 // Otherwise insert a new phandle node 1014 property_value v; 1015 while (used_phandles.find(phandle) != used_phandles.end()) 1016 { 1017 // Note that we only don't need to 1018 // store this phandle in the set, 1019 // because we are monotonically 1020 // increasing the value of phandle and 1021 // so will only ever revisit this value 1022 // if we have used 2^32 phandles, at 1023 // which point our blob won't fit in 1024 // any 32-bit system and we've done 1025 // something badly wrong elsewhere 1026 // already. 1027 phandle++; 1028 } 1029 push_big_endian(v.byte_data, phandle++); 1030 if (phandle_node_name == BOTH || phandle_node_name == LINUX) 1031 { 1032 p = new property(string("linux,phandle")); 1033 p->add_value(v); 1034 target->add_property(p); 1035 } 1036 if (phandle_node_name == BOTH || phandle_node_name == EPAPR) 1037 { 1038 p = new property(string("phandle")); 1039 p->add_value(v); 1040 target->add_property(p); 1041 } 1042 } 1043 p->begin()->push_to_buffer((*i)->byte_data); 1044 assert((*i)->byte_data.size() == 4); 1045 } 1046 } 1047 1048 void 1049 device_tree::parse_roots(input_buffer &input, std::vector<node*> &roots) 1050 { 1051 input.next_token(); 1052 while (valid && input.consume('/')) 1053 { 1054 input.next_token(); 1055 node *n = node::parse(input, string("", 1), string(), string(), &defines); 1056 if (n) 1057 { 1058 roots.push_back(n); 1059 } 1060 else 1061 { 1062 valid = false; 1063 } 1064 input.next_token(); 1065 } 1066 } 1067 1068 input_buffer* 1069 device_tree::buffer_for_file(const char *path) 1070 { 1071 if (string(path) == string("-")) 1072 { 1073 input_buffer *b = new stream_input_buffer(); 1074 buffers.push_back(b); 1075 return b; 1076 } 1077 int source = open(path, O_RDONLY); 1078 if (source == -1) 1079 { 1080 fprintf(stderr, "Unable to open file %s\n", path); 1081 return 0; 1082 } 1083 struct stat st; 1084 if (fstat(source, &st) == 0 && S_ISDIR(st.st_mode)) 1085 { 1086 fprintf(stderr, "File %s is a directory\n", path); 1087 close(source); 1088 return 0; 1089 } 1090 input_buffer *b = new mmap_input_buffer(source); 1091 // Keep the buffer that owns the memory around for the lifetime 1092 // of this FDT. Ones simply referring to it may have shorter 1093 // lifetimes. 1094 buffers.push_back(b); 1095 close(source); 1096 return b; 1097 } 1098 1099 template<class writer> void 1100 device_tree::write(int fd) 1101 { 1102 dtb::string_table st; 1103 dtb::header head; 1104 writer head_writer; 1105 writer reservation_writer; 1106 writer struct_writer; 1107 writer strings_writer; 1108 1109 // Build the reservation table 1110 reservation_writer.write_comment(string("Memory reservations")); 1111 reservation_writer.write_label(string("dt_reserve_map")); 1112 for (std::vector<reservation>::iterator i=reservations.begin(), 1113 e=reservations.end() ; i!=e ; ++i) 1114 { 1115 reservation_writer.write_comment(string("Reservation start")); 1116 reservation_writer.write_data(i->first); 1117 reservation_writer.write_comment(string("Reservation length")); 1118 reservation_writer.write_data(i->first); 1119 } 1120 // Write n spare reserve map entries, plus the trailing 0. 1121 for (uint32_t i=0 ; i<=spare_reserve_map_entries ; i++) 1122 { 1123 reservation_writer.write_data((uint64_t)0); 1124 reservation_writer.write_data((uint64_t)0); 1125 } 1126 1127 1128 struct_writer.write_comment(string("Device tree")); 1129 struct_writer.write_label(string("dt_struct_start")); 1130 root->write(struct_writer, st); 1131 struct_writer.write_token(dtb::FDT_END); 1132 struct_writer.write_label(string("dt_struct_end")); 1133 1134 st.write(strings_writer); 1135 // Find the strings size before we stick padding on the end. 1136 // Note: We should possibly use a new writer for the padding. 1137 head.size_dt_strings = strings_writer.size(); 1138 1139 // Stick the padding in the strings writer, but after the 1140 // marker indicating that it's the end. 1141 // Note: We probably should add a padding call to the writer so 1142 // that the asm back end can write padding directives instead 1143 // of a load of 0 bytes. 1144 for (uint32_t i=0 ; i<blob_padding ; i++) 1145 { 1146 strings_writer.write_data((uint8_t)0); 1147 } 1148 head.totalsize = sizeof(head) + strings_writer.size() + 1149 struct_writer.size() + reservation_writer.size(); 1150 while (head.totalsize < minimum_blob_size) 1151 { 1152 head.totalsize++; 1153 strings_writer.write_data((uint8_t)0); 1154 } 1155 head.off_dt_struct = sizeof(head) + reservation_writer.size();; 1156 head.off_dt_strings = head.off_dt_struct + struct_writer.size(); 1157 head.off_mem_rsvmap = sizeof(head); 1158 head.boot_cpuid_phys = boot_cpu; 1159 head.size_dt_struct = struct_writer.size(); 1160 head.write(head_writer); 1161 1162 head_writer.write_to_file(fd); 1163 reservation_writer.write_to_file(fd); 1164 struct_writer.write_to_file(fd); 1165 strings_writer.write_label(string("dt_blob_end")); 1166 strings_writer.write_to_file(fd); 1167 } 1168 1169 node* 1170 device_tree::referenced_node(property_value &v) 1171 { 1172 if (v.is_phandle()) 1173 { 1174 return node_names[v.string_data]; 1175 } 1176 if (v.is_binary()) 1177 { 1178 return used_phandles[v.get_as_uint32()]; 1179 } 1180 return 0; 1181 } 1182 1183 void 1184 device_tree::write_binary(int fd) 1185 { 1186 write<dtb::binary_writer>(fd); 1187 } 1188 1189 void 1190 device_tree::write_asm(int fd) 1191 { 1192 write<dtb::asm_writer>(fd); 1193 } 1194 1195 void 1196 device_tree::write_dts(int fd) 1197 { 1198 FILE *file = fdopen(fd, "w"); 1199 fputs("/dts-v1/;\n\n", file); 1200 1201 if (!reservations.empty()) 1202 { 1203 const char msg[] = "/memreserve/"; 1204 fwrite(msg, sizeof(msg), 1, file); 1205 for (std::vector<reservation>::iterator i=reservations.begin(), 1206 e=reservations.end() ; i!=e ; ++i) 1207 { 1208 fprintf(file, " %" PRIx64 " %" PRIx64, i->first, i->second); 1209 } 1210 fputs(";\n\n", file); 1211 } 1212 putc('/', file); 1213 putc(' ', file); 1214 root->write_dts(file, 0); 1215 fclose(file); 1216 } 1217 1218 void 1219 device_tree::parse_dtb(const char *fn, FILE *depfile) 1220 { 1221 input_buffer *in = buffer_for_file(fn); 1222 if (in == 0) 1223 { 1224 valid = false; 1225 return; 1226 } 1227 input_buffer &input = *in; 1228 dtb::header h; 1229 valid = h.read_dtb(input); 1230 boot_cpu = h.boot_cpuid_phys; 1231 if (h.last_comp_version > 17) 1232 { 1233 fprintf(stderr, "Don't know how to read this version of the device tree blob"); 1234 valid = false; 1235 } 1236 if (!valid) 1237 { 1238 return; 1239 } 1240 input_buffer reservation_map = 1241 input.buffer_from_offset(h.off_mem_rsvmap, 0); 1242 uint64_t start, length; 1243 do 1244 { 1245 if (!(reservation_map.consume_binary(start) && 1246 reservation_map.consume_binary(length))) 1247 { 1248 fprintf(stderr, "Failed to read memory reservation table\n"); 1249 valid = false; 1250 return; 1251 } 1252 } while (!((start == 0) && (length == 0))); 1253 input_buffer struct_table = 1254 input.buffer_from_offset(h.off_dt_struct, h.size_dt_struct); 1255 input_buffer strings_table = 1256 input.buffer_from_offset(h.off_dt_strings, h.size_dt_strings); 1257 uint32_t token; 1258 if (!(struct_table.consume_binary(token) && 1259 (token == dtb::FDT_BEGIN_NODE))) 1260 { 1261 fprintf(stderr, "Expected FDT_BEGIN_NODE token.\n"); 1262 valid = false; 1263 return; 1264 } 1265 root = node::parse_dtb(struct_table, strings_table); 1266 if (!(struct_table.consume_binary(token) && (token == dtb::FDT_END))) 1267 { 1268 fprintf(stderr, "Expected FDT_END token after parsing root node.\n"); 1269 valid = false; 1270 return; 1271 } 1272 valid = (root != 0); 1273 } 1274 1275 void 1276 device_tree::parse_dts(const char *fn, FILE *depfile) 1277 { 1278 input_buffer *in = buffer_for_file(fn); 1279 if (in == 0) 1280 { 1281 valid = false; 1282 return; 1283 } 1284 std::vector<node*> roots; 1285 input_buffer &input = *in; 1286 input.next_token(); 1287 bool read_header = false; 1288 // Read the header 1289 if (input.consume("/dts-v1/;")) 1290 { 1291 read_header = true; 1292 } 1293 input.next_token(); 1294 while(input.consume("/include/")) 1295 { 1296 bool reallyInclude = true; 1297 if (input.consume("if ")) 1298 { 1299 input.next_token(); 1300 string name = string::parse_property_name(input); 1301 // XXX: Error handling 1302 if (defines.find(name) == defines.end()) 1303 { 1304 reallyInclude = false; 1305 } 1306 input.consume('/'); 1307 } 1308 input.next_token(); 1309 if (!input.consume('"')) 1310 { 1311 input.parse_error("Expected quoted filename"); 1312 valid = false; 1313 return; 1314 } 1315 int length = 0; 1316 while (input[length] != '"') length++; 1317 1318 const char *file = (const char*)input; 1319 const char *dir = dirname(fn); 1320 int dir_length = strlen(dir); 1321 char *include_file = (char*)malloc(strlen(dir) + length + 2); 1322 memcpy(include_file, dir, dir_length); 1323 include_file[dir_length] = '/'; 1324 memcpy(include_file+dir_length+1, file, length); 1325 include_file[dir_length+length+1] = 0; 1326 1327 input.consume(include_file+dir_length+1); 1328 input.consume('"'); 1329 if (!reallyInclude) 1330 { 1331 continue; 1332 } 1333 1334 input_buffer *include_buffer = buffer_for_file(include_file); 1335 1336 if (include_buffer == 0) 1337 { 1338 for (std::vector<const char*>::iterator i=include_paths.begin(), e=include_paths.end() ; e!=i ; ++i) 1339 { 1340 free(include_file); 1341 dir = *i; 1342 dir_length = strlen(dir); 1343 include_file = (char*)malloc(strlen(dir) + 1344 length + 2); 1345 memcpy(include_file, dir, dir_length); 1346 include_file[dir_length] = '/'; 1347 memcpy(include_file+dir_length+1, file, length); 1348 include_file[dir_length+length+1] = 0; 1349 include_buffer = buffer_for_file(include_file); 1350 if (include_buffer != 0) 1351 { 1352 break; 1353 } 1354 } 1355 } 1356 if (depfile != 0) 1357 { 1358 putc(' ', depfile); 1359 fputs(include_file, depfile); 1360 } 1361 if (include_buffer == 0) 1362 { 1363 valid = false; 1364 return; 1365 } 1366 input_buffer &include = *include_buffer; 1367 free((void*)include_file); 1368 1369 if (!read_header) 1370 { 1371 include.next_token(); 1372 read_header = include.consume("/dts-v1/;"); 1373 } 1374 parse_roots(include, roots); 1375 } 1376 input.next_token(); 1377 if (!read_header) 1378 { 1379 input.parse_error("Expected /dts-v1/; version string"); 1380 } 1381 // Read any memory reservations 1382 while(input.consume("/memreserve/")) 1383 { 1384 long long start, len; 1385 input.next_token(); 1386 // Read the start and length. 1387 if (!(input.consume_integer(start) && 1388 (input.next_token(), 1389 input.consume_integer(len)))) 1390 { 1391 input.parse_error("Expected size on /memreserve/ node."); 1392 } 1393 input.next_token(); 1394 input.consume(';'); 1395 reservations.push_back(reservation(start, len)); 1396 } 1397 parse_roots(input, roots); 1398 switch (roots.size()) 1399 { 1400 case 0: 1401 valid = false; 1402 input.parse_error("Failed to find root node /."); 1403 return; 1404 case 1: 1405 root = roots[0]; 1406 break; 1407 default: 1408 { 1409 root = roots[0]; 1410 for (std::vector<node*>::iterator i=roots.begin()+1, 1411 e=roots.end() ; i!=e ; ++i) 1412 { 1413 root->merge_node(*i); 1414 delete *i; 1415 } 1416 roots.resize(1); 1417 } 1418 } 1419 collect_names(); 1420 resolve_cross_references(); 1421 } 1422 1423 device_tree::~device_tree() 1424 { 1425 if (root != 0) 1426 { 1427 delete root; 1428 } 1429 while (!buffers.empty()) 1430 { 1431 delete buffers.back(); 1432 buffers.pop_back(); 1433 } 1434 for (define_map::iterator i=defines.begin(), e=defines.end() ; 1435 i!=e ; ++i) 1436 { 1437 delete i->second; 1438 } 1439 } 1440 1441 bool device_tree::parse_define(const char *def) 1442 { 1443 char *val = strchr(def, '='); 1444 if (!val) 1445 { 1446 if (strlen(def) != 0) 1447 { 1448 string name(def); 1449 defines[name]; 1450 return true; 1451 } 1452 return false; 1453 } 1454 string name(def, val-def); 1455 val++; 1456 input_buffer in = input_buffer(val, strlen(val)); 1457 property *p = property::parse(in, name, string(), false); 1458 if (p) 1459 defines[name] = p; 1460 return p; 1461 } 1462 1463 } // namespace fdt 1464 1465 } // namespace dtc 1466 1467