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