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