1 /* $NetBSD: ofctl.c,v 1.14 2018/05/28 12:42:45 wiz Exp $ */ 2 3 /*- 4 * Copyright (c) 2006, 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Thomas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 34 #ifndef lint 35 __COPYRIGHT("@(#) Copyright (c) 2006, 2007\ 36 The NetBSD Foundation, Inc. All rights reserved."); 37 __RCSID("$NetBSD: ofctl.c,v 1.14 2018/05/28 12:42:45 wiz Exp $"); 38 #endif /* not lint */ 39 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <unistd.h> 43 #include <errno.h> 44 #include <ctype.h> 45 #include <string.h> 46 #include <assert.h> 47 #include <err.h> 48 #include <sys/types.h> 49 #include <sys/ioctl.h> 50 #include <sys/file.h> 51 #include <sys/queue.h> 52 #include <dev/ofw/openfirmio.h> 53 54 #include <prop/proplib.h> 55 56 static void oflist(int, const char *, int, void *, size_t); 57 static void ofprop(int); 58 static void ofgetprop(int, const char *); 59 #if 0 60 static int isstrprint(const char *, size_t, int); 61 #endif 62 63 static int lflag; 64 static int pflag; 65 static int vflag; 66 67 struct of_node { 68 TAILQ_ENTRY(of_node) of_sibling; 69 TAILQ_HEAD(,of_node) of_children; 70 TAILQ_HEAD(,of_prop) of_properties; 71 struct of_node *of_parent; 72 struct of_prop *of_name; 73 struct of_prop *of_device_type; 74 struct of_prop *of_reg; 75 int of_nodeid; 76 }; 77 78 struct of_prop { 79 TAILQ_ENTRY(of_prop) prop_sibling; 80 char *prop_name; 81 u_int8_t *prop_data; 82 size_t prop_length; 83 size_t prop_namelen; 84 }; 85 86 struct of_node of_root; 87 unsigned long of_node_count; 88 unsigned long of_prop_count; 89 prop_dictionary_t of_proplib; 90 91 int OF_parent(int); 92 int OF_child(int); 93 int OF_peer(int); 94 int OF_finddevice(const char *); 95 int OF_getproplen(int, const char *); 96 int OF_getprop(int, const char *, void *, size_t); 97 int OF_nextprop(int, const char *, void *); 98 99 struct of_prop *of_tree_getprop(int, const char *); 100 101 static int of_fd = -1; 102 103 static void 104 of_tree_mkprop(struct of_node *node, prop_dictionary_t propdict, 105 prop_dictionary_keysym_t key) 106 { 107 struct of_prop *prop; 108 prop_data_t obj; 109 const char *name; 110 111 name = prop_dictionary_keysym_cstring_nocopy(key); 112 obj = prop_dictionary_get_keysym(propdict, key); 113 114 prop = malloc(sizeof(*prop) + strlen(name) + 1); 115 if (prop == NULL) 116 err(1, "malloc(%zu)", sizeof(*prop) + strlen(name) + 1); 117 118 memset(prop, 0, sizeof(*prop)); 119 prop->prop_name = (char *) (prop + 1); 120 prop->prop_namelen = strlen(name); 121 memcpy(prop->prop_name, name, prop->prop_namelen+1); 122 TAILQ_INSERT_TAIL(&node->of_properties, prop, prop_sibling); 123 124 if (!strcmp(name, "name")) 125 node->of_name = prop; 126 else if (!strcmp(name, "device_type")) 127 node->of_device_type = prop; 128 else if (!strcmp(name, "reg")) 129 node->of_reg = prop; 130 131 of_prop_count++; 132 133 prop->prop_length = prop_data_size(obj); 134 if (prop->prop_length) 135 prop->prop_data = prop_data_data(obj); 136 } 137 138 static struct of_node * 139 of_tree_mknode(struct of_node *parent) 140 { 141 struct of_node *newnode; 142 newnode = malloc(sizeof(*newnode)); 143 if (newnode == NULL) 144 err(1, "malloc(%zu)", sizeof(*newnode)); 145 146 of_node_count++; 147 148 memset(newnode, 0, sizeof(*newnode)); 149 TAILQ_INIT(&newnode->of_children); 150 TAILQ_INIT(&newnode->of_properties); 151 newnode->of_parent = parent; 152 153 TAILQ_INSERT_TAIL(&parent->of_children, newnode, of_sibling); 154 155 return newnode; 156 } 157 158 static void 159 of_tree_fill(prop_dictionary_t dict, struct of_node *node) 160 { 161 prop_dictionary_t propdict; 162 prop_array_t propkeys; 163 prop_array_t children; 164 unsigned int i, count; 165 166 node->of_nodeid = prop_number_unsigned_integer_value( 167 prop_dictionary_get(dict, "node")); 168 169 propdict = prop_dictionary_get(dict, "properties"); 170 propkeys = prop_dictionary_all_keys(propdict); 171 count = prop_array_count(propkeys); 172 173 for (i = 0; i < count; i++) 174 of_tree_mkprop(node, propdict, prop_array_get(propkeys, i)); 175 176 children = prop_dictionary_get(dict, "children"); 177 if (children) { 178 count = prop_array_count(children); 179 180 for (i = 0; i < count; i++) { 181 of_tree_fill( 182 prop_array_get(children, i), 183 of_tree_mknode(node)); 184 } 185 } 186 } 187 188 static void 189 of_tree_init(prop_dictionary_t dict) 190 { 191 /* 192 * Initialize the root node of the OFW tree. 193 */ 194 TAILQ_INIT(&of_root.of_children); 195 TAILQ_INIT(&of_root.of_properties); 196 197 of_tree_fill(dict, &of_root); 198 } 199 200 static prop_object_t 201 of_proplib_mkprop(int fd, int nodeid, char *name) 202 { 203 struct ofiocdesc ofio; 204 prop_object_t obj; 205 206 ofio.of_nodeid = nodeid; 207 ofio.of_name = name; 208 ofio.of_namelen = strlen(name); 209 ofio.of_buf = NULL; 210 ofio.of_buflen = 32; 211 212 again: 213 if (ofio.of_buf != NULL) 214 free(ofio.of_buf); 215 ofio.of_buf = malloc(ofio.of_buflen); 216 if (ofio.of_buf == NULL) 217 err(1, "malloc(%d)", ofio.of_buflen); 218 if (ioctl(fd, OFIOCGET, &ofio) < 0) { 219 if (errno == ENOMEM) { 220 ofio.of_buflen *= 2; 221 goto again; 222 } 223 warn("OFIOCGET(%d, \"%s\")", fd, name); 224 free(ofio.of_buf); 225 return NULL; 226 } 227 obj = prop_data_create_data(ofio.of_buf, ofio.of_buflen); 228 free(ofio.of_buf); 229 return obj; 230 } 231 232 static prop_dictionary_t 233 of_proplib_tree_fill(int fd, int nodeid) 234 { 235 int childid = nodeid; 236 struct ofiocdesc ofio; 237 char namebuf[33]; 238 char newnamebuf[33]; 239 prop_array_t children; 240 prop_dictionary_t dict, propdict; 241 prop_object_t obj; 242 243 ofio.of_nodeid = nodeid; 244 ofio.of_name = namebuf; 245 ofio.of_namelen = 1; 246 ofio.of_buf = newnamebuf; 247 248 namebuf[0] = '\0'; 249 250 dict = prop_dictionary_create(); 251 prop_dictionary_set(dict, "node", 252 prop_number_create_unsigned_integer(nodeid)); 253 254 propdict = prop_dictionary_create(); 255 for (;;) { 256 ofio.of_buflen = sizeof(newnamebuf); 257 258 if (ioctl(fd, OFIOCNEXTPROP, &ofio) < 0) { 259 if (errno == ENOENT) 260 break; 261 err(1, "OFIOCNEXTPROP(%d, %#x, \"%s\")", fd, 262 ofio.of_nodeid, ofio.of_name); 263 } 264 265 ofio.of_namelen = ofio.of_buflen; 266 if (ofio.of_namelen == 0) 267 break; 268 newnamebuf[ofio.of_buflen] = '\0'; 269 strcpy(namebuf, newnamebuf); 270 obj = of_proplib_mkprop(fd, nodeid, namebuf); 271 if (obj) 272 prop_dictionary_set(propdict, namebuf, obj); 273 } 274 prop_dictionary_set(dict, "properties", propdict); 275 276 if (ioctl(fd, OFIOCGETCHILD, &childid) < 0) 277 err(1, "OFIOCGETCHILD(%d, %#x)", fd, childid); 278 279 children = NULL; 280 while (childid != 0) { 281 if (children == NULL) 282 children = prop_array_create(); 283 prop_array_add(children, of_proplib_tree_fill(fd, childid)); 284 if (ioctl(fd, OFIOCGETNEXT, &childid) < 0) 285 err(1, "OFIOCGETNEXT(%d, %#x)", fd, childid); 286 } 287 if (children != NULL) { 288 prop_array_make_immutable(children); 289 prop_dictionary_set(dict, "children", children); 290 } 291 292 return dict; 293 } 294 295 static prop_dictionary_t 296 of_proplib_init(const char *file) 297 { 298 prop_dictionary_t dict; 299 int rootid = 0; 300 int fd; 301 302 fd = open(file, O_RDONLY); 303 if (fd < 0) 304 err(1, "%s", file); 305 306 if (ioctl(fd, OFIOCGETNEXT, &rootid) < 0) 307 err(1, "OFIOCGETNEXT(%d, %#x)", fd, rootid); 308 309 dict = of_proplib_tree_fill(fd, rootid); 310 311 /* keep the device open for the benefit of OF_finddevice */ 312 of_fd = fd; 313 314 return dict; 315 } 316 317 static struct of_node * 318 of_tree_walk(struct of_node *node, 319 struct of_node *(*fn)(struct of_node *, const void *), 320 const void *ctx) 321 { 322 struct of_node *child, *match; 323 324 if ((match = (*fn)(node, ctx)) != NULL) 325 return match; 326 327 TAILQ_FOREACH(child, &node->of_children, of_sibling) { 328 if ((match = of_tree_walk(child, fn, ctx)) != NULL) 329 return match; 330 } 331 return NULL; 332 } 333 334 static struct of_node * 335 of_match_by_nodeid(struct of_node *node, const void *ctx) 336 { 337 return (node->of_nodeid == *(const int *) ctx) ? node : NULL; 338 } 339 340 static struct of_node * 341 of_match_by_parentid(struct of_node *node, const void *ctx) 342 { 343 if (node->of_parent == NULL) 344 return NULL; 345 return (node->of_parent->of_nodeid == *(const int *) ctx) ? node : NULL; 346 } 347 348 int 349 OF_parent(int childid) 350 { 351 struct of_node *child; 352 353 if (childid == 0) 354 return 0; 355 356 child = of_tree_walk(&of_root, of_match_by_nodeid, &childid); 357 if (child == NULL || child->of_parent == NULL) 358 return 0; 359 return child->of_parent->of_nodeid; 360 } 361 362 int 363 OF_child(int parentid) 364 { 365 struct of_node *child; 366 367 child = of_tree_walk(&of_root, of_match_by_parentid, &parentid); 368 if (child == NULL) 369 return 0; 370 return child->of_nodeid; 371 } 372 373 int 374 OF_peer(int peerid) 375 { 376 struct of_node *node, *match; 377 378 if (peerid == 0) 379 return of_root.of_nodeid; 380 381 node = of_tree_walk(&of_root, of_match_by_nodeid, &peerid); 382 if (node == NULL || node->of_parent == NULL) 383 return 0; 384 385 /* 386 * The peer should be our next sibling (if one exists). 387 */ 388 match = TAILQ_NEXT(node, of_sibling); 389 return (match != NULL) ? match->of_nodeid : 0; 390 } 391 392 int 393 OF_finddevice(const char *name) 394 { 395 struct ofiocdesc ofio; 396 397 ofio.of_nodeid = 0; 398 ofio.of_name = __UNCONST(name); 399 ofio.of_namelen = strlen(name); 400 ofio.of_buf = NULL; 401 ofio.of_buflen = 0; 402 if (ioctl(of_fd, OFIOCFINDDEVICE, &ofio) < 0) { 403 if (errno == ENOENT) { 404 err(1, "OF node '%s' not found", name); 405 } else { 406 err(1, "OFIOCFINDDEVICE(%d, \"%s\")", of_fd, name); 407 } 408 } 409 410 return ofio.of_nodeid; 411 } 412 413 struct of_prop * 414 of_tree_getprop(int nodeid, const char *name) 415 { 416 struct of_node *node; 417 struct of_prop *prop; 418 419 if (nodeid == 0) 420 return 0; 421 422 node = of_tree_walk(&of_root, of_match_by_nodeid, &nodeid); 423 if (node == NULL) 424 return NULL; 425 426 if (name[0] == '\0') 427 return TAILQ_FIRST(&node->of_properties); 428 429 if (!strcmp(name, "name")) 430 return node->of_name; 431 if (!strcmp(name, "device_type")) 432 return node->of_device_type; 433 if (!strcmp(name, "reg")) 434 return node->of_reg; 435 436 TAILQ_FOREACH(prop, &node->of_properties, prop_sibling) { 437 if (!strcmp(name, prop->prop_name)) 438 break; 439 } 440 return prop; 441 } 442 443 int 444 OF_getproplen(int nodeid, const char *name) 445 { 446 struct of_prop *prop = of_tree_getprop(nodeid, name); 447 return (prop != NULL) ? (int)prop->prop_length : -1; 448 } 449 450 int 451 OF_getprop(int nodeid, const char *name, void *buf, size_t len) 452 { 453 struct of_prop *prop = of_tree_getprop(nodeid, name); 454 if (prop == NULL) 455 return -1; 456 if (len > prop->prop_length) 457 len = prop->prop_length; 458 memcpy(buf, prop->prop_data, len); 459 return len; 460 } 461 462 int 463 OF_nextprop(int nodeid, const char *name, void *nextname) 464 { 465 struct of_prop *prop = of_tree_getprop(nodeid, name); 466 if (prop == NULL) 467 return -1; 468 if (name[0] != '\0') { 469 prop = TAILQ_NEXT(prop, prop_sibling); 470 if (prop == NULL) 471 return -1; 472 } 473 strcpy(nextname, prop->prop_name); 474 return strlen(prop->prop_name); 475 } 476 477 static u_int32_t 478 of_decode_int(const u_int8_t *p) 479 { 480 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 481 } 482 483 /* 484 * Now we start the real program 485 */ 486 487 int 488 main(int argc, char **argv) 489 { 490 u_long of_buf[256]; 491 char device_type[33]; 492 int phandle; 493 int errflag = 0; 494 int c; 495 int len; 496 #if defined(__sparc__) || defined(__sparc64__) 497 const char *file = "/dev/openprom"; 498 #else 499 const char *file = "/dev/openfirm"; 500 #endif 501 const char *propfilein = NULL; 502 const char *propfileout = NULL; 503 504 while ((c = getopt(argc, argv, "f:lpr:vw:")) != EOF) { 505 switch (c) { 506 case 'l': lflag++; break; 507 case 'p': pflag++; break; 508 case 'v': vflag++; break; 509 case 'f': file = optarg; break; 510 case 'r': propfilein = optarg; break; 511 case 'w': propfileout = optarg; break; 512 default: errflag++; break; 513 } 514 } 515 if (errflag) 516 errx(1, "usage: ofctl [-lpv] [-f file] [-r propfile] [-w propfile] [node...]"); 517 518 if (propfilein != NULL) { 519 of_proplib = prop_dictionary_internalize_from_file(propfilein); 520 } else { 521 of_proplib = of_proplib_init(file); 522 } 523 524 if (propfileout) 525 prop_dictionary_externalize_to_file(of_proplib, propfileout); 526 527 of_tree_init(of_proplib); 528 printf("[Caching %lu nodes and %lu properties]\n", 529 of_node_count, of_prop_count); 530 531 if (argc == optind) { 532 phandle = OF_peer(0); 533 device_type[0] = '\0'; 534 len = OF_getprop(phandle, "device_type", device_type, 535 sizeof(device_type)); 536 if (len <= 0) 537 len = OF_getprop(phandle, "name", device_type, 538 sizeof(device_type)); 539 if (len >= 0) 540 device_type[len] = '\0'; 541 oflist(phandle, device_type, 0, of_buf, sizeof(of_buf)); 542 } else { 543 phandle = OF_finddevice(argv[optind++]); 544 device_type[0] = '\0'; 545 len = OF_getprop(phandle, "device_type", device_type, 546 sizeof(device_type)); 547 if (len <= 0) 548 len = OF_getprop(phandle, "name", device_type, 549 sizeof(device_type)); 550 if (len >= 0) 551 device_type[len] = '\0'; 552 553 if (argc == optind) { 554 if (lflag) 555 oflist(phandle, device_type, 0, of_buf, sizeof(of_buf)); 556 else 557 ofprop(phandle); 558 } else { 559 for (; optind < argc; optind++) { 560 ofgetprop(phandle, argv[optind]); 561 } 562 } 563 } 564 exit(0); 565 } 566 567 static size_t 568 ofname(int node, char *buf, size_t buflen) 569 { 570 u_int8_t address_cells_buf[4]; 571 u_int8_t reg_buf[4096]; 572 char name[33]; 573 char device_type[33]; 574 size_t off = 0; 575 int parent = OF_parent(node); 576 int reglen; 577 int reg[sizeof(reg_buf)/sizeof(int)]; 578 int address_cells; 579 int len; 580 581 len = OF_getprop(node, "name", name, sizeof(name)); 582 if (len <= 0) 583 name[0] = '\0'; 584 off += snprintf(buf + off, buflen - off, "/%s", name); 585 586 reglen = OF_getprop(node, "reg", reg_buf, sizeof(reg_buf)); 587 if (reglen <= 0) 588 return off; 589 590 len = OF_getprop(parent, "device_type", 591 device_type, sizeof(device_type)); 592 if (len <= 0) 593 len = OF_getprop(parent, "name", 594 device_type, sizeof(device_type)); 595 device_type[len] = '\0'; 596 597 for (;;) { 598 len = OF_getprop(parent, "#address-cells", 599 address_cells_buf, sizeof(address_cells_buf)); 600 if (len >= 0) { 601 assert(len == 4); 602 break; 603 } 604 parent = OF_parent(parent); 605 if (parent == 0) 606 break; 607 } 608 609 if (parent == 0) { 610 611 parent = OF_parent(node); 612 613 for (;;) { 614 len = OF_getprop(parent, "#size-cells", 615 address_cells_buf, sizeof(address_cells_buf)); 616 if (len >= 0) { 617 assert(len == 4); 618 break; 619 } 620 parent = OF_parent(parent); 621 if (parent == 0) 622 break; 623 } 624 /* no #size-cells */ 625 len = 0; 626 } 627 628 if (len == 0) { 629 /* looks like we're on an OBP2 system */ 630 if (reglen > 12) 631 return off; 632 off += snprintf(buf + off, buflen - off, "@"); 633 memcpy(reg, reg_buf, 8); 634 off += snprintf(buf + off, buflen - off, "%x,%x", reg[0], 635 reg[1]); 636 return off; 637 } 638 639 off += snprintf(buf + off, buflen - off, "@"); 640 address_cells = of_decode_int(address_cells_buf); 641 for (len = 0; len < address_cells; len ++) 642 reg[len] = of_decode_int(®_buf[len * 4]); 643 644 if (!strcmp(device_type,"pci")) { 645 off += snprintf(buf + off, buflen - off, 646 "%x", (reg[0] >> 11) & 31); 647 if (reg[0] & 0x700) 648 off += snprintf(buf + off, buflen - off, 649 ",%x", (reg[0] >> 8) & 7); 650 } else if (!strcmp(device_type,"upa")) { 651 off += snprintf(buf + off, buflen - off, 652 "%x", (reg[0] >> 4) & 63); 653 for (len = 1; len < address_cells; len++) 654 off += snprintf(buf + off, buflen - off, 655 ",%x", reg[len]); 656 #if !defined(__sparc__) && !defined(__sparc64__) 657 } else if (!strcmp(device_type,"isa")) { 658 #endif 659 } else { 660 off += snprintf(buf + off, buflen - off, "%x", reg[0]); 661 for (len = 1; len < address_cells; len++) 662 off += snprintf(buf + off, buflen - off, 663 ",%x", reg[len]); 664 } 665 return off; 666 } 667 668 static size_t 669 offullname2(int node, char *buf, size_t len) 670 { 671 size_t off; 672 int parent = OF_parent(node); 673 if (parent == 0) 674 return 0; 675 676 off = offullname2(parent, buf, len); 677 off += ofname(node, buf + off, len - off); 678 return off; 679 } 680 681 static size_t 682 offullname(int node, char *buf, size_t len) 683 { 684 if (node == OF_peer(0)) { 685 size_t off = snprintf(buf, len, "/"); 686 off += OF_getprop(node, "name", buf + off, len - off); 687 return off; 688 } 689 return offullname2(node, buf, len); 690 } 691 692 static void 693 oflist(int node, const char *parent_device_type, int depth, 694 void *of_buf, size_t of_buflen) 695 { 696 int len; 697 while (node != 0) { 698 int child; 699 if (pflag == 0 && vflag == 0) { 700 len = ofname(node, of_buf, of_buflen-1); 701 printf("%08x: %*s%s", node, depth * 2, "", 702 (char *) of_buf); 703 } else { 704 len = offullname(node, of_buf, of_buflen-1); 705 printf("%08x: %s", node, (char *) of_buf); 706 } 707 putchar('\n'); 708 if (pflag) { 709 putchar('\n'); 710 ofprop(node); 711 puts("\n----------------------------------------" 712 "----------------------------------------\n\n"); 713 } 714 child = OF_child(node); 715 if (child != -1 && child != 0) { 716 char device_type[33]; 717 len = OF_getprop(node, "device_type", 718 device_type, sizeof(device_type)); 719 if (len <= 0) 720 len = OF_getprop(node, "name", 721 device_type, sizeof(device_type)); 722 if (len >= 0) 723 device_type[len] = '\0'; 724 depth++; 725 oflist(child, device_type, depth, of_buf, of_buflen); 726 depth--; 727 } 728 if (depth == 0) 729 break; 730 node = OF_peer(node); 731 } 732 } 733 734 static void 735 print_line(const u_int8_t *buf, size_t off, size_t len) 736 { 737 if (len - off > 16) 738 len = off + 16; 739 740 for (; off < ((len + 15) & ~15); off++) { 741 if (off > 0) { 742 if ((off & 15) == 0) 743 printf("%12s%04lx:%7s", "", 744 (unsigned long int) off, ""); 745 else if ((off & 3) == 0) 746 putchar(' '); 747 } 748 if (off < len) 749 printf("%02x", buf[off]); 750 #if 0 751 else if (off >= ((len + 3) & ~3)) 752 printf(" "); 753 #endif 754 else 755 printf(".."); 756 } 757 } 758 759 static void 760 default_format(int node, const u_int8_t *buf, size_t len) 761 { 762 size_t off = 0; 763 while (off < len) { 764 size_t end; 765 print_line(buf, off, len); 766 printf(" "); /* 24 + 32 + 3 = 59, so +3 makes 62 */ 767 end = len; 768 if (end > off + 16) 769 end = off + 16; 770 for (; off < end; off++) { 771 char ch = buf[off]; 772 if (isascii(ch) && 773 (isalnum((int)ch) || ispunct((int)ch) || ch == ' ')) 774 putchar(ch); 775 else 776 putchar('.'); 777 } 778 putchar('\n'); 779 } 780 } 781 782 static void 783 reg_format(int node, const u_int8_t *buf, size_t len) 784 { 785 /* parent = OF_parent(node); */ 786 default_format(node, buf, len); 787 } 788 789 static void 790 frequency_format(int node, const u_int8_t *buf, size_t len) 791 { 792 if (len == 4) { 793 u_int32_t freq = of_decode_int(buf); 794 u_int32_t divisor, whole, frac; 795 const char *units = ""; 796 print_line(buf, 0, len); 797 for (divisor = 1000000000; divisor > 1; divisor /= 1000) { 798 if (freq >= divisor) 799 break; 800 } 801 whole = freq / divisor; 802 if (divisor == 1) 803 frac = 0; 804 else 805 frac = (freq / (divisor / 1000)) % 1000; 806 807 switch (divisor) { 808 case 1000000000: units = "GHz"; break; 809 case 1000000: units = "MHz"; break; 810 case 1000: units = "KHz"; break; 811 case 1: units = "Hz"; break; 812 } 813 if (frac > 0) 814 printf(" %u.%03u%s\n", whole, frac, units); 815 else 816 printf(" %u%s\n", whole, units); 817 } else 818 default_format(node, buf, len); 819 } 820 821 static void 822 size_format(int node, const u_int8_t *buf, size_t len) 823 { 824 if (len == 4) { 825 u_int32_t freq = of_decode_int(buf); 826 u_int32_t divisor, whole, frac; 827 const char *units = ""; 828 print_line(buf, 0, len); 829 for (divisor = 0x40000000; divisor > 1; divisor >>= 10) { 830 if (freq >= divisor) 831 break; 832 } 833 whole = freq / divisor; 834 if (divisor == 1) 835 frac = 0; 836 else 837 frac = (freq / (divisor >> 10)) & 1023; 838 839 switch (divisor) { 840 case 0x40000000: units = "G"; break; 841 case 0x100000: units = "M"; break; 842 case 0x400: units = "K"; break; 843 case 1: units = ""; break; 844 } 845 if (frac > 0) 846 printf(" %3u.%03u%s\n", whole, frac, units); 847 else 848 printf(" %3u%s\n", whole, units); 849 } else 850 default_format(node, buf, len); 851 } 852 853 static void 854 string_format(int node, const u_int8_t *buf, size_t len) 855 { 856 size_t off = 0; 857 int first_line = 1; 858 while (off < len) { 859 size_t string_len = 0; 860 int leading = 1; 861 for (; off + string_len < len; string_len++) { 862 if (buf[off+string_len] == '\0') { 863 string_len++; 864 break; 865 } 866 } 867 while (string_len > 0) { 868 size_t line_len = string_len; 869 if (line_len > 16) 870 line_len = 16; 871 if (!first_line) 872 printf("%12s%04lx:%7s", "", 873 (unsigned long int) off, ""); 874 print_line(buf + off, 0, line_len); 875 printf(" "); 876 if (leading) 877 putchar('"'); 878 first_line = 0; 879 leading = 0; 880 string_len -= line_len; 881 for (; line_len > 0; line_len--, off++) { 882 if (buf[off] != '\0') 883 putchar(buf[off]); 884 } 885 if (string_len == 0) 886 putchar('"'); 887 putchar('\n'); 888 } 889 } 890 } 891 892 static const struct { 893 const char *prop_name; 894 void (*prop_format)(int, const u_int8_t *, size_t); 895 } formatters[] = { 896 { "reg", reg_format }, 897 #if 0 898 { "assigned-addresses", assigned_addresses_format }, 899 { "ranges", ranges_format }, 900 { "interrupt-map", interrup_map_format }, 901 { "interrupt", interrupt_format }, 902 #endif 903 { "model", string_format }, 904 { "name", string_format }, 905 { "device_type", string_format }, 906 { "compatible", string_format }, 907 { "*frequency", frequency_format }, 908 { "*-size", size_format }, 909 { "*-cells", size_format }, 910 { "*-entries", size_format }, 911 { "*-associativity", size_format }, 912 { NULL, default_format } 913 }; 914 915 static void 916 ofgetprop(int node, const char *name) 917 { 918 u_int8_t of_buf[4097]; 919 int len; 920 int i; 921 922 len = OF_getprop(node, name, of_buf, sizeof(of_buf) - 1); 923 if (len < 0) 924 return; 925 of_buf[len] = '\0'; 926 printf("%-24s", name); 927 if (len == 0) { 928 putchar('\n'); 929 return; 930 } 931 if (strlen(name) >= 24) 932 printf("\n%24s", ""); 933 934 for (i = 0; formatters[i].prop_name != NULL; i++) { 935 if (formatters[i].prop_name[0] == '*') { 936 if (strstr(name, &formatters[i].prop_name[1]) != NULL) { 937 (*formatters[i].prop_format)(node, of_buf, len); 938 return; 939 } 940 continue; 941 } 942 if (strcmp(name, formatters[i].prop_name) == 0) { 943 (*formatters[i].prop_format)(node, of_buf, len); 944 return; 945 } 946 } 947 (*formatters[i].prop_format)(node, of_buf, len); 948 } 949 950 static void 951 ofprop(int node) 952 { 953 char namebuf[33]; 954 char newnamebuf[33]; 955 int len; 956 957 namebuf[0] = '\0'; 958 959 for (;;) { 960 len = OF_nextprop(node, namebuf, newnamebuf); 961 if (len <= 0) 962 break; 963 964 newnamebuf[len] = '\0'; 965 strcpy(namebuf, newnamebuf); 966 ofgetprop(node, newnamebuf); 967 } 968 } 969 #if 0 970 static int 971 isstrprint(const char *str, size_t len, int ignorenulls) 972 { 973 if (*str == '\0') 974 return 0; 975 for (; len-- > 0; str++) { 976 if (*str == '\0' && len > 0 && str[1] == '\0') 977 return 0; 978 if (len == 0 && *str == '\0') 979 return 1; 980 if (ignorenulls) { 981 if (*str == '\0') 982 continue; 983 if (isalnum(*str) || ispunct(*str) || *str == ' ') 984 continue; 985 return 0; 986 } 987 if (!isprint(*str)) 988 return 0; 989 } 990 return 1; 991 } 992 #endif 993