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