18446b206SNathan Whitehorn /* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */ 28446b206SNathan Whitehorn 38446b206SNathan Whitehorn /*- 471e3c308SPedro F. Giffuni * SPDX-License-Identifier:BSD-4-Clause AND BSD-2-Clause-FreeBSD 571e3c308SPedro F. Giffuni * 68446b206SNathan Whitehorn * Copyright (C) 1995, 1996 Wolfgang Solfrank. 78446b206SNathan Whitehorn * Copyright (C) 1995, 1996 TooLs GmbH. 88446b206SNathan Whitehorn * All rights reserved. 98446b206SNathan Whitehorn * 108446b206SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 118446b206SNathan Whitehorn * modification, are permitted provided that the following conditions 128446b206SNathan Whitehorn * are met: 138446b206SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 148446b206SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 158446b206SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 168446b206SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 178446b206SNathan Whitehorn * documentation and/or other materials provided with the distribution. 188446b206SNathan Whitehorn * 3. All advertising materials mentioning features or use of this software 198446b206SNathan Whitehorn * must display the following acknowledgement: 208446b206SNathan Whitehorn * This product includes software developed by TooLs GmbH. 218446b206SNathan Whitehorn * 4. The name of TooLs GmbH may not be used to endorse or promote products 228446b206SNathan Whitehorn * derived from this software without specific prior written permission. 238446b206SNathan Whitehorn * 248446b206SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 258446b206SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 268446b206SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 278446b206SNathan Whitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 288446b206SNathan Whitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 298446b206SNathan Whitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 308446b206SNathan Whitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 318446b206SNathan Whitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 328446b206SNathan Whitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 338446b206SNathan Whitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 348446b206SNathan Whitehorn */ 358446b206SNathan Whitehorn /*- 368446b206SNathan Whitehorn * Copyright (C) 2000 Benno Rice. 378446b206SNathan Whitehorn * All rights reserved. 388446b206SNathan Whitehorn * 398446b206SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 408446b206SNathan Whitehorn * modification, are permitted provided that the following conditions 418446b206SNathan Whitehorn * are met: 428446b206SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 438446b206SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 448446b206SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 458446b206SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 468446b206SNathan Whitehorn * documentation and/or other materials provided with the distribution. 478446b206SNathan Whitehorn * 488446b206SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 498446b206SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 508446b206SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 518446b206SNathan Whitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 528446b206SNathan Whitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 538446b206SNathan Whitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 548446b206SNathan Whitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 558446b206SNathan Whitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 568446b206SNathan Whitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 578446b206SNathan Whitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 588446b206SNathan Whitehorn */ 598446b206SNathan Whitehorn 608446b206SNathan Whitehorn #include <sys/cdefs.h> 618446b206SNathan Whitehorn __FBSDID("$FreeBSD$"); 628446b206SNathan Whitehorn 63b49db827SBrandon Bergren #include <sys/endian.h> 648446b206SNathan Whitehorn #include <sys/param.h> 658446b206SNathan Whitehorn #include <sys/kernel.h> 668446b206SNathan Whitehorn #include <sys/lock.h> 678446b206SNathan Whitehorn #include <sys/mutex.h> 688446b206SNathan Whitehorn #include <sys/systm.h> 698446b206SNathan Whitehorn 708446b206SNathan Whitehorn #include <vm/vm.h> 7170d75337SNathan Whitehorn #include <vm/vm_page.h> 728446b206SNathan Whitehorn #include <vm/pmap.h> 738446b206SNathan Whitehorn 748446b206SNathan Whitehorn #include <machine/bus.h> 7570d75337SNathan Whitehorn #include <machine/md_var.h> 768446b206SNathan Whitehorn #include <machine/ofw_machdep.h> 7770d75337SNathan Whitehorn #include <machine/stdarg.h> 788446b206SNathan Whitehorn 798446b206SNathan Whitehorn #include <dev/ofw/openfirm.h> 808446b206SNathan Whitehorn #include <dev/ofw/ofwvar.h> 818446b206SNathan Whitehorn #include "ofw_if.h" 828446b206SNathan Whitehorn 838297758aSRafal Jaworowski static int ofw_real_init(ofw_t, void *openfirm); 848446b206SNathan Whitehorn static int ofw_real_test(ofw_t, const char *name); 858446b206SNathan Whitehorn static phandle_t ofw_real_peer(ofw_t, phandle_t node); 868446b206SNathan Whitehorn static phandle_t ofw_real_child(ofw_t, phandle_t node); 878446b206SNathan Whitehorn static phandle_t ofw_real_parent(ofw_t, phandle_t node); 888446b206SNathan Whitehorn static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance); 898446b206SNathan Whitehorn static ssize_t ofw_real_getproplen(ofw_t, phandle_t package, 908446b206SNathan Whitehorn const char *propname); 918446b206SNathan Whitehorn static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname, 928446b206SNathan Whitehorn void *buf, size_t buflen); 938446b206SNathan Whitehorn static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous, 948446b206SNathan Whitehorn char *buf, size_t); 954fc23012SAndriy Gapon static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname, 964fc23012SAndriy Gapon const void *buf, size_t len); 978446b206SNathan Whitehorn static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len); 988446b206SNathan Whitehorn static phandle_t ofw_real_finddevice(ofw_t, const char *device); 998446b206SNathan Whitehorn static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf, 1008446b206SNathan Whitehorn size_t len); 1018446b206SNathan Whitehorn static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf, 1028446b206SNathan Whitehorn size_t len); 1038446b206SNathan Whitehorn static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method, 104054e5dcbSNathan Whitehorn int nargs, int nreturns, cell_t *args_and_returns); 10570d75337SNathan Whitehorn static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, 106cdb25d82SMarius Strobl cell_t *returns); 1078446b206SNathan Whitehorn static ihandle_t ofw_real_open(ofw_t, const char *device); 1088446b206SNathan Whitehorn static void ofw_real_close(ofw_t, ihandle_t instance); 1098446b206SNathan Whitehorn static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len); 1108446b206SNathan Whitehorn static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr, 1118446b206SNathan Whitehorn size_t len); 1128446b206SNathan Whitehorn static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos); 1138446b206SNathan Whitehorn static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align); 1148446b206SNathan Whitehorn static void ofw_real_release(ofw_t, void *virt, size_t size); 1158446b206SNathan Whitehorn static void ofw_real_enter(ofw_t); 1168446b206SNathan Whitehorn static void ofw_real_exit(ofw_t); 1178446b206SNathan Whitehorn 1188446b206SNathan Whitehorn static ofw_method_t ofw_real_methods[] = { 1198446b206SNathan Whitehorn OFWMETHOD(ofw_init, ofw_real_init), 1208446b206SNathan Whitehorn OFWMETHOD(ofw_peer, ofw_real_peer), 1218446b206SNathan Whitehorn OFWMETHOD(ofw_child, ofw_real_child), 1228446b206SNathan Whitehorn OFWMETHOD(ofw_parent, ofw_real_parent), 1238446b206SNathan Whitehorn OFWMETHOD(ofw_instance_to_package, ofw_real_instance_to_package), 1248446b206SNathan Whitehorn OFWMETHOD(ofw_getproplen, ofw_real_getproplen), 1258446b206SNathan Whitehorn OFWMETHOD(ofw_getprop, ofw_real_getprop), 1268446b206SNathan Whitehorn OFWMETHOD(ofw_nextprop, ofw_real_nextprop), 1278446b206SNathan Whitehorn OFWMETHOD(ofw_setprop, ofw_real_setprop), 1288446b206SNathan Whitehorn OFWMETHOD(ofw_canon, ofw_real_canon), 1298446b206SNathan Whitehorn OFWMETHOD(ofw_finddevice, ofw_real_finddevice), 1308446b206SNathan Whitehorn OFWMETHOD(ofw_instance_to_path, ofw_real_instance_to_path), 1318446b206SNathan Whitehorn OFWMETHOD(ofw_package_to_path, ofw_real_package_to_path), 1328446b206SNathan Whitehorn 1338446b206SNathan Whitehorn OFWMETHOD(ofw_test, ofw_real_test), 1348446b206SNathan Whitehorn OFWMETHOD(ofw_call_method, ofw_real_call_method), 13570d75337SNathan Whitehorn OFWMETHOD(ofw_interpret, ofw_real_interpret), 1368446b206SNathan Whitehorn OFWMETHOD(ofw_open, ofw_real_open), 1378446b206SNathan Whitehorn OFWMETHOD(ofw_close, ofw_real_close), 1388446b206SNathan Whitehorn OFWMETHOD(ofw_read, ofw_real_read), 1398446b206SNathan Whitehorn OFWMETHOD(ofw_write, ofw_real_write), 1408446b206SNathan Whitehorn OFWMETHOD(ofw_seek, ofw_real_seek), 1418446b206SNathan Whitehorn OFWMETHOD(ofw_claim, ofw_real_claim), 1428446b206SNathan Whitehorn OFWMETHOD(ofw_release, ofw_real_release), 1438446b206SNathan Whitehorn OFWMETHOD(ofw_enter, ofw_real_enter), 1448446b206SNathan Whitehorn OFWMETHOD(ofw_exit, ofw_real_exit), 1458446b206SNathan Whitehorn { 0, 0 } 1468446b206SNathan Whitehorn }; 1478446b206SNathan Whitehorn 1488446b206SNathan Whitehorn static ofw_def_t ofw_real = { 1498446b206SNathan Whitehorn OFW_STD_REAL, 1508446b206SNathan Whitehorn ofw_real_methods, 1518446b206SNathan Whitehorn 0 1528446b206SNathan Whitehorn }; 1538446b206SNathan Whitehorn OFW_DEF(ofw_real); 1548446b206SNathan Whitehorn 15570d75337SNathan Whitehorn static ofw_def_t ofw_32bit = { 15670d75337SNathan Whitehorn OFW_STD_32BIT, 15770d75337SNathan Whitehorn ofw_real_methods, 15870d75337SNathan Whitehorn 0 15970d75337SNathan Whitehorn }; 16070d75337SNathan Whitehorn OFW_DEF(ofw_32bit); 16170d75337SNathan Whitehorn 162d745c852SEd Schouten static MALLOC_DEFINE(M_OFWREAL, "ofwreal", 163d745c852SEd Schouten "Open Firmware Real Mode Bounce Page"); 1648446b206SNathan Whitehorn 1658446b206SNathan Whitehorn static int (*openfirmware)(void *); 1668446b206SNathan Whitehorn 1678446b206SNathan Whitehorn static vm_offset_t of_bounce_phys; 1688446b206SNathan Whitehorn static caddr_t of_bounce_virt; 1698446b206SNathan Whitehorn static off_t of_bounce_offset; 1708446b206SNathan Whitehorn static size_t of_bounce_size; 17135f29427SLeandro Lupori 172b49db827SBrandon Bergren #define IN(x) htobe32(x) 173b49db827SBrandon Bergren #define OUT(x) be32toh(x) 174b49db827SBrandon Bergren 17535f29427SLeandro Lupori /* 17635f29427SLeandro Lupori * To be able to use OFW console on PPC, that requires real mode OFW, 17735f29427SLeandro Lupori * the mutex that guards the mapping/unmapping of virtual to physical 17835f29427SLeandro Lupori * buffers (of_real_mtx) must be of SPIN type. This is needed because 17935f29427SLeandro Lupori * kernel console first locks a SPIN mutex before calling OFW real. 18035f29427SLeandro Lupori * By default, of_real_mtx is a sleepable mutex. To make it of SPIN 18135f29427SLeandro Lupori * type, use the following tunnable: 18235f29427SLeandro Lupori * machdep.ofw.mtx_spin=1 18335f29427SLeandro Lupori * 18435f29427SLeandro Lupori * Besides that, a few more tunables are needed to select and use the 18535f29427SLeandro Lupori * OFW console with real mode OFW. 18635f29427SLeandro Lupori * 18735f29427SLeandro Lupori * In order to disable the use of OFW FrameBuffer and fallback to the 18835f29427SLeandro Lupori * OFW console, use: 18935f29427SLeandro Lupori * hw.ofwfb.disable=1 19035f29427SLeandro Lupori * 19135f29427SLeandro Lupori * To disable the use of FDT (that doesn't support OFW read/write methods) 19235f29427SLeandro Lupori * and use real OFW instead, unset the following loader variable: 19335f29427SLeandro Lupori * unset usefdt 19435f29427SLeandro Lupori * 19535f29427SLeandro Lupori * OFW is put in quiesce state in early kernel boot, which usually disables 19635f29427SLeandro Lupori * OFW read/write capabilities (in QEMU write continue to work, but 19735f29427SLeandro Lupori * read doesn't). To avoid OFW quiesce, use: 19835f29427SLeandro Lupori * debug.quiesce_ofw=0 19935f29427SLeandro Lupori * 20035f29427SLeandro Lupori * Note that disabling OFW quiesce can cause conflicts between kernel and 20135f29427SLeandro Lupori * OFW trying to control the same hardware. Thus, it must be used with care. 20235f29427SLeandro Lupori * Some conflicts can be avoided by disabling kernel drivers with hints. 20335f29427SLeandro Lupori * For instance, to disable a xhci controller and an USB keyboard connected 20435f29427SLeandro Lupori * to it, that may be already being used for input by OFW, use: 20535f29427SLeandro Lupori * hint.xhci.0.disabled=1 20635f29427SLeandro Lupori */ 20735f29427SLeandro Lupori 2088446b206SNathan Whitehorn static struct mtx of_bounce_mtx; 20935f29427SLeandro Lupori static struct mtx of_spin_mtx; 21035f29427SLeandro Lupori static struct mtx *of_real_mtx; 21135f29427SLeandro Lupori static void (*of_mtx_lock)(void); 21235f29427SLeandro Lupori static void (*of_mtx_unlock)(void); 2138446b206SNathan Whitehorn 21470d75337SNathan Whitehorn extern int ofw_real_mode; 21570d75337SNathan Whitehorn 2168446b206SNathan Whitehorn /* 2178446b206SNathan Whitehorn * After the VM is up, allocate a wired, low memory bounce page. 2188446b206SNathan Whitehorn */ 2198446b206SNathan Whitehorn 2208446b206SNathan Whitehorn static void ofw_real_bounce_alloc(void *); 2218446b206SNathan Whitehorn 22270d75337SNathan Whitehorn SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY, 2238446b206SNathan Whitehorn ofw_real_bounce_alloc, NULL); 2248446b206SNathan Whitehorn 2258446b206SNathan Whitehorn static void 22635f29427SLeandro Lupori ofw_real_mtx_lock_spin(void) 22735f29427SLeandro Lupori { 22835f29427SLeandro Lupori mtx_lock_spin(of_real_mtx); 22935f29427SLeandro Lupori } 23035f29427SLeandro Lupori 23135f29427SLeandro Lupori static void 23235f29427SLeandro Lupori ofw_real_mtx_lock(void) 23335f29427SLeandro Lupori { 23435f29427SLeandro Lupori mtx_lock(of_real_mtx); 23535f29427SLeandro Lupori } 23635f29427SLeandro Lupori 23735f29427SLeandro Lupori static void 23835f29427SLeandro Lupori ofw_real_mtx_unlock_spin(void) 23935f29427SLeandro Lupori { 24035f29427SLeandro Lupori mtx_unlock_spin(of_real_mtx); 24135f29427SLeandro Lupori } 24235f29427SLeandro Lupori 24335f29427SLeandro Lupori static void 24435f29427SLeandro Lupori ofw_real_mtx_unlock(void) 24535f29427SLeandro Lupori { 24635f29427SLeandro Lupori mtx_unlock(of_real_mtx); 24735f29427SLeandro Lupori } 24835f29427SLeandro Lupori 24935f29427SLeandro Lupori static void 2508446b206SNathan Whitehorn ofw_real_start(void) 2518446b206SNathan Whitehorn { 25235f29427SLeandro Lupori (*of_mtx_lock)(); 2538446b206SNathan Whitehorn of_bounce_offset = 0; 2548446b206SNathan Whitehorn } 2558446b206SNathan Whitehorn 2568446b206SNathan Whitehorn static void 2578446b206SNathan Whitehorn ofw_real_stop(void) 2588446b206SNathan Whitehorn { 25935f29427SLeandro Lupori (*of_mtx_unlock)(); 2608446b206SNathan Whitehorn } 2618446b206SNathan Whitehorn 2628446b206SNathan Whitehorn static void 2638446b206SNathan Whitehorn ofw_real_bounce_alloc(void *junk) 2648446b206SNathan Whitehorn { 265d6d06708SJustin Hibbits caddr_t temp; 266d6d06708SJustin Hibbits 2678446b206SNathan Whitehorn /* 2688446b206SNathan Whitehorn * Check that ofw_real is actually in use before allocating wads 2698446b206SNathan Whitehorn * of memory. Do this by checking if our mutex has been set up. 2708446b206SNathan Whitehorn */ 2718446b206SNathan Whitehorn if (!mtx_initialized(&of_bounce_mtx)) 2728446b206SNathan Whitehorn return; 2738446b206SNathan Whitehorn 2748446b206SNathan Whitehorn /* 2758446b206SNathan Whitehorn * Allocate a page of contiguous, wired physical memory that can 27617879090SNathan Whitehorn * fit into a 32-bit address space and accessed from real mode. 2778446b206SNathan Whitehorn */ 278d6d06708SJustin Hibbits temp = contigmalloc(4 * PAGE_SIZE, M_OFWREAL, 0, 0, 279d6d06708SJustin Hibbits ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE, 280d6d06708SJustin Hibbits 4 * PAGE_SIZE); 281d6d06708SJustin Hibbits if (temp == NULL) 282d6d06708SJustin Hibbits panic("%s: Not able to allocated contiguous memory\n", __func__); 2838446b206SNathan Whitehorn 2848446b206SNathan Whitehorn mtx_lock(&of_bounce_mtx); 2858446b206SNathan Whitehorn 286d6d06708SJustin Hibbits of_bounce_virt = temp; 28770d75337SNathan Whitehorn 2888446b206SNathan Whitehorn of_bounce_phys = vtophys(of_bounce_virt); 28915b5b0acSJustin Hibbits of_bounce_size = 4 * PAGE_SIZE; 2908446b206SNathan Whitehorn 29170d75337SNathan Whitehorn /* 29270d75337SNathan Whitehorn * For virtual-mode OF, direct map this physical address so that 29370d75337SNathan Whitehorn * we have a 32-bit virtual address to give OF. 29470d75337SNathan Whitehorn */ 29570d75337SNathan Whitehorn 296f9edb09dSNathan Whitehorn if (!ofw_real_mode && (!hw_direct_map || DMAP_BASE_ADDRESS != 0)) 29770d75337SNathan Whitehorn pmap_kenter(of_bounce_phys, of_bounce_phys); 29870d75337SNathan Whitehorn 2998446b206SNathan Whitehorn mtx_unlock(&of_bounce_mtx); 3008446b206SNathan Whitehorn } 3018446b206SNathan Whitehorn 3028446b206SNathan Whitehorn static cell_t 3038446b206SNathan Whitehorn ofw_real_map(const void *buf, size_t len) 3048446b206SNathan Whitehorn { 30570d75337SNathan Whitehorn static char emergency_buffer[255]; 3068446b206SNathan Whitehorn cell_t phys; 3078446b206SNathan Whitehorn 30835f29427SLeandro Lupori mtx_assert(of_real_mtx, MA_OWNED); 3098446b206SNathan Whitehorn 3108446b206SNathan Whitehorn if (of_bounce_virt == NULL) { 31170d75337SNathan Whitehorn /* 31270d75337SNathan Whitehorn * If we haven't set up the MMU, then buf is guaranteed 31370d75337SNathan Whitehorn * to be accessible to OF, because the only memory we 31470d75337SNathan Whitehorn * can use right now is memory mapped by firmware. 31570d75337SNathan Whitehorn */ 3168446b206SNathan Whitehorn if (!pmap_bootstrapped) 317f9edb09dSNathan Whitehorn return (cell_t)((uintptr_t)buf & ~DMAP_BASE_ADDRESS); 3188446b206SNathan Whitehorn 3198446b206SNathan Whitehorn /* 3208446b206SNathan Whitehorn * XXX: It is possible for us to get called before the VM has 3218446b206SNathan Whitehorn * come online, but after the MMU is up. We don't have the 3228446b206SNathan Whitehorn * bounce buffer yet, but can no longer presume a 1:1 mapping. 32370d75337SNathan Whitehorn * Copy into the emergency buffer, and reset at the end. 3248446b206SNathan Whitehorn */ 32570d75337SNathan Whitehorn of_bounce_virt = emergency_buffer; 326f9edb09dSNathan Whitehorn of_bounce_phys = (vm_offset_t)of_bounce_virt & 327f9edb09dSNathan Whitehorn ~DMAP_BASE_ADDRESS; 32870d75337SNathan Whitehorn of_bounce_size = sizeof(emergency_buffer); 3298446b206SNathan Whitehorn } 3308446b206SNathan Whitehorn 3318446b206SNathan Whitehorn /* 3328446b206SNathan Whitehorn * Make sure the bounce page offset satisfies any reasonable 3338446b206SNathan Whitehorn * alignment constraint. 3348446b206SNathan Whitehorn */ 335f9edb09dSNathan Whitehorn of_bounce_offset += sizeof(register_t) - 336f9edb09dSNathan Whitehorn (of_bounce_offset % sizeof(register_t)); 3378446b206SNathan Whitehorn 3388446b206SNathan Whitehorn if (of_bounce_offset + len > of_bounce_size) { 3398446b206SNathan Whitehorn panic("Oversize Open Firmware call!"); 3408446b206SNathan Whitehorn return 0; 3418446b206SNathan Whitehorn } 3428446b206SNathan Whitehorn 343ec664c11SAndreas Tobler if (buf != NULL) 3448446b206SNathan Whitehorn memcpy(of_bounce_virt + of_bounce_offset, buf, len); 345ec664c11SAndreas Tobler else 346ec664c11SAndreas Tobler return (0); 347ec664c11SAndreas Tobler 3488446b206SNathan Whitehorn phys = of_bounce_phys + of_bounce_offset; 3498446b206SNathan Whitehorn 3508446b206SNathan Whitehorn of_bounce_offset += len; 3518446b206SNathan Whitehorn 35270d75337SNathan Whitehorn return (phys); 3538446b206SNathan Whitehorn } 3548446b206SNathan Whitehorn 3558446b206SNathan Whitehorn static void 3568446b206SNathan Whitehorn ofw_real_unmap(cell_t physaddr, void *buf, size_t len) 3578446b206SNathan Whitehorn { 35835f29427SLeandro Lupori mtx_assert(of_real_mtx, MA_OWNED); 3598446b206SNathan Whitehorn 3608446b206SNathan Whitehorn if (of_bounce_virt == NULL) 3618446b206SNathan Whitehorn return; 3628446b206SNathan Whitehorn 363ec664c11SAndreas Tobler if (physaddr == 0) 364ec664c11SAndreas Tobler return; 365ec664c11SAndreas Tobler 3668446b206SNathan Whitehorn memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len); 3678446b206SNathan Whitehorn } 3688446b206SNathan Whitehorn 3698446b206SNathan Whitehorn /* Initialiser */ 3708446b206SNathan Whitehorn 3718297758aSRafal Jaworowski static int 3728446b206SNathan Whitehorn ofw_real_init(ofw_t ofw, void *openfirm) 3738446b206SNathan Whitehorn { 37435f29427SLeandro Lupori int mtx_spin; 3758446b206SNathan Whitehorn 37635f29427SLeandro Lupori openfirmware = (int (*)(void *))openfirm; 377d01195e3SChristian Brueffer mtx_init(&of_bounce_mtx, "OF Bounce Page", NULL, MTX_DEF); 37835f29427SLeandro Lupori 37935f29427SLeandro Lupori mtx_spin = 0; 38035f29427SLeandro Lupori TUNABLE_INT_FETCH("machdep.ofw.mtx_spin", &mtx_spin); 38135f29427SLeandro Lupori if (mtx_spin) { 38235f29427SLeandro Lupori mtx_init(&of_spin_mtx, "OF Real", NULL, MTX_SPIN); 38335f29427SLeandro Lupori of_real_mtx = &of_spin_mtx; 38435f29427SLeandro Lupori of_mtx_lock = ofw_real_mtx_lock_spin; 38535f29427SLeandro Lupori of_mtx_unlock = ofw_real_mtx_unlock_spin; 38635f29427SLeandro Lupori } else { 38735f29427SLeandro Lupori of_real_mtx = &of_bounce_mtx; 38835f29427SLeandro Lupori of_mtx_lock = ofw_real_mtx_lock; 38935f29427SLeandro Lupori of_mtx_unlock = ofw_real_mtx_unlock; 39035f29427SLeandro Lupori } 39135f29427SLeandro Lupori 3928446b206SNathan Whitehorn of_bounce_virt = NULL; 3938297758aSRafal Jaworowski return (0); 3948446b206SNathan Whitehorn } 3958446b206SNathan Whitehorn 3968446b206SNathan Whitehorn /* 3978446b206SNathan Whitehorn * Generic functions 3988446b206SNathan Whitehorn */ 3998446b206SNathan Whitehorn 4008446b206SNathan Whitehorn /* Test to see if a service exists. */ 4018446b206SNathan Whitehorn static int 4028446b206SNathan Whitehorn ofw_real_test(ofw_t ofw, const char *name) 4038446b206SNathan Whitehorn { 40470d75337SNathan Whitehorn vm_offset_t argsptr; 405d4bccd63SNathan Whitehorn struct { 4068446b206SNathan Whitehorn cell_t name; 4078446b206SNathan Whitehorn cell_t nargs; 4088446b206SNathan Whitehorn cell_t nreturns; 4098446b206SNathan Whitehorn cell_t service; 4108446b206SNathan Whitehorn cell_t missing; 41170d75337SNathan Whitehorn } args; 41270d75337SNathan Whitehorn 413b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"test"); 414b49db827SBrandon Bergren args.nargs = IN(1); 415b49db827SBrandon Bergren args.nreturns = IN(1); 4168446b206SNathan Whitehorn 4178446b206SNathan Whitehorn ofw_real_start(); 4188446b206SNathan Whitehorn 419b49db827SBrandon Bergren args.service = IN(ofw_real_map(name, strlen(name) + 1)); 42070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 42170d75337SNathan Whitehorn if (args.service == 0 || openfirmware((void *)argsptr) == -1) { 4228446b206SNathan Whitehorn ofw_real_stop(); 4238446b206SNathan Whitehorn return (-1); 4248446b206SNathan Whitehorn } 42570d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 4268446b206SNathan Whitehorn ofw_real_stop(); 427b49db827SBrandon Bergren return (OUT(args.missing)); 4288446b206SNathan Whitehorn } 4298446b206SNathan Whitehorn 4308446b206SNathan Whitehorn /* 4318446b206SNathan Whitehorn * Device tree functions 4328446b206SNathan Whitehorn */ 4338446b206SNathan Whitehorn 4348446b206SNathan Whitehorn /* Return the next sibling of this node or 0. */ 4358446b206SNathan Whitehorn static phandle_t 4368446b206SNathan Whitehorn ofw_real_peer(ofw_t ofw, phandle_t node) 4378446b206SNathan Whitehorn { 43870d75337SNathan Whitehorn vm_offset_t argsptr; 439d4bccd63SNathan Whitehorn struct { 4408446b206SNathan Whitehorn cell_t name; 4418446b206SNathan Whitehorn cell_t nargs; 4428446b206SNathan Whitehorn cell_t nreturns; 4438446b206SNathan Whitehorn cell_t node; 4448446b206SNathan Whitehorn cell_t next; 44570d75337SNathan Whitehorn } args; 44670d75337SNathan Whitehorn 447b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"peer"); 448b49db827SBrandon Bergren args.nargs = IN(1); 449b49db827SBrandon Bergren args.nreturns = IN(1); 4508446b206SNathan Whitehorn 451b49db827SBrandon Bergren args.node = IN(node); 45270d75337SNathan Whitehorn ofw_real_start(); 45370d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 45470d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 45570d75337SNathan Whitehorn ofw_real_stop(); 45665184f89SNathan Whitehorn return (0); 45770d75337SNathan Whitehorn } 45870d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 45970d75337SNathan Whitehorn ofw_real_stop(); 460b49db827SBrandon Bergren return (OUT(args.next)); 4618446b206SNathan Whitehorn } 4628446b206SNathan Whitehorn 4638446b206SNathan Whitehorn /* Return the first child of this node or 0. */ 4648446b206SNathan Whitehorn static phandle_t 4658446b206SNathan Whitehorn ofw_real_child(ofw_t ofw, phandle_t node) 4668446b206SNathan Whitehorn { 46770d75337SNathan Whitehorn vm_offset_t argsptr; 468d4bccd63SNathan Whitehorn struct { 4698446b206SNathan Whitehorn cell_t name; 4708446b206SNathan Whitehorn cell_t nargs; 4718446b206SNathan Whitehorn cell_t nreturns; 4728446b206SNathan Whitehorn cell_t node; 4738446b206SNathan Whitehorn cell_t child; 47470d75337SNathan Whitehorn } args; 47570d75337SNathan Whitehorn 476b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"child"); 477b49db827SBrandon Bergren args.nargs = IN(1); 478b49db827SBrandon Bergren args.nreturns = IN(1); 4798446b206SNathan Whitehorn 480b49db827SBrandon Bergren args.node = IN(node); 48170d75337SNathan Whitehorn ofw_real_start(); 48270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 48370d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 48470d75337SNathan Whitehorn ofw_real_stop(); 48565184f89SNathan Whitehorn return (0); 48670d75337SNathan Whitehorn } 48770d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 48870d75337SNathan Whitehorn ofw_real_stop(); 489b49db827SBrandon Bergren return (OUT(args.child)); 4908446b206SNathan Whitehorn } 4918446b206SNathan Whitehorn 4928446b206SNathan Whitehorn /* Return the parent of this node or 0. */ 4938446b206SNathan Whitehorn static phandle_t 4948446b206SNathan Whitehorn ofw_real_parent(ofw_t ofw, phandle_t node) 4958446b206SNathan Whitehorn { 49670d75337SNathan Whitehorn vm_offset_t argsptr; 497d4bccd63SNathan Whitehorn struct { 4988446b206SNathan Whitehorn cell_t name; 4998446b206SNathan Whitehorn cell_t nargs; 5008446b206SNathan Whitehorn cell_t nreturns; 5018446b206SNathan Whitehorn cell_t node; 5028446b206SNathan Whitehorn cell_t parent; 50370d75337SNathan Whitehorn } args; 50470d75337SNathan Whitehorn 505b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"parent"); 506b49db827SBrandon Bergren args.nargs = IN(1); 507b49db827SBrandon Bergren args.nreturns = IN(1); 5088446b206SNathan Whitehorn 509b49db827SBrandon Bergren args.node = IN(node); 51070d75337SNathan Whitehorn ofw_real_start(); 51170d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 51270d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 51370d75337SNathan Whitehorn ofw_real_stop(); 51465184f89SNathan Whitehorn return (0); 51570d75337SNathan Whitehorn } 51670d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 51770d75337SNathan Whitehorn ofw_real_stop(); 518b49db827SBrandon Bergren return (OUT(args.parent)); 5198446b206SNathan Whitehorn } 5208446b206SNathan Whitehorn 5218446b206SNathan Whitehorn /* Return the package handle that corresponds to an instance handle. */ 5228446b206SNathan Whitehorn static phandle_t 5238446b206SNathan Whitehorn ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance) 5248446b206SNathan Whitehorn { 52570d75337SNathan Whitehorn vm_offset_t argsptr; 526d4bccd63SNathan Whitehorn struct { 5278446b206SNathan Whitehorn cell_t name; 5288446b206SNathan Whitehorn cell_t nargs; 5298446b206SNathan Whitehorn cell_t nreturns; 5308446b206SNathan Whitehorn cell_t instance; 5318446b206SNathan Whitehorn cell_t package; 53270d75337SNathan Whitehorn } args; 53370d75337SNathan Whitehorn 534b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"instance-to-package"); 535b49db827SBrandon Bergren args.nargs = IN(1); 536b49db827SBrandon Bergren args.nreturns = IN(1); 5378446b206SNathan Whitehorn 538b49db827SBrandon Bergren args.instance = IN(instance); 53970d75337SNathan Whitehorn ofw_real_start(); 54070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 54170d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 54270d75337SNathan Whitehorn ofw_real_stop(); 5438446b206SNathan Whitehorn return (-1); 54470d75337SNathan Whitehorn } 54570d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 54670d75337SNathan Whitehorn ofw_real_stop(); 547b49db827SBrandon Bergren return (OUT(args.package)); 5488446b206SNathan Whitehorn } 5498446b206SNathan Whitehorn 5508446b206SNathan Whitehorn /* Get the length of a property of a package. */ 5518446b206SNathan Whitehorn static ssize_t 5528446b206SNathan Whitehorn ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname) 5538446b206SNathan Whitehorn { 55470d75337SNathan Whitehorn vm_offset_t argsptr; 555d4bccd63SNathan Whitehorn struct { 5568446b206SNathan Whitehorn cell_t name; 5578446b206SNathan Whitehorn cell_t nargs; 5588446b206SNathan Whitehorn cell_t nreturns; 5598446b206SNathan Whitehorn cell_t package; 5608446b206SNathan Whitehorn cell_t propname; 56170d75337SNathan Whitehorn int32_t proplen; 56270d75337SNathan Whitehorn } args; 56370d75337SNathan Whitehorn 564b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"getproplen"); 565b49db827SBrandon Bergren args.nargs = IN(2); 566b49db827SBrandon Bergren args.nreturns = IN(1); 5678446b206SNathan Whitehorn 5688446b206SNathan Whitehorn ofw_real_start(); 5698446b206SNathan Whitehorn 570b49db827SBrandon Bergren args.package = IN(package); 571b49db827SBrandon Bergren args.propname = IN(ofw_real_map(propname, strlen(propname) + 1)); 57270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 57370d75337SNathan Whitehorn if (args.propname == 0 || openfirmware((void *)argsptr) == -1) { 5748446b206SNathan Whitehorn ofw_real_stop(); 5758446b206SNathan Whitehorn return (-1); 5768446b206SNathan Whitehorn } 57770d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 5788446b206SNathan Whitehorn ofw_real_stop(); 579b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.proplen)); 5808446b206SNathan Whitehorn } 5818446b206SNathan Whitehorn 5828446b206SNathan Whitehorn /* Get the value of a property of a package. */ 5838446b206SNathan Whitehorn static ssize_t 5848446b206SNathan Whitehorn ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, 5858446b206SNathan Whitehorn size_t buflen) 5868446b206SNathan Whitehorn { 58770d75337SNathan Whitehorn vm_offset_t argsptr; 588d4bccd63SNathan Whitehorn struct { 5898446b206SNathan Whitehorn cell_t name; 5908446b206SNathan Whitehorn cell_t nargs; 5918446b206SNathan Whitehorn cell_t nreturns; 5928446b206SNathan Whitehorn cell_t package; 5938446b206SNathan Whitehorn cell_t propname; 5948446b206SNathan Whitehorn cell_t buf; 5958446b206SNathan Whitehorn cell_t buflen; 59670d75337SNathan Whitehorn int32_t size; 59770d75337SNathan Whitehorn } args; 59870d75337SNathan Whitehorn 599b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"getprop"); 600b49db827SBrandon Bergren args.nargs = IN(4); 601b49db827SBrandon Bergren args.nreturns = IN(1); 6028446b206SNathan Whitehorn 6038446b206SNathan Whitehorn ofw_real_start(); 6048446b206SNathan Whitehorn 605b49db827SBrandon Bergren args.package = IN(package); 606b49db827SBrandon Bergren args.propname = IN(ofw_real_map(propname, strlen(propname) + 1)); 607b49db827SBrandon Bergren args.buf = IN(ofw_real_map(buf, buflen)); 608b49db827SBrandon Bergren args.buflen = IN(buflen); 60970d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 61070d75337SNathan Whitehorn if (args.propname == 0 || args.buf == 0 || 61170d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 6128446b206SNathan Whitehorn ofw_real_stop(); 6138446b206SNathan Whitehorn return (-1); 6148446b206SNathan Whitehorn } 61570d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 616b49db827SBrandon Bergren ofw_real_unmap(OUT(args.buf), buf, buflen); 6178446b206SNathan Whitehorn 6188446b206SNathan Whitehorn ofw_real_stop(); 619b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.size)); 6208446b206SNathan Whitehorn } 6218446b206SNathan Whitehorn 6228446b206SNathan Whitehorn /* Get the next property of a package. */ 6238446b206SNathan Whitehorn static int 6248446b206SNathan Whitehorn ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous, 6258446b206SNathan Whitehorn char *buf, size_t size) 6268446b206SNathan Whitehorn { 62770d75337SNathan Whitehorn vm_offset_t argsptr; 628d4bccd63SNathan Whitehorn struct { 6298446b206SNathan Whitehorn cell_t name; 6308446b206SNathan Whitehorn cell_t nargs; 6318446b206SNathan Whitehorn cell_t nreturns; 6328446b206SNathan Whitehorn cell_t package; 6338446b206SNathan Whitehorn cell_t previous; 6348446b206SNathan Whitehorn cell_t buf; 6358446b206SNathan Whitehorn cell_t flag; 63670d75337SNathan Whitehorn } args; 63770d75337SNathan Whitehorn 638b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"nextprop"); 639b49db827SBrandon Bergren args.nargs = IN(3); 640b49db827SBrandon Bergren args.nreturns = IN(1); 6418446b206SNathan Whitehorn 6428446b206SNathan Whitehorn ofw_real_start(); 6438446b206SNathan Whitehorn 644b49db827SBrandon Bergren args.package = IN(package); 645b49db827SBrandon Bergren args.previous = IN(ofw_real_map(previous, (previous != NULL) ? (strlen(previous) + 1) : 0)); 646b49db827SBrandon Bergren args.buf = IN(ofw_real_map(buf, size)); 64770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 648ec664c11SAndreas Tobler if (args.buf == 0 || openfirmware((void *)argsptr) == -1) { 6498446b206SNathan Whitehorn ofw_real_stop(); 6508446b206SNathan Whitehorn return (-1); 6518446b206SNathan Whitehorn } 65270d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 653b49db827SBrandon Bergren ofw_real_unmap(OUT(args.buf), buf, size); 6548446b206SNathan Whitehorn 6558446b206SNathan Whitehorn ofw_real_stop(); 656b49db827SBrandon Bergren return (OUT(args.flag)); 6578446b206SNathan Whitehorn } 6588446b206SNathan Whitehorn 6598446b206SNathan Whitehorn /* Set the value of a property of a package. */ 6608446b206SNathan Whitehorn /* XXX Has a bug on FirePower */ 6618446b206SNathan Whitehorn static int 6624fc23012SAndriy Gapon ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname, 6634fc23012SAndriy Gapon const void *buf, size_t len) 6648446b206SNathan Whitehorn { 66570d75337SNathan Whitehorn vm_offset_t argsptr; 666d4bccd63SNathan Whitehorn struct { 6678446b206SNathan Whitehorn cell_t name; 6688446b206SNathan Whitehorn cell_t nargs; 6698446b206SNathan Whitehorn cell_t nreturns; 6708446b206SNathan Whitehorn cell_t package; 6718446b206SNathan Whitehorn cell_t propname; 6728446b206SNathan Whitehorn cell_t buf; 6738446b206SNathan Whitehorn cell_t len; 6748446b206SNathan Whitehorn cell_t size; 67570d75337SNathan Whitehorn } args; 67670d75337SNathan Whitehorn 677b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"setprop"); 678b49db827SBrandon Bergren args.nargs = IN(4); 679b49db827SBrandon Bergren args.nreturns = IN(1); 6808446b206SNathan Whitehorn 6818446b206SNathan Whitehorn ofw_real_start(); 6828446b206SNathan Whitehorn 683b49db827SBrandon Bergren args.package = IN(package); 684b49db827SBrandon Bergren args.propname = IN(ofw_real_map(propname, strlen(propname) + 1)); 685b49db827SBrandon Bergren args.buf = IN(ofw_real_map(buf, len)); 686b49db827SBrandon Bergren args.len = IN(len); 68770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 68870d75337SNathan Whitehorn if (args.propname == 0 || args.buf == 0 || 68970d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 6908446b206SNathan Whitehorn ofw_real_stop(); 6918446b206SNathan Whitehorn return (-1); 6928446b206SNathan Whitehorn } 69370d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 6948446b206SNathan Whitehorn ofw_real_stop(); 695b49db827SBrandon Bergren return (OUT(args.size)); 6968446b206SNathan Whitehorn } 6978446b206SNathan Whitehorn 6988446b206SNathan Whitehorn /* Convert a device specifier to a fully qualified pathname. */ 6998446b206SNathan Whitehorn static ssize_t 7008446b206SNathan Whitehorn ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len) 7018446b206SNathan Whitehorn { 70270d75337SNathan Whitehorn vm_offset_t argsptr; 703d4bccd63SNathan Whitehorn struct { 7048446b206SNathan Whitehorn cell_t name; 7058446b206SNathan Whitehorn cell_t nargs; 7068446b206SNathan Whitehorn cell_t nreturns; 7078446b206SNathan Whitehorn cell_t device; 7088446b206SNathan Whitehorn cell_t buf; 7098446b206SNathan Whitehorn cell_t len; 71070d75337SNathan Whitehorn int32_t size; 71170d75337SNathan Whitehorn } args; 71270d75337SNathan Whitehorn 713b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"canon"); 714b49db827SBrandon Bergren args.nargs = IN(3); 715b49db827SBrandon Bergren args.nreturns = IN(1); 7168446b206SNathan Whitehorn 7178446b206SNathan Whitehorn ofw_real_start(); 7188446b206SNathan Whitehorn 719b49db827SBrandon Bergren args.device = IN(ofw_real_map(device, strlen(device) + 1)); 720b49db827SBrandon Bergren args.buf = IN(ofw_real_map(buf, len)); 721b49db827SBrandon Bergren args.len = IN(len); 72270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 72370d75337SNathan Whitehorn if (args.device == 0 || args.buf == 0 || 72470d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 7258446b206SNathan Whitehorn ofw_real_stop(); 7268446b206SNathan Whitehorn return (-1); 7278446b206SNathan Whitehorn } 72870d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 729b49db827SBrandon Bergren ofw_real_unmap(OUT(args.buf), buf, len); 7308446b206SNathan Whitehorn 7318446b206SNathan Whitehorn ofw_real_stop(); 732b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.size)); 7338446b206SNathan Whitehorn } 7348446b206SNathan Whitehorn 7358446b206SNathan Whitehorn /* Return a package handle for the specified device. */ 7368446b206SNathan Whitehorn static phandle_t 7378446b206SNathan Whitehorn ofw_real_finddevice(ofw_t ofw, const char *device) 7388446b206SNathan Whitehorn { 73970d75337SNathan Whitehorn vm_offset_t argsptr; 740d4bccd63SNathan Whitehorn struct { 7418446b206SNathan Whitehorn cell_t name; 7428446b206SNathan Whitehorn cell_t nargs; 7438446b206SNathan Whitehorn cell_t nreturns; 7448446b206SNathan Whitehorn cell_t device; 7458446b206SNathan Whitehorn cell_t package; 74670d75337SNathan Whitehorn } args; 74770d75337SNathan Whitehorn 748b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"finddevice"); 749b49db827SBrandon Bergren args.nargs = IN(1); 750b49db827SBrandon Bergren args.nreturns = IN(1); 7518446b206SNathan Whitehorn 7528446b206SNathan Whitehorn ofw_real_start(); 7538446b206SNathan Whitehorn 754b49db827SBrandon Bergren args.device = IN(ofw_real_map(device, strlen(device) + 1)); 75570d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 75670d75337SNathan Whitehorn if (args.device == 0 || 75770d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 7588446b206SNathan Whitehorn ofw_real_stop(); 7598446b206SNathan Whitehorn return (-1); 7608446b206SNathan Whitehorn } 76170d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 7628446b206SNathan Whitehorn ofw_real_stop(); 763b49db827SBrandon Bergren return (OUT(args.package)); 7648446b206SNathan Whitehorn } 7658446b206SNathan Whitehorn 7668446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to an instance. */ 7678446b206SNathan Whitehorn static ssize_t 7688446b206SNathan Whitehorn ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) 7698446b206SNathan Whitehorn { 77070d75337SNathan Whitehorn vm_offset_t argsptr; 771d4bccd63SNathan Whitehorn struct { 7728446b206SNathan Whitehorn cell_t name; 7738446b206SNathan Whitehorn cell_t nargs; 7748446b206SNathan Whitehorn cell_t nreturns; 7758446b206SNathan Whitehorn cell_t instance; 7768446b206SNathan Whitehorn cell_t buf; 7778446b206SNathan Whitehorn cell_t len; 77870d75337SNathan Whitehorn int32_t size; 77970d75337SNathan Whitehorn } args; 78070d75337SNathan Whitehorn 781b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"instance-to-path"); 782b49db827SBrandon Bergren args.nargs = IN(3); 783b49db827SBrandon Bergren args.nreturns = IN(1); 7848446b206SNathan Whitehorn 7858446b206SNathan Whitehorn ofw_real_start(); 7868446b206SNathan Whitehorn 787b49db827SBrandon Bergren args.instance = IN(instance); 788b49db827SBrandon Bergren args.buf = IN(ofw_real_map(buf, len)); 789b49db827SBrandon Bergren args.len = IN(len); 79070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 79170d75337SNathan Whitehorn if (args.buf == 0 || 79270d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 7938446b206SNathan Whitehorn ofw_real_stop(); 7948446b206SNathan Whitehorn return (-1); 7958446b206SNathan Whitehorn } 79670d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 797b49db827SBrandon Bergren ofw_real_unmap(OUT(args.buf), buf, len); 7988446b206SNathan Whitehorn 7998446b206SNathan Whitehorn ofw_real_stop(); 800b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.size)); 8018446b206SNathan Whitehorn } 8028446b206SNathan Whitehorn 8038446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to a package. */ 8048446b206SNathan Whitehorn static ssize_t 8058446b206SNathan Whitehorn ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len) 8068446b206SNathan Whitehorn { 80770d75337SNathan Whitehorn vm_offset_t argsptr; 808d4bccd63SNathan Whitehorn struct { 8098446b206SNathan Whitehorn cell_t name; 8108446b206SNathan Whitehorn cell_t nargs; 8118446b206SNathan Whitehorn cell_t nreturns; 8128446b206SNathan Whitehorn cell_t package; 8138446b206SNathan Whitehorn cell_t buf; 8148446b206SNathan Whitehorn cell_t len; 81570d75337SNathan Whitehorn int32_t size; 81670d75337SNathan Whitehorn } args; 81770d75337SNathan Whitehorn 818b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"package-to-path"); 819b49db827SBrandon Bergren args.nargs = IN(3); 820b49db827SBrandon Bergren args.nreturns = IN(1); 8218446b206SNathan Whitehorn 8228446b206SNathan Whitehorn ofw_real_start(); 8238446b206SNathan Whitehorn 824b49db827SBrandon Bergren args.package = IN(package); 825b49db827SBrandon Bergren args.buf = IN(ofw_real_map(buf, len)); 826b49db827SBrandon Bergren args.len = IN(len); 82770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 82870d75337SNathan Whitehorn if (args.buf == 0 || 82970d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 8308446b206SNathan Whitehorn ofw_real_stop(); 8318446b206SNathan Whitehorn return (-1); 8328446b206SNathan Whitehorn } 83370d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 834b49db827SBrandon Bergren ofw_real_unmap(OUT(args.buf), buf, len); 8358446b206SNathan Whitehorn 8368446b206SNathan Whitehorn ofw_real_stop(); 837b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.size)); 8388446b206SNathan Whitehorn } 8398446b206SNathan Whitehorn 8408446b206SNathan Whitehorn /* Call the method in the scope of a given instance. */ 8418446b206SNathan Whitehorn static int 8428446b206SNathan Whitehorn ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, 843054e5dcbSNathan Whitehorn int nargs, int nreturns, cell_t *args_and_returns) 8448446b206SNathan Whitehorn { 84570d75337SNathan Whitehorn vm_offset_t argsptr; 846d4bccd63SNathan Whitehorn struct { 8478446b206SNathan Whitehorn cell_t name; 8488446b206SNathan Whitehorn cell_t nargs; 8498446b206SNathan Whitehorn cell_t nreturns; 8508446b206SNathan Whitehorn cell_t method; 8518446b206SNathan Whitehorn cell_t instance; 8528446b206SNathan Whitehorn cell_t args_n_results[12]; 85370d75337SNathan Whitehorn } args; 854cdb25d82SMarius Strobl cell_t *ap, *cp; 8558446b206SNathan Whitehorn int n; 8568446b206SNathan Whitehorn 857b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"call-method"); 858b49db827SBrandon Bergren args.nargs = IN(2); 859b49db827SBrandon Bergren args.nreturns = IN(1); 86070d75337SNathan Whitehorn 8618446b206SNathan Whitehorn if (nargs > 6) 8628446b206SNathan Whitehorn return (-1); 8638446b206SNathan Whitehorn 8648446b206SNathan Whitehorn ofw_real_start(); 865b49db827SBrandon Bergren args.nargs = IN(nargs + 2); 866b49db827SBrandon Bergren args.nreturns = IN(nreturns + 1); 867b49db827SBrandon Bergren args.method = IN(ofw_real_map(method, strlen(method) + 1)); 868b49db827SBrandon Bergren args.instance = IN(instance); 8698446b206SNathan Whitehorn 8708446b206SNathan Whitehorn ap = args_and_returns; 8718446b206SNathan Whitehorn for (cp = args.args_n_results + (n = nargs); --n >= 0;) 872b49db827SBrandon Bergren *--cp = IN(*(ap++)); 87370d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 87470d75337SNathan Whitehorn if (args.method == 0 || 87570d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 8768446b206SNathan Whitehorn ofw_real_stop(); 8778446b206SNathan Whitehorn return (-1); 8788446b206SNathan Whitehorn } 87970d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 8808446b206SNathan Whitehorn ofw_real_stop(); 881b49db827SBrandon Bergren if (OUT(args.args_n_results[nargs])) 882b49db827SBrandon Bergren return (OUT(args.args_n_results[nargs])); 883b49db827SBrandon Bergren for (cp = args.args_n_results + nargs + (n = OUT(args.nreturns)); --n > 0;) 884b49db827SBrandon Bergren *(ap++) = OUT(*--cp); 8858446b206SNathan Whitehorn return (0); 8868446b206SNathan Whitehorn } 8878446b206SNathan Whitehorn 88870d75337SNathan Whitehorn static int 889cdb25d82SMarius Strobl ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns) 89070d75337SNathan Whitehorn { 89170d75337SNathan Whitehorn vm_offset_t argsptr; 89270d75337SNathan Whitehorn struct { 89370d75337SNathan Whitehorn cell_t name; 89470d75337SNathan Whitehorn cell_t nargs; 89570d75337SNathan Whitehorn cell_t nreturns; 89670d75337SNathan Whitehorn cell_t slot[16]; 89770d75337SNathan Whitehorn } args; 89870d75337SNathan Whitehorn cell_t status; 89970d75337SNathan Whitehorn int i = 0, j = 0; 90070d75337SNathan Whitehorn 901b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"interpret"); 902b49db827SBrandon Bergren args.nargs = IN(1); 90370d75337SNathan Whitehorn 90470d75337SNathan Whitehorn ofw_real_start(); 905b49db827SBrandon Bergren args.nreturns = IN(++nreturns); 906b49db827SBrandon Bergren args.slot[i++] = IN(ofw_real_map(cmd, strlen(cmd) + 1)); 90770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 90870d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 90970d75337SNathan Whitehorn ofw_real_stop(); 91070d75337SNathan Whitehorn return (-1); 91170d75337SNathan Whitehorn } 91270d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 91370d75337SNathan Whitehorn ofw_real_stop(); 914b49db827SBrandon Bergren status = OUT(args.slot[i++]); 91570d75337SNathan Whitehorn while (i < 1 + nreturns) 916b49db827SBrandon Bergren returns[j++] = OUT(args.slot[i++]); 91770d75337SNathan Whitehorn return (status); 91870d75337SNathan Whitehorn } 91970d75337SNathan Whitehorn 9208446b206SNathan Whitehorn /* 9218446b206SNathan Whitehorn * Device I/O functions 9228446b206SNathan Whitehorn */ 9238446b206SNathan Whitehorn 9248446b206SNathan Whitehorn /* Open an instance for a device. */ 9258446b206SNathan Whitehorn static ihandle_t 9268446b206SNathan Whitehorn ofw_real_open(ofw_t ofw, const char *device) 9278446b206SNathan Whitehorn { 92870d75337SNathan Whitehorn vm_offset_t argsptr; 929d4bccd63SNathan Whitehorn struct { 9308446b206SNathan Whitehorn cell_t name; 9318446b206SNathan Whitehorn cell_t nargs; 9328446b206SNathan Whitehorn cell_t nreturns; 9338446b206SNathan Whitehorn cell_t device; 9348446b206SNathan Whitehorn cell_t instance; 93570d75337SNathan Whitehorn } args; 93670d75337SNathan Whitehorn 937b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"open"); 938b49db827SBrandon Bergren args.nargs = IN(1); 939b49db827SBrandon Bergren args.nreturns = IN(1); 9408446b206SNathan Whitehorn 9418446b206SNathan Whitehorn ofw_real_start(); 9428446b206SNathan Whitehorn 943b49db827SBrandon Bergren args.device = IN(ofw_real_map(device, strlen(device) + 1)); 94470d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 94570d75337SNathan Whitehorn if (args.device == 0 || openfirmware((void *)argsptr) == -1 9468446b206SNathan Whitehorn || args.instance == 0) { 9478446b206SNathan Whitehorn ofw_real_stop(); 9488446b206SNathan Whitehorn return (-1); 9498446b206SNathan Whitehorn } 95070d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 9518446b206SNathan Whitehorn ofw_real_stop(); 952b49db827SBrandon Bergren return (OUT(args.instance)); 9538446b206SNathan Whitehorn } 9548446b206SNathan Whitehorn 9558446b206SNathan Whitehorn /* Close an instance. */ 9568446b206SNathan Whitehorn static void 9578446b206SNathan Whitehorn ofw_real_close(ofw_t ofw, ihandle_t instance) 9588446b206SNathan Whitehorn { 95970d75337SNathan Whitehorn vm_offset_t argsptr; 960d4bccd63SNathan Whitehorn struct { 9618446b206SNathan Whitehorn cell_t name; 9628446b206SNathan Whitehorn cell_t nargs; 9638446b206SNathan Whitehorn cell_t nreturns; 9648446b206SNathan Whitehorn cell_t instance; 96570d75337SNathan Whitehorn } args; 9668446b206SNathan Whitehorn 967b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"close"); 968b49db827SBrandon Bergren args.nargs = IN(1); 969b49db827SBrandon Bergren args.nreturns = IN(0); 970b49db827SBrandon Bergren args.instance = IN(instance); 97170d75337SNathan Whitehorn ofw_real_start(); 97270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 97370d75337SNathan Whitehorn openfirmware((void *)argsptr); 97470d75337SNathan Whitehorn ofw_real_stop(); 9758446b206SNathan Whitehorn } 9768446b206SNathan Whitehorn 9778446b206SNathan Whitehorn /* Read from an instance. */ 9788446b206SNathan Whitehorn static ssize_t 9798446b206SNathan Whitehorn ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) 9808446b206SNathan Whitehorn { 98170d75337SNathan Whitehorn vm_offset_t argsptr; 982d4bccd63SNathan Whitehorn struct { 9838446b206SNathan Whitehorn cell_t name; 9848446b206SNathan Whitehorn cell_t nargs; 9858446b206SNathan Whitehorn cell_t nreturns; 9868446b206SNathan Whitehorn cell_t instance; 9878446b206SNathan Whitehorn cell_t addr; 9888446b206SNathan Whitehorn cell_t len; 98970d75337SNathan Whitehorn int32_t actual; 99070d75337SNathan Whitehorn } args; 99170d75337SNathan Whitehorn 992b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"read"); 993b49db827SBrandon Bergren args.nargs = IN(3); 994b49db827SBrandon Bergren args.nreturns = IN(1); 9958446b206SNathan Whitehorn 9968446b206SNathan Whitehorn ofw_real_start(); 9978446b206SNathan Whitehorn 998b49db827SBrandon Bergren args.instance = IN(instance); 999b49db827SBrandon Bergren args.addr = IN(ofw_real_map(addr, len)); 1000b49db827SBrandon Bergren args.len = IN(len); 100170d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 100270d75337SNathan Whitehorn if (args.addr == 0 || openfirmware((void *)argsptr) == -1) { 10038446b206SNathan Whitehorn ofw_real_stop(); 10048446b206SNathan Whitehorn return (-1); 10058446b206SNathan Whitehorn } 100670d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 1007b49db827SBrandon Bergren ofw_real_unmap(OUT(args.addr), addr, len); 10088446b206SNathan Whitehorn 10098446b206SNathan Whitehorn ofw_real_stop(); 1010b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.actual)); 10118446b206SNathan Whitehorn } 10128446b206SNathan Whitehorn 10138446b206SNathan Whitehorn /* Write to an instance. */ 10148446b206SNathan Whitehorn static ssize_t 10158446b206SNathan Whitehorn ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) 10168446b206SNathan Whitehorn { 101770d75337SNathan Whitehorn vm_offset_t argsptr; 1018d4bccd63SNathan Whitehorn struct { 10198446b206SNathan Whitehorn cell_t name; 10208446b206SNathan Whitehorn cell_t nargs; 10218446b206SNathan Whitehorn cell_t nreturns; 10228446b206SNathan Whitehorn cell_t instance; 10238446b206SNathan Whitehorn cell_t addr; 10248446b206SNathan Whitehorn cell_t len; 102570d75337SNathan Whitehorn int32_t actual; 102670d75337SNathan Whitehorn } args; 102770d75337SNathan Whitehorn 1028b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"write"); 1029b49db827SBrandon Bergren args.nargs = IN(3); 1030b49db827SBrandon Bergren args.nreturns = IN(1); 10318446b206SNathan Whitehorn 10328446b206SNathan Whitehorn ofw_real_start(); 10338446b206SNathan Whitehorn 1034b49db827SBrandon Bergren args.instance = IN(instance); 1035b49db827SBrandon Bergren args.addr = IN(ofw_real_map(addr, len)); 1036b49db827SBrandon Bergren args.len = IN(len); 103770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 103870d75337SNathan Whitehorn if (args.addr == 0 || openfirmware((void *)argsptr) == -1) { 10398446b206SNathan Whitehorn ofw_real_stop(); 10408446b206SNathan Whitehorn return (-1); 10418446b206SNathan Whitehorn } 104270d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 10438446b206SNathan Whitehorn ofw_real_stop(); 1044b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.actual)); 10458446b206SNathan Whitehorn } 10468446b206SNathan Whitehorn 10478446b206SNathan Whitehorn /* Seek to a position. */ 10488446b206SNathan Whitehorn static int 10498446b206SNathan Whitehorn ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos) 10508446b206SNathan Whitehorn { 105170d75337SNathan Whitehorn vm_offset_t argsptr; 1052d4bccd63SNathan Whitehorn struct { 10538446b206SNathan Whitehorn cell_t name; 10548446b206SNathan Whitehorn cell_t nargs; 10558446b206SNathan Whitehorn cell_t nreturns; 10568446b206SNathan Whitehorn cell_t instance; 10578446b206SNathan Whitehorn cell_t poshi; 10588446b206SNathan Whitehorn cell_t poslo; 10598446b206SNathan Whitehorn cell_t status; 106070d75337SNathan Whitehorn } args; 106170d75337SNathan Whitehorn 1062b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"seek"); 1063b49db827SBrandon Bergren args.nargs = IN(3); 1064b49db827SBrandon Bergren args.nreturns = IN(1); 10658446b206SNathan Whitehorn 1066b49db827SBrandon Bergren args.instance = IN(instance); 1067b49db827SBrandon Bergren args.poshi = IN(pos >> 32); 1068b49db827SBrandon Bergren args.poslo = IN(pos); 106970d75337SNathan Whitehorn ofw_real_start(); 107070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 107170d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 107270d75337SNathan Whitehorn ofw_real_stop(); 10738446b206SNathan Whitehorn return (-1); 107470d75337SNathan Whitehorn } 107570d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 107670d75337SNathan Whitehorn ofw_real_stop(); 1077b49db827SBrandon Bergren return (OUT(args.status)); 10788446b206SNathan Whitehorn } 10798446b206SNathan Whitehorn 10808446b206SNathan Whitehorn /* 10818446b206SNathan Whitehorn * Memory functions 10828446b206SNathan Whitehorn */ 10838446b206SNathan Whitehorn 10848446b206SNathan Whitehorn /* Claim an area of memory. */ 10858446b206SNathan Whitehorn static caddr_t 10868446b206SNathan Whitehorn ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align) 10878446b206SNathan Whitehorn { 108870d75337SNathan Whitehorn vm_offset_t argsptr; 1089d4bccd63SNathan Whitehorn struct { 10908446b206SNathan Whitehorn cell_t name; 10918446b206SNathan Whitehorn cell_t nargs; 10928446b206SNathan Whitehorn cell_t nreturns; 10938446b206SNathan Whitehorn cell_t virt; 10948446b206SNathan Whitehorn cell_t size; 10958446b206SNathan Whitehorn cell_t align; 10968446b206SNathan Whitehorn cell_t baseaddr; 109770d75337SNathan Whitehorn } args; 10988446b206SNathan Whitehorn 1099b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"claim"); 1100b49db827SBrandon Bergren args.nargs = IN(3); 1101b49db827SBrandon Bergren args.nreturns = IN(1); 110270d75337SNathan Whitehorn 1103b49db827SBrandon Bergren args.virt = IN((cell_t)(uintptr_t)virt); 1104b49db827SBrandon Bergren args.size = IN(size); 1105b49db827SBrandon Bergren args.align = IN(align); 110670d75337SNathan Whitehorn ofw_real_start(); 110770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 110870d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 110970d75337SNathan Whitehorn ofw_real_stop(); 11108446b206SNathan Whitehorn return ((void *)-1); 111170d75337SNathan Whitehorn } 111270d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 111370d75337SNathan Whitehorn ofw_real_stop(); 1114b49db827SBrandon Bergren return ((void *)(uintptr_t)(OUT(args.baseaddr))); 11158446b206SNathan Whitehorn } 11168446b206SNathan Whitehorn 11178446b206SNathan Whitehorn /* Release an area of memory. */ 11188446b206SNathan Whitehorn static void 11198446b206SNathan Whitehorn ofw_real_release(ofw_t ofw, void *virt, size_t size) 11208446b206SNathan Whitehorn { 112170d75337SNathan Whitehorn vm_offset_t argsptr; 1122d4bccd63SNathan Whitehorn struct { 11238446b206SNathan Whitehorn cell_t name; 11248446b206SNathan Whitehorn cell_t nargs; 11258446b206SNathan Whitehorn cell_t nreturns; 11268446b206SNathan Whitehorn cell_t virt; 11278446b206SNathan Whitehorn cell_t size; 112870d75337SNathan Whitehorn } args; 11298446b206SNathan Whitehorn 1130b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"release"); 1131b49db827SBrandon Bergren args.nargs = IN(2); 1132b49db827SBrandon Bergren args.nreturns = IN(0); 113370d75337SNathan Whitehorn 1134b49db827SBrandon Bergren args.virt = IN((cell_t)(uintptr_t)virt); 1135b49db827SBrandon Bergren args.size = IN(size); 113670d75337SNathan Whitehorn ofw_real_start(); 113770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 113870d75337SNathan Whitehorn openfirmware((void *)argsptr); 113970d75337SNathan Whitehorn ofw_real_stop(); 11408446b206SNathan Whitehorn } 11418446b206SNathan Whitehorn 11428446b206SNathan Whitehorn /* 11438446b206SNathan Whitehorn * Control transfer functions 11448446b206SNathan Whitehorn */ 11458446b206SNathan Whitehorn 11468446b206SNathan Whitehorn /* Suspend and drop back to the Open Firmware interface. */ 11478446b206SNathan Whitehorn static void 11488446b206SNathan Whitehorn ofw_real_enter(ofw_t ofw) 11498446b206SNathan Whitehorn { 115070d75337SNathan Whitehorn vm_offset_t argsptr; 1151d4bccd63SNathan Whitehorn struct { 11528446b206SNathan Whitehorn cell_t name; 11538446b206SNathan Whitehorn cell_t nargs; 11548446b206SNathan Whitehorn cell_t nreturns; 115570d75337SNathan Whitehorn } args; 11568446b206SNathan Whitehorn 1157b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"enter"); 1158b49db827SBrandon Bergren args.nargs = IN(0); 1159b49db827SBrandon Bergren args.nreturns = IN(0); 116070d75337SNathan Whitehorn 116170d75337SNathan Whitehorn ofw_real_start(); 116270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 116370d75337SNathan Whitehorn openfirmware((void *)argsptr); 11648446b206SNathan Whitehorn /* We may come back. */ 116570d75337SNathan Whitehorn ofw_real_stop(); 11668446b206SNathan Whitehorn } 11678446b206SNathan Whitehorn 11688446b206SNathan Whitehorn /* Shut down and drop back to the Open Firmware interface. */ 11698446b206SNathan Whitehorn static void 11708446b206SNathan Whitehorn ofw_real_exit(ofw_t ofw) 11718446b206SNathan Whitehorn { 117270d75337SNathan Whitehorn vm_offset_t argsptr; 1173d4bccd63SNathan Whitehorn struct { 11748446b206SNathan Whitehorn cell_t name; 11758446b206SNathan Whitehorn cell_t nargs; 11768446b206SNathan Whitehorn cell_t nreturns; 117770d75337SNathan Whitehorn } args; 11788446b206SNathan Whitehorn 1179b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"exit"); 1180b49db827SBrandon Bergren args.nargs = IN(0); 1181b49db827SBrandon Bergren args.nreturns = IN(0); 118270d75337SNathan Whitehorn 118370d75337SNathan Whitehorn ofw_real_start(); 118470d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 118570d75337SNathan Whitehorn openfirmware((void *)argsptr); 11868446b206SNathan Whitehorn for (;;) /* just in case */ 11878446b206SNathan Whitehorn ; 118870d75337SNathan Whitehorn ofw_real_stop(); 11898446b206SNathan Whitehorn } 1190