18446b206SNathan Whitehorn /* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */ 28446b206SNathan Whitehorn 38446b206SNathan Whitehorn /*- 48446b206SNathan Whitehorn * Copyright (C) 1995, 1996 Wolfgang Solfrank. 58446b206SNathan Whitehorn * Copyright (C) 1995, 1996 TooLs GmbH. 68446b206SNathan Whitehorn * All rights reserved. 78446b206SNathan Whitehorn * 88446b206SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 98446b206SNathan Whitehorn * modification, are permitted provided that the following conditions 108446b206SNathan Whitehorn * are met: 118446b206SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 128446b206SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 138446b206SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 148446b206SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 158446b206SNathan Whitehorn * documentation and/or other materials provided with the distribution. 168446b206SNathan Whitehorn * 3. All advertising materials mentioning features or use of this software 178446b206SNathan Whitehorn * must display the following acknowledgement: 188446b206SNathan Whitehorn * This product includes software developed by TooLs GmbH. 198446b206SNathan Whitehorn * 4. The name of TooLs GmbH may not be used to endorse or promote products 208446b206SNathan Whitehorn * derived from this software without specific prior written permission. 218446b206SNathan Whitehorn * 228446b206SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 238446b206SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 248446b206SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 258446b206SNathan Whitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 268446b206SNathan Whitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 278446b206SNathan Whitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 288446b206SNathan Whitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 298446b206SNathan Whitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 308446b206SNathan Whitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 318446b206SNathan Whitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 328446b206SNathan Whitehorn */ 338446b206SNathan Whitehorn /*- 348446b206SNathan Whitehorn * Copyright (C) 2000 Benno Rice. 358446b206SNathan Whitehorn * All rights reserved. 368446b206SNathan Whitehorn * 378446b206SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 388446b206SNathan Whitehorn * modification, are permitted provided that the following conditions 398446b206SNathan Whitehorn * are met: 408446b206SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 418446b206SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 428446b206SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 438446b206SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 448446b206SNathan Whitehorn * documentation and/or other materials provided with the distribution. 458446b206SNathan Whitehorn * 468446b206SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 478446b206SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 488446b206SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 498446b206SNathan Whitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 508446b206SNathan Whitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 518446b206SNathan Whitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 528446b206SNathan Whitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 538446b206SNathan Whitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 548446b206SNathan Whitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 558446b206SNathan Whitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 568446b206SNathan Whitehorn */ 578446b206SNathan Whitehorn 588446b206SNathan Whitehorn #include <sys/cdefs.h> 598446b206SNathan Whitehorn __FBSDID("$FreeBSD$"); 608446b206SNathan Whitehorn 618446b206SNathan Whitehorn #include <sys/param.h> 628446b206SNathan Whitehorn #include <sys/kernel.h> 638446b206SNathan Whitehorn #include <sys/lock.h> 648446b206SNathan Whitehorn #include <sys/mutex.h> 658446b206SNathan Whitehorn #include <sys/systm.h> 668446b206SNathan Whitehorn 678446b206SNathan Whitehorn #include <vm/vm.h> 6870d75337SNathan Whitehorn #include <vm/vm_page.h> 698446b206SNathan Whitehorn #include <vm/pmap.h> 708446b206SNathan Whitehorn 718446b206SNathan Whitehorn #include <machine/bus.h> 7270d75337SNathan Whitehorn #include <machine/md_var.h> 738446b206SNathan Whitehorn #include <machine/ofw_machdep.h> 7470d75337SNathan Whitehorn #include <machine/pmap.h> 7570d75337SNathan Whitehorn #include <machine/stdarg.h> 768446b206SNathan Whitehorn 778446b206SNathan Whitehorn #include <dev/ofw/openfirm.h> 788446b206SNathan Whitehorn #include <dev/ofw/ofwvar.h> 798446b206SNathan Whitehorn #include "ofw_if.h" 808446b206SNathan Whitehorn 818297758aSRafal Jaworowski static int ofw_real_init(ofw_t, void *openfirm); 828446b206SNathan Whitehorn static int ofw_real_test(ofw_t, const char *name); 838446b206SNathan Whitehorn static phandle_t ofw_real_peer(ofw_t, phandle_t node); 848446b206SNathan Whitehorn static phandle_t ofw_real_child(ofw_t, phandle_t node); 858446b206SNathan Whitehorn static phandle_t ofw_real_parent(ofw_t, phandle_t node); 868446b206SNathan Whitehorn static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance); 878446b206SNathan Whitehorn static ssize_t ofw_real_getproplen(ofw_t, phandle_t package, 888446b206SNathan Whitehorn const char *propname); 898446b206SNathan Whitehorn static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname, 908446b206SNathan Whitehorn void *buf, size_t buflen); 918446b206SNathan Whitehorn static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous, 928446b206SNathan Whitehorn char *buf, size_t); 934fc23012SAndriy Gapon static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname, 944fc23012SAndriy Gapon const void *buf, size_t len); 958446b206SNathan Whitehorn static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len); 968446b206SNathan Whitehorn static phandle_t ofw_real_finddevice(ofw_t, const char *device); 978446b206SNathan Whitehorn static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf, 988446b206SNathan Whitehorn size_t len); 998446b206SNathan Whitehorn static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf, 1008446b206SNathan Whitehorn size_t len); 1018446b206SNathan Whitehorn static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method, 102054e5dcbSNathan Whitehorn int nargs, int nreturns, cell_t *args_and_returns); 10370d75337SNathan Whitehorn static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, 104*cdb25d82SMarius Strobl cell_t *returns); 1058446b206SNathan Whitehorn static ihandle_t ofw_real_open(ofw_t, const char *device); 1068446b206SNathan Whitehorn static void ofw_real_close(ofw_t, ihandle_t instance); 1078446b206SNathan Whitehorn static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len); 1088446b206SNathan Whitehorn static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr, 1098446b206SNathan Whitehorn size_t len); 1108446b206SNathan Whitehorn static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos); 1118446b206SNathan Whitehorn static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align); 1128446b206SNathan Whitehorn static void ofw_real_release(ofw_t, void *virt, size_t size); 1138446b206SNathan Whitehorn static void ofw_real_enter(ofw_t); 1148446b206SNathan Whitehorn static void ofw_real_exit(ofw_t); 1158446b206SNathan Whitehorn 1168446b206SNathan Whitehorn static ofw_method_t ofw_real_methods[] = { 1178446b206SNathan Whitehorn OFWMETHOD(ofw_init, ofw_real_init), 1188446b206SNathan Whitehorn OFWMETHOD(ofw_peer, ofw_real_peer), 1198446b206SNathan Whitehorn OFWMETHOD(ofw_child, ofw_real_child), 1208446b206SNathan Whitehorn OFWMETHOD(ofw_parent, ofw_real_parent), 1218446b206SNathan Whitehorn OFWMETHOD(ofw_instance_to_package, ofw_real_instance_to_package), 1228446b206SNathan Whitehorn OFWMETHOD(ofw_getproplen, ofw_real_getproplen), 1238446b206SNathan Whitehorn OFWMETHOD(ofw_getprop, ofw_real_getprop), 1248446b206SNathan Whitehorn OFWMETHOD(ofw_nextprop, ofw_real_nextprop), 1258446b206SNathan Whitehorn OFWMETHOD(ofw_setprop, ofw_real_setprop), 1268446b206SNathan Whitehorn OFWMETHOD(ofw_canon, ofw_real_canon), 1278446b206SNathan Whitehorn OFWMETHOD(ofw_finddevice, ofw_real_finddevice), 1288446b206SNathan Whitehorn OFWMETHOD(ofw_instance_to_path, ofw_real_instance_to_path), 1298446b206SNathan Whitehorn OFWMETHOD(ofw_package_to_path, ofw_real_package_to_path), 1308446b206SNathan Whitehorn 1318446b206SNathan Whitehorn OFWMETHOD(ofw_test, ofw_real_test), 1328446b206SNathan Whitehorn OFWMETHOD(ofw_call_method, ofw_real_call_method), 13370d75337SNathan Whitehorn OFWMETHOD(ofw_interpret, ofw_real_interpret), 1348446b206SNathan Whitehorn OFWMETHOD(ofw_open, ofw_real_open), 1358446b206SNathan Whitehorn OFWMETHOD(ofw_close, ofw_real_close), 1368446b206SNathan Whitehorn OFWMETHOD(ofw_read, ofw_real_read), 1378446b206SNathan Whitehorn OFWMETHOD(ofw_write, ofw_real_write), 1388446b206SNathan Whitehorn OFWMETHOD(ofw_seek, ofw_real_seek), 1398446b206SNathan Whitehorn OFWMETHOD(ofw_claim, ofw_real_claim), 1408446b206SNathan Whitehorn OFWMETHOD(ofw_release, ofw_real_release), 1418446b206SNathan Whitehorn OFWMETHOD(ofw_enter, ofw_real_enter), 1428446b206SNathan Whitehorn OFWMETHOD(ofw_exit, ofw_real_exit), 1438446b206SNathan Whitehorn 1448446b206SNathan Whitehorn { 0, 0 } 1458446b206SNathan Whitehorn }; 1468446b206SNathan Whitehorn 1478446b206SNathan Whitehorn static ofw_def_t ofw_real = { 1488446b206SNathan Whitehorn OFW_STD_REAL, 1498446b206SNathan Whitehorn ofw_real_methods, 1508446b206SNathan Whitehorn 0 1518446b206SNathan Whitehorn }; 1528446b206SNathan Whitehorn OFW_DEF(ofw_real); 1538446b206SNathan Whitehorn 15470d75337SNathan Whitehorn static ofw_def_t ofw_32bit = { 15570d75337SNathan Whitehorn OFW_STD_32BIT, 15670d75337SNathan Whitehorn ofw_real_methods, 15770d75337SNathan Whitehorn 0 15870d75337SNathan Whitehorn }; 15970d75337SNathan Whitehorn OFW_DEF(ofw_32bit); 16070d75337SNathan Whitehorn 1618446b206SNathan Whitehorn MALLOC_DEFINE(M_OFWREAL, "ofwreal", "Open Firmware Real Mode Bounce Page"); 1628446b206SNathan Whitehorn 1638446b206SNathan Whitehorn static int (*openfirmware)(void *); 1648446b206SNathan Whitehorn 1658446b206SNathan Whitehorn static vm_offset_t of_bounce_phys; 1668446b206SNathan Whitehorn static caddr_t of_bounce_virt; 1678446b206SNathan Whitehorn static off_t of_bounce_offset; 1688446b206SNathan Whitehorn static size_t of_bounce_size; 1698446b206SNathan Whitehorn static struct mtx of_bounce_mtx; 1708446b206SNathan Whitehorn 17170d75337SNathan Whitehorn extern int ofw_real_mode; 17270d75337SNathan Whitehorn extern struct pmap ofw_pmap; 17370d75337SNathan Whitehorn 1748446b206SNathan Whitehorn /* 1758446b206SNathan Whitehorn * After the VM is up, allocate a wired, low memory bounce page. 1768446b206SNathan Whitehorn */ 1778446b206SNathan Whitehorn 1788446b206SNathan Whitehorn static void ofw_real_bounce_alloc(void *); 1798446b206SNathan Whitehorn 18070d75337SNathan Whitehorn SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY, 1818446b206SNathan Whitehorn ofw_real_bounce_alloc, NULL); 1828446b206SNathan Whitehorn 1838446b206SNathan Whitehorn static void 1848446b206SNathan Whitehorn ofw_real_start(void) 1858446b206SNathan Whitehorn { 1868446b206SNathan Whitehorn mtx_lock(&of_bounce_mtx); 1878446b206SNathan Whitehorn of_bounce_offset = 0; 1888446b206SNathan Whitehorn } 1898446b206SNathan Whitehorn 1908446b206SNathan Whitehorn static void 1918446b206SNathan Whitehorn ofw_real_stop(void) 1928446b206SNathan Whitehorn { 1938446b206SNathan Whitehorn mtx_unlock(&of_bounce_mtx); 1948446b206SNathan Whitehorn } 1958446b206SNathan Whitehorn 1968446b206SNathan Whitehorn static void 1978446b206SNathan Whitehorn ofw_real_bounce_alloc(void *junk) 1988446b206SNathan Whitehorn { 1998446b206SNathan Whitehorn /* 2008446b206SNathan Whitehorn * Check that ofw_real is actually in use before allocating wads 2018446b206SNathan Whitehorn * of memory. Do this by checking if our mutex has been set up. 2028446b206SNathan Whitehorn */ 2038446b206SNathan Whitehorn if (!mtx_initialized(&of_bounce_mtx)) 2048446b206SNathan Whitehorn return; 2058446b206SNathan Whitehorn 2068446b206SNathan Whitehorn /* 2078446b206SNathan Whitehorn * Allocate a page of contiguous, wired physical memory that can 2088446b206SNathan Whitehorn * fit into a 32-bit address space. 2098446b206SNathan Whitehorn */ 2108446b206SNathan Whitehorn 2118446b206SNathan Whitehorn mtx_lock(&of_bounce_mtx); 2128446b206SNathan Whitehorn 2138446b206SNathan Whitehorn of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0, 2148446b206SNathan Whitehorn 0, BUS_SPACE_MAXADDR_32BIT, PAGE_SIZE, PAGE_SIZE); 21570d75337SNathan Whitehorn 2168446b206SNathan Whitehorn of_bounce_phys = vtophys(of_bounce_virt); 2178446b206SNathan Whitehorn of_bounce_size = PAGE_SIZE; 2188446b206SNathan Whitehorn 21970d75337SNathan Whitehorn /* 22070d75337SNathan Whitehorn * For virtual-mode OF, direct map this physical address so that 22170d75337SNathan Whitehorn * we have a 32-bit virtual address to give OF. 22270d75337SNathan Whitehorn */ 22370d75337SNathan Whitehorn 22470d75337SNathan Whitehorn if (!ofw_real_mode && !hw_direct_map) 22570d75337SNathan Whitehorn pmap_kenter(of_bounce_phys, of_bounce_phys); 22670d75337SNathan Whitehorn 2278446b206SNathan Whitehorn mtx_unlock(&of_bounce_mtx); 2288446b206SNathan Whitehorn } 2298446b206SNathan Whitehorn 2308446b206SNathan Whitehorn static cell_t 2318446b206SNathan Whitehorn ofw_real_map(const void *buf, size_t len) 2328446b206SNathan Whitehorn { 23370d75337SNathan Whitehorn static char emergency_buffer[255]; 2348446b206SNathan Whitehorn cell_t phys; 2358446b206SNathan Whitehorn 2368446b206SNathan Whitehorn mtx_assert(&of_bounce_mtx, MA_OWNED); 2378446b206SNathan Whitehorn 2388446b206SNathan Whitehorn if (of_bounce_virt == NULL) { 23970d75337SNathan Whitehorn /* 24070d75337SNathan Whitehorn * If we haven't set up the MMU, then buf is guaranteed 24170d75337SNathan Whitehorn * to be accessible to OF, because the only memory we 24270d75337SNathan Whitehorn * can use right now is memory mapped by firmware. 24370d75337SNathan Whitehorn */ 2448446b206SNathan Whitehorn if (!pmap_bootstrapped) 24570d75337SNathan Whitehorn return (cell_t)(uintptr_t)buf; 2468446b206SNathan Whitehorn 2478446b206SNathan Whitehorn /* 2488446b206SNathan Whitehorn * XXX: It is possible for us to get called before the VM has 2498446b206SNathan Whitehorn * come online, but after the MMU is up. We don't have the 2508446b206SNathan Whitehorn * bounce buffer yet, but can no longer presume a 1:1 mapping. 25170d75337SNathan Whitehorn * Copy into the emergency buffer, and reset at the end. 2528446b206SNathan Whitehorn */ 25370d75337SNathan Whitehorn of_bounce_virt = emergency_buffer; 25470d75337SNathan Whitehorn of_bounce_phys = (vm_offset_t)of_bounce_virt; 25570d75337SNathan Whitehorn of_bounce_size = sizeof(emergency_buffer); 2568446b206SNathan Whitehorn } 2578446b206SNathan Whitehorn 2588446b206SNathan Whitehorn /* 2598446b206SNathan Whitehorn * Make sure the bounce page offset satisfies any reasonable 2608446b206SNathan Whitehorn * alignment constraint. 2618446b206SNathan Whitehorn */ 26270d75337SNathan Whitehorn of_bounce_offset += sizeof(register_t) - (of_bounce_offset % sizeof(register_t)); 2638446b206SNathan Whitehorn 2648446b206SNathan Whitehorn if (of_bounce_offset + len > of_bounce_size) { 2658446b206SNathan Whitehorn panic("Oversize Open Firmware call!"); 2668446b206SNathan Whitehorn return 0; 2678446b206SNathan Whitehorn } 2688446b206SNathan Whitehorn 2698446b206SNathan Whitehorn memcpy(of_bounce_virt + of_bounce_offset, buf, len); 2708446b206SNathan Whitehorn phys = of_bounce_phys + of_bounce_offset; 2718446b206SNathan Whitehorn 2728446b206SNathan Whitehorn of_bounce_offset += len; 2738446b206SNathan Whitehorn 27470d75337SNathan Whitehorn return (phys); 2758446b206SNathan Whitehorn } 2768446b206SNathan Whitehorn 2778446b206SNathan Whitehorn static void 2788446b206SNathan Whitehorn ofw_real_unmap(cell_t physaddr, void *buf, size_t len) 2798446b206SNathan Whitehorn { 2808446b206SNathan Whitehorn mtx_assert(&of_bounce_mtx, MA_OWNED); 2818446b206SNathan Whitehorn 2828446b206SNathan Whitehorn if (of_bounce_virt == NULL) 2838446b206SNathan Whitehorn return; 2848446b206SNathan Whitehorn 2858446b206SNathan Whitehorn memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len); 2868446b206SNathan Whitehorn } 2878446b206SNathan Whitehorn 2888446b206SNathan Whitehorn /* Initialiser */ 2898446b206SNathan Whitehorn 2908297758aSRafal Jaworowski static int 2918446b206SNathan Whitehorn ofw_real_init(ofw_t ofw, void *openfirm) 2928446b206SNathan Whitehorn { 2938446b206SNathan Whitehorn openfirmware = (int (*)(void *))openfirm; 2948446b206SNathan Whitehorn 2958446b206SNathan Whitehorn mtx_init(&of_bounce_mtx, "OF Bounce Page", MTX_DEF, 0); 2968446b206SNathan Whitehorn of_bounce_virt = NULL; 2978297758aSRafal Jaworowski return (0); 2988446b206SNathan Whitehorn } 2998446b206SNathan Whitehorn 3008446b206SNathan Whitehorn /* 3018446b206SNathan Whitehorn * Generic functions 3028446b206SNathan Whitehorn */ 3038446b206SNathan Whitehorn 3048446b206SNathan Whitehorn /* Test to see if a service exists. */ 3058446b206SNathan Whitehorn static int 3068446b206SNathan Whitehorn ofw_real_test(ofw_t ofw, const char *name) 3078446b206SNathan Whitehorn { 30870d75337SNathan Whitehorn vm_offset_t argsptr; 309d4bccd63SNathan Whitehorn struct { 3108446b206SNathan Whitehorn cell_t name; 3118446b206SNathan Whitehorn cell_t nargs; 3128446b206SNathan Whitehorn cell_t nreturns; 3138446b206SNathan Whitehorn cell_t service; 3148446b206SNathan Whitehorn cell_t missing; 31570d75337SNathan Whitehorn } args; 31670d75337SNathan Whitehorn 31770d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"test"; 31870d75337SNathan Whitehorn args.nargs = 1; 31970d75337SNathan Whitehorn args.nreturns = 1; 3208446b206SNathan Whitehorn 3218446b206SNathan Whitehorn ofw_real_start(); 3228446b206SNathan Whitehorn 3238446b206SNathan Whitehorn args.service = ofw_real_map(name, strlen(name) + 1); 32470d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 32570d75337SNathan Whitehorn if (args.service == 0 || openfirmware((void *)argsptr) == -1) { 3268446b206SNathan Whitehorn ofw_real_stop(); 3278446b206SNathan Whitehorn return (-1); 3288446b206SNathan Whitehorn } 32970d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 3308446b206SNathan Whitehorn ofw_real_stop(); 3318446b206SNathan Whitehorn return (args.missing); 3328446b206SNathan Whitehorn } 3338446b206SNathan Whitehorn 3348446b206SNathan Whitehorn /* 3358446b206SNathan Whitehorn * Device tree functions 3368446b206SNathan Whitehorn */ 3378446b206SNathan Whitehorn 3388446b206SNathan Whitehorn /* Return the next sibling of this node or 0. */ 3398446b206SNathan Whitehorn static phandle_t 3408446b206SNathan Whitehorn ofw_real_peer(ofw_t ofw, phandle_t node) 3418446b206SNathan Whitehorn { 34270d75337SNathan Whitehorn vm_offset_t argsptr; 343d4bccd63SNathan Whitehorn struct { 3448446b206SNathan Whitehorn cell_t name; 3458446b206SNathan Whitehorn cell_t nargs; 3468446b206SNathan Whitehorn cell_t nreturns; 3478446b206SNathan Whitehorn cell_t node; 3488446b206SNathan Whitehorn cell_t next; 34970d75337SNathan Whitehorn } args; 35070d75337SNathan Whitehorn 35170d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"peer"; 35270d75337SNathan Whitehorn args.nargs = 1; 35370d75337SNathan Whitehorn args.nreturns = 1; 3548446b206SNathan Whitehorn 3558446b206SNathan Whitehorn args.node = node; 35670d75337SNathan Whitehorn ofw_real_start(); 35770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 35870d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 35970d75337SNathan Whitehorn ofw_real_stop(); 3608446b206SNathan Whitehorn return (-1); 36170d75337SNathan Whitehorn } 36270d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 36370d75337SNathan Whitehorn ofw_real_stop(); 3648446b206SNathan Whitehorn return (args.next); 3658446b206SNathan Whitehorn } 3668446b206SNathan Whitehorn 3678446b206SNathan Whitehorn /* Return the first child of this node or 0. */ 3688446b206SNathan Whitehorn static phandle_t 3698446b206SNathan Whitehorn ofw_real_child(ofw_t ofw, phandle_t node) 3708446b206SNathan Whitehorn { 37170d75337SNathan Whitehorn vm_offset_t argsptr; 372d4bccd63SNathan Whitehorn struct { 3738446b206SNathan Whitehorn cell_t name; 3748446b206SNathan Whitehorn cell_t nargs; 3758446b206SNathan Whitehorn cell_t nreturns; 3768446b206SNathan Whitehorn cell_t node; 3778446b206SNathan Whitehorn cell_t child; 37870d75337SNathan Whitehorn } args; 37970d75337SNathan Whitehorn 38070d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"child"; 38170d75337SNathan Whitehorn args.nargs = 1; 38270d75337SNathan Whitehorn args.nreturns = 1; 3838446b206SNathan Whitehorn 3848446b206SNathan Whitehorn args.node = node; 38570d75337SNathan Whitehorn ofw_real_start(); 38670d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 38770d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 38870d75337SNathan Whitehorn ofw_real_stop(); 3898446b206SNathan Whitehorn return (-1); 39070d75337SNathan Whitehorn } 39170d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 39270d75337SNathan Whitehorn ofw_real_stop(); 3938446b206SNathan Whitehorn return (args.child); 3948446b206SNathan Whitehorn } 3958446b206SNathan Whitehorn 3968446b206SNathan Whitehorn /* Return the parent of this node or 0. */ 3978446b206SNathan Whitehorn static phandle_t 3988446b206SNathan Whitehorn ofw_real_parent(ofw_t ofw, phandle_t node) 3998446b206SNathan Whitehorn { 40070d75337SNathan Whitehorn vm_offset_t argsptr; 401d4bccd63SNathan Whitehorn struct { 4028446b206SNathan Whitehorn cell_t name; 4038446b206SNathan Whitehorn cell_t nargs; 4048446b206SNathan Whitehorn cell_t nreturns; 4058446b206SNathan Whitehorn cell_t node; 4068446b206SNathan Whitehorn cell_t parent; 40770d75337SNathan Whitehorn } args; 40870d75337SNathan Whitehorn 40970d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"parent"; 41070d75337SNathan Whitehorn args.nargs = 1; 41170d75337SNathan Whitehorn args.nreturns = 1; 4128446b206SNathan Whitehorn 4138446b206SNathan Whitehorn args.node = node; 41470d75337SNathan Whitehorn ofw_real_start(); 41570d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 41670d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 41770d75337SNathan Whitehorn ofw_real_stop(); 4188446b206SNathan Whitehorn return (-1); 41970d75337SNathan Whitehorn } 42070d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 42170d75337SNathan Whitehorn ofw_real_stop(); 4228446b206SNathan Whitehorn return (args.parent); 4238446b206SNathan Whitehorn } 4248446b206SNathan Whitehorn 4258446b206SNathan Whitehorn /* Return the package handle that corresponds to an instance handle. */ 4268446b206SNathan Whitehorn static phandle_t 4278446b206SNathan Whitehorn ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance) 4288446b206SNathan Whitehorn { 42970d75337SNathan Whitehorn vm_offset_t argsptr; 430d4bccd63SNathan Whitehorn struct { 4318446b206SNathan Whitehorn cell_t name; 4328446b206SNathan Whitehorn cell_t nargs; 4338446b206SNathan Whitehorn cell_t nreturns; 4348446b206SNathan Whitehorn cell_t instance; 4358446b206SNathan Whitehorn cell_t package; 43670d75337SNathan Whitehorn } args; 43770d75337SNathan Whitehorn 43870d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"instance-to-package"; 43970d75337SNathan Whitehorn args.nargs = 1; 44070d75337SNathan Whitehorn args.nreturns = 1; 4418446b206SNathan Whitehorn 4428446b206SNathan Whitehorn args.instance = instance; 44370d75337SNathan Whitehorn ofw_real_start(); 44470d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 44570d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 44670d75337SNathan Whitehorn ofw_real_stop(); 4478446b206SNathan Whitehorn return (-1); 44870d75337SNathan Whitehorn } 44970d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 45070d75337SNathan Whitehorn ofw_real_stop(); 4518446b206SNathan Whitehorn return (args.package); 4528446b206SNathan Whitehorn } 4538446b206SNathan Whitehorn 4548446b206SNathan Whitehorn /* Get the length of a property of a package. */ 4558446b206SNathan Whitehorn static ssize_t 4568446b206SNathan Whitehorn ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname) 4578446b206SNathan Whitehorn { 45870d75337SNathan Whitehorn vm_offset_t argsptr; 459d4bccd63SNathan Whitehorn struct { 4608446b206SNathan Whitehorn cell_t name; 4618446b206SNathan Whitehorn cell_t nargs; 4628446b206SNathan Whitehorn cell_t nreturns; 4638446b206SNathan Whitehorn cell_t package; 4648446b206SNathan Whitehorn cell_t propname; 46570d75337SNathan Whitehorn int32_t proplen; 46670d75337SNathan Whitehorn } args; 46770d75337SNathan Whitehorn 46870d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"getproplen"; 46970d75337SNathan Whitehorn args.nargs = 2; 47070d75337SNathan Whitehorn args.nreturns = 1; 4718446b206SNathan Whitehorn 4728446b206SNathan Whitehorn ofw_real_start(); 4738446b206SNathan Whitehorn 4748446b206SNathan Whitehorn args.package = package; 4758446b206SNathan Whitehorn args.propname = ofw_real_map(propname, strlen(propname) + 1); 47670d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 47770d75337SNathan Whitehorn if (args.propname == 0 || openfirmware((void *)argsptr) == -1) { 4788446b206SNathan Whitehorn ofw_real_stop(); 4798446b206SNathan Whitehorn return (-1); 4808446b206SNathan Whitehorn } 48170d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 4828446b206SNathan Whitehorn ofw_real_stop(); 4838446b206SNathan Whitehorn return (args.proplen); 4848446b206SNathan Whitehorn } 4858446b206SNathan Whitehorn 4868446b206SNathan Whitehorn /* Get the value of a property of a package. */ 4878446b206SNathan Whitehorn static ssize_t 4888446b206SNathan Whitehorn ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, 4898446b206SNathan Whitehorn size_t buflen) 4908446b206SNathan Whitehorn { 49170d75337SNathan Whitehorn vm_offset_t argsptr; 492d4bccd63SNathan Whitehorn struct { 4938446b206SNathan Whitehorn cell_t name; 4948446b206SNathan Whitehorn cell_t nargs; 4958446b206SNathan Whitehorn cell_t nreturns; 4968446b206SNathan Whitehorn cell_t package; 4978446b206SNathan Whitehorn cell_t propname; 4988446b206SNathan Whitehorn cell_t buf; 4998446b206SNathan Whitehorn cell_t buflen; 50070d75337SNathan Whitehorn int32_t size; 50170d75337SNathan Whitehorn } args; 50270d75337SNathan Whitehorn 50370d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"getprop"; 50470d75337SNathan Whitehorn args.nargs = 4; 50570d75337SNathan Whitehorn args.nreturns = 1; 5068446b206SNathan Whitehorn 5078446b206SNathan Whitehorn ofw_real_start(); 5088446b206SNathan Whitehorn 5098446b206SNathan Whitehorn args.package = package; 5108446b206SNathan Whitehorn args.propname = ofw_real_map(propname, strlen(propname) + 1); 5118446b206SNathan Whitehorn args.buf = ofw_real_map(buf, buflen); 5128446b206SNathan Whitehorn args.buflen = buflen; 51370d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 51470d75337SNathan Whitehorn if (args.propname == 0 || args.buf == 0 || 51570d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 5168446b206SNathan Whitehorn ofw_real_stop(); 5178446b206SNathan Whitehorn return (-1); 5188446b206SNathan Whitehorn } 51970d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 5208446b206SNathan Whitehorn ofw_real_unmap(args.buf, buf, buflen); 5218446b206SNathan Whitehorn 5228446b206SNathan Whitehorn ofw_real_stop(); 5238446b206SNathan Whitehorn return (args.size); 5248446b206SNathan Whitehorn } 5258446b206SNathan Whitehorn 5268446b206SNathan Whitehorn /* Get the next property of a package. */ 5278446b206SNathan Whitehorn static int 5288446b206SNathan Whitehorn ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous, 5298446b206SNathan Whitehorn char *buf, size_t size) 5308446b206SNathan Whitehorn { 53170d75337SNathan Whitehorn vm_offset_t argsptr; 532d4bccd63SNathan Whitehorn struct { 5338446b206SNathan Whitehorn cell_t name; 5348446b206SNathan Whitehorn cell_t nargs; 5358446b206SNathan Whitehorn cell_t nreturns; 5368446b206SNathan Whitehorn cell_t package; 5378446b206SNathan Whitehorn cell_t previous; 5388446b206SNathan Whitehorn cell_t buf; 5398446b206SNathan Whitehorn cell_t flag; 54070d75337SNathan Whitehorn } args; 54170d75337SNathan Whitehorn 54270d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"nextprop"; 54370d75337SNathan Whitehorn args.nargs = 3; 54470d75337SNathan Whitehorn args.nreturns = 1; 5458446b206SNathan Whitehorn 5468446b206SNathan Whitehorn ofw_real_start(); 5478446b206SNathan Whitehorn 5488446b206SNathan Whitehorn args.package = package; 5498446b206SNathan Whitehorn args.previous = ofw_real_map(previous, strlen(previous) + 1); 5508446b206SNathan Whitehorn args.buf = ofw_real_map(buf, size); 55170d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 55270d75337SNathan Whitehorn if (args.previous == 0 || args.buf == 0 || 55370d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 5548446b206SNathan Whitehorn ofw_real_stop(); 5558446b206SNathan Whitehorn return (-1); 5568446b206SNathan Whitehorn } 55770d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 5588446b206SNathan Whitehorn ofw_real_unmap(args.buf, buf, size); 5598446b206SNathan Whitehorn 5608446b206SNathan Whitehorn ofw_real_stop(); 5618446b206SNathan Whitehorn return (args.flag); 5628446b206SNathan Whitehorn } 5638446b206SNathan Whitehorn 5648446b206SNathan Whitehorn /* Set the value of a property of a package. */ 5658446b206SNathan Whitehorn /* XXX Has a bug on FirePower */ 5668446b206SNathan Whitehorn static int 5674fc23012SAndriy Gapon ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname, 5684fc23012SAndriy Gapon const void *buf, size_t len) 5698446b206SNathan Whitehorn { 57070d75337SNathan Whitehorn vm_offset_t argsptr; 571d4bccd63SNathan Whitehorn struct { 5728446b206SNathan Whitehorn cell_t name; 5738446b206SNathan Whitehorn cell_t nargs; 5748446b206SNathan Whitehorn cell_t nreturns; 5758446b206SNathan Whitehorn cell_t package; 5768446b206SNathan Whitehorn cell_t propname; 5778446b206SNathan Whitehorn cell_t buf; 5788446b206SNathan Whitehorn cell_t len; 5798446b206SNathan Whitehorn cell_t size; 58070d75337SNathan Whitehorn } args; 58170d75337SNathan Whitehorn 58270d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"setprop"; 58370d75337SNathan Whitehorn args.nargs = 4; 58470d75337SNathan Whitehorn args.nreturns = 1; 5858446b206SNathan Whitehorn 5868446b206SNathan Whitehorn ofw_real_start(); 5878446b206SNathan Whitehorn 5888446b206SNathan Whitehorn args.package = package; 5898446b206SNathan Whitehorn args.propname = ofw_real_map(propname, strlen(propname) + 1); 5908446b206SNathan Whitehorn args.buf = ofw_real_map(buf, len); 5918446b206SNathan Whitehorn args.len = len; 59270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 59370d75337SNathan Whitehorn if (args.propname == 0 || args.buf == 0 || 59470d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 5958446b206SNathan Whitehorn ofw_real_stop(); 5968446b206SNathan Whitehorn return (-1); 5978446b206SNathan Whitehorn } 59870d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 5998446b206SNathan Whitehorn ofw_real_stop(); 6008446b206SNathan Whitehorn return (args.size); 6018446b206SNathan Whitehorn } 6028446b206SNathan Whitehorn 6038446b206SNathan Whitehorn /* Convert a device specifier to a fully qualified pathname. */ 6048446b206SNathan Whitehorn static ssize_t 6058446b206SNathan Whitehorn ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len) 6068446b206SNathan Whitehorn { 60770d75337SNathan Whitehorn vm_offset_t argsptr; 608d4bccd63SNathan Whitehorn struct { 6098446b206SNathan Whitehorn cell_t name; 6108446b206SNathan Whitehorn cell_t nargs; 6118446b206SNathan Whitehorn cell_t nreturns; 6128446b206SNathan Whitehorn cell_t device; 6138446b206SNathan Whitehorn cell_t buf; 6148446b206SNathan Whitehorn cell_t len; 61570d75337SNathan Whitehorn int32_t size; 61670d75337SNathan Whitehorn } args; 61770d75337SNathan Whitehorn 61870d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"canon"; 61970d75337SNathan Whitehorn args.nargs = 3; 62070d75337SNathan Whitehorn args.nreturns = 1; 6218446b206SNathan Whitehorn 6228446b206SNathan Whitehorn ofw_real_start(); 6238446b206SNathan Whitehorn 6248446b206SNathan Whitehorn args.device = ofw_real_map(device, strlen(device) + 1); 6258446b206SNathan Whitehorn args.buf = ofw_real_map(buf, len); 6268446b206SNathan Whitehorn args.len = len; 62770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 62870d75337SNathan Whitehorn if (args.device == 0 || args.buf == 0 || 62970d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 6308446b206SNathan Whitehorn ofw_real_stop(); 6318446b206SNathan Whitehorn return (-1); 6328446b206SNathan Whitehorn } 63370d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 6348446b206SNathan Whitehorn ofw_real_unmap(args.buf, buf, len); 6358446b206SNathan Whitehorn 6368446b206SNathan Whitehorn ofw_real_stop(); 6378446b206SNathan Whitehorn return (args.size); 6388446b206SNathan Whitehorn } 6398446b206SNathan Whitehorn 6408446b206SNathan Whitehorn /* Return a package handle for the specified device. */ 6418446b206SNathan Whitehorn static phandle_t 6428446b206SNathan Whitehorn ofw_real_finddevice(ofw_t ofw, const char *device) 6438446b206SNathan Whitehorn { 64470d75337SNathan Whitehorn vm_offset_t argsptr; 645d4bccd63SNathan Whitehorn struct { 6468446b206SNathan Whitehorn cell_t name; 6478446b206SNathan Whitehorn cell_t nargs; 6488446b206SNathan Whitehorn cell_t nreturns; 6498446b206SNathan Whitehorn cell_t device; 6508446b206SNathan Whitehorn cell_t package; 65170d75337SNathan Whitehorn } args; 65270d75337SNathan Whitehorn 65370d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"finddevice"; 65470d75337SNathan Whitehorn args.nargs = 1; 65570d75337SNathan Whitehorn args.nreturns = 1; 6568446b206SNathan Whitehorn 6578446b206SNathan Whitehorn ofw_real_start(); 6588446b206SNathan Whitehorn 6598446b206SNathan Whitehorn args.device = ofw_real_map(device, strlen(device) + 1); 66070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 66170d75337SNathan Whitehorn if (args.device == 0 || 66270d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 6638446b206SNathan Whitehorn ofw_real_stop(); 6648446b206SNathan Whitehorn return (-1); 6658446b206SNathan Whitehorn } 66670d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 6678446b206SNathan Whitehorn ofw_real_stop(); 6688446b206SNathan Whitehorn return (args.package); 6698446b206SNathan Whitehorn } 6708446b206SNathan Whitehorn 6718446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to an instance. */ 6728446b206SNathan Whitehorn static ssize_t 6738446b206SNathan Whitehorn ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) 6748446b206SNathan Whitehorn { 67570d75337SNathan Whitehorn vm_offset_t argsptr; 676d4bccd63SNathan Whitehorn struct { 6778446b206SNathan Whitehorn cell_t name; 6788446b206SNathan Whitehorn cell_t nargs; 6798446b206SNathan Whitehorn cell_t nreturns; 6808446b206SNathan Whitehorn cell_t instance; 6818446b206SNathan Whitehorn cell_t buf; 6828446b206SNathan Whitehorn cell_t len; 68370d75337SNathan Whitehorn int32_t size; 68470d75337SNathan Whitehorn } args; 68570d75337SNathan Whitehorn 68670d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"instance-to-path"; 68770d75337SNathan Whitehorn args.nargs = 3; 68870d75337SNathan Whitehorn args.nreturns = 1; 6898446b206SNathan Whitehorn 6908446b206SNathan Whitehorn ofw_real_start(); 6918446b206SNathan Whitehorn 6928446b206SNathan Whitehorn args.instance = instance; 6938446b206SNathan Whitehorn args.buf = ofw_real_map(buf, len); 6948446b206SNathan Whitehorn args.len = len; 69570d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 69670d75337SNathan Whitehorn if (args.buf == 0 || 69770d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 6988446b206SNathan Whitehorn ofw_real_stop(); 6998446b206SNathan Whitehorn return (-1); 7008446b206SNathan Whitehorn } 70170d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 7028446b206SNathan Whitehorn ofw_real_unmap(args.buf, buf, len); 7038446b206SNathan Whitehorn 7048446b206SNathan Whitehorn ofw_real_stop(); 7058446b206SNathan Whitehorn return (args.size); 7068446b206SNathan Whitehorn } 7078446b206SNathan Whitehorn 7088446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to a package. */ 7098446b206SNathan Whitehorn static ssize_t 7108446b206SNathan Whitehorn ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len) 7118446b206SNathan Whitehorn { 71270d75337SNathan Whitehorn vm_offset_t argsptr; 713d4bccd63SNathan Whitehorn struct { 7148446b206SNathan Whitehorn cell_t name; 7158446b206SNathan Whitehorn cell_t nargs; 7168446b206SNathan Whitehorn cell_t nreturns; 7178446b206SNathan Whitehorn cell_t package; 7188446b206SNathan Whitehorn cell_t buf; 7198446b206SNathan Whitehorn cell_t len; 72070d75337SNathan Whitehorn int32_t size; 72170d75337SNathan Whitehorn } args; 72270d75337SNathan Whitehorn 72370d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"package-to-path"; 72470d75337SNathan Whitehorn args.nargs = 3; 72570d75337SNathan Whitehorn args.nreturns = 1; 7268446b206SNathan Whitehorn 7278446b206SNathan Whitehorn ofw_real_start(); 7288446b206SNathan Whitehorn 7298446b206SNathan Whitehorn args.package = package; 7308446b206SNathan Whitehorn args.buf = ofw_real_map(buf, len); 7318446b206SNathan Whitehorn args.len = len; 73270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 73370d75337SNathan Whitehorn if (args.buf == 0 || 73470d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 7358446b206SNathan Whitehorn ofw_real_stop(); 7368446b206SNathan Whitehorn return (-1); 7378446b206SNathan Whitehorn } 73870d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 7398446b206SNathan Whitehorn ofw_real_unmap(args.buf, buf, len); 7408446b206SNathan Whitehorn 7418446b206SNathan Whitehorn ofw_real_stop(); 7428446b206SNathan Whitehorn return (args.size); 7438446b206SNathan Whitehorn } 7448446b206SNathan Whitehorn 7458446b206SNathan Whitehorn /* Call the method in the scope of a given instance. */ 7468446b206SNathan Whitehorn static int 7478446b206SNathan Whitehorn ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, 748054e5dcbSNathan Whitehorn int nargs, int nreturns, cell_t *args_and_returns) 7498446b206SNathan Whitehorn { 75070d75337SNathan Whitehorn vm_offset_t argsptr; 751d4bccd63SNathan Whitehorn struct { 7528446b206SNathan Whitehorn cell_t name; 7538446b206SNathan Whitehorn cell_t nargs; 7548446b206SNathan Whitehorn cell_t nreturns; 7558446b206SNathan Whitehorn cell_t method; 7568446b206SNathan Whitehorn cell_t instance; 7578446b206SNathan Whitehorn cell_t args_n_results[12]; 75870d75337SNathan Whitehorn } args; 759*cdb25d82SMarius Strobl cell_t *ap, *cp; 7608446b206SNathan Whitehorn int n; 7618446b206SNathan Whitehorn 76270d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"call-method"; 76370d75337SNathan Whitehorn args.nargs = 2; 76470d75337SNathan Whitehorn args.nreturns = 1; 76570d75337SNathan Whitehorn 7668446b206SNathan Whitehorn if (nargs > 6) 7678446b206SNathan Whitehorn return (-1); 7688446b206SNathan Whitehorn 7698446b206SNathan Whitehorn ofw_real_start(); 7708446b206SNathan Whitehorn args.nargs = nargs + 2; 7718446b206SNathan Whitehorn args.nreturns = nreturns + 1; 7728446b206SNathan Whitehorn args.method = ofw_real_map(method, strlen(method) + 1); 7738446b206SNathan Whitehorn args.instance = instance; 7748446b206SNathan Whitehorn 7758446b206SNathan Whitehorn ap = args_and_returns; 7768446b206SNathan Whitehorn for (cp = args.args_n_results + (n = nargs); --n >= 0;) 7778446b206SNathan Whitehorn *--cp = *(ap++); 77870d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 77970d75337SNathan Whitehorn if (args.method == 0 || 78070d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 7818446b206SNathan Whitehorn ofw_real_stop(); 7828446b206SNathan Whitehorn return (-1); 7838446b206SNathan Whitehorn } 78470d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 7858446b206SNathan Whitehorn ofw_real_stop(); 7868446b206SNathan Whitehorn if (args.args_n_results[nargs]) 7878446b206SNathan Whitehorn return (args.args_n_results[nargs]); 7888446b206SNathan Whitehorn for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) 7898446b206SNathan Whitehorn *(ap++) = *--cp; 7908446b206SNathan Whitehorn return (0); 7918446b206SNathan Whitehorn } 7928446b206SNathan Whitehorn 79370d75337SNathan Whitehorn static int 794*cdb25d82SMarius Strobl ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns) 79570d75337SNathan Whitehorn { 79670d75337SNathan Whitehorn vm_offset_t argsptr; 79770d75337SNathan Whitehorn struct { 79870d75337SNathan Whitehorn cell_t name; 79970d75337SNathan Whitehorn cell_t nargs; 80070d75337SNathan Whitehorn cell_t nreturns; 80170d75337SNathan Whitehorn cell_t slot[16]; 80270d75337SNathan Whitehorn } args; 80370d75337SNathan Whitehorn cell_t status; 80470d75337SNathan Whitehorn int i = 0, j = 0; 80570d75337SNathan Whitehorn 80670d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"interpret"; 80770d75337SNathan Whitehorn args.nargs = 1; 80870d75337SNathan Whitehorn 80970d75337SNathan Whitehorn ofw_real_start(); 81070d75337SNathan Whitehorn args.nreturns = ++nreturns; 81170d75337SNathan Whitehorn args.slot[i++] = ofw_real_map(cmd, strlen(cmd) + 1); 81270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 81370d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 81470d75337SNathan Whitehorn ofw_real_stop(); 81570d75337SNathan Whitehorn return (-1); 81670d75337SNathan Whitehorn } 81770d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 81870d75337SNathan Whitehorn ofw_real_stop(); 81970d75337SNathan Whitehorn status = args.slot[i++]; 82070d75337SNathan Whitehorn while (i < 1 + nreturns) 82170d75337SNathan Whitehorn returns[j++] = args.slot[i++]; 82270d75337SNathan Whitehorn return (status); 82370d75337SNathan Whitehorn } 82470d75337SNathan Whitehorn 8258446b206SNathan Whitehorn /* 8268446b206SNathan Whitehorn * Device I/O functions 8278446b206SNathan Whitehorn */ 8288446b206SNathan Whitehorn 8298446b206SNathan Whitehorn /* Open an instance for a device. */ 8308446b206SNathan Whitehorn static ihandle_t 8318446b206SNathan Whitehorn ofw_real_open(ofw_t ofw, const char *device) 8328446b206SNathan Whitehorn { 83370d75337SNathan Whitehorn vm_offset_t argsptr; 834d4bccd63SNathan Whitehorn struct { 8358446b206SNathan Whitehorn cell_t name; 8368446b206SNathan Whitehorn cell_t nargs; 8378446b206SNathan Whitehorn cell_t nreturns; 8388446b206SNathan Whitehorn cell_t device; 8398446b206SNathan Whitehorn cell_t instance; 84070d75337SNathan Whitehorn } args; 84170d75337SNathan Whitehorn 84270d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"open"; 84370d75337SNathan Whitehorn args.nargs = 1; 84470d75337SNathan Whitehorn args.nreturns = 1; 8458446b206SNathan Whitehorn 8468446b206SNathan Whitehorn ofw_real_start(); 8478446b206SNathan Whitehorn 8488446b206SNathan Whitehorn args.device = ofw_real_map(device, strlen(device) + 1); 84970d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 85070d75337SNathan Whitehorn if (args.device == 0 || openfirmware((void *)argsptr) == -1 8518446b206SNathan Whitehorn || args.instance == 0) { 8528446b206SNathan Whitehorn ofw_real_stop(); 8538446b206SNathan Whitehorn return (-1); 8548446b206SNathan Whitehorn } 85570d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 8568446b206SNathan Whitehorn ofw_real_stop(); 8578446b206SNathan Whitehorn return (args.instance); 8588446b206SNathan Whitehorn } 8598446b206SNathan Whitehorn 8608446b206SNathan Whitehorn /* Close an instance. */ 8618446b206SNathan Whitehorn static void 8628446b206SNathan Whitehorn ofw_real_close(ofw_t ofw, ihandle_t instance) 8638446b206SNathan Whitehorn { 86470d75337SNathan Whitehorn vm_offset_t argsptr; 865d4bccd63SNathan Whitehorn struct { 8668446b206SNathan Whitehorn cell_t name; 8678446b206SNathan Whitehorn cell_t nargs; 8688446b206SNathan Whitehorn cell_t nreturns; 8698446b206SNathan Whitehorn cell_t instance; 87070d75337SNathan Whitehorn } args; 8718446b206SNathan Whitehorn 87270d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"close"; 87370d75337SNathan Whitehorn args.nargs = 1; 87470d75337SNathan Whitehorn args.nreturns = 0; 8758446b206SNathan Whitehorn args.instance = instance; 87670d75337SNathan Whitehorn ofw_real_start(); 87770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 87870d75337SNathan Whitehorn openfirmware((void *)argsptr); 87970d75337SNathan Whitehorn ofw_real_stop(); 8808446b206SNathan Whitehorn } 8818446b206SNathan Whitehorn 8828446b206SNathan Whitehorn /* Read from an instance. */ 8838446b206SNathan Whitehorn static ssize_t 8848446b206SNathan Whitehorn ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) 8858446b206SNathan Whitehorn { 88670d75337SNathan Whitehorn vm_offset_t argsptr; 887d4bccd63SNathan Whitehorn struct { 8888446b206SNathan Whitehorn cell_t name; 8898446b206SNathan Whitehorn cell_t nargs; 8908446b206SNathan Whitehorn cell_t nreturns; 8918446b206SNathan Whitehorn cell_t instance; 8928446b206SNathan Whitehorn cell_t addr; 8938446b206SNathan Whitehorn cell_t len; 89470d75337SNathan Whitehorn int32_t actual; 89570d75337SNathan Whitehorn } args; 89670d75337SNathan Whitehorn 89770d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"read"; 89870d75337SNathan Whitehorn args.nargs = 3; 89970d75337SNathan Whitehorn args.nreturns = 1; 9008446b206SNathan Whitehorn 9018446b206SNathan Whitehorn ofw_real_start(); 9028446b206SNathan Whitehorn 9038446b206SNathan Whitehorn args.instance = instance; 9048446b206SNathan Whitehorn args.addr = ofw_real_map(addr, len); 9058446b206SNathan Whitehorn args.len = len; 90670d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 90770d75337SNathan Whitehorn if (args.addr == 0 || openfirmware((void *)argsptr) == -1) { 9088446b206SNathan Whitehorn ofw_real_stop(); 9098446b206SNathan Whitehorn return (-1); 9108446b206SNathan Whitehorn } 91170d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 9128446b206SNathan Whitehorn ofw_real_unmap(args.addr, addr, len); 9138446b206SNathan Whitehorn 9148446b206SNathan Whitehorn ofw_real_stop(); 9158446b206SNathan Whitehorn return (args.actual); 9168446b206SNathan Whitehorn } 9178446b206SNathan Whitehorn 9188446b206SNathan Whitehorn /* Write to an instance. */ 9198446b206SNathan Whitehorn static ssize_t 9208446b206SNathan Whitehorn ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) 9218446b206SNathan Whitehorn { 92270d75337SNathan Whitehorn vm_offset_t argsptr; 923d4bccd63SNathan Whitehorn struct { 9248446b206SNathan Whitehorn cell_t name; 9258446b206SNathan Whitehorn cell_t nargs; 9268446b206SNathan Whitehorn cell_t nreturns; 9278446b206SNathan Whitehorn cell_t instance; 9288446b206SNathan Whitehorn cell_t addr; 9298446b206SNathan Whitehorn cell_t len; 93070d75337SNathan Whitehorn int32_t actual; 93170d75337SNathan Whitehorn } args; 93270d75337SNathan Whitehorn 93370d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"write"; 93470d75337SNathan Whitehorn args.nargs = 3; 93570d75337SNathan Whitehorn args.nreturns = 1; 9368446b206SNathan Whitehorn 9378446b206SNathan Whitehorn ofw_real_start(); 9388446b206SNathan Whitehorn 9398446b206SNathan Whitehorn args.instance = instance; 9408446b206SNathan Whitehorn args.addr = ofw_real_map(addr, len); 9418446b206SNathan Whitehorn args.len = len; 94270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 94370d75337SNathan Whitehorn if (args.addr == 0 || openfirmware((void *)argsptr) == -1) { 9448446b206SNathan Whitehorn ofw_real_stop(); 9458446b206SNathan Whitehorn return (-1); 9468446b206SNathan Whitehorn } 94770d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 9488446b206SNathan Whitehorn ofw_real_stop(); 9498446b206SNathan Whitehorn return (args.actual); 9508446b206SNathan Whitehorn } 9518446b206SNathan Whitehorn 9528446b206SNathan Whitehorn /* Seek to a position. */ 9538446b206SNathan Whitehorn static int 9548446b206SNathan Whitehorn ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos) 9558446b206SNathan Whitehorn { 95670d75337SNathan Whitehorn vm_offset_t argsptr; 957d4bccd63SNathan Whitehorn struct { 9588446b206SNathan Whitehorn cell_t name; 9598446b206SNathan Whitehorn cell_t nargs; 9608446b206SNathan Whitehorn cell_t nreturns; 9618446b206SNathan Whitehorn cell_t instance; 9628446b206SNathan Whitehorn cell_t poshi; 9638446b206SNathan Whitehorn cell_t poslo; 9648446b206SNathan Whitehorn cell_t status; 96570d75337SNathan Whitehorn } args; 96670d75337SNathan Whitehorn 96770d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"seek"; 96870d75337SNathan Whitehorn args.nargs = 3; 96970d75337SNathan Whitehorn args.nreturns = 1; 9708446b206SNathan Whitehorn 9718446b206SNathan Whitehorn args.instance = instance; 9728446b206SNathan Whitehorn args.poshi = pos >> 32; 9738446b206SNathan Whitehorn args.poslo = pos; 97470d75337SNathan Whitehorn ofw_real_start(); 97570d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 97670d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 97770d75337SNathan Whitehorn ofw_real_stop(); 9788446b206SNathan Whitehorn return (-1); 97970d75337SNathan Whitehorn } 98070d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 98170d75337SNathan Whitehorn ofw_real_stop(); 9828446b206SNathan Whitehorn return (args.status); 9838446b206SNathan Whitehorn } 9848446b206SNathan Whitehorn 9858446b206SNathan Whitehorn /* 9868446b206SNathan Whitehorn * Memory functions 9878446b206SNathan Whitehorn */ 9888446b206SNathan Whitehorn 9898446b206SNathan Whitehorn /* Claim an area of memory. */ 9908446b206SNathan Whitehorn static caddr_t 9918446b206SNathan Whitehorn ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align) 9928446b206SNathan Whitehorn { 99370d75337SNathan Whitehorn vm_offset_t argsptr; 994d4bccd63SNathan Whitehorn struct { 9958446b206SNathan Whitehorn cell_t name; 9968446b206SNathan Whitehorn cell_t nargs; 9978446b206SNathan Whitehorn cell_t nreturns; 9988446b206SNathan Whitehorn cell_t virt; 9998446b206SNathan Whitehorn cell_t size; 10008446b206SNathan Whitehorn cell_t align; 10018446b206SNathan Whitehorn cell_t baseaddr; 100270d75337SNathan Whitehorn } args; 10038446b206SNathan Whitehorn 100470d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"claim"; 100570d75337SNathan Whitehorn args.nargs = 3; 100670d75337SNathan Whitehorn args.nreturns = 1; 100770d75337SNathan Whitehorn 100870d75337SNathan Whitehorn args.virt = (cell_t)(uintptr_t)virt; 10098446b206SNathan Whitehorn args.size = size; 10108446b206SNathan Whitehorn args.align = align; 101170d75337SNathan Whitehorn ofw_real_start(); 101270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 101370d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 101470d75337SNathan Whitehorn ofw_real_stop(); 10158446b206SNathan Whitehorn return ((void *)-1); 101670d75337SNathan Whitehorn } 101770d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 101870d75337SNathan Whitehorn ofw_real_stop(); 101970d75337SNathan Whitehorn return ((void *)(uintptr_t)args.baseaddr); 10208446b206SNathan Whitehorn } 10218446b206SNathan Whitehorn 10228446b206SNathan Whitehorn /* Release an area of memory. */ 10238446b206SNathan Whitehorn static void 10248446b206SNathan Whitehorn ofw_real_release(ofw_t ofw, void *virt, size_t size) 10258446b206SNathan Whitehorn { 102670d75337SNathan Whitehorn vm_offset_t argsptr; 1027d4bccd63SNathan Whitehorn struct { 10288446b206SNathan Whitehorn cell_t name; 10298446b206SNathan Whitehorn cell_t nargs; 10308446b206SNathan Whitehorn cell_t nreturns; 10318446b206SNathan Whitehorn cell_t virt; 10328446b206SNathan Whitehorn cell_t size; 103370d75337SNathan Whitehorn } args; 10348446b206SNathan Whitehorn 103570d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"release"; 103670d75337SNathan Whitehorn args.nargs = 2; 103770d75337SNathan Whitehorn args.nreturns = 0; 103870d75337SNathan Whitehorn 103970d75337SNathan Whitehorn args.virt = (cell_t)(uintptr_t)virt; 10408446b206SNathan Whitehorn args.size = size; 104170d75337SNathan Whitehorn ofw_real_start(); 104270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 104370d75337SNathan Whitehorn openfirmware((void *)argsptr); 104470d75337SNathan Whitehorn ofw_real_stop(); 10458446b206SNathan Whitehorn } 10468446b206SNathan Whitehorn 10478446b206SNathan Whitehorn /* 10488446b206SNathan Whitehorn * Control transfer functions 10498446b206SNathan Whitehorn */ 10508446b206SNathan Whitehorn 10518446b206SNathan Whitehorn /* Suspend and drop back to the Open Firmware interface. */ 10528446b206SNathan Whitehorn static void 10538446b206SNathan Whitehorn ofw_real_enter(ofw_t ofw) 10548446b206SNathan Whitehorn { 105570d75337SNathan Whitehorn vm_offset_t argsptr; 1056d4bccd63SNathan Whitehorn struct { 10578446b206SNathan Whitehorn cell_t name; 10588446b206SNathan Whitehorn cell_t nargs; 10598446b206SNathan Whitehorn cell_t nreturns; 106070d75337SNathan Whitehorn } args; 10618446b206SNathan Whitehorn 106270d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"enter"; 106370d75337SNathan Whitehorn args.nargs = 0; 106470d75337SNathan Whitehorn args.nreturns = 0; 106570d75337SNathan Whitehorn 106670d75337SNathan Whitehorn ofw_real_start(); 106770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 106870d75337SNathan Whitehorn openfirmware((void *)argsptr); 10698446b206SNathan Whitehorn /* We may come back. */ 107070d75337SNathan Whitehorn ofw_real_stop(); 10718446b206SNathan Whitehorn } 10728446b206SNathan Whitehorn 10738446b206SNathan Whitehorn /* Shut down and drop back to the Open Firmware interface. */ 10748446b206SNathan Whitehorn static void 10758446b206SNathan Whitehorn ofw_real_exit(ofw_t ofw) 10768446b206SNathan Whitehorn { 107770d75337SNathan Whitehorn vm_offset_t argsptr; 1078d4bccd63SNathan Whitehorn struct { 10798446b206SNathan Whitehorn cell_t name; 10808446b206SNathan Whitehorn cell_t nargs; 10818446b206SNathan Whitehorn cell_t nreturns; 108270d75337SNathan Whitehorn } args; 10838446b206SNathan Whitehorn 108470d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"exit"; 108570d75337SNathan Whitehorn args.nargs = 0; 108670d75337SNathan Whitehorn args.nreturns = 0; 108770d75337SNathan Whitehorn 108870d75337SNathan Whitehorn ofw_real_start(); 108970d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 109070d75337SNathan Whitehorn openfirmware((void *)argsptr); 10918446b206SNathan Whitehorn for (;;) /* just in case */ 10928446b206SNathan Whitehorn ; 109370d75337SNathan Whitehorn ofw_real_stop(); 10948446b206SNathan Whitehorn } 10958446b206SNathan Whitehorn 1096