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 638446b206SNathan Whitehorn #include <sys/param.h> 648446b206SNathan Whitehorn #include <sys/kernel.h> 658446b206SNathan Whitehorn #include <sys/lock.h> 668446b206SNathan Whitehorn #include <sys/mutex.h> 678446b206SNathan Whitehorn #include <sys/systm.h> 688446b206SNathan Whitehorn 698446b206SNathan Whitehorn #include <vm/vm.h> 7070d75337SNathan Whitehorn #include <vm/vm_page.h> 718446b206SNathan Whitehorn #include <vm/pmap.h> 728446b206SNathan Whitehorn 738446b206SNathan Whitehorn #include <machine/bus.h> 7470d75337SNathan Whitehorn #include <machine/md_var.h> 758446b206SNathan Whitehorn #include <machine/ofw_machdep.h> 7670d75337SNathan Whitehorn #include <machine/stdarg.h> 778446b206SNathan Whitehorn 788446b206SNathan Whitehorn #include <dev/ofw/openfirm.h> 798446b206SNathan Whitehorn #include <dev/ofw/ofwvar.h> 808446b206SNathan Whitehorn #include "ofw_if.h" 818446b206SNathan Whitehorn 828297758aSRafal Jaworowski static int ofw_real_init(ofw_t, void *openfirm); 838446b206SNathan Whitehorn static int ofw_real_test(ofw_t, const char *name); 848446b206SNathan Whitehorn static phandle_t ofw_real_peer(ofw_t, phandle_t node); 858446b206SNathan Whitehorn static phandle_t ofw_real_child(ofw_t, phandle_t node); 868446b206SNathan Whitehorn static phandle_t ofw_real_parent(ofw_t, phandle_t node); 878446b206SNathan Whitehorn static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance); 888446b206SNathan Whitehorn static ssize_t ofw_real_getproplen(ofw_t, phandle_t package, 898446b206SNathan Whitehorn const char *propname); 908446b206SNathan Whitehorn static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname, 918446b206SNathan Whitehorn void *buf, size_t buflen); 928446b206SNathan Whitehorn static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous, 938446b206SNathan Whitehorn char *buf, size_t); 944fc23012SAndriy Gapon static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname, 954fc23012SAndriy Gapon const void *buf, size_t len); 968446b206SNathan Whitehorn static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len); 978446b206SNathan Whitehorn static phandle_t ofw_real_finddevice(ofw_t, const char *device); 988446b206SNathan Whitehorn static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf, 998446b206SNathan Whitehorn size_t len); 1008446b206SNathan Whitehorn static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf, 1018446b206SNathan Whitehorn size_t len); 1028446b206SNathan Whitehorn static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method, 103054e5dcbSNathan Whitehorn int nargs, int nreturns, cell_t *args_and_returns); 10470d75337SNathan Whitehorn static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, 105cdb25d82SMarius Strobl cell_t *returns); 1068446b206SNathan Whitehorn static ihandle_t ofw_real_open(ofw_t, const char *device); 1078446b206SNathan Whitehorn static void ofw_real_close(ofw_t, ihandle_t instance); 1088446b206SNathan Whitehorn static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len); 1098446b206SNathan Whitehorn static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr, 1108446b206SNathan Whitehorn size_t len); 1118446b206SNathan Whitehorn static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos); 1128446b206SNathan Whitehorn static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align); 1138446b206SNathan Whitehorn static void ofw_real_release(ofw_t, void *virt, size_t size); 1148446b206SNathan Whitehorn static void ofw_real_enter(ofw_t); 1158446b206SNathan Whitehorn static void ofw_real_exit(ofw_t); 1168446b206SNathan Whitehorn 1178446b206SNathan Whitehorn static ofw_method_t ofw_real_methods[] = { 1188446b206SNathan Whitehorn OFWMETHOD(ofw_init, ofw_real_init), 1198446b206SNathan Whitehorn OFWMETHOD(ofw_peer, ofw_real_peer), 1208446b206SNathan Whitehorn OFWMETHOD(ofw_child, ofw_real_child), 1218446b206SNathan Whitehorn OFWMETHOD(ofw_parent, ofw_real_parent), 1228446b206SNathan Whitehorn OFWMETHOD(ofw_instance_to_package, ofw_real_instance_to_package), 1238446b206SNathan Whitehorn OFWMETHOD(ofw_getproplen, ofw_real_getproplen), 1248446b206SNathan Whitehorn OFWMETHOD(ofw_getprop, ofw_real_getprop), 1258446b206SNathan Whitehorn OFWMETHOD(ofw_nextprop, ofw_real_nextprop), 1268446b206SNathan Whitehorn OFWMETHOD(ofw_setprop, ofw_real_setprop), 1278446b206SNathan Whitehorn OFWMETHOD(ofw_canon, ofw_real_canon), 1288446b206SNathan Whitehorn OFWMETHOD(ofw_finddevice, ofw_real_finddevice), 1298446b206SNathan Whitehorn OFWMETHOD(ofw_instance_to_path, ofw_real_instance_to_path), 1308446b206SNathan Whitehorn OFWMETHOD(ofw_package_to_path, ofw_real_package_to_path), 1318446b206SNathan Whitehorn 1328446b206SNathan Whitehorn OFWMETHOD(ofw_test, ofw_real_test), 1338446b206SNathan Whitehorn OFWMETHOD(ofw_call_method, ofw_real_call_method), 13470d75337SNathan Whitehorn OFWMETHOD(ofw_interpret, ofw_real_interpret), 1358446b206SNathan Whitehorn OFWMETHOD(ofw_open, ofw_real_open), 1368446b206SNathan Whitehorn OFWMETHOD(ofw_close, ofw_real_close), 1378446b206SNathan Whitehorn OFWMETHOD(ofw_read, ofw_real_read), 1388446b206SNathan Whitehorn OFWMETHOD(ofw_write, ofw_real_write), 1398446b206SNathan Whitehorn OFWMETHOD(ofw_seek, ofw_real_seek), 1408446b206SNathan Whitehorn OFWMETHOD(ofw_claim, ofw_real_claim), 1418446b206SNathan Whitehorn OFWMETHOD(ofw_release, ofw_real_release), 1428446b206SNathan Whitehorn OFWMETHOD(ofw_enter, ofw_real_enter), 1438446b206SNathan Whitehorn OFWMETHOD(ofw_exit, ofw_real_exit), 1448446b206SNathan Whitehorn 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; 1718446b206SNathan Whitehorn static struct mtx of_bounce_mtx; 1728446b206SNathan Whitehorn 17370d75337SNathan Whitehorn extern int ofw_real_mode; 17470d75337SNathan Whitehorn 1758446b206SNathan Whitehorn /* 1768446b206SNathan Whitehorn * After the VM is up, allocate a wired, low memory bounce page. 1778446b206SNathan Whitehorn */ 1788446b206SNathan Whitehorn 1798446b206SNathan Whitehorn static void ofw_real_bounce_alloc(void *); 1808446b206SNathan Whitehorn 18170d75337SNathan Whitehorn SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY, 1828446b206SNathan Whitehorn ofw_real_bounce_alloc, NULL); 1838446b206SNathan Whitehorn 1848446b206SNathan Whitehorn static void 1858446b206SNathan Whitehorn ofw_real_start(void) 1868446b206SNathan Whitehorn { 1878446b206SNathan Whitehorn mtx_lock(&of_bounce_mtx); 1888446b206SNathan Whitehorn of_bounce_offset = 0; 1898446b206SNathan Whitehorn } 1908446b206SNathan Whitehorn 1918446b206SNathan Whitehorn static void 1928446b206SNathan Whitehorn ofw_real_stop(void) 1938446b206SNathan Whitehorn { 1948446b206SNathan Whitehorn mtx_unlock(&of_bounce_mtx); 1958446b206SNathan Whitehorn } 1968446b206SNathan Whitehorn 1978446b206SNathan Whitehorn static void 1988446b206SNathan Whitehorn ofw_real_bounce_alloc(void *junk) 1998446b206SNathan Whitehorn { 200d6d06708SJustin Hibbits caddr_t temp; 201d6d06708SJustin Hibbits 2028446b206SNathan Whitehorn /* 2038446b206SNathan Whitehorn * Check that ofw_real is actually in use before allocating wads 2048446b206SNathan Whitehorn * of memory. Do this by checking if our mutex has been set up. 2058446b206SNathan Whitehorn */ 2068446b206SNathan Whitehorn if (!mtx_initialized(&of_bounce_mtx)) 2078446b206SNathan Whitehorn return; 2088446b206SNathan Whitehorn 2098446b206SNathan Whitehorn /* 2108446b206SNathan Whitehorn * Allocate a page of contiguous, wired physical memory that can 21117879090SNathan Whitehorn * fit into a 32-bit address space and accessed from real mode. 2128446b206SNathan Whitehorn */ 213d6d06708SJustin Hibbits temp = contigmalloc(4 * PAGE_SIZE, M_OFWREAL, 0, 0, 214d6d06708SJustin Hibbits ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE, 215d6d06708SJustin Hibbits 4 * PAGE_SIZE); 216d6d06708SJustin Hibbits if (temp == NULL) 217d6d06708SJustin Hibbits panic("%s: Not able to allocated contiguous memory\n", __func__); 2188446b206SNathan Whitehorn 2198446b206SNathan Whitehorn mtx_lock(&of_bounce_mtx); 2208446b206SNathan Whitehorn 221d6d06708SJustin Hibbits of_bounce_virt = temp; 22270d75337SNathan Whitehorn 2238446b206SNathan Whitehorn of_bounce_phys = vtophys(of_bounce_virt); 22415b5b0acSJustin Hibbits of_bounce_size = 4 * PAGE_SIZE; 2258446b206SNathan Whitehorn 22670d75337SNathan Whitehorn /* 22770d75337SNathan Whitehorn * For virtual-mode OF, direct map this physical address so that 22870d75337SNathan Whitehorn * we have a 32-bit virtual address to give OF. 22970d75337SNathan Whitehorn */ 23070d75337SNathan Whitehorn 231f9edb09dSNathan Whitehorn if (!ofw_real_mode && (!hw_direct_map || DMAP_BASE_ADDRESS != 0)) 23270d75337SNathan Whitehorn pmap_kenter(of_bounce_phys, of_bounce_phys); 23370d75337SNathan Whitehorn 2348446b206SNathan Whitehorn mtx_unlock(&of_bounce_mtx); 2358446b206SNathan Whitehorn } 2368446b206SNathan Whitehorn 2378446b206SNathan Whitehorn static cell_t 2388446b206SNathan Whitehorn ofw_real_map(const void *buf, size_t len) 2398446b206SNathan Whitehorn { 24070d75337SNathan Whitehorn static char emergency_buffer[255]; 2418446b206SNathan Whitehorn cell_t phys; 2428446b206SNathan Whitehorn 2438446b206SNathan Whitehorn mtx_assert(&of_bounce_mtx, MA_OWNED); 2448446b206SNathan Whitehorn 2458446b206SNathan Whitehorn if (of_bounce_virt == NULL) { 24670d75337SNathan Whitehorn /* 24770d75337SNathan Whitehorn * If we haven't set up the MMU, then buf is guaranteed 24870d75337SNathan Whitehorn * to be accessible to OF, because the only memory we 24970d75337SNathan Whitehorn * can use right now is memory mapped by firmware. 25070d75337SNathan Whitehorn */ 2518446b206SNathan Whitehorn if (!pmap_bootstrapped) 252f9edb09dSNathan Whitehorn return (cell_t)((uintptr_t)buf & ~DMAP_BASE_ADDRESS); 2538446b206SNathan Whitehorn 2548446b206SNathan Whitehorn /* 2558446b206SNathan Whitehorn * XXX: It is possible for us to get called before the VM has 2568446b206SNathan Whitehorn * come online, but after the MMU is up. We don't have the 2578446b206SNathan Whitehorn * bounce buffer yet, but can no longer presume a 1:1 mapping. 25870d75337SNathan Whitehorn * Copy into the emergency buffer, and reset at the end. 2598446b206SNathan Whitehorn */ 26070d75337SNathan Whitehorn of_bounce_virt = emergency_buffer; 261f9edb09dSNathan Whitehorn of_bounce_phys = (vm_offset_t)of_bounce_virt & 262f9edb09dSNathan Whitehorn ~DMAP_BASE_ADDRESS; 26370d75337SNathan Whitehorn of_bounce_size = sizeof(emergency_buffer); 2648446b206SNathan Whitehorn } 2658446b206SNathan Whitehorn 2668446b206SNathan Whitehorn /* 2678446b206SNathan Whitehorn * Make sure the bounce page offset satisfies any reasonable 2688446b206SNathan Whitehorn * alignment constraint. 2698446b206SNathan Whitehorn */ 270f9edb09dSNathan Whitehorn of_bounce_offset += sizeof(register_t) - 271f9edb09dSNathan Whitehorn (of_bounce_offset % sizeof(register_t)); 2728446b206SNathan Whitehorn 2738446b206SNathan Whitehorn if (of_bounce_offset + len > of_bounce_size) { 2748446b206SNathan Whitehorn panic("Oversize Open Firmware call!"); 2758446b206SNathan Whitehorn return 0; 2768446b206SNathan Whitehorn } 2778446b206SNathan Whitehorn 278ec664c11SAndreas Tobler if (buf != NULL) 2798446b206SNathan Whitehorn memcpy(of_bounce_virt + of_bounce_offset, buf, len); 280ec664c11SAndreas Tobler else 281ec664c11SAndreas Tobler return (0); 282ec664c11SAndreas Tobler 2838446b206SNathan Whitehorn phys = of_bounce_phys + of_bounce_offset; 2848446b206SNathan Whitehorn 2858446b206SNathan Whitehorn of_bounce_offset += len; 2868446b206SNathan Whitehorn 28770d75337SNathan Whitehorn return (phys); 2888446b206SNathan Whitehorn } 2898446b206SNathan Whitehorn 2908446b206SNathan Whitehorn static void 2918446b206SNathan Whitehorn ofw_real_unmap(cell_t physaddr, void *buf, size_t len) 2928446b206SNathan Whitehorn { 2938446b206SNathan Whitehorn mtx_assert(&of_bounce_mtx, MA_OWNED); 2948446b206SNathan Whitehorn 2958446b206SNathan Whitehorn if (of_bounce_virt == NULL) 2968446b206SNathan Whitehorn return; 2978446b206SNathan Whitehorn 298ec664c11SAndreas Tobler if (physaddr == 0) 299ec664c11SAndreas Tobler return; 300ec664c11SAndreas Tobler 3018446b206SNathan Whitehorn memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len); 3028446b206SNathan Whitehorn } 3038446b206SNathan Whitehorn 3048446b206SNathan Whitehorn /* Initialiser */ 3058446b206SNathan Whitehorn 3068297758aSRafal Jaworowski static int 3078446b206SNathan Whitehorn ofw_real_init(ofw_t ofw, void *openfirm) 3088446b206SNathan Whitehorn { 3098446b206SNathan Whitehorn openfirmware = (int (*)(void *))openfirm; 3108446b206SNathan Whitehorn 311d01195e3SChristian Brueffer mtx_init(&of_bounce_mtx, "OF Bounce Page", NULL, MTX_DEF); 3128446b206SNathan Whitehorn of_bounce_virt = NULL; 3138297758aSRafal Jaworowski return (0); 3148446b206SNathan Whitehorn } 3158446b206SNathan Whitehorn 3168446b206SNathan Whitehorn /* 3178446b206SNathan Whitehorn * Generic functions 3188446b206SNathan Whitehorn */ 3198446b206SNathan Whitehorn 3208446b206SNathan Whitehorn /* Test to see if a service exists. */ 3218446b206SNathan Whitehorn static int 3228446b206SNathan Whitehorn ofw_real_test(ofw_t ofw, const char *name) 3238446b206SNathan Whitehorn { 32470d75337SNathan Whitehorn vm_offset_t argsptr; 325d4bccd63SNathan Whitehorn struct { 3268446b206SNathan Whitehorn cell_t name; 3278446b206SNathan Whitehorn cell_t nargs; 3288446b206SNathan Whitehorn cell_t nreturns; 3298446b206SNathan Whitehorn cell_t service; 3308446b206SNathan Whitehorn cell_t missing; 33170d75337SNathan Whitehorn } args; 33270d75337SNathan Whitehorn 33370d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"test"; 33470d75337SNathan Whitehorn args.nargs = 1; 33570d75337SNathan Whitehorn args.nreturns = 1; 3368446b206SNathan Whitehorn 3378446b206SNathan Whitehorn ofw_real_start(); 3388446b206SNathan Whitehorn 3398446b206SNathan Whitehorn args.service = ofw_real_map(name, strlen(name) + 1); 34070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 34170d75337SNathan Whitehorn if (args.service == 0 || openfirmware((void *)argsptr) == -1) { 3428446b206SNathan Whitehorn ofw_real_stop(); 3438446b206SNathan Whitehorn return (-1); 3448446b206SNathan Whitehorn } 34570d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 3468446b206SNathan Whitehorn ofw_real_stop(); 3478446b206SNathan Whitehorn return (args.missing); 3488446b206SNathan Whitehorn } 3498446b206SNathan Whitehorn 3508446b206SNathan Whitehorn /* 3518446b206SNathan Whitehorn * Device tree functions 3528446b206SNathan Whitehorn */ 3538446b206SNathan Whitehorn 3548446b206SNathan Whitehorn /* Return the next sibling of this node or 0. */ 3558446b206SNathan Whitehorn static phandle_t 3568446b206SNathan Whitehorn ofw_real_peer(ofw_t ofw, phandle_t node) 3578446b206SNathan Whitehorn { 35870d75337SNathan Whitehorn vm_offset_t argsptr; 359d4bccd63SNathan Whitehorn struct { 3608446b206SNathan Whitehorn cell_t name; 3618446b206SNathan Whitehorn cell_t nargs; 3628446b206SNathan Whitehorn cell_t nreturns; 3638446b206SNathan Whitehorn cell_t node; 3648446b206SNathan Whitehorn cell_t next; 36570d75337SNathan Whitehorn } args; 36670d75337SNathan Whitehorn 36770d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"peer"; 36870d75337SNathan Whitehorn args.nargs = 1; 36970d75337SNathan Whitehorn args.nreturns = 1; 3708446b206SNathan Whitehorn 3718446b206SNathan Whitehorn args.node = node; 37270d75337SNathan Whitehorn ofw_real_start(); 37370d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 37470d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 37570d75337SNathan Whitehorn ofw_real_stop(); 37665184f89SNathan Whitehorn return (0); 37770d75337SNathan Whitehorn } 37870d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 37970d75337SNathan Whitehorn ofw_real_stop(); 3808446b206SNathan Whitehorn return (args.next); 3818446b206SNathan Whitehorn } 3828446b206SNathan Whitehorn 3838446b206SNathan Whitehorn /* Return the first child of this node or 0. */ 3848446b206SNathan Whitehorn static phandle_t 3858446b206SNathan Whitehorn ofw_real_child(ofw_t ofw, phandle_t node) 3868446b206SNathan Whitehorn { 38770d75337SNathan Whitehorn vm_offset_t argsptr; 388d4bccd63SNathan Whitehorn struct { 3898446b206SNathan Whitehorn cell_t name; 3908446b206SNathan Whitehorn cell_t nargs; 3918446b206SNathan Whitehorn cell_t nreturns; 3928446b206SNathan Whitehorn cell_t node; 3938446b206SNathan Whitehorn cell_t child; 39470d75337SNathan Whitehorn } args; 39570d75337SNathan Whitehorn 39670d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"child"; 39770d75337SNathan Whitehorn args.nargs = 1; 39870d75337SNathan Whitehorn args.nreturns = 1; 3998446b206SNathan Whitehorn 4008446b206SNathan Whitehorn args.node = node; 40170d75337SNathan Whitehorn ofw_real_start(); 40270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 40370d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 40470d75337SNathan Whitehorn ofw_real_stop(); 40565184f89SNathan Whitehorn return (0); 40670d75337SNathan Whitehorn } 40770d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 40870d75337SNathan Whitehorn ofw_real_stop(); 4098446b206SNathan Whitehorn return (args.child); 4108446b206SNathan Whitehorn } 4118446b206SNathan Whitehorn 4128446b206SNathan Whitehorn /* Return the parent of this node or 0. */ 4138446b206SNathan Whitehorn static phandle_t 4148446b206SNathan Whitehorn ofw_real_parent(ofw_t ofw, phandle_t node) 4158446b206SNathan Whitehorn { 41670d75337SNathan Whitehorn vm_offset_t argsptr; 417d4bccd63SNathan Whitehorn struct { 4188446b206SNathan Whitehorn cell_t name; 4198446b206SNathan Whitehorn cell_t nargs; 4208446b206SNathan Whitehorn cell_t nreturns; 4218446b206SNathan Whitehorn cell_t node; 4228446b206SNathan Whitehorn cell_t parent; 42370d75337SNathan Whitehorn } args; 42470d75337SNathan Whitehorn 42570d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"parent"; 42670d75337SNathan Whitehorn args.nargs = 1; 42770d75337SNathan Whitehorn args.nreturns = 1; 4288446b206SNathan Whitehorn 4298446b206SNathan Whitehorn args.node = node; 43070d75337SNathan Whitehorn ofw_real_start(); 43170d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 43270d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 43370d75337SNathan Whitehorn ofw_real_stop(); 43465184f89SNathan Whitehorn return (0); 43570d75337SNathan Whitehorn } 43670d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 43770d75337SNathan Whitehorn ofw_real_stop(); 4388446b206SNathan Whitehorn return (args.parent); 4398446b206SNathan Whitehorn } 4408446b206SNathan Whitehorn 4418446b206SNathan Whitehorn /* Return the package handle that corresponds to an instance handle. */ 4428446b206SNathan Whitehorn static phandle_t 4438446b206SNathan Whitehorn ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance) 4448446b206SNathan Whitehorn { 44570d75337SNathan Whitehorn vm_offset_t argsptr; 446d4bccd63SNathan Whitehorn struct { 4478446b206SNathan Whitehorn cell_t name; 4488446b206SNathan Whitehorn cell_t nargs; 4498446b206SNathan Whitehorn cell_t nreturns; 4508446b206SNathan Whitehorn cell_t instance; 4518446b206SNathan Whitehorn cell_t package; 45270d75337SNathan Whitehorn } args; 45370d75337SNathan Whitehorn 45470d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"instance-to-package"; 45570d75337SNathan Whitehorn args.nargs = 1; 45670d75337SNathan Whitehorn args.nreturns = 1; 4578446b206SNathan Whitehorn 4588446b206SNathan Whitehorn args.instance = instance; 45970d75337SNathan Whitehorn ofw_real_start(); 46070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 46170d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 46270d75337SNathan Whitehorn ofw_real_stop(); 4638446b206SNathan Whitehorn return (-1); 46470d75337SNathan Whitehorn } 46570d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 46670d75337SNathan Whitehorn ofw_real_stop(); 4678446b206SNathan Whitehorn return (args.package); 4688446b206SNathan Whitehorn } 4698446b206SNathan Whitehorn 4708446b206SNathan Whitehorn /* Get the length of a property of a package. */ 4718446b206SNathan Whitehorn static ssize_t 4728446b206SNathan Whitehorn ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname) 4738446b206SNathan Whitehorn { 47470d75337SNathan Whitehorn vm_offset_t argsptr; 475d4bccd63SNathan Whitehorn struct { 4768446b206SNathan Whitehorn cell_t name; 4778446b206SNathan Whitehorn cell_t nargs; 4788446b206SNathan Whitehorn cell_t nreturns; 4798446b206SNathan Whitehorn cell_t package; 4808446b206SNathan Whitehorn cell_t propname; 48170d75337SNathan Whitehorn int32_t proplen; 48270d75337SNathan Whitehorn } args; 48370d75337SNathan Whitehorn 48470d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"getproplen"; 48570d75337SNathan Whitehorn args.nargs = 2; 48670d75337SNathan Whitehorn args.nreturns = 1; 4878446b206SNathan Whitehorn 4888446b206SNathan Whitehorn ofw_real_start(); 4898446b206SNathan Whitehorn 4908446b206SNathan Whitehorn args.package = package; 4918446b206SNathan Whitehorn args.propname = ofw_real_map(propname, strlen(propname) + 1); 49270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 49370d75337SNathan Whitehorn if (args.propname == 0 || openfirmware((void *)argsptr) == -1) { 4948446b206SNathan Whitehorn ofw_real_stop(); 4958446b206SNathan Whitehorn return (-1); 4968446b206SNathan Whitehorn } 49770d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 4988446b206SNathan Whitehorn ofw_real_stop(); 4998446b206SNathan Whitehorn return (args.proplen); 5008446b206SNathan Whitehorn } 5018446b206SNathan Whitehorn 5028446b206SNathan Whitehorn /* Get the value of a property of a package. */ 5038446b206SNathan Whitehorn static ssize_t 5048446b206SNathan Whitehorn ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, 5058446b206SNathan Whitehorn size_t buflen) 5068446b206SNathan Whitehorn { 50770d75337SNathan Whitehorn vm_offset_t argsptr; 508d4bccd63SNathan Whitehorn struct { 5098446b206SNathan Whitehorn cell_t name; 5108446b206SNathan Whitehorn cell_t nargs; 5118446b206SNathan Whitehorn cell_t nreturns; 5128446b206SNathan Whitehorn cell_t package; 5138446b206SNathan Whitehorn cell_t propname; 5148446b206SNathan Whitehorn cell_t buf; 5158446b206SNathan Whitehorn cell_t buflen; 51670d75337SNathan Whitehorn int32_t size; 51770d75337SNathan Whitehorn } args; 51870d75337SNathan Whitehorn 51970d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"getprop"; 52070d75337SNathan Whitehorn args.nargs = 4; 52170d75337SNathan Whitehorn args.nreturns = 1; 5228446b206SNathan Whitehorn 5238446b206SNathan Whitehorn ofw_real_start(); 5248446b206SNathan Whitehorn 5258446b206SNathan Whitehorn args.package = package; 5268446b206SNathan Whitehorn args.propname = ofw_real_map(propname, strlen(propname) + 1); 5278446b206SNathan Whitehorn args.buf = ofw_real_map(buf, buflen); 5288446b206SNathan Whitehorn args.buflen = buflen; 52970d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 53070d75337SNathan Whitehorn if (args.propname == 0 || args.buf == 0 || 53170d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 5328446b206SNathan Whitehorn ofw_real_stop(); 5338446b206SNathan Whitehorn return (-1); 5348446b206SNathan Whitehorn } 53570d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 5368446b206SNathan Whitehorn ofw_real_unmap(args.buf, buf, buflen); 5378446b206SNathan Whitehorn 5388446b206SNathan Whitehorn ofw_real_stop(); 5398446b206SNathan Whitehorn return (args.size); 5408446b206SNathan Whitehorn } 5418446b206SNathan Whitehorn 5428446b206SNathan Whitehorn /* Get the next property of a package. */ 5438446b206SNathan Whitehorn static int 5448446b206SNathan Whitehorn ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous, 5458446b206SNathan Whitehorn char *buf, size_t size) 5468446b206SNathan Whitehorn { 54770d75337SNathan Whitehorn vm_offset_t argsptr; 548d4bccd63SNathan Whitehorn struct { 5498446b206SNathan Whitehorn cell_t name; 5508446b206SNathan Whitehorn cell_t nargs; 5518446b206SNathan Whitehorn cell_t nreturns; 5528446b206SNathan Whitehorn cell_t package; 5538446b206SNathan Whitehorn cell_t previous; 5548446b206SNathan Whitehorn cell_t buf; 5558446b206SNathan Whitehorn cell_t flag; 55670d75337SNathan Whitehorn } args; 55770d75337SNathan Whitehorn 55870d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"nextprop"; 55970d75337SNathan Whitehorn args.nargs = 3; 56070d75337SNathan Whitehorn args.nreturns = 1; 5618446b206SNathan Whitehorn 5628446b206SNathan Whitehorn ofw_real_start(); 5638446b206SNathan Whitehorn 5648446b206SNathan Whitehorn args.package = package; 565ec664c11SAndreas Tobler args.previous = ofw_real_map(previous, (previous != NULL) ? (strlen(previous) + 1) : 0); 5668446b206SNathan Whitehorn args.buf = ofw_real_map(buf, size); 56770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 568ec664c11SAndreas Tobler if (args.buf == 0 || openfirmware((void *)argsptr) == -1) { 5698446b206SNathan Whitehorn ofw_real_stop(); 5708446b206SNathan Whitehorn return (-1); 5718446b206SNathan Whitehorn } 57270d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 5738446b206SNathan Whitehorn ofw_real_unmap(args.buf, buf, size); 5748446b206SNathan Whitehorn 5758446b206SNathan Whitehorn ofw_real_stop(); 5768446b206SNathan Whitehorn return (args.flag); 5778446b206SNathan Whitehorn } 5788446b206SNathan Whitehorn 5798446b206SNathan Whitehorn /* Set the value of a property of a package. */ 5808446b206SNathan Whitehorn /* XXX Has a bug on FirePower */ 5818446b206SNathan Whitehorn static int 5824fc23012SAndriy Gapon ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname, 5834fc23012SAndriy Gapon const void *buf, size_t len) 5848446b206SNathan Whitehorn { 58570d75337SNathan Whitehorn vm_offset_t argsptr; 586d4bccd63SNathan Whitehorn struct { 5878446b206SNathan Whitehorn cell_t name; 5888446b206SNathan Whitehorn cell_t nargs; 5898446b206SNathan Whitehorn cell_t nreturns; 5908446b206SNathan Whitehorn cell_t package; 5918446b206SNathan Whitehorn cell_t propname; 5928446b206SNathan Whitehorn cell_t buf; 5938446b206SNathan Whitehorn cell_t len; 5948446b206SNathan Whitehorn cell_t size; 59570d75337SNathan Whitehorn } args; 59670d75337SNathan Whitehorn 59770d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"setprop"; 59870d75337SNathan Whitehorn args.nargs = 4; 59970d75337SNathan Whitehorn args.nreturns = 1; 6008446b206SNathan Whitehorn 6018446b206SNathan Whitehorn ofw_real_start(); 6028446b206SNathan Whitehorn 6038446b206SNathan Whitehorn args.package = package; 6048446b206SNathan Whitehorn args.propname = ofw_real_map(propname, strlen(propname) + 1); 6058446b206SNathan Whitehorn args.buf = ofw_real_map(buf, len); 6068446b206SNathan Whitehorn args.len = len; 60770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 60870d75337SNathan Whitehorn if (args.propname == 0 || args.buf == 0 || 60970d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 6108446b206SNathan Whitehorn ofw_real_stop(); 6118446b206SNathan Whitehorn return (-1); 6128446b206SNathan Whitehorn } 61370d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 6148446b206SNathan Whitehorn ofw_real_stop(); 6158446b206SNathan Whitehorn return (args.size); 6168446b206SNathan Whitehorn } 6178446b206SNathan Whitehorn 6188446b206SNathan Whitehorn /* Convert a device specifier to a fully qualified pathname. */ 6198446b206SNathan Whitehorn static ssize_t 6208446b206SNathan Whitehorn ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len) 6218446b206SNathan Whitehorn { 62270d75337SNathan Whitehorn vm_offset_t argsptr; 623d4bccd63SNathan Whitehorn struct { 6248446b206SNathan Whitehorn cell_t name; 6258446b206SNathan Whitehorn cell_t nargs; 6268446b206SNathan Whitehorn cell_t nreturns; 6278446b206SNathan Whitehorn cell_t device; 6288446b206SNathan Whitehorn cell_t buf; 6298446b206SNathan Whitehorn cell_t len; 63070d75337SNathan Whitehorn int32_t size; 63170d75337SNathan Whitehorn } args; 63270d75337SNathan Whitehorn 63370d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"canon"; 63470d75337SNathan Whitehorn args.nargs = 3; 63570d75337SNathan Whitehorn args.nreturns = 1; 6368446b206SNathan Whitehorn 6378446b206SNathan Whitehorn ofw_real_start(); 6388446b206SNathan Whitehorn 6398446b206SNathan Whitehorn args.device = ofw_real_map(device, strlen(device) + 1); 6408446b206SNathan Whitehorn args.buf = ofw_real_map(buf, len); 6418446b206SNathan Whitehorn args.len = len; 64270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 64370d75337SNathan Whitehorn if (args.device == 0 || args.buf == 0 || 64470d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 6458446b206SNathan Whitehorn ofw_real_stop(); 6468446b206SNathan Whitehorn return (-1); 6478446b206SNathan Whitehorn } 64870d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 6498446b206SNathan Whitehorn ofw_real_unmap(args.buf, buf, len); 6508446b206SNathan Whitehorn 6518446b206SNathan Whitehorn ofw_real_stop(); 6528446b206SNathan Whitehorn return (args.size); 6538446b206SNathan Whitehorn } 6548446b206SNathan Whitehorn 6558446b206SNathan Whitehorn /* Return a package handle for the specified device. */ 6568446b206SNathan Whitehorn static phandle_t 6578446b206SNathan Whitehorn ofw_real_finddevice(ofw_t ofw, const char *device) 6588446b206SNathan Whitehorn { 65970d75337SNathan Whitehorn vm_offset_t argsptr; 660d4bccd63SNathan Whitehorn struct { 6618446b206SNathan Whitehorn cell_t name; 6628446b206SNathan Whitehorn cell_t nargs; 6638446b206SNathan Whitehorn cell_t nreturns; 6648446b206SNathan Whitehorn cell_t device; 6658446b206SNathan Whitehorn cell_t package; 66670d75337SNathan Whitehorn } args; 66770d75337SNathan Whitehorn 66870d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"finddevice"; 66970d75337SNathan Whitehorn args.nargs = 1; 67070d75337SNathan Whitehorn args.nreturns = 1; 6718446b206SNathan Whitehorn 6728446b206SNathan Whitehorn ofw_real_start(); 6738446b206SNathan Whitehorn 6748446b206SNathan Whitehorn args.device = ofw_real_map(device, strlen(device) + 1); 67570d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 67670d75337SNathan Whitehorn if (args.device == 0 || 67770d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 6788446b206SNathan Whitehorn ofw_real_stop(); 6798446b206SNathan Whitehorn return (-1); 6808446b206SNathan Whitehorn } 68170d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 6828446b206SNathan Whitehorn ofw_real_stop(); 6838446b206SNathan Whitehorn return (args.package); 6848446b206SNathan Whitehorn } 6858446b206SNathan Whitehorn 6868446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to an instance. */ 6878446b206SNathan Whitehorn static ssize_t 6888446b206SNathan Whitehorn ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) 6898446b206SNathan Whitehorn { 69070d75337SNathan Whitehorn vm_offset_t argsptr; 691d4bccd63SNathan Whitehorn struct { 6928446b206SNathan Whitehorn cell_t name; 6938446b206SNathan Whitehorn cell_t nargs; 6948446b206SNathan Whitehorn cell_t nreturns; 6958446b206SNathan Whitehorn cell_t instance; 6968446b206SNathan Whitehorn cell_t buf; 6978446b206SNathan Whitehorn cell_t len; 69870d75337SNathan Whitehorn int32_t size; 69970d75337SNathan Whitehorn } args; 70070d75337SNathan Whitehorn 70170d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"instance-to-path"; 70270d75337SNathan Whitehorn args.nargs = 3; 70370d75337SNathan Whitehorn args.nreturns = 1; 7048446b206SNathan Whitehorn 7058446b206SNathan Whitehorn ofw_real_start(); 7068446b206SNathan Whitehorn 7078446b206SNathan Whitehorn args.instance = instance; 7088446b206SNathan Whitehorn args.buf = ofw_real_map(buf, len); 7098446b206SNathan Whitehorn args.len = len; 71070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 71170d75337SNathan Whitehorn if (args.buf == 0 || 71270d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 7138446b206SNathan Whitehorn ofw_real_stop(); 7148446b206SNathan Whitehorn return (-1); 7158446b206SNathan Whitehorn } 71670d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 7178446b206SNathan Whitehorn ofw_real_unmap(args.buf, buf, len); 7188446b206SNathan Whitehorn 7198446b206SNathan Whitehorn ofw_real_stop(); 7208446b206SNathan Whitehorn return (args.size); 7218446b206SNathan Whitehorn } 7228446b206SNathan Whitehorn 7238446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to a package. */ 7248446b206SNathan Whitehorn static ssize_t 7258446b206SNathan Whitehorn ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len) 7268446b206SNathan Whitehorn { 72770d75337SNathan Whitehorn vm_offset_t argsptr; 728d4bccd63SNathan Whitehorn struct { 7298446b206SNathan Whitehorn cell_t name; 7308446b206SNathan Whitehorn cell_t nargs; 7318446b206SNathan Whitehorn cell_t nreturns; 7328446b206SNathan Whitehorn cell_t package; 7338446b206SNathan Whitehorn cell_t buf; 7348446b206SNathan Whitehorn cell_t len; 73570d75337SNathan Whitehorn int32_t size; 73670d75337SNathan Whitehorn } args; 73770d75337SNathan Whitehorn 73870d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"package-to-path"; 73970d75337SNathan Whitehorn args.nargs = 3; 74070d75337SNathan Whitehorn args.nreturns = 1; 7418446b206SNathan Whitehorn 7428446b206SNathan Whitehorn ofw_real_start(); 7438446b206SNathan Whitehorn 7448446b206SNathan Whitehorn args.package = package; 7458446b206SNathan Whitehorn args.buf = ofw_real_map(buf, len); 7468446b206SNathan Whitehorn args.len = len; 74770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 74870d75337SNathan Whitehorn if (args.buf == 0 || 74970d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 7508446b206SNathan Whitehorn ofw_real_stop(); 7518446b206SNathan Whitehorn return (-1); 7528446b206SNathan Whitehorn } 75370d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 7548446b206SNathan Whitehorn ofw_real_unmap(args.buf, buf, len); 7558446b206SNathan Whitehorn 7568446b206SNathan Whitehorn ofw_real_stop(); 7578446b206SNathan Whitehorn return (args.size); 7588446b206SNathan Whitehorn } 7598446b206SNathan Whitehorn 7608446b206SNathan Whitehorn /* Call the method in the scope of a given instance. */ 7618446b206SNathan Whitehorn static int 7628446b206SNathan Whitehorn ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, 763054e5dcbSNathan Whitehorn int nargs, int nreturns, cell_t *args_and_returns) 7648446b206SNathan Whitehorn { 76570d75337SNathan Whitehorn vm_offset_t argsptr; 766d4bccd63SNathan Whitehorn struct { 7678446b206SNathan Whitehorn cell_t name; 7688446b206SNathan Whitehorn cell_t nargs; 7698446b206SNathan Whitehorn cell_t nreturns; 7708446b206SNathan Whitehorn cell_t method; 7718446b206SNathan Whitehorn cell_t instance; 7728446b206SNathan Whitehorn cell_t args_n_results[12]; 77370d75337SNathan Whitehorn } args; 774cdb25d82SMarius Strobl cell_t *ap, *cp; 7758446b206SNathan Whitehorn int n; 7768446b206SNathan Whitehorn 77770d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"call-method"; 77870d75337SNathan Whitehorn args.nargs = 2; 77970d75337SNathan Whitehorn args.nreturns = 1; 78070d75337SNathan Whitehorn 7818446b206SNathan Whitehorn if (nargs > 6) 7828446b206SNathan Whitehorn return (-1); 7838446b206SNathan Whitehorn 7848446b206SNathan Whitehorn ofw_real_start(); 7858446b206SNathan Whitehorn args.nargs = nargs + 2; 7868446b206SNathan Whitehorn args.nreturns = nreturns + 1; 7878446b206SNathan Whitehorn args.method = ofw_real_map(method, strlen(method) + 1); 7888446b206SNathan Whitehorn args.instance = instance; 7898446b206SNathan Whitehorn 7908446b206SNathan Whitehorn ap = args_and_returns; 7918446b206SNathan Whitehorn for (cp = args.args_n_results + (n = nargs); --n >= 0;) 7928446b206SNathan Whitehorn *--cp = *(ap++); 79370d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 79470d75337SNathan Whitehorn if (args.method == 0 || 79570d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) { 7968446b206SNathan Whitehorn ofw_real_stop(); 7978446b206SNathan Whitehorn return (-1); 7988446b206SNathan Whitehorn } 79970d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 8008446b206SNathan Whitehorn ofw_real_stop(); 8018446b206SNathan Whitehorn if (args.args_n_results[nargs]) 8028446b206SNathan Whitehorn return (args.args_n_results[nargs]); 8038446b206SNathan Whitehorn for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) 8048446b206SNathan Whitehorn *(ap++) = *--cp; 8058446b206SNathan Whitehorn return (0); 8068446b206SNathan Whitehorn } 8078446b206SNathan Whitehorn 80870d75337SNathan Whitehorn static int 809cdb25d82SMarius Strobl ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns) 81070d75337SNathan Whitehorn { 81170d75337SNathan Whitehorn vm_offset_t argsptr; 81270d75337SNathan Whitehorn struct { 81370d75337SNathan Whitehorn cell_t name; 81470d75337SNathan Whitehorn cell_t nargs; 81570d75337SNathan Whitehorn cell_t nreturns; 81670d75337SNathan Whitehorn cell_t slot[16]; 81770d75337SNathan Whitehorn } args; 81870d75337SNathan Whitehorn cell_t status; 81970d75337SNathan Whitehorn int i = 0, j = 0; 82070d75337SNathan Whitehorn 82170d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"interpret"; 82270d75337SNathan Whitehorn args.nargs = 1; 82370d75337SNathan Whitehorn 82470d75337SNathan Whitehorn ofw_real_start(); 82570d75337SNathan Whitehorn args.nreturns = ++nreturns; 82670d75337SNathan Whitehorn args.slot[i++] = ofw_real_map(cmd, strlen(cmd) + 1); 82770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 82870d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 82970d75337SNathan Whitehorn ofw_real_stop(); 83070d75337SNathan Whitehorn return (-1); 83170d75337SNathan Whitehorn } 83270d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 83370d75337SNathan Whitehorn ofw_real_stop(); 83470d75337SNathan Whitehorn status = args.slot[i++]; 83570d75337SNathan Whitehorn while (i < 1 + nreturns) 83670d75337SNathan Whitehorn returns[j++] = args.slot[i++]; 83770d75337SNathan Whitehorn return (status); 83870d75337SNathan Whitehorn } 83970d75337SNathan Whitehorn 8408446b206SNathan Whitehorn /* 8418446b206SNathan Whitehorn * Device I/O functions 8428446b206SNathan Whitehorn */ 8438446b206SNathan Whitehorn 8448446b206SNathan Whitehorn /* Open an instance for a device. */ 8458446b206SNathan Whitehorn static ihandle_t 8468446b206SNathan Whitehorn ofw_real_open(ofw_t ofw, const char *device) 8478446b206SNathan Whitehorn { 84870d75337SNathan Whitehorn vm_offset_t argsptr; 849d4bccd63SNathan Whitehorn struct { 8508446b206SNathan Whitehorn cell_t name; 8518446b206SNathan Whitehorn cell_t nargs; 8528446b206SNathan Whitehorn cell_t nreturns; 8538446b206SNathan Whitehorn cell_t device; 8548446b206SNathan Whitehorn cell_t instance; 85570d75337SNathan Whitehorn } args; 85670d75337SNathan Whitehorn 85770d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"open"; 85870d75337SNathan Whitehorn args.nargs = 1; 85970d75337SNathan Whitehorn args.nreturns = 1; 8608446b206SNathan Whitehorn 8618446b206SNathan Whitehorn ofw_real_start(); 8628446b206SNathan Whitehorn 8638446b206SNathan Whitehorn args.device = ofw_real_map(device, strlen(device) + 1); 86470d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 86570d75337SNathan Whitehorn if (args.device == 0 || openfirmware((void *)argsptr) == -1 8668446b206SNathan Whitehorn || args.instance == 0) { 8678446b206SNathan Whitehorn ofw_real_stop(); 8688446b206SNathan Whitehorn return (-1); 8698446b206SNathan Whitehorn } 87070d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 8718446b206SNathan Whitehorn ofw_real_stop(); 8728446b206SNathan Whitehorn return (args.instance); 8738446b206SNathan Whitehorn } 8748446b206SNathan Whitehorn 8758446b206SNathan Whitehorn /* Close an instance. */ 8768446b206SNathan Whitehorn static void 8778446b206SNathan Whitehorn ofw_real_close(ofw_t ofw, ihandle_t instance) 8788446b206SNathan Whitehorn { 87970d75337SNathan Whitehorn vm_offset_t argsptr; 880d4bccd63SNathan Whitehorn struct { 8818446b206SNathan Whitehorn cell_t name; 8828446b206SNathan Whitehorn cell_t nargs; 8838446b206SNathan Whitehorn cell_t nreturns; 8848446b206SNathan Whitehorn cell_t instance; 88570d75337SNathan Whitehorn } args; 8868446b206SNathan Whitehorn 88770d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"close"; 88870d75337SNathan Whitehorn args.nargs = 1; 88970d75337SNathan Whitehorn args.nreturns = 0; 8908446b206SNathan Whitehorn args.instance = instance; 89170d75337SNathan Whitehorn ofw_real_start(); 89270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 89370d75337SNathan Whitehorn openfirmware((void *)argsptr); 89470d75337SNathan Whitehorn ofw_real_stop(); 8958446b206SNathan Whitehorn } 8968446b206SNathan Whitehorn 8978446b206SNathan Whitehorn /* Read from an instance. */ 8988446b206SNathan Whitehorn static ssize_t 8998446b206SNathan Whitehorn ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) 9008446b206SNathan Whitehorn { 90170d75337SNathan Whitehorn vm_offset_t argsptr; 902d4bccd63SNathan Whitehorn struct { 9038446b206SNathan Whitehorn cell_t name; 9048446b206SNathan Whitehorn cell_t nargs; 9058446b206SNathan Whitehorn cell_t nreturns; 9068446b206SNathan Whitehorn cell_t instance; 9078446b206SNathan Whitehorn cell_t addr; 9088446b206SNathan Whitehorn cell_t len; 90970d75337SNathan Whitehorn int32_t actual; 91070d75337SNathan Whitehorn } args; 91170d75337SNathan Whitehorn 91270d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"read"; 91370d75337SNathan Whitehorn args.nargs = 3; 91470d75337SNathan Whitehorn args.nreturns = 1; 9158446b206SNathan Whitehorn 9168446b206SNathan Whitehorn ofw_real_start(); 9178446b206SNathan Whitehorn 9188446b206SNathan Whitehorn args.instance = instance; 9198446b206SNathan Whitehorn args.addr = ofw_real_map(addr, len); 9208446b206SNathan Whitehorn args.len = len; 92170d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 92270d75337SNathan Whitehorn if (args.addr == 0 || openfirmware((void *)argsptr) == -1) { 9238446b206SNathan Whitehorn ofw_real_stop(); 9248446b206SNathan Whitehorn return (-1); 9258446b206SNathan Whitehorn } 92670d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 9278446b206SNathan Whitehorn ofw_real_unmap(args.addr, addr, len); 9288446b206SNathan Whitehorn 9298446b206SNathan Whitehorn ofw_real_stop(); 9308446b206SNathan Whitehorn return (args.actual); 9318446b206SNathan Whitehorn } 9328446b206SNathan Whitehorn 9338446b206SNathan Whitehorn /* Write to an instance. */ 9348446b206SNathan Whitehorn static ssize_t 9358446b206SNathan Whitehorn ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) 9368446b206SNathan Whitehorn { 93770d75337SNathan Whitehorn vm_offset_t argsptr; 938d4bccd63SNathan Whitehorn struct { 9398446b206SNathan Whitehorn cell_t name; 9408446b206SNathan Whitehorn cell_t nargs; 9418446b206SNathan Whitehorn cell_t nreturns; 9428446b206SNathan Whitehorn cell_t instance; 9438446b206SNathan Whitehorn cell_t addr; 9448446b206SNathan Whitehorn cell_t len; 94570d75337SNathan Whitehorn int32_t actual; 94670d75337SNathan Whitehorn } args; 94770d75337SNathan Whitehorn 94870d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"write"; 94970d75337SNathan Whitehorn args.nargs = 3; 95070d75337SNathan Whitehorn args.nreturns = 1; 9518446b206SNathan Whitehorn 9528446b206SNathan Whitehorn ofw_real_start(); 9538446b206SNathan Whitehorn 9548446b206SNathan Whitehorn args.instance = instance; 9558446b206SNathan Whitehorn args.addr = ofw_real_map(addr, len); 9568446b206SNathan Whitehorn args.len = len; 95770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 95870d75337SNathan Whitehorn if (args.addr == 0 || openfirmware((void *)argsptr) == -1) { 9598446b206SNathan Whitehorn ofw_real_stop(); 9608446b206SNathan Whitehorn return (-1); 9618446b206SNathan Whitehorn } 96270d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 9638446b206SNathan Whitehorn ofw_real_stop(); 9648446b206SNathan Whitehorn return (args.actual); 9658446b206SNathan Whitehorn } 9668446b206SNathan Whitehorn 9678446b206SNathan Whitehorn /* Seek to a position. */ 9688446b206SNathan Whitehorn static int 9698446b206SNathan Whitehorn ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos) 9708446b206SNathan Whitehorn { 97170d75337SNathan Whitehorn vm_offset_t argsptr; 972d4bccd63SNathan Whitehorn struct { 9738446b206SNathan Whitehorn cell_t name; 9748446b206SNathan Whitehorn cell_t nargs; 9758446b206SNathan Whitehorn cell_t nreturns; 9768446b206SNathan Whitehorn cell_t instance; 9778446b206SNathan Whitehorn cell_t poshi; 9788446b206SNathan Whitehorn cell_t poslo; 9798446b206SNathan Whitehorn cell_t status; 98070d75337SNathan Whitehorn } args; 98170d75337SNathan Whitehorn 98270d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"seek"; 98370d75337SNathan Whitehorn args.nargs = 3; 98470d75337SNathan Whitehorn args.nreturns = 1; 9858446b206SNathan Whitehorn 9868446b206SNathan Whitehorn args.instance = instance; 9878446b206SNathan Whitehorn args.poshi = pos >> 32; 9888446b206SNathan Whitehorn args.poslo = pos; 98970d75337SNathan Whitehorn ofw_real_start(); 99070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 99170d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 99270d75337SNathan Whitehorn ofw_real_stop(); 9938446b206SNathan Whitehorn return (-1); 99470d75337SNathan Whitehorn } 99570d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 99670d75337SNathan Whitehorn ofw_real_stop(); 9978446b206SNathan Whitehorn return (args.status); 9988446b206SNathan Whitehorn } 9998446b206SNathan Whitehorn 10008446b206SNathan Whitehorn /* 10018446b206SNathan Whitehorn * Memory functions 10028446b206SNathan Whitehorn */ 10038446b206SNathan Whitehorn 10048446b206SNathan Whitehorn /* Claim an area of memory. */ 10058446b206SNathan Whitehorn static caddr_t 10068446b206SNathan Whitehorn ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align) 10078446b206SNathan Whitehorn { 100870d75337SNathan Whitehorn vm_offset_t argsptr; 1009d4bccd63SNathan Whitehorn struct { 10108446b206SNathan Whitehorn cell_t name; 10118446b206SNathan Whitehorn cell_t nargs; 10128446b206SNathan Whitehorn cell_t nreturns; 10138446b206SNathan Whitehorn cell_t virt; 10148446b206SNathan Whitehorn cell_t size; 10158446b206SNathan Whitehorn cell_t align; 10168446b206SNathan Whitehorn cell_t baseaddr; 101770d75337SNathan Whitehorn } args; 10188446b206SNathan Whitehorn 101970d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"claim"; 102070d75337SNathan Whitehorn args.nargs = 3; 102170d75337SNathan Whitehorn args.nreturns = 1; 102270d75337SNathan Whitehorn 102370d75337SNathan Whitehorn args.virt = (cell_t)(uintptr_t)virt; 10248446b206SNathan Whitehorn args.size = size; 10258446b206SNathan Whitehorn args.align = align; 102670d75337SNathan Whitehorn ofw_real_start(); 102770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 102870d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) { 102970d75337SNathan Whitehorn ofw_real_stop(); 10308446b206SNathan Whitehorn return ((void *)-1); 103170d75337SNathan Whitehorn } 103270d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args)); 103370d75337SNathan Whitehorn ofw_real_stop(); 103470d75337SNathan Whitehorn return ((void *)(uintptr_t)args.baseaddr); 10358446b206SNathan Whitehorn } 10368446b206SNathan Whitehorn 10378446b206SNathan Whitehorn /* Release an area of memory. */ 10388446b206SNathan Whitehorn static void 10398446b206SNathan Whitehorn ofw_real_release(ofw_t ofw, void *virt, size_t size) 10408446b206SNathan Whitehorn { 104170d75337SNathan Whitehorn vm_offset_t argsptr; 1042d4bccd63SNathan Whitehorn struct { 10438446b206SNathan Whitehorn cell_t name; 10448446b206SNathan Whitehorn cell_t nargs; 10458446b206SNathan Whitehorn cell_t nreturns; 10468446b206SNathan Whitehorn cell_t virt; 10478446b206SNathan Whitehorn cell_t size; 104870d75337SNathan Whitehorn } args; 10498446b206SNathan Whitehorn 105070d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"release"; 105170d75337SNathan Whitehorn args.nargs = 2; 105270d75337SNathan Whitehorn args.nreturns = 0; 105370d75337SNathan Whitehorn 105470d75337SNathan Whitehorn args.virt = (cell_t)(uintptr_t)virt; 10558446b206SNathan Whitehorn args.size = size; 105670d75337SNathan Whitehorn ofw_real_start(); 105770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 105870d75337SNathan Whitehorn openfirmware((void *)argsptr); 105970d75337SNathan Whitehorn ofw_real_stop(); 10608446b206SNathan Whitehorn } 10618446b206SNathan Whitehorn 10628446b206SNathan Whitehorn /* 10638446b206SNathan Whitehorn * Control transfer functions 10648446b206SNathan Whitehorn */ 10658446b206SNathan Whitehorn 10668446b206SNathan Whitehorn /* Suspend and drop back to the Open Firmware interface. */ 10678446b206SNathan Whitehorn static void 10688446b206SNathan Whitehorn ofw_real_enter(ofw_t ofw) 10698446b206SNathan Whitehorn { 107070d75337SNathan Whitehorn vm_offset_t argsptr; 1071d4bccd63SNathan Whitehorn struct { 10728446b206SNathan Whitehorn cell_t name; 10738446b206SNathan Whitehorn cell_t nargs; 10748446b206SNathan Whitehorn cell_t nreturns; 107570d75337SNathan Whitehorn } args; 10768446b206SNathan Whitehorn 107770d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"enter"; 107870d75337SNathan Whitehorn args.nargs = 0; 107970d75337SNathan Whitehorn args.nreturns = 0; 108070d75337SNathan Whitehorn 108170d75337SNathan Whitehorn ofw_real_start(); 108270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 108370d75337SNathan Whitehorn openfirmware((void *)argsptr); 10848446b206SNathan Whitehorn /* We may come back. */ 108570d75337SNathan Whitehorn ofw_real_stop(); 10868446b206SNathan Whitehorn } 10878446b206SNathan Whitehorn 10888446b206SNathan Whitehorn /* Shut down and drop back to the Open Firmware interface. */ 10898446b206SNathan Whitehorn static void 10908446b206SNathan Whitehorn ofw_real_exit(ofw_t ofw) 10918446b206SNathan Whitehorn { 109270d75337SNathan Whitehorn vm_offset_t argsptr; 1093d4bccd63SNathan Whitehorn struct { 10948446b206SNathan Whitehorn cell_t name; 10958446b206SNathan Whitehorn cell_t nargs; 10968446b206SNathan Whitehorn cell_t nreturns; 109770d75337SNathan Whitehorn } args; 10988446b206SNathan Whitehorn 109970d75337SNathan Whitehorn args.name = (cell_t)(uintptr_t)"exit"; 110070d75337SNathan Whitehorn args.nargs = 0; 110170d75337SNathan Whitehorn args.nreturns = 0; 110270d75337SNathan Whitehorn 110370d75337SNathan Whitehorn ofw_real_start(); 110470d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args)); 110570d75337SNathan Whitehorn openfirmware((void *)argsptr); 11068446b206SNathan Whitehorn for (;;) /* just in case */ 11078446b206SNathan Whitehorn ; 110870d75337SNathan Whitehorn ofw_real_stop(); 11098446b206SNathan Whitehorn } 11108446b206SNathan Whitehorn 1111