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 58 #include <sys/cdefs.h> 59 __FBSDID("$FreeBSD$"); 60 61 #include <sys/param.h> 62 #include <sys/kernel.h> 63 #include <sys/lock.h> 64 #include <sys/mutex.h> 65 #include <sys/systm.h> 66 67 #include <vm/vm.h> 68 #include <vm/vm_page.h> 69 #include <vm/pmap.h> 70 71 #include <machine/bus.h> 72 #include <machine/md_var.h> 73 #include <machine/ofw_machdep.h> 74 #include <machine/pmap.h> 75 #include <machine/stdarg.h> 76 77 #include <dev/ofw/openfirm.h> 78 #include <dev/ofw/ofwvar.h> 79 #include "ofw_if.h" 80 81 static int ofw_real_init(ofw_t, void *openfirm); 82 static int ofw_real_test(ofw_t, const char *name); 83 static phandle_t ofw_real_peer(ofw_t, phandle_t node); 84 static phandle_t ofw_real_child(ofw_t, phandle_t node); 85 static phandle_t ofw_real_parent(ofw_t, phandle_t node); 86 static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance); 87 static ssize_t ofw_real_getproplen(ofw_t, phandle_t package, 88 const char *propname); 89 static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname, 90 void *buf, size_t buflen); 91 static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous, 92 char *buf, size_t); 93 static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname, 94 const void *buf, size_t len); 95 static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len); 96 static phandle_t ofw_real_finddevice(ofw_t, const char *device); 97 static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf, 98 size_t len); 99 static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf, 100 size_t len); 101 static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method, 102 int nargs, int nreturns, cell_t *args_and_returns); 103 static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, 104 unsigned long *returns); 105 static ihandle_t ofw_real_open(ofw_t, const char *device); 106 static void ofw_real_close(ofw_t, ihandle_t instance); 107 static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len); 108 static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr, 109 size_t len); 110 static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos); 111 static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align); 112 static void ofw_real_release(ofw_t, void *virt, size_t size); 113 static void ofw_real_enter(ofw_t); 114 static void ofw_real_exit(ofw_t); 115 116 static ofw_method_t ofw_real_methods[] = { 117 OFWMETHOD(ofw_init, ofw_real_init), 118 OFWMETHOD(ofw_peer, ofw_real_peer), 119 OFWMETHOD(ofw_child, ofw_real_child), 120 OFWMETHOD(ofw_parent, ofw_real_parent), 121 OFWMETHOD(ofw_instance_to_package, ofw_real_instance_to_package), 122 OFWMETHOD(ofw_getproplen, ofw_real_getproplen), 123 OFWMETHOD(ofw_getprop, ofw_real_getprop), 124 OFWMETHOD(ofw_nextprop, ofw_real_nextprop), 125 OFWMETHOD(ofw_setprop, ofw_real_setprop), 126 OFWMETHOD(ofw_canon, ofw_real_canon), 127 OFWMETHOD(ofw_finddevice, ofw_real_finddevice), 128 OFWMETHOD(ofw_instance_to_path, ofw_real_instance_to_path), 129 OFWMETHOD(ofw_package_to_path, ofw_real_package_to_path), 130 131 OFWMETHOD(ofw_test, ofw_real_test), 132 OFWMETHOD(ofw_call_method, ofw_real_call_method), 133 OFWMETHOD(ofw_interpret, ofw_real_interpret), 134 OFWMETHOD(ofw_open, ofw_real_open), 135 OFWMETHOD(ofw_close, ofw_real_close), 136 OFWMETHOD(ofw_read, ofw_real_read), 137 OFWMETHOD(ofw_write, ofw_real_write), 138 OFWMETHOD(ofw_seek, ofw_real_seek), 139 OFWMETHOD(ofw_claim, ofw_real_claim), 140 OFWMETHOD(ofw_release, ofw_real_release), 141 OFWMETHOD(ofw_enter, ofw_real_enter), 142 OFWMETHOD(ofw_exit, ofw_real_exit), 143 144 { 0, 0 } 145 }; 146 147 static ofw_def_t ofw_real = { 148 OFW_STD_REAL, 149 ofw_real_methods, 150 0 151 }; 152 OFW_DEF(ofw_real); 153 154 static ofw_def_t ofw_32bit = { 155 OFW_STD_32BIT, 156 ofw_real_methods, 157 0 158 }; 159 OFW_DEF(ofw_32bit); 160 161 MALLOC_DEFINE(M_OFWREAL, "ofwreal", "Open Firmware Real Mode Bounce Page"); 162 163 static int (*openfirmware)(void *); 164 165 static vm_offset_t of_bounce_phys; 166 static caddr_t of_bounce_virt; 167 static off_t of_bounce_offset; 168 static size_t of_bounce_size; 169 static struct mtx of_bounce_mtx; 170 171 extern int ofw_real_mode; 172 extern struct pmap ofw_pmap; 173 174 /* 175 * After the VM is up, allocate a wired, low memory bounce page. 176 */ 177 178 static void ofw_real_bounce_alloc(void *); 179 180 SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY, 181 ofw_real_bounce_alloc, NULL); 182 183 static void 184 ofw_real_start(void) 185 { 186 mtx_lock(&of_bounce_mtx); 187 of_bounce_offset = 0; 188 } 189 190 static void 191 ofw_real_stop(void) 192 { 193 mtx_unlock(&of_bounce_mtx); 194 } 195 196 static void 197 ofw_real_bounce_alloc(void *junk) 198 { 199 /* 200 * Check that ofw_real is actually in use before allocating wads 201 * of memory. Do this by checking if our mutex has been set up. 202 */ 203 if (!mtx_initialized(&of_bounce_mtx)) 204 return; 205 206 /* 207 * Allocate a page of contiguous, wired physical memory that can 208 * fit into a 32-bit address space. 209 */ 210 211 mtx_lock(&of_bounce_mtx); 212 213 of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0, 214 0, BUS_SPACE_MAXADDR_32BIT, PAGE_SIZE, PAGE_SIZE); 215 216 of_bounce_phys = vtophys(of_bounce_virt); 217 of_bounce_size = PAGE_SIZE; 218 219 /* 220 * For virtual-mode OF, direct map this physical address so that 221 * we have a 32-bit virtual address to give OF. 222 */ 223 224 if (!ofw_real_mode && !hw_direct_map) 225 pmap_kenter(of_bounce_phys, of_bounce_phys); 226 227 mtx_unlock(&of_bounce_mtx); 228 } 229 230 static cell_t 231 ofw_real_map(const void *buf, size_t len) 232 { 233 static char emergency_buffer[255]; 234 cell_t phys; 235 236 mtx_assert(&of_bounce_mtx, MA_OWNED); 237 238 if (of_bounce_virt == NULL) { 239 /* 240 * If we haven't set up the MMU, then buf is guaranteed 241 * to be accessible to OF, because the only memory we 242 * can use right now is memory mapped by firmware. 243 */ 244 if (!pmap_bootstrapped) 245 return (cell_t)(uintptr_t)buf; 246 247 /* 248 * XXX: It is possible for us to get called before the VM has 249 * come online, but after the MMU is up. We don't have the 250 * bounce buffer yet, but can no longer presume a 1:1 mapping. 251 * Copy into the emergency buffer, and reset at the end. 252 */ 253 of_bounce_virt = emergency_buffer; 254 of_bounce_phys = (vm_offset_t)of_bounce_virt; 255 of_bounce_size = sizeof(emergency_buffer); 256 } 257 258 /* 259 * Make sure the bounce page offset satisfies any reasonable 260 * alignment constraint. 261 */ 262 of_bounce_offset += sizeof(register_t) - (of_bounce_offset % sizeof(register_t)); 263 264 if (of_bounce_offset + len > of_bounce_size) { 265 panic("Oversize Open Firmware call!"); 266 return 0; 267 } 268 269 memcpy(of_bounce_virt + of_bounce_offset, buf, len); 270 phys = of_bounce_phys + of_bounce_offset; 271 272 of_bounce_offset += len; 273 274 return (phys); 275 } 276 277 static void 278 ofw_real_unmap(cell_t physaddr, void *buf, size_t len) 279 { 280 mtx_assert(&of_bounce_mtx, MA_OWNED); 281 282 if (of_bounce_virt == NULL) 283 return; 284 285 memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len); 286 } 287 288 /* Initialiser */ 289 290 static int 291 ofw_real_init(ofw_t ofw, void *openfirm) 292 { 293 openfirmware = (int (*)(void *))openfirm; 294 295 mtx_init(&of_bounce_mtx, "OF Bounce Page", MTX_DEF, 0); 296 of_bounce_virt = NULL; 297 return (0); 298 } 299 300 /* 301 * Generic functions 302 */ 303 304 /* Test to see if a service exists. */ 305 static int 306 ofw_real_test(ofw_t ofw, const char *name) 307 { 308 vm_offset_t argsptr; 309 struct { 310 cell_t name; 311 cell_t nargs; 312 cell_t nreturns; 313 cell_t service; 314 cell_t missing; 315 } args; 316 317 args.name = (cell_t)(uintptr_t)"test"; 318 args.nargs = 1; 319 args.nreturns = 1; 320 321 ofw_real_start(); 322 323 args.service = ofw_real_map(name, strlen(name) + 1); 324 argsptr = ofw_real_map(&args, sizeof(args)); 325 if (args.service == 0 || openfirmware((void *)argsptr) == -1) { 326 ofw_real_stop(); 327 return (-1); 328 } 329 ofw_real_unmap(argsptr, &args, sizeof(args)); 330 ofw_real_stop(); 331 return (args.missing); 332 } 333 334 /* 335 * Device tree functions 336 */ 337 338 /* Return the next sibling of this node or 0. */ 339 static phandle_t 340 ofw_real_peer(ofw_t ofw, phandle_t node) 341 { 342 vm_offset_t argsptr; 343 struct { 344 cell_t name; 345 cell_t nargs; 346 cell_t nreturns; 347 cell_t node; 348 cell_t next; 349 } args; 350 351 args.name = (cell_t)(uintptr_t)"peer"; 352 args.nargs = 1; 353 args.nreturns = 1; 354 355 args.node = node; 356 ofw_real_start(); 357 argsptr = ofw_real_map(&args, sizeof(args)); 358 if (openfirmware((void *)argsptr) == -1) { 359 ofw_real_stop(); 360 return (-1); 361 } 362 ofw_real_unmap(argsptr, &args, sizeof(args)); 363 ofw_real_stop(); 364 return (args.next); 365 } 366 367 /* Return the first child of this node or 0. */ 368 static phandle_t 369 ofw_real_child(ofw_t ofw, phandle_t node) 370 { 371 vm_offset_t argsptr; 372 struct { 373 cell_t name; 374 cell_t nargs; 375 cell_t nreturns; 376 cell_t node; 377 cell_t child; 378 } args; 379 380 args.name = (cell_t)(uintptr_t)"child"; 381 args.nargs = 1; 382 args.nreturns = 1; 383 384 args.node = node; 385 ofw_real_start(); 386 argsptr = ofw_real_map(&args, sizeof(args)); 387 if (openfirmware((void *)argsptr) == -1) { 388 ofw_real_stop(); 389 return (-1); 390 } 391 ofw_real_unmap(argsptr, &args, sizeof(args)); 392 ofw_real_stop(); 393 return (args.child); 394 } 395 396 /* Return the parent of this node or 0. */ 397 static phandle_t 398 ofw_real_parent(ofw_t ofw, phandle_t node) 399 { 400 vm_offset_t argsptr; 401 struct { 402 cell_t name; 403 cell_t nargs; 404 cell_t nreturns; 405 cell_t node; 406 cell_t parent; 407 } args; 408 409 args.name = (cell_t)(uintptr_t)"parent"; 410 args.nargs = 1; 411 args.nreturns = 1; 412 413 args.node = node; 414 ofw_real_start(); 415 argsptr = ofw_real_map(&args, sizeof(args)); 416 if (openfirmware((void *)argsptr) == -1) { 417 ofw_real_stop(); 418 return (-1); 419 } 420 ofw_real_unmap(argsptr, &args, sizeof(args)); 421 ofw_real_stop(); 422 return (args.parent); 423 } 424 425 /* Return the package handle that corresponds to an instance handle. */ 426 static phandle_t 427 ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance) 428 { 429 vm_offset_t argsptr; 430 struct { 431 cell_t name; 432 cell_t nargs; 433 cell_t nreturns; 434 cell_t instance; 435 cell_t package; 436 } args; 437 438 args.name = (cell_t)(uintptr_t)"instance-to-package"; 439 args.nargs = 1; 440 args.nreturns = 1; 441 442 args.instance = instance; 443 ofw_real_start(); 444 argsptr = ofw_real_map(&args, sizeof(args)); 445 if (openfirmware((void *)argsptr) == -1) { 446 ofw_real_stop(); 447 return (-1); 448 } 449 ofw_real_unmap(argsptr, &args, sizeof(args)); 450 ofw_real_stop(); 451 return (args.package); 452 } 453 454 /* Get the length of a property of a package. */ 455 static ssize_t 456 ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname) 457 { 458 vm_offset_t argsptr; 459 struct { 460 cell_t name; 461 cell_t nargs; 462 cell_t nreturns; 463 cell_t package; 464 cell_t propname; 465 int32_t proplen; 466 } args; 467 468 args.name = (cell_t)(uintptr_t)"getproplen"; 469 args.nargs = 2; 470 args.nreturns = 1; 471 472 ofw_real_start(); 473 474 args.package = package; 475 args.propname = ofw_real_map(propname, strlen(propname) + 1); 476 argsptr = ofw_real_map(&args, sizeof(args)); 477 if (args.propname == 0 || openfirmware((void *)argsptr) == -1) { 478 ofw_real_stop(); 479 return (-1); 480 } 481 ofw_real_unmap(argsptr, &args, sizeof(args)); 482 ofw_real_stop(); 483 return (args.proplen); 484 } 485 486 /* Get the value of a property of a package. */ 487 static ssize_t 488 ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, 489 size_t buflen) 490 { 491 vm_offset_t argsptr; 492 struct { 493 cell_t name; 494 cell_t nargs; 495 cell_t nreturns; 496 cell_t package; 497 cell_t propname; 498 cell_t buf; 499 cell_t buflen; 500 int32_t size; 501 } args; 502 503 args.name = (cell_t)(uintptr_t)"getprop"; 504 args.nargs = 4; 505 args.nreturns = 1; 506 507 ofw_real_start(); 508 509 args.package = package; 510 args.propname = ofw_real_map(propname, strlen(propname) + 1); 511 args.buf = ofw_real_map(buf, buflen); 512 args.buflen = buflen; 513 argsptr = ofw_real_map(&args, sizeof(args)); 514 if (args.propname == 0 || args.buf == 0 || 515 openfirmware((void *)argsptr) == -1) { 516 ofw_real_stop(); 517 return (-1); 518 } 519 ofw_real_unmap(argsptr, &args, sizeof(args)); 520 ofw_real_unmap(args.buf, buf, buflen); 521 522 ofw_real_stop(); 523 return (args.size); 524 } 525 526 /* Get the next property of a package. */ 527 static int 528 ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous, 529 char *buf, size_t size) 530 { 531 vm_offset_t argsptr; 532 struct { 533 cell_t name; 534 cell_t nargs; 535 cell_t nreturns; 536 cell_t package; 537 cell_t previous; 538 cell_t buf; 539 cell_t flag; 540 } args; 541 542 args.name = (cell_t)(uintptr_t)"nextprop"; 543 args.nargs = 3; 544 args.nreturns = 1; 545 546 ofw_real_start(); 547 548 args.package = package; 549 args.previous = ofw_real_map(previous, strlen(previous) + 1); 550 args.buf = ofw_real_map(buf, size); 551 argsptr = ofw_real_map(&args, sizeof(args)); 552 if (args.previous == 0 || args.buf == 0 || 553 openfirmware((void *)argsptr) == -1) { 554 ofw_real_stop(); 555 return (-1); 556 } 557 ofw_real_unmap(argsptr, &args, sizeof(args)); 558 ofw_real_unmap(args.buf, buf, size); 559 560 ofw_real_stop(); 561 return (args.flag); 562 } 563 564 /* Set the value of a property of a package. */ 565 /* XXX Has a bug on FirePower */ 566 static int 567 ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname, 568 const void *buf, size_t len) 569 { 570 vm_offset_t argsptr; 571 struct { 572 cell_t name; 573 cell_t nargs; 574 cell_t nreturns; 575 cell_t package; 576 cell_t propname; 577 cell_t buf; 578 cell_t len; 579 cell_t size; 580 } args; 581 582 args.name = (cell_t)(uintptr_t)"setprop"; 583 args.nargs = 4; 584 args.nreturns = 1; 585 586 ofw_real_start(); 587 588 args.package = package; 589 args.propname = ofw_real_map(propname, strlen(propname) + 1); 590 args.buf = ofw_real_map(buf, len); 591 args.len = len; 592 argsptr = ofw_real_map(&args, sizeof(args)); 593 if (args.propname == 0 || args.buf == 0 || 594 openfirmware((void *)argsptr) == -1) { 595 ofw_real_stop(); 596 return (-1); 597 } 598 ofw_real_unmap(argsptr, &args, sizeof(args)); 599 ofw_real_stop(); 600 return (args.size); 601 } 602 603 /* Convert a device specifier to a fully qualified pathname. */ 604 static ssize_t 605 ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len) 606 { 607 vm_offset_t argsptr; 608 struct { 609 cell_t name; 610 cell_t nargs; 611 cell_t nreturns; 612 cell_t device; 613 cell_t buf; 614 cell_t len; 615 int32_t size; 616 } args; 617 618 args.name = (cell_t)(uintptr_t)"canon"; 619 args.nargs = 3; 620 args.nreturns = 1; 621 622 ofw_real_start(); 623 624 args.device = ofw_real_map(device, strlen(device) + 1); 625 args.buf = ofw_real_map(buf, len); 626 args.len = len; 627 argsptr = ofw_real_map(&args, sizeof(args)); 628 if (args.device == 0 || args.buf == 0 || 629 openfirmware((void *)argsptr) == -1) { 630 ofw_real_stop(); 631 return (-1); 632 } 633 ofw_real_unmap(argsptr, &args, sizeof(args)); 634 ofw_real_unmap(args.buf, buf, len); 635 636 ofw_real_stop(); 637 return (args.size); 638 } 639 640 /* Return a package handle for the specified device. */ 641 static phandle_t 642 ofw_real_finddevice(ofw_t ofw, const char *device) 643 { 644 vm_offset_t argsptr; 645 struct { 646 cell_t name; 647 cell_t nargs; 648 cell_t nreturns; 649 cell_t device; 650 cell_t package; 651 } args; 652 653 args.name = (cell_t)(uintptr_t)"finddevice"; 654 args.nargs = 1; 655 args.nreturns = 1; 656 657 ofw_real_start(); 658 659 args.device = ofw_real_map(device, strlen(device) + 1); 660 argsptr = ofw_real_map(&args, sizeof(args)); 661 if (args.device == 0 || 662 openfirmware((void *)argsptr) == -1) { 663 ofw_real_stop(); 664 return (-1); 665 } 666 ofw_real_unmap(argsptr, &args, sizeof(args)); 667 ofw_real_stop(); 668 return (args.package); 669 } 670 671 /* Return the fully qualified pathname corresponding to an instance. */ 672 static ssize_t 673 ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) 674 { 675 vm_offset_t argsptr; 676 struct { 677 cell_t name; 678 cell_t nargs; 679 cell_t nreturns; 680 cell_t instance; 681 cell_t buf; 682 cell_t len; 683 int32_t size; 684 } args; 685 686 args.name = (cell_t)(uintptr_t)"instance-to-path"; 687 args.nargs = 3; 688 args.nreturns = 1; 689 690 ofw_real_start(); 691 692 args.instance = instance; 693 args.buf = ofw_real_map(buf, len); 694 args.len = len; 695 argsptr = ofw_real_map(&args, sizeof(args)); 696 if (args.buf == 0 || 697 openfirmware((void *)argsptr) == -1) { 698 ofw_real_stop(); 699 return (-1); 700 } 701 ofw_real_unmap(argsptr, &args, sizeof(args)); 702 ofw_real_unmap(args.buf, buf, len); 703 704 ofw_real_stop(); 705 return (args.size); 706 } 707 708 /* Return the fully qualified pathname corresponding to a package. */ 709 static ssize_t 710 ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len) 711 { 712 vm_offset_t argsptr; 713 struct { 714 cell_t name; 715 cell_t nargs; 716 cell_t nreturns; 717 cell_t package; 718 cell_t buf; 719 cell_t len; 720 int32_t size; 721 } args; 722 723 args.name = (cell_t)(uintptr_t)"package-to-path"; 724 args.nargs = 3; 725 args.nreturns = 1; 726 727 ofw_real_start(); 728 729 args.package = package; 730 args.buf = ofw_real_map(buf, len); 731 args.len = len; 732 argsptr = ofw_real_map(&args, sizeof(args)); 733 if (args.buf == 0 || 734 openfirmware((void *)argsptr) == -1) { 735 ofw_real_stop(); 736 return (-1); 737 } 738 ofw_real_unmap(argsptr, &args, sizeof(args)); 739 ofw_real_unmap(args.buf, buf, len); 740 741 ofw_real_stop(); 742 return (args.size); 743 } 744 745 /* Call the method in the scope of a given instance. */ 746 static int 747 ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, 748 int nargs, int nreturns, cell_t *args_and_returns) 749 { 750 vm_offset_t argsptr; 751 struct { 752 cell_t name; 753 cell_t nargs; 754 cell_t nreturns; 755 cell_t method; 756 cell_t instance; 757 cell_t args_n_results[12]; 758 } args; 759 cell_t *cp, *ap; 760 int n; 761 762 args.name = (cell_t)(uintptr_t)"call-method"; 763 args.nargs = 2; 764 args.nreturns = 1; 765 766 if (nargs > 6) 767 return (-1); 768 769 ofw_real_start(); 770 args.nargs = nargs + 2; 771 args.nreturns = nreturns + 1; 772 args.method = ofw_real_map(method, strlen(method) + 1); 773 args.instance = instance; 774 775 ap = args_and_returns; 776 for (cp = args.args_n_results + (n = nargs); --n >= 0;) 777 *--cp = *(ap++); 778 argsptr = ofw_real_map(&args, sizeof(args)); 779 if (args.method == 0 || 780 openfirmware((void *)argsptr) == -1) { 781 ofw_real_stop(); 782 return (-1); 783 } 784 ofw_real_unmap(argsptr, &args, sizeof(args)); 785 ofw_real_stop(); 786 if (args.args_n_results[nargs]) 787 return (args.args_n_results[nargs]); 788 for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) 789 *(ap++) = *--cp; 790 return (0); 791 } 792 793 static int 794 ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, 795 unsigned long *returns) 796 { 797 vm_offset_t argsptr; 798 struct { 799 cell_t name; 800 cell_t nargs; 801 cell_t nreturns; 802 cell_t slot[16]; 803 } args; 804 cell_t status; 805 int i = 0, j = 0; 806 807 args.name = (cell_t)(uintptr_t)"interpret"; 808 args.nargs = 1; 809 810 ofw_real_start(); 811 args.nreturns = ++nreturns; 812 args.slot[i++] = ofw_real_map(cmd, strlen(cmd) + 1); 813 argsptr = ofw_real_map(&args, sizeof(args)); 814 if (openfirmware((void *)argsptr) == -1) { 815 ofw_real_stop(); 816 return (-1); 817 } 818 ofw_real_unmap(argsptr, &args, sizeof(args)); 819 ofw_real_stop(); 820 status = args.slot[i++]; 821 while (i < 1 + nreturns) 822 returns[j++] = args.slot[i++]; 823 return (status); 824 } 825 826 /* 827 * Device I/O functions 828 */ 829 830 /* Open an instance for a device. */ 831 static ihandle_t 832 ofw_real_open(ofw_t ofw, const char *device) 833 { 834 vm_offset_t argsptr; 835 struct { 836 cell_t name; 837 cell_t nargs; 838 cell_t nreturns; 839 cell_t device; 840 cell_t instance; 841 } args; 842 843 args.name = (cell_t)(uintptr_t)"open"; 844 args.nargs = 1; 845 args.nreturns = 1; 846 847 ofw_real_start(); 848 849 args.device = ofw_real_map(device, strlen(device) + 1); 850 argsptr = ofw_real_map(&args, sizeof(args)); 851 if (args.device == 0 || openfirmware((void *)argsptr) == -1 852 || args.instance == 0) { 853 ofw_real_stop(); 854 return (-1); 855 } 856 ofw_real_unmap(argsptr, &args, sizeof(args)); 857 ofw_real_stop(); 858 return (args.instance); 859 } 860 861 /* Close an instance. */ 862 static void 863 ofw_real_close(ofw_t ofw, ihandle_t instance) 864 { 865 vm_offset_t argsptr; 866 struct { 867 cell_t name; 868 cell_t nargs; 869 cell_t nreturns; 870 cell_t instance; 871 } args; 872 873 args.name = (cell_t)(uintptr_t)"close"; 874 args.nargs = 1; 875 args.nreturns = 0; 876 args.instance = instance; 877 ofw_real_start(); 878 argsptr = ofw_real_map(&args, sizeof(args)); 879 openfirmware((void *)argsptr); 880 ofw_real_stop(); 881 } 882 883 /* Read from an instance. */ 884 static ssize_t 885 ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) 886 { 887 vm_offset_t argsptr; 888 struct { 889 cell_t name; 890 cell_t nargs; 891 cell_t nreturns; 892 cell_t instance; 893 cell_t addr; 894 cell_t len; 895 int32_t actual; 896 } args; 897 898 args.name = (cell_t)(uintptr_t)"read"; 899 args.nargs = 3; 900 args.nreturns = 1; 901 902 ofw_real_start(); 903 904 args.instance = instance; 905 args.addr = ofw_real_map(addr, len); 906 args.len = len; 907 argsptr = ofw_real_map(&args, sizeof(args)); 908 if (args.addr == 0 || openfirmware((void *)argsptr) == -1) { 909 ofw_real_stop(); 910 return (-1); 911 } 912 ofw_real_unmap(argsptr, &args, sizeof(args)); 913 ofw_real_unmap(args.addr, addr, len); 914 915 ofw_real_stop(); 916 return (args.actual); 917 } 918 919 /* Write to an instance. */ 920 static ssize_t 921 ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) 922 { 923 vm_offset_t argsptr; 924 struct { 925 cell_t name; 926 cell_t nargs; 927 cell_t nreturns; 928 cell_t instance; 929 cell_t addr; 930 cell_t len; 931 int32_t actual; 932 } args; 933 934 args.name = (cell_t)(uintptr_t)"write"; 935 args.nargs = 3; 936 args.nreturns = 1; 937 938 ofw_real_start(); 939 940 args.instance = instance; 941 args.addr = ofw_real_map(addr, len); 942 args.len = len; 943 argsptr = ofw_real_map(&args, sizeof(args)); 944 if (args.addr == 0 || openfirmware((void *)argsptr) == -1) { 945 ofw_real_stop(); 946 return (-1); 947 } 948 ofw_real_unmap(argsptr, &args, sizeof(args)); 949 ofw_real_stop(); 950 return (args.actual); 951 } 952 953 /* Seek to a position. */ 954 static int 955 ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos) 956 { 957 vm_offset_t argsptr; 958 struct { 959 cell_t name; 960 cell_t nargs; 961 cell_t nreturns; 962 cell_t instance; 963 cell_t poshi; 964 cell_t poslo; 965 cell_t status; 966 } args; 967 968 args.name = (cell_t)(uintptr_t)"seek"; 969 args.nargs = 3; 970 args.nreturns = 1; 971 972 args.instance = instance; 973 args.poshi = pos >> 32; 974 args.poslo = pos; 975 ofw_real_start(); 976 argsptr = ofw_real_map(&args, sizeof(args)); 977 if (openfirmware((void *)argsptr) == -1) { 978 ofw_real_stop(); 979 return (-1); 980 } 981 ofw_real_unmap(argsptr, &args, sizeof(args)); 982 ofw_real_stop(); 983 return (args.status); 984 } 985 986 /* 987 * Memory functions 988 */ 989 990 /* Claim an area of memory. */ 991 static caddr_t 992 ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align) 993 { 994 vm_offset_t argsptr; 995 struct { 996 cell_t name; 997 cell_t nargs; 998 cell_t nreturns; 999 cell_t virt; 1000 cell_t size; 1001 cell_t align; 1002 cell_t baseaddr; 1003 } args; 1004 1005 args.name = (cell_t)(uintptr_t)"claim"; 1006 args.nargs = 3; 1007 args.nreturns = 1; 1008 1009 args.virt = (cell_t)(uintptr_t)virt; 1010 args.size = size; 1011 args.align = align; 1012 ofw_real_start(); 1013 argsptr = ofw_real_map(&args, sizeof(args)); 1014 if (openfirmware((void *)argsptr) == -1) { 1015 ofw_real_stop(); 1016 return ((void *)-1); 1017 } 1018 ofw_real_unmap(argsptr, &args, sizeof(args)); 1019 ofw_real_stop(); 1020 return ((void *)(uintptr_t)args.baseaddr); 1021 } 1022 1023 /* Release an area of memory. */ 1024 static void 1025 ofw_real_release(ofw_t ofw, void *virt, size_t size) 1026 { 1027 vm_offset_t argsptr; 1028 struct { 1029 cell_t name; 1030 cell_t nargs; 1031 cell_t nreturns; 1032 cell_t virt; 1033 cell_t size; 1034 } args; 1035 1036 args.name = (cell_t)(uintptr_t)"release"; 1037 args.nargs = 2; 1038 args.nreturns = 0; 1039 1040 args.virt = (cell_t)(uintptr_t)virt; 1041 args.size = size; 1042 ofw_real_start(); 1043 argsptr = ofw_real_map(&args, sizeof(args)); 1044 openfirmware((void *)argsptr); 1045 ofw_real_stop(); 1046 } 1047 1048 /* 1049 * Control transfer functions 1050 */ 1051 1052 /* Suspend and drop back to the Open Firmware interface. */ 1053 static void 1054 ofw_real_enter(ofw_t ofw) 1055 { 1056 vm_offset_t argsptr; 1057 struct { 1058 cell_t name; 1059 cell_t nargs; 1060 cell_t nreturns; 1061 } args; 1062 1063 args.name = (cell_t)(uintptr_t)"enter"; 1064 args.nargs = 0; 1065 args.nreturns = 0; 1066 1067 ofw_real_start(); 1068 argsptr = ofw_real_map(&args, sizeof(args)); 1069 openfirmware((void *)argsptr); 1070 /* We may come back. */ 1071 ofw_real_stop(); 1072 } 1073 1074 /* Shut down and drop back to the Open Firmware interface. */ 1075 static void 1076 ofw_real_exit(ofw_t ofw) 1077 { 1078 vm_offset_t argsptr; 1079 struct { 1080 cell_t name; 1081 cell_t nargs; 1082 cell_t nreturns; 1083 } args; 1084 1085 args.name = (cell_t)(uintptr_t)"exit"; 1086 args.nargs = 0; 1087 args.nreturns = 0; 1088 1089 ofw_real_start(); 1090 argsptr = ofw_real_map(&args, sizeof(args)); 1091 openfirmware((void *)argsptr); 1092 for (;;) /* just in case */ 1093 ; 1094 ofw_real_stop(); 1095 } 1096 1097