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