openfirm.c revision 84617
1/* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */ 2 3/* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33/* 34 * Copyright (C) 2000 Benno Rice. 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 52 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 53 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 54 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 55 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 * 57 * $FreeBSD: head/sys/boot/ofw/libofw/openfirm.c 84617 2001-10-07 13:22:25Z benno $ 58 */ 59 60#include <machine/stdarg.h> 61 62#include <stand.h> 63 64#include "openfirm.h" 65 66static int (*openfirmware)(void *); 67static ihandle_t stdin; 68static ihandle_t stdout; 69 70static ihandle_t mmu; 71static ihandle_t memory; 72 73/* Initialiaser */ 74 75void 76OF_init(int (*openfirm)(void *)) 77{ 78 phandle_t chosen; 79 80 openfirmware = openfirm; 81 82 chosen = OF_finddevice("/chosen"); 83 OF_getprop(chosen, "memory", &memory, sizeof(memory)); 84 if (memory == 0) 85 panic("failed to get memory ihandle"); 86 OF_getprop(chosen, "mmu", &mmu, sizeof(mmu)); 87 if (mmu == 0) 88 panic("failed to get mmu ihandle"); 89} 90 91/* 92 * Generic functions 93 */ 94 95/* Test to see if a service exists. */ 96int 97OF_test(char *name) 98{ 99 static struct { 100 char *name; 101 int nargs; 102 int nreturns; 103 char *service; 104 int missing; 105 } args = { 106 "test", 107 1, 108 1, 109 }; 110 111 args.service = name; 112 if (openfirmware(&args) == -1) 113 return -1; 114 return args.missing; 115} 116 117/* Return firmware millisecond count. */ 118int 119OF_milliseconds() 120{ 121 static struct { 122 char *name; 123 int nargs; 124 int nreturns; 125 int ms; 126 } args = { 127 "milliseconds", 128 0, 129 1, 130 }; 131 132 openfirmware(&args); 133 return args.ms; 134} 135 136/* 137 * Device tree functions 138 */ 139 140/* Return the next sibling of this node or 0. */ 141phandle_t 142OF_peer(phandle_t node) 143{ 144 static struct { 145 char *name; 146 int nargs; 147 int nreturns; 148 phandle_t node; 149 phandle_t next; 150 } args = { 151 "peer", 152 1, 153 1, 154 }; 155 156 args.node = node; 157 if (openfirmware(&args) == -1) 158 return -1; 159 return args.next; 160} 161 162/* Return the first child of this node or 0. */ 163phandle_t 164OF_child(phandle_t node) 165{ 166 static struct { 167 char *name; 168 int nargs; 169 int nreturns; 170 phandle_t node; 171 phandle_t child; 172 } args = { 173 "child", 174 1, 175 1, 176 }; 177 178 args.node = node; 179 if (openfirmware(&args) == -1) 180 return -1; 181 return args.child; 182} 183 184/* Return the parent of this node or 0. */ 185phandle_t 186OF_parent(phandle_t node) 187{ 188 static struct { 189 char *name; 190 int nargs; 191 int nreturns; 192 phandle_t node; 193 phandle_t parent; 194 } args = { 195 "parent", 196 1, 197 1, 198 }; 199 200 args.node = node; 201 if (openfirmware(&args) == -1) 202 return -1; 203 return args.parent; 204} 205 206/* Return the package handle that corresponds to an instance handle. */ 207phandle_t 208OF_instance_to_package(ihandle_t instance) 209{ 210 static struct { 211 char *name; 212 int nargs; 213 int nreturns; 214 ihandle_t instance; 215 phandle_t package; 216 } args = { 217 "instance-to-package", 218 1, 219 1, 220 }; 221 222 args.instance = instance; 223 if (openfirmware(&args) == -1) 224 return -1; 225 return args.package; 226} 227 228/* Get the length of a property of a package. */ 229int 230OF_getproplen(phandle_t package, char *propname) 231{ 232 static struct { 233 char *name; 234 int nargs; 235 int nreturns; 236 phandle_t package; 237 char *propname; 238 int proplen; 239 } args = { 240 "getproplen", 241 2, 242 1, 243 }; 244 245 args.package = package; 246 args.propname = propname; 247 if (openfirmware(&args) == -1) 248 return -1; 249 return args.proplen; 250} 251 252/* Get the value of a property of a package. */ 253int 254OF_getprop(phandle_t package, char *propname, void *buf, int buflen) 255{ 256 static struct { 257 char *name; 258 int nargs; 259 int nreturns; 260 phandle_t package; 261 char *propname; 262 void *buf; 263 int buflen; 264 int size; 265 } args = { 266 "getprop", 267 4, 268 1, 269 }; 270 271 args.package = package; 272 args.propname = propname; 273 args.buf = buf; 274 args.buflen = buflen; 275 if (openfirmware(&args) == -1) 276 return -1; 277 return args.size; 278} 279 280/* Get the next property of a package. */ 281int 282OF_nextprop(phandle_t package, char *previous, char *buf) 283{ 284 static struct { 285 char *name; 286 int nargs; 287 int nreturns; 288 phandle_t package; 289 char *previous; 290 char *buf; 291 int flag; 292 } args = { 293 "nextprop", 294 3, 295 1, 296 }; 297 298 args.package = package; 299 args.previous = previous; 300 args.buf = buf; 301 if (openfirmware(&args) == -1) 302 return -1; 303 return args.flag; 304} 305 306/* Set the value of a property of a package. */ 307/* XXX Has a bug on FirePower */ 308int 309OF_setprop(phandle_t package, char *propname, void *buf, int len) 310{ 311 static struct { 312 char *name; 313 int nargs; 314 int nreturns; 315 phandle_t package; 316 char *propname; 317 void *buf; 318 int len; 319 int size; 320 } args = { 321 "setprop", 322 4, 323 1, 324 }; 325 326 args.package = package; 327 args.propname = propname; 328 args.buf = buf; 329 args.len = len; 330 if (openfirmware(&args) == -1) 331 return -1; 332 return args.size; 333} 334 335/* Convert a device specifier to a fully qualified pathname. */ 336int 337OF_canon(const char *device, char *buf, int len) 338{ 339 static struct { 340 char *name; 341 int nargs; 342 int nreturns; 343 char *device; 344 char *buf; 345 int len; 346 int size; 347 } args = { 348 "canon", 349 3, 350 1, 351 }; 352 353 args.device = (char *)(uintptr_t *)device; 354 args.buf = buf; 355 args.len = len; 356 if (openfirmware(&args) == -1) 357 return -1; 358 return args.size; 359} 360 361/* Return a package handle for the specified device. */ 362phandle_t 363OF_finddevice(const char *device) 364{ 365 static struct { 366 char *name; 367 int nargs; 368 int nreturns; 369 char *device; 370 phandle_t package; 371 } args = { 372 "finddevice", 373 1, 374 1, 375 }; 376 377 args.device = (char *)(uintptr_t *)device; 378 if (openfirmware(&args) == -1) 379 return -1; 380 return args.package; 381} 382 383/* Return the fully qualified pathname corresponding to an instance. */ 384int 385OF_instance_to_path(ihandle_t instance, char *buf, int len) 386{ 387 static struct { 388 char *name; 389 int nargs; 390 int nreturns; 391 ihandle_t instance; 392 char *buf; 393 int len; 394 int size; 395 } args = { 396 "instance-to-path", 397 3, 398 1, 399 }; 400 401 args.instance = instance; 402 args.buf = buf; 403 args.len = len; 404 if (openfirmware(&args) == -1) 405 return -1; 406 return(args.size); 407} 408 409/* Return the fully qualified pathname corresponding to a package. */ 410int 411OF_package_to_path(phandle_t package, char *buf, int len) 412{ 413 static struct { 414 char *name; 415 int nargs; 416 int nreturns; 417 phandle_t package; 418 char *buf; 419 int len; 420 int size; 421 } args = { 422 "package-to-path", 423 3, 424 1, 425 }; 426 427 args.package = package; 428 args.buf = buf; 429 args.len = len; 430 if (openfirmware(&args) == -1) 431 return -1; 432 return(args.size); 433} 434 435/* Call the method in the scope of a given instance. */ 436int 437OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...) 438{ 439 va_list ap; 440 static struct { 441 char *name; 442 int nargs; 443 int nreturns; 444 char *method; 445 ihandle_t instance; 446 int args_n_results[12]; 447 } args = { 448 "call-method", 449 2, 450 1, 451 }; 452 int *ip, n; 453 454 if (nargs > 6) 455 return -1; 456 args.nargs = nargs + 2; 457 args.nreturns = nreturns + 1; 458 args.method = method; 459 args.instance = instance; 460 va_start(ap, nreturns); 461 for (ip = args.args_n_results + (n = nargs); --n >= 0;) 462 *--ip = va_arg(ap, int); 463 464 if (openfirmware(&args) == -1) 465 return -1; 466 if (args.args_n_results[nargs]) 467 return args.args_n_results[nargs]; 468 for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) 469 *va_arg(ap, int *) = *--ip; 470 va_end(ap); 471 return 0; 472} 473 474/* 475 * Device I/O functions. 476 */ 477 478/* Open an instance for a device. */ 479ihandle_t 480OF_open(char *device) 481{ 482 static struct { 483 char *name; 484 int nargs; 485 int nreturns; 486 char *device; 487 ihandle_t instance; 488 } args = { 489 "open", 490 1, 491 1, 492 }; 493 494 args.device = device; 495 if (openfirmware(&args) == -1 || args.instance == 0) { 496 return -1; 497 } 498 return args.instance; 499} 500 501/* Close an instance. */ 502void 503OF_close(ihandle_t instance) 504{ 505 static struct { 506 char *name; 507 int nargs; 508 int nreturns; 509 ihandle_t instance; 510 } args = { 511 "close", 512 1, 513 0, 514 }; 515 516 args.instance = instance; 517 openfirmware(&args); 518} 519 520/* Read from an instance. */ 521int 522OF_read(ihandle_t instance, void *addr, int len) 523{ 524 static struct { 525 char *name; 526 int nargs; 527 int nreturns; 528 ihandle_t instance; 529 void *addr; 530 int len; 531 int actual; 532 } args = { 533 "read", 534 3, 535 1, 536 }; 537 538 args.instance = instance; 539 args.addr = addr; 540 args.len = len; 541 542#if defined(OPENFIRM_DEBUG) 543 printf("OF_read: called with instance=%08x, addr=%p, len=%d\n", 544 args.instance, args.addr, args.len); 545#endif 546 547 if (openfirmware(&args) == -1) 548 return -1; 549 550#if defined(OPENFIRM_DEBUG) 551 printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n", 552 args.instance, args.addr, args.len, args.actual); 553#endif 554 555 return args.actual; 556} 557 558/* Write to an instance. */ 559int 560OF_write(ihandle_t instance, void *addr, int len) 561{ 562 static struct { 563 char *name; 564 int nargs; 565 int nreturns; 566 ihandle_t instance; 567 void *addr; 568 int len; 569 int actual; 570 } args = { 571 "write", 572 3, 573 1, 574 }; 575 576 args.instance = instance; 577 args.addr = addr; 578 args.len = len; 579 if (openfirmware(&args) == -1) 580 return -1; 581 return args.actual; 582} 583 584/* Seek to a position. */ 585int 586OF_seek(ihandle_t instance, u_int64_t pos) 587{ 588 static struct { 589 char *name; 590 int nargs; 591 int nreturns; 592 ihandle_t instance; 593 int poshi; 594 int poslo; 595 int status; 596 } args = { 597 "seek", 598 3, 599 1, 600 }; 601 602 args.instance = instance; 603 args.poshi = (int)(pos >> 32); 604 args.poslo = (int)pos; 605 if (openfirmware(&args) == -1) 606 return -1; 607 return args.status; 608} 609 610/* 611 * Memory functions. 612 */ 613 614/* Claim an area of memory. */ 615void * 616OF_claim(void *virt, u_int size, u_int align) 617{ 618 static struct { 619 char *name; 620 int nargs; 621 int nreturns; 622 void *virt; 623 u_int size; 624 u_int align; 625 void *baseaddr; 626 } args = { 627 "claim", 628 3, 629 1, 630 }; 631 632 args.virt = virt; 633 args.size = size; 634 args.align = align; 635 if (openfirmware(&args) == -1) 636 return (void *)-1; 637 return args.baseaddr; 638} 639 640/* Release an area of memory. */ 641void 642OF_release(void *virt, u_int size) 643{ 644 static struct { 645 char *name; 646 int nargs; 647 int nreturns; 648 void *virt; 649 u_int size; 650 } args = { 651 "release", 652 2, 653 0, 654 }; 655 656 args.virt = virt; 657 args.size = size; 658 openfirmware(&args); 659} 660 661/* 662 * Control transfer functions. 663 */ 664 665/* Reset the system and call "boot <bootspec>". */ 666void 667OF_boot(char *bootspec) 668{ 669 static struct { 670 char *name; 671 int nargs; 672 int nreturns; 673 char *bootspec; 674 } args = { 675 "boot", 676 1, 677 0, 678 }; 679 680 args.bootspec = bootspec; 681 openfirmware(&args); 682 for (;;); /* just in case */ 683} 684 685/* Suspend and drop back to the OpenFirmware interface. */ 686void 687OF_enter() 688{ 689 static struct { 690 char *name; 691 int nargs; 692 int nreturns; 693 } args = { 694 "enter", 695 0, 696 0 697 }; 698 699 openfirmware(&args); 700 return; /* We may come back. */ 701} 702 703/* Shut down and drop back to the OpenFirmware interface. */ 704void 705OF_exit() 706{ 707 static struct { 708 char *name; 709 int nargs; 710 int nreturns; 711 } args = { 712 "exit", 713 0, 714 0 715 }; 716 717 openfirmware(&args); 718 for (;;); /* just in case */ 719} 720 721/* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */ 722#if 0 723void 724OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 725{ 726 static struct { 727 char *name; 728 int nargs; 729 int nreturns; 730 void *virt; 731 u_int size; 732 void (*entry)(); 733 void *arg; 734 u_int len; 735 } args = { 736 "chain", 737 5, 738 0, 739 }; 740 741 args.virt = virt; 742 args.size = size; 743 args.entry = entry; 744 args.arg = arg; 745 args.len = len; 746 openfirmware(&args); 747} 748#else 749void 750OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 751{ 752 /* 753 * This is a REALLY dirty hack till the firmware gets this going 754 */ 755 if (size > 0) 756 OF_release(virt, size); 757 758 entry(0, 0, openfirmware, arg, len); 759} 760#endif 761