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