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