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