diff options
author | nwhitehorn <nwhitehorn@FreeBSD.org> | 2010-07-08 14:35:35 +0000 |
---|---|---|
committer | nwhitehorn <nwhitehorn@FreeBSD.org> | 2010-07-08 14:35:35 +0000 |
commit | eddb9f922e228f95579e4973b4705fdb83f70a9e (patch) | |
tree | e3b74753864922cc2aa8b14e169e56cb592ddfe3 /sys/powerpc/ofw/ofw_real.c | |
parent | adddad4aafc2fb4c2b3bdb127bfd6c811dccb9f5 (diff) | |
download | FreeBSD-src-eddb9f922e228f95579e4973b4705fdb83f70a9e.zip FreeBSD-src-eddb9f922e228f95579e4973b4705fdb83f70a9e.tar.gz |
Fix several bugs in the real-mode Open Firmware implementation and provide
a virtual-mode version for use on 64-bit systems, which have 32-bit
firmware implementations and require similar constraints on addressing
to the real-mode implementation.
Diffstat (limited to 'sys/powerpc/ofw/ofw_real.c')
-rw-r--r-- | sys/powerpc/ofw/ofw_real.c | 482 |
1 files changed, 325 insertions, 157 deletions
diff --git a/sys/powerpc/ofw/ofw_real.c b/sys/powerpc/ofw/ofw_real.c index 9cde977..8eb86b4 100644 --- a/sys/powerpc/ofw/ofw_real.c +++ b/sys/powerpc/ofw/ofw_real.c @@ -65,12 +65,14 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <vm/vm.h> +#include <vm/vm_page.h> #include <vm/pmap.h> -#include <machine/stdarg.h> #include <machine/bus.h> -#include <machine/pmap.h> +#include <machine/md_var.h> #include <machine/ofw_machdep.h> +#include <machine/pmap.h> +#include <machine/stdarg.h> #include <dev/ofw/openfirm.h> #include <dev/ofw/ofwvar.h> @@ -98,6 +100,8 @@ static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf, size_t len); static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method, int nargs, int nreturns, cell_t *args_and_returns); +static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, + unsigned long *returns); static ihandle_t ofw_real_open(ofw_t, const char *device); static void ofw_real_close(ofw_t, ihandle_t instance); static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len); @@ -126,6 +130,7 @@ static ofw_method_t ofw_real_methods[] = { OFWMETHOD(ofw_test, ofw_real_test), OFWMETHOD(ofw_call_method, ofw_real_call_method), + OFWMETHOD(ofw_interpret, ofw_real_interpret), OFWMETHOD(ofw_open, ofw_real_open), OFWMETHOD(ofw_close, ofw_real_close), OFWMETHOD(ofw_read, ofw_real_read), @@ -146,6 +151,13 @@ static ofw_def_t ofw_real = { }; OFW_DEF(ofw_real); +static ofw_def_t ofw_32bit = { + OFW_STD_32BIT, + ofw_real_methods, + 0 +}; +OFW_DEF(ofw_32bit); + MALLOC_DEFINE(M_OFWREAL, "ofwreal", "Open Firmware Real Mode Bounce Page"); static int (*openfirmware)(void *); @@ -156,13 +168,16 @@ static off_t of_bounce_offset; static size_t of_bounce_size; static struct mtx of_bounce_mtx; +extern int ofw_real_mode; +extern struct pmap ofw_pmap; + /* * After the VM is up, allocate a wired, low memory bounce page. */ static void ofw_real_bounce_alloc(void *); -SYSINIT(ofw_real_bounce_alloc, SI_SUB_VM, SI_ORDER_ANY, +SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY, ofw_real_bounce_alloc, NULL); static void @@ -197,38 +212,54 @@ ofw_real_bounce_alloc(void *junk) of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0, 0, BUS_SPACE_MAXADDR_32BIT, PAGE_SIZE, PAGE_SIZE); + of_bounce_phys = vtophys(of_bounce_virt); of_bounce_size = PAGE_SIZE; + /* + * For virtual-mode OF, direct map this physical address so that + * we have a 32-bit virtual address to give OF. + */ + + if (!ofw_real_mode && !hw_direct_map) + pmap_kenter(of_bounce_phys, of_bounce_phys); + mtx_unlock(&of_bounce_mtx); } static cell_t ofw_real_map(const void *buf, size_t len) { + static char emergency_buffer[255]; cell_t phys; mtx_assert(&of_bounce_mtx, MA_OWNED); if (of_bounce_virt == NULL) { + /* + * If we haven't set up the MMU, then buf is guaranteed + * to be accessible to OF, because the only memory we + * can use right now is memory mapped by firmware. + */ if (!pmap_bootstrapped) - return (cell_t)buf; + return (cell_t)(uintptr_t)buf; /* * XXX: It is possible for us to get called before the VM has * come online, but after the MMU is up. We don't have the * bounce buffer yet, but can no longer presume a 1:1 mapping. - * Grab the physical address of the buffer, and hope it is - * in range if this happens. + * Copy into the emergency buffer, and reset at the end. */ - return (cell_t)vtophys(buf); + of_bounce_virt = emergency_buffer; + of_bounce_phys = (vm_offset_t)of_bounce_virt; + of_bounce_size = sizeof(emergency_buffer); } /* * Make sure the bounce page offset satisfies any reasonable * alignment constraint. */ - of_bounce_offset += of_bounce_offset % sizeof(register_t); + of_bounce_offset += sizeof(register_t) - (of_bounce_offset % sizeof(register_t)); if (of_bounce_offset + len > of_bounce_size) { panic("Oversize Open Firmware call!"); @@ -240,7 +271,7 @@ ofw_real_map(const void *buf, size_t len) of_bounce_offset += len; - return phys; + return (phys); } static void @@ -274,25 +305,28 @@ ofw_real_init(ofw_t ofw, void *openfirm) static int ofw_real_test(ofw_t ofw, const char *name) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t service; cell_t missing; - } args = { - (cell_t)"test", - 1, - 1, - }; + } args; + + args.name = (cell_t)(uintptr_t)"test"; + args.nargs = 1; + args.nreturns = 1; ofw_real_start(); args.service = ofw_real_map(name, strlen(name) + 1); - if (args.service == 0 || openfirmware(&args) == -1) { + argsptr = ofw_real_map(&args, sizeof(args)); + if (args.service == 0 || openfirmware((void *)argsptr) == -1) { ofw_real_stop(); return (-1); } + ofw_real_unmap(argsptr, &args, sizeof(args)); ofw_real_stop(); return (args.missing); } @@ -305,21 +339,28 @@ ofw_real_test(ofw_t ofw, const char *name) static phandle_t ofw_real_peer(ofw_t ofw, phandle_t node) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t node; cell_t next; - } args = { - (cell_t)"peer", - 1, - 1, - }; + } args; + + args.name = (cell_t)(uintptr_t)"peer"; + args.nargs = 1; + args.nreturns = 1; args.node = node; - if (openfirmware(&args) == -1) + ofw_real_start(); + argsptr = ofw_real_map(&args, sizeof(args)); + if (openfirmware((void *)argsptr) == -1) { + ofw_real_stop(); return (-1); + } + ofw_real_unmap(argsptr, &args, sizeof(args)); + ofw_real_stop(); return (args.next); } @@ -327,21 +368,28 @@ ofw_real_peer(ofw_t ofw, phandle_t node) static phandle_t ofw_real_child(ofw_t ofw, phandle_t node) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t node; cell_t child; - } args = { - (cell_t)"child", - 1, - 1, - }; + } args; + + args.name = (cell_t)(uintptr_t)"child"; + args.nargs = 1; + args.nreturns = 1; args.node = node; - if (openfirmware(&args) == -1) + ofw_real_start(); + argsptr = ofw_real_map(&args, sizeof(args)); + if (openfirmware((void *)argsptr) == -1) { + ofw_real_stop(); return (-1); + } + ofw_real_unmap(argsptr, &args, sizeof(args)); + ofw_real_stop(); return (args.child); } @@ -349,21 +397,28 @@ ofw_real_child(ofw_t ofw, phandle_t node) static phandle_t ofw_real_parent(ofw_t ofw, phandle_t node) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t node; cell_t parent; - } args = { - (cell_t)"parent", - 1, - 1, - }; + } args; + + args.name = (cell_t)(uintptr_t)"parent"; + args.nargs = 1; + args.nreturns = 1; args.node = node; - if (openfirmware(&args) == -1) + ofw_real_start(); + argsptr = ofw_real_map(&args, sizeof(args)); + if (openfirmware((void *)argsptr) == -1) { + ofw_real_stop(); return (-1); + } + ofw_real_unmap(argsptr, &args, sizeof(args)); + ofw_real_stop(); return (args.parent); } @@ -371,21 +426,28 @@ ofw_real_parent(ofw_t ofw, phandle_t node) static phandle_t ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t instance; cell_t package; - } args = { - (cell_t)"instance-to-package", - 1, - 1, - }; + } args; + + args.name = (cell_t)(uintptr_t)"instance-to-package"; + args.nargs = 1; + args.nreturns = 1; args.instance = instance; - if (openfirmware(&args) == -1) + ofw_real_start(); + argsptr = ofw_real_map(&args, sizeof(args)); + if (openfirmware((void *)argsptr) == -1) { + ofw_real_stop(); return (-1); + } + ofw_real_unmap(argsptr, &args, sizeof(args)); + ofw_real_stop(); return (args.package); } @@ -393,27 +455,30 @@ ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance) static ssize_t ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t package; cell_t propname; - cell_t proplen; - } args = { - (cell_t)"getproplen", - 2, - 1, - }; + int32_t proplen; + } args; + + args.name = (cell_t)(uintptr_t)"getproplen"; + args.nargs = 2; + args.nreturns = 1; ofw_real_start(); args.package = package; args.propname = ofw_real_map(propname, strlen(propname) + 1); - if (args.propname == 0 || openfirmware(&args) == -1) { + argsptr = ofw_real_map(&args, sizeof(args)); + if (args.propname == 0 || openfirmware((void *)argsptr) == -1) { ofw_real_stop(); return (-1); } + ofw_real_unmap(argsptr, &args, sizeof(args)); ofw_real_stop(); return (args.proplen); } @@ -423,6 +488,7 @@ static ssize_t ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, size_t buflen) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; @@ -431,12 +497,12 @@ ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, cell_t propname; cell_t buf; cell_t buflen; - cell_t size; - } args = { - (cell_t)"getprop", - 4, - 1, - }; + int32_t size; + } args; + + args.name = (cell_t)(uintptr_t)"getprop"; + args.nargs = 4; + args.nreturns = 1; ofw_real_start(); @@ -444,10 +510,13 @@ ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, args.propname = ofw_real_map(propname, strlen(propname) + 1); args.buf = ofw_real_map(buf, buflen); args.buflen = buflen; - if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) { + argsptr = ofw_real_map(&args, sizeof(args)); + if (args.propname == 0 || args.buf == 0 || + openfirmware((void *)argsptr) == -1) { ofw_real_stop(); return (-1); } + ofw_real_unmap(argsptr, &args, sizeof(args)); ofw_real_unmap(args.buf, buf, buflen); ofw_real_stop(); @@ -459,6 +528,7 @@ static int ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf, size_t size) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; @@ -467,21 +537,24 @@ ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous, cell_t previous; cell_t buf; cell_t flag; - } args = { - (cell_t)"nextprop", - 3, - 1, - }; + } args; + + args.name = (cell_t)(uintptr_t)"nextprop"; + args.nargs = 3; + args.nreturns = 1; ofw_real_start(); args.package = package; args.previous = ofw_real_map(previous, strlen(previous) + 1); args.buf = ofw_real_map(buf, size); - if (args.previous == 0 || args.buf == 0 || openfirmware(&args) == -1) { + argsptr = ofw_real_map(&args, sizeof(args)); + if (args.previous == 0 || args.buf == 0 || + openfirmware((void *)argsptr) == -1) { ofw_real_stop(); return (-1); } + ofw_real_unmap(argsptr, &args, sizeof(args)); ofw_real_unmap(args.buf, buf, size); ofw_real_stop(); @@ -494,6 +567,7 @@ static int ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname, const void *buf, size_t len) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; @@ -503,11 +577,11 @@ ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname, cell_t buf; cell_t len; cell_t size; - } args = { - (cell_t)"setprop", - 4, - 1, - }; + } args; + + args.name = (cell_t)(uintptr_t)"setprop"; + args.nargs = 4; + args.nreturns = 1; ofw_real_start(); @@ -515,10 +589,13 @@ ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname, args.propname = ofw_real_map(propname, strlen(propname) + 1); args.buf = ofw_real_map(buf, len); args.len = len; - if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) { + argsptr = ofw_real_map(&args, sizeof(args)); + if (args.propname == 0 || args.buf == 0 || + openfirmware((void *)argsptr) == -1) { ofw_real_stop(); return (-1); } + ofw_real_unmap(argsptr, &args, sizeof(args)); ofw_real_stop(); return (args.size); } @@ -527,6 +604,7 @@ ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname, static ssize_t ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; @@ -534,22 +612,25 @@ ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len) cell_t device; cell_t buf; cell_t len; - cell_t size; - } args = { - (cell_t)"canon", - 3, - 1, - }; + int32_t size; + } args; + + args.name = (cell_t)(uintptr_t)"canon"; + args.nargs = 3; + args.nreturns = 1; ofw_real_start(); args.device = ofw_real_map(device, strlen(device) + 1); args.buf = ofw_real_map(buf, len); args.len = len; - if (args.device == 0 || args.buf == 0 || openfirmware(&args) == -1) { + argsptr = ofw_real_map(&args, sizeof(args)); + if (args.device == 0 || args.buf == 0 || + openfirmware((void *)argsptr) == -1) { ofw_real_stop(); return (-1); } + ofw_real_unmap(argsptr, &args, sizeof(args)); ofw_real_unmap(args.buf, buf, len); ofw_real_stop(); @@ -560,25 +641,29 @@ ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len) static phandle_t ofw_real_finddevice(ofw_t ofw, const char *device) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t device; cell_t package; - } args = { - (cell_t)"finddevice", - 1, - 1, - }; + } args; + + args.name = (cell_t)(uintptr_t)"finddevice"; + args.nargs = 1; + args.nreturns = 1; ofw_real_start(); args.device = ofw_real_map(device, strlen(device) + 1); - if (args.device == 0 || openfirmware(&args) == -1) { + argsptr = ofw_real_map(&args, sizeof(args)); + if (args.device == 0 || + openfirmware((void *)argsptr) == -1) { ofw_real_stop(); return (-1); } + ofw_real_unmap(argsptr, &args, sizeof(args)); ofw_real_stop(); return (args.package); } @@ -587,6 +672,7 @@ ofw_real_finddevice(ofw_t ofw, const char *device) static ssize_t ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; @@ -594,22 +680,25 @@ ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) cell_t instance; cell_t buf; cell_t len; - cell_t size; - } args = { - (cell_t)"instance-to-path", - 3, - 1, - }; + int32_t size; + } args; + + args.name = (cell_t)(uintptr_t)"instance-to-path"; + args.nargs = 3; + args.nreturns = 1; ofw_real_start(); args.instance = instance; args.buf = ofw_real_map(buf, len); args.len = len; - if (args.buf == 0 || openfirmware(&args) == -1) { + argsptr = ofw_real_map(&args, sizeof(args)); + if (args.buf == 0 || + openfirmware((void *)argsptr) == -1) { ofw_real_stop(); return (-1); } + ofw_real_unmap(argsptr, &args, sizeof(args)); ofw_real_unmap(args.buf, buf, len); ofw_real_stop(); @@ -620,6 +709,7 @@ ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) static ssize_t ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; @@ -627,22 +717,25 @@ ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len) cell_t package; cell_t buf; cell_t len; - cell_t size; - } args = { - (cell_t)"package-to-path", - 3, - 1, - }; + int32_t size; + } args; + + args.name = (cell_t)(uintptr_t)"package-to-path"; + args.nargs = 3; + args.nreturns = 1; ofw_real_start(); args.package = package; args.buf = ofw_real_map(buf, len); args.len = len; - if (args.buf == 0 || openfirmware(&args) == -1) { + argsptr = ofw_real_map(&args, sizeof(args)); + if (args.buf == 0 || + openfirmware((void *)argsptr) == -1) { ofw_real_stop(); return (-1); } + ofw_real_unmap(argsptr, &args, sizeof(args)); ofw_real_unmap(args.buf, buf, len); ofw_real_stop(); @@ -654,6 +747,7 @@ static int ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, int nargs, int nreturns, cell_t *args_and_returns) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; @@ -661,14 +755,14 @@ ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, cell_t method; cell_t instance; cell_t args_n_results[12]; - } args = { - (cell_t)"call-method", - 2, - 1, - }; + } args; cell_t *cp, *ap; int n; + args.name = (cell_t)(uintptr_t)"call-method"; + args.nargs = 2; + args.nreturns = 1; + if (nargs > 6) return (-1); @@ -681,10 +775,13 @@ ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, ap = args_and_returns; for (cp = args.args_n_results + (n = nargs); --n >= 0;) *--cp = *(ap++); - if (args.method == 0 || openfirmware(&args) == -1) { + argsptr = ofw_real_map(&args, sizeof(args)); + if (args.method == 0 || + openfirmware((void *)argsptr) == -1) { ofw_real_stop(); return (-1); } + ofw_real_unmap(argsptr, &args, sizeof(args)); ofw_real_stop(); if (args.args_n_results[nargs]) return (args.args_n_results[nargs]); @@ -693,6 +790,39 @@ ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, return (0); } +static int +ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, + unsigned long *returns) +{ + vm_offset_t argsptr; + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t slot[16]; + } args; + cell_t status; + int i = 0, j = 0; + + args.name = (cell_t)(uintptr_t)"interpret"; + args.nargs = 1; + + ofw_real_start(); + args.nreturns = ++nreturns; + args.slot[i++] = ofw_real_map(cmd, strlen(cmd) + 1); + argsptr = ofw_real_map(&args, sizeof(args)); + if (openfirmware((void *)argsptr) == -1) { + ofw_real_stop(); + return (-1); + } + ofw_real_unmap(argsptr, &args, sizeof(args)); + ofw_real_stop(); + status = args.slot[i++]; + while (i < 1 + nreturns) + returns[j++] = args.slot[i++]; + return (status); +} + /* * Device I/O functions */ @@ -701,26 +831,29 @@ ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, static ihandle_t ofw_real_open(ofw_t ofw, const char *device) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t device; cell_t instance; - } args = { - (cell_t)"open", - 1, - 1, - }; + } args; + + args.name = (cell_t)(uintptr_t)"open"; + args.nargs = 1; + args.nreturns = 1; ofw_real_start(); args.device = ofw_real_map(device, strlen(device) + 1); - if (args.device == 0 || openfirmware(&args) == -1 + argsptr = ofw_real_map(&args, sizeof(args)); + if (args.device == 0 || openfirmware((void *)argsptr) == -1 || args.instance == 0) { ofw_real_stop(); return (-1); } + ofw_real_unmap(argsptr, &args, sizeof(args)); ofw_real_stop(); return (args.instance); } @@ -729,25 +862,29 @@ ofw_real_open(ofw_t ofw, const char *device) static void ofw_real_close(ofw_t ofw, ihandle_t instance) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t instance; - } args = { - (cell_t)"close", - 1, - 0, - }; + } args; + args.name = (cell_t)(uintptr_t)"close"; + args.nargs = 1; + args.nreturns = 0; args.instance = instance; - openfirmware(&args); + ofw_real_start(); + argsptr = ofw_real_map(&args, sizeof(args)); + openfirmware((void *)argsptr); + ofw_real_stop(); } /* Read from an instance. */ static ssize_t ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; @@ -755,22 +892,24 @@ ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) cell_t instance; cell_t addr; cell_t len; - cell_t actual; - } args = { - (cell_t)"read", - 3, - 1, - }; + int32_t actual; + } args; + + args.name = (cell_t)(uintptr_t)"read"; + args.nargs = 3; + args.nreturns = 1; ofw_real_start(); args.instance = instance; args.addr = ofw_real_map(addr, len); args.len = len; - if (args.addr == 0 || openfirmware(&args) == -1) { + argsptr = ofw_real_map(&args, sizeof(args)); + if (args.addr == 0 || openfirmware((void *)argsptr) == -1) { ofw_real_stop(); return (-1); } + ofw_real_unmap(argsptr, &args, sizeof(args)); ofw_real_unmap(args.addr, addr, len); ofw_real_stop(); @@ -781,6 +920,7 @@ ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) static ssize_t ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; @@ -788,22 +928,24 @@ ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) cell_t instance; cell_t addr; cell_t len; - cell_t actual; - } args = { - (cell_t)"write", - 3, - 1, - }; + int32_t actual; + } args; + + args.name = (cell_t)(uintptr_t)"write"; + args.nargs = 3; + args.nreturns = 1; ofw_real_start(); args.instance = instance; args.addr = ofw_real_map(addr, len); args.len = len; - if (args.addr == 0 || openfirmware(&args) == -1) { + argsptr = ofw_real_map(&args, sizeof(args)); + if (args.addr == 0 || openfirmware((void *)argsptr) == -1) { ofw_real_stop(); return (-1); } + ofw_real_unmap(argsptr, &args, sizeof(args)); ofw_real_stop(); return (args.actual); } @@ -812,6 +954,7 @@ ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) static int ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; @@ -820,17 +963,23 @@ ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos) cell_t poshi; cell_t poslo; cell_t status; - } args = { - (cell_t)"seek", - 3, - 1, - }; + } args; + + args.name = (cell_t)(uintptr_t)"seek"; + args.nargs = 3; + args.nreturns = 1; args.instance = instance; args.poshi = pos >> 32; args.poslo = pos; - if (openfirmware(&args) == -1) + ofw_real_start(); + argsptr = ofw_real_map(&args, sizeof(args)); + if (openfirmware((void *)argsptr) == -1) { + ofw_real_stop(); return (-1); + } + ofw_real_unmap(argsptr, &args, sizeof(args)); + ofw_real_stop(); return (args.status); } @@ -842,6 +991,7 @@ ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos) static caddr_t ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; @@ -850,39 +1000,49 @@ ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align) cell_t size; cell_t align; cell_t baseaddr; - } args = { - (cell_t)"claim", - 3, - 1, - }; + } args; + + args.name = (cell_t)(uintptr_t)"claim"; + args.nargs = 3; + args.nreturns = 1; - args.virt = (cell_t)virt; + args.virt = (cell_t)(uintptr_t)virt; args.size = size; args.align = align; - if (openfirmware(&args) == -1) + ofw_real_start(); + argsptr = ofw_real_map(&args, sizeof(args)); + if (openfirmware((void *)argsptr) == -1) { + ofw_real_stop(); return ((void *)-1); - return ((void *)args.baseaddr); + } + ofw_real_unmap(argsptr, &args, sizeof(args)); + ofw_real_stop(); + return ((void *)(uintptr_t)args.baseaddr); } /* Release an area of memory. */ static void ofw_real_release(ofw_t ofw, void *virt, size_t size) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t virt; cell_t size; - } args = { - (cell_t)"release", - 2, - 0, - }; + } args; + + args.name = (cell_t)(uintptr_t)"release"; + args.nargs = 2; + args.nreturns = 0; - args.virt = (cell_t)virt; + args.virt = (cell_t)(uintptr_t)virt; args.size = size; - openfirmware(&args); + ofw_real_start(); + argsptr = ofw_real_map(&args, sizeof(args)); + openfirmware((void *)argsptr); + ofw_real_stop(); } /* @@ -893,36 +1053,44 @@ ofw_real_release(ofw_t ofw, void *virt, size_t size) static void ofw_real_enter(ofw_t ofw) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; cell_t nreturns; - } args = { - (cell_t)"enter", - 0, - 0, - }; + } args; + + args.name = (cell_t)(uintptr_t)"enter"; + args.nargs = 0; + args.nreturns = 0; - openfirmware(&args); + ofw_real_start(); + argsptr = ofw_real_map(&args, sizeof(args)); + openfirmware((void *)argsptr); /* We may come back. */ + ofw_real_stop(); } /* Shut down and drop back to the Open Firmware interface. */ static void ofw_real_exit(ofw_t ofw) { + vm_offset_t argsptr; struct { cell_t name; cell_t nargs; cell_t nreturns; - } args = { - (cell_t)"exit", - 0, - 0, - }; + } args; + + args.name = (cell_t)(uintptr_t)"exit"; + args.nargs = 0; + args.nreturns = 0; - openfirmware(&args); + ofw_real_start(); + argsptr = ofw_real_map(&args, sizeof(args)); + openfirmware((void *)argsptr); for (;;) /* just in case */ ; + ofw_real_stop(); } |