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