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