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