1 /* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */
2
3 /*-
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 /*-
34 * Copyright (C) 2000 Benno Rice.
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 *
46 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
52 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
54 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
55 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 */
57
58 #include <sys/cdefs.h>
59 __FBSDID("$FreeBSD: releng/9.0/sys/powerpc/ofw/ofw_real.c 222613 2011-06-02 14:12:37Z nwhitehorn $");
60
61 #include <sys/param.h>
62 #include <sys/kernel.h>
63 #include <sys/lock.h>
64 #include <sys/mutex.h>
65 #include <sys/systm.h>
66
67 #include <vm/vm.h>
68 #include <vm/vm_page.h>
69 #include <vm/pmap.h>
70
71 #include <machine/bus.h>
72 #include <machine/md_var.h>
73 #include <machine/ofw_machdep.h>
74 #include <machine/pmap.h>
75 #include <machine/stdarg.h>
76
77 #include <dev/ofw/openfirm.h>
78 #include <dev/ofw/ofwvar.h>
79 #include "ofw_if.h"
80
81 static int ofw_real_init(ofw_t, void *openfirm);
82 static int ofw_real_test(ofw_t, const char *name);
83 static phandle_t ofw_real_peer(ofw_t, phandle_t node);
84 static phandle_t ofw_real_child(ofw_t, phandle_t node);
85 static phandle_t ofw_real_parent(ofw_t, phandle_t node);
86 static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
87 static ssize_t ofw_real_getproplen(ofw_t, phandle_t package,
88 const char *propname);
89 static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname,
90 void *buf, size_t buflen);
91 static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous,
92 char *buf, size_t);
93 static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
94 const void *buf, size_t len);
95 static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
96 static phandle_t ofw_real_finddevice(ofw_t, const char *device);
97 static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf,
98 size_t len);
99 static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf,
100 size_t len);
101 static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method,
102 int nargs, int nreturns, cell_t *args_and_returns);
103 static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns,
104 cell_t *returns);
105 static ihandle_t ofw_real_open(ofw_t, const char *device);
106 static void ofw_real_close(ofw_t, ihandle_t instance);
107 static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
108 static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr,
109 size_t len);
110 static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
111 static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
112 static void ofw_real_release(ofw_t, void *virt, size_t size);
113 static void ofw_real_enter(ofw_t);
114 static void ofw_real_exit(ofw_t);
115
116 static ofw_method_t ofw_real_methods[] = {
117 OFWMETHOD(ofw_init, ofw_real_init),
118 OFWMETHOD(ofw_peer, ofw_real_peer),
119 OFWMETHOD(ofw_child, ofw_real_child),
120 OFWMETHOD(ofw_parent, ofw_real_parent),
121 OFWMETHOD(ofw_instance_to_package, ofw_real_instance_to_package),
122 OFWMETHOD(ofw_getproplen, ofw_real_getproplen),
123 OFWMETHOD(ofw_getprop, ofw_real_getprop),
124 OFWMETHOD(ofw_nextprop, ofw_real_nextprop),
125 OFWMETHOD(ofw_setprop, ofw_real_setprop),
126 OFWMETHOD(ofw_canon, ofw_real_canon),
127 OFWMETHOD(ofw_finddevice, ofw_real_finddevice),
128 OFWMETHOD(ofw_instance_to_path, ofw_real_instance_to_path),
129 OFWMETHOD(ofw_package_to_path, ofw_real_package_to_path),
130
131 OFWMETHOD(ofw_test, ofw_real_test),
132 OFWMETHOD(ofw_call_method, ofw_real_call_method),
133 OFWMETHOD(ofw_interpret, ofw_real_interpret),
134 OFWMETHOD(ofw_open, ofw_real_open),
135 OFWMETHOD(ofw_close, ofw_real_close),
136 OFWMETHOD(ofw_read, ofw_real_read),
137 OFWMETHOD(ofw_write, ofw_real_write),
138 OFWMETHOD(ofw_seek, ofw_real_seek),
139 OFWMETHOD(ofw_claim, ofw_real_claim),
140 OFWMETHOD(ofw_release, ofw_real_release),
141 OFWMETHOD(ofw_enter, ofw_real_enter),
142 OFWMETHOD(ofw_exit, ofw_real_exit),
143
144 { 0, 0 }
145 };
146
147 static ofw_def_t ofw_real = {
148 OFW_STD_REAL,
149 ofw_real_methods,
150 0
151 };
152 OFW_DEF(ofw_real);
153
154 static ofw_def_t ofw_32bit = {
155 OFW_STD_32BIT,
156 ofw_real_methods,
157 0
158 };
159 OFW_DEF(ofw_32bit);
160
161 MALLOC_DEFINE(M_OFWREAL, "ofwreal", "Open Firmware Real Mode Bounce Page");
162
163 static int (*openfirmware)(void *);
164
165 static vm_offset_t of_bounce_phys;
166 static caddr_t of_bounce_virt;
167 static off_t of_bounce_offset;
168 static size_t of_bounce_size;
169 static struct mtx of_bounce_mtx;
170
171 extern int ofw_real_mode;
172 extern struct pmap ofw_pmap;
173
174 /*
175 * After the VM is up, allocate a wired, low memory bounce page.
176 */
177
178 static void ofw_real_bounce_alloc(void *);
179
180 SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY,
181 ofw_real_bounce_alloc, NULL);
182
183 static void
184 ofw_real_start(void)
185 {
186 mtx_lock(&of_bounce_mtx);
187 of_bounce_offset = 0;
188 }
189
190 static void
191 ofw_real_stop(void)
192 {
193 mtx_unlock(&of_bounce_mtx);
194 }
195
196 static void
197 ofw_real_bounce_alloc(void *junk)
198 {
199 /*
200 * Check that ofw_real is actually in use before allocating wads
201 * of memory. Do this by checking if our mutex has been set up.
202 */
203 if (!mtx_initialized(&of_bounce_mtx))
204 return;
205
206 /*
207 * Allocate a page of contiguous, wired physical memory that can
208 * fit into a 32-bit address space and accessed from real mode.
209 */
210
211 mtx_lock(&of_bounce_mtx);
212
213 of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0, 0,
214 ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
215 PAGE_SIZE);
216
217 of_bounce_phys = vtophys(of_bounce_virt);
218 of_bounce_size = PAGE_SIZE;
219
220 /*
221 * For virtual-mode OF, direct map this physical address so that
222 * we have a 32-bit virtual address to give OF.
223 */
224
225 if (!ofw_real_mode && !hw_direct_map)
226 pmap_kenter(of_bounce_phys, of_bounce_phys);
227
228 mtx_unlock(&of_bounce_mtx);
229 }
230
231 static cell_t
232 ofw_real_map(const void *buf, size_t len)
233 {
234 static char emergency_buffer[255];
235 cell_t phys;
236
237 mtx_assert(&of_bounce_mtx, MA_OWNED);
238
239 if (of_bounce_virt == NULL) {
240 /*
241 * If we haven't set up the MMU, then buf is guaranteed
242 * to be accessible to OF, because the only memory we
243 * can use right now is memory mapped by firmware.
244 */
245 if (!pmap_bootstrapped)
246 return (cell_t)(uintptr_t)buf;
247
248 /*
249 * XXX: It is possible for us to get called before the VM has
250 * come online, but after the MMU is up. We don't have the
251 * bounce buffer yet, but can no longer presume a 1:1 mapping.
252 * Copy into the emergency buffer, and reset at the end.
253 */
254 of_bounce_virt = emergency_buffer;
255 of_bounce_phys = (vm_offset_t)of_bounce_virt;
256 of_bounce_size = sizeof(emergency_buffer);
257 }
258
259 /*
260 * Make sure the bounce page offset satisfies any reasonable
261 * alignment constraint.
262 */
263 of_bounce_offset += sizeof(register_t) - (of_bounce_offset % sizeof(register_t));
264
265 if (of_bounce_offset + len > of_bounce_size) {
266 panic("Oversize Open Firmware call!");
267 return 0;
268 }
269
270 if (buf != NULL)
271 memcpy(of_bounce_virt + of_bounce_offset, buf, len);
272 else
273 return (0);
274
275 phys = of_bounce_phys + of_bounce_offset;
276
277 of_bounce_offset += len;
278
279 return (phys);
280 }
281
282 static void
283 ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
284 {
285 mtx_assert(&of_bounce_mtx, MA_OWNED);
286
287 if (of_bounce_virt == NULL)
288 return;
289
290 if (physaddr == 0)
291 return;
292
293 memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
294 }
295
296 /* Initialiser */
297
298 static int
299 ofw_real_init(ofw_t ofw, void *openfirm)
300 {
301 openfirmware = (int (*)(void *))openfirm;
302
303 mtx_init(&of_bounce_mtx, "OF Bounce Page", MTX_DEF, 0);
304 of_bounce_virt = NULL;
305 return (0);
306 }
307
308 /*
309 * Generic functions
310 */
311
312 /* Test to see if a service exists. */
313 static int
314 ofw_real_test(ofw_t ofw, const char *name)
315 {
316 vm_offset_t argsptr;
317 struct {
318 cell_t name;
319 cell_t nargs;
320 cell_t nreturns;
321 cell_t service;
322 cell_t missing;
323 } args;
324
325 args.name = (cell_t)(uintptr_t)"test";
326 args.nargs = 1;
327 args.nreturns = 1;
328
329 ofw_real_start();
330
331 args.service = ofw_real_map(name, strlen(name) + 1);
332 argsptr = ofw_real_map(&args, sizeof(args));
333 if (args.service == 0 || openfirmware((void *)argsptr) == -1) {
334 ofw_real_stop();
335 return (-1);
336 }
337 ofw_real_unmap(argsptr, &args, sizeof(args));
338 ofw_real_stop();
339 return (args.missing);
340 }
341
342 /*
343 * Device tree functions
344 */
345
346 /* Return the next sibling of this node or 0. */
347 static phandle_t
348 ofw_real_peer(ofw_t ofw, phandle_t node)
349 {
350 vm_offset_t argsptr;
351 struct {
352 cell_t name;
353 cell_t nargs;
354 cell_t nreturns;
355 cell_t node;
356 cell_t next;
357 } args;
358
359 args.name = (cell_t)(uintptr_t)"peer";
360 args.nargs = 1;
361 args.nreturns = 1;
362
363 args.node = node;
364 ofw_real_start();
365 argsptr = ofw_real_map(&args, sizeof(args));
366 if (openfirmware((void *)argsptr) == -1) {
367 ofw_real_stop();
368 return (-1);
369 }
370 ofw_real_unmap(argsptr, &args, sizeof(args));
371 ofw_real_stop();
372 return (args.next);
373 }
374
375 /* Return the first child of this node or 0. */
376 static phandle_t
377 ofw_real_child(ofw_t ofw, phandle_t node)
378 {
379 vm_offset_t argsptr;
380 struct {
381 cell_t name;
382 cell_t nargs;
383 cell_t nreturns;
384 cell_t node;
385 cell_t child;
386 } args;
387
388 args.name = (cell_t)(uintptr_t)"child";
389 args.nargs = 1;
390 args.nreturns = 1;
391
392 args.node = node;
393 ofw_real_start();
394 argsptr = ofw_real_map(&args, sizeof(args));
395 if (openfirmware((void *)argsptr) == -1) {
396 ofw_real_stop();
397 return (-1);
398 }
399 ofw_real_unmap(argsptr, &args, sizeof(args));
400 ofw_real_stop();
401 return (args.child);
402 }
403
404 /* Return the parent of this node or 0. */
405 static phandle_t
406 ofw_real_parent(ofw_t ofw, phandle_t node)
407 {
408 vm_offset_t argsptr;
409 struct {
410 cell_t name;
411 cell_t nargs;
412 cell_t nreturns;
413 cell_t node;
414 cell_t parent;
415 } args;
416
417 args.name = (cell_t)(uintptr_t)"parent";
418 args.nargs = 1;
419 args.nreturns = 1;
420
421 args.node = node;
422 ofw_real_start();
423 argsptr = ofw_real_map(&args, sizeof(args));
424 if (openfirmware((void *)argsptr) == -1) {
425 ofw_real_stop();
426 return (-1);
427 }
428 ofw_real_unmap(argsptr, &args, sizeof(args));
429 ofw_real_stop();
430 return (args.parent);
431 }
432
433 /* Return the package handle that corresponds to an instance handle. */
434 static phandle_t
435 ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
436 {
437 vm_offset_t argsptr;
438 struct {
439 cell_t name;
440 cell_t nargs;
441 cell_t nreturns;
442 cell_t instance;
443 cell_t package;
444 } args;
445
446 args.name = (cell_t)(uintptr_t)"instance-to-package";
447 args.nargs = 1;
448 args.nreturns = 1;
449
450 args.instance = instance;
451 ofw_real_start();
452 argsptr = ofw_real_map(&args, sizeof(args));
453 if (openfirmware((void *)argsptr) == -1) {
454 ofw_real_stop();
455 return (-1);
456 }
457 ofw_real_unmap(argsptr, &args, sizeof(args));
458 ofw_real_stop();
459 return (args.package);
460 }
461
462 /* Get the length of a property of a package. */
463 static ssize_t
464 ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
465 {
466 vm_offset_t argsptr;
467 struct {
468 cell_t name;
469 cell_t nargs;
470 cell_t nreturns;
471 cell_t package;
472 cell_t propname;
473 int32_t proplen;
474 } args;
475
476 args.name = (cell_t)(uintptr_t)"getproplen";
477 args.nargs = 2;
478 args.nreturns = 1;
479
480 ofw_real_start();
481
482 args.package = package;
483 args.propname = ofw_real_map(propname, strlen(propname) + 1);
484 argsptr = ofw_real_map(&args, sizeof(args));
485 if (args.propname == 0 || openfirmware((void *)argsptr) == -1) {
486 ofw_real_stop();
487 return (-1);
488 }
489 ofw_real_unmap(argsptr, &args, sizeof(args));
490 ofw_real_stop();
491 return (args.proplen);
492 }
493
494 /* Get the value of a property of a package. */
495 static ssize_t
496 ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
497 size_t buflen)
498 {
499 vm_offset_t argsptr;
500 struct {
501 cell_t name;
502 cell_t nargs;
503 cell_t nreturns;
504 cell_t package;
505 cell_t propname;
506 cell_t buf;
507 cell_t buflen;
508 int32_t size;
509 } args;
510
511 args.name = (cell_t)(uintptr_t)"getprop";
512 args.nargs = 4;
513 args.nreturns = 1;
514
515 ofw_real_start();
516
517 args.package = package;
518 args.propname = ofw_real_map(propname, strlen(propname) + 1);
519 args.buf = ofw_real_map(buf, buflen);
520 args.buflen = buflen;
521 argsptr = ofw_real_map(&args, sizeof(args));
522 if (args.propname == 0 || args.buf == 0 ||
523 openfirmware((void *)argsptr) == -1) {
524 ofw_real_stop();
525 return (-1);
526 }
527 ofw_real_unmap(argsptr, &args, sizeof(args));
528 ofw_real_unmap(args.buf, buf, buflen);
529
530 ofw_real_stop();
531 return (args.size);
532 }
533
534 /* Get the next property of a package. */
535 static int
536 ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous,
537 char *buf, size_t size)
538 {
539 vm_offset_t argsptr;
540 struct {
541 cell_t name;
542 cell_t nargs;
543 cell_t nreturns;
544 cell_t package;
545 cell_t previous;
546 cell_t buf;
547 cell_t flag;
548 } args;
549
550 args.name = (cell_t)(uintptr_t)"nextprop";
551 args.nargs = 3;
552 args.nreturns = 1;
553
554 ofw_real_start();
555
556 args.package = package;
557 args.previous = ofw_real_map(previous, (previous != NULL) ? (strlen(previous) + 1) : 0);
558 args.buf = ofw_real_map(buf, size);
559 argsptr = ofw_real_map(&args, sizeof(args));
560 if (args.buf == 0 || openfirmware((void *)argsptr) == -1) {
561 ofw_real_stop();
562 return (-1);
563 }
564 ofw_real_unmap(argsptr, &args, sizeof(args));
565 ofw_real_unmap(args.buf, buf, size);
566
567 ofw_real_stop();
568 return (args.flag);
569 }
570
571 /* Set the value of a property of a package. */
572 /* XXX Has a bug on FirePower */
573 static int
574 ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
575 const void *buf, size_t len)
576 {
577 vm_offset_t argsptr;
578 struct {
579 cell_t name;
580 cell_t nargs;
581 cell_t nreturns;
582 cell_t package;
583 cell_t propname;
584 cell_t buf;
585 cell_t len;
586 cell_t size;
587 } args;
588
589 args.name = (cell_t)(uintptr_t)"setprop";
590 args.nargs = 4;
591 args.nreturns = 1;
592
593 ofw_real_start();
594
595 args.package = package;
596 args.propname = ofw_real_map(propname, strlen(propname) + 1);
597 args.buf = ofw_real_map(buf, len);
598 args.len = len;
599 argsptr = ofw_real_map(&args, sizeof(args));
600 if (args.propname == 0 || args.buf == 0 ||
601 openfirmware((void *)argsptr) == -1) {
602 ofw_real_stop();
603 return (-1);
604 }
605 ofw_real_unmap(argsptr, &args, sizeof(args));
606 ofw_real_stop();
607 return (args.size);
608 }
609
610 /* Convert a device specifier to a fully qualified pathname. */
611 static ssize_t
612 ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
613 {
614 vm_offset_t argsptr;
615 struct {
616 cell_t name;
617 cell_t nargs;
618 cell_t nreturns;
619 cell_t device;
620 cell_t buf;
621 cell_t len;
622 int32_t size;
623 } args;
624
625 args.name = (cell_t)(uintptr_t)"canon";
626 args.nargs = 3;
627 args.nreturns = 1;
628
629 ofw_real_start();
630
631 args.device = ofw_real_map(device, strlen(device) + 1);
632 args.buf = ofw_real_map(buf, len);
633 args.len = len;
634 argsptr = ofw_real_map(&args, sizeof(args));
635 if (args.device == 0 || args.buf == 0 ||
636 openfirmware((void *)argsptr) == -1) {
637 ofw_real_stop();
638 return (-1);
639 }
640 ofw_real_unmap(argsptr, &args, sizeof(args));
641 ofw_real_unmap(args.buf, buf, len);
642
643 ofw_real_stop();
644 return (args.size);
645 }
646
647 /* Return a package handle for the specified device. */
648 static phandle_t
649 ofw_real_finddevice(ofw_t ofw, const char *device)
650 {
651 vm_offset_t argsptr;
652 struct {
653 cell_t name;
654 cell_t nargs;
655 cell_t nreturns;
656 cell_t device;
657 cell_t package;
658 } args;
659
660 args.name = (cell_t)(uintptr_t)"finddevice";
661 args.nargs = 1;
662 args.nreturns = 1;
663
664 ofw_real_start();
665
666 args.device = ofw_real_map(device, strlen(device) + 1);
667 argsptr = ofw_real_map(&args, sizeof(args));
668 if (args.device == 0 ||
669 openfirmware((void *)argsptr) == -1) {
670 ofw_real_stop();
671 return (-1);
672 }
673 ofw_real_unmap(argsptr, &args, sizeof(args));
674 ofw_real_stop();
675 return (args.package);
676 }
677
678 /* Return the fully qualified pathname corresponding to an instance. */
679 static ssize_t
680 ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
681 {
682 vm_offset_t argsptr;
683 struct {
684 cell_t name;
685 cell_t nargs;
686 cell_t nreturns;
687 cell_t instance;
688 cell_t buf;
689 cell_t len;
690 int32_t size;
691 } args;
692
693 args.name = (cell_t)(uintptr_t)"instance-to-path";
694 args.nargs = 3;
695 args.nreturns = 1;
696
697 ofw_real_start();
698
699 args.instance = instance;
700 args.buf = ofw_real_map(buf, len);
701 args.len = len;
702 argsptr = ofw_real_map(&args, sizeof(args));
703 if (args.buf == 0 ||
704 openfirmware((void *)argsptr) == -1) {
705 ofw_real_stop();
706 return (-1);
707 }
708 ofw_real_unmap(argsptr, &args, sizeof(args));
709 ofw_real_unmap(args.buf, buf, len);
710
711 ofw_real_stop();
712 return (args.size);
713 }
714
715 /* Return the fully qualified pathname corresponding to a package. */
716 static ssize_t
717 ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
718 {
719 vm_offset_t argsptr;
720 struct {
721 cell_t name;
722 cell_t nargs;
723 cell_t nreturns;
724 cell_t package;
725 cell_t buf;
726 cell_t len;
727 int32_t size;
728 } args;
729
730 args.name = (cell_t)(uintptr_t)"package-to-path";
731 args.nargs = 3;
732 args.nreturns = 1;
733
734 ofw_real_start();
735
736 args.package = package;
737 args.buf = ofw_real_map(buf, len);
738 args.len = len;
739 argsptr = ofw_real_map(&args, sizeof(args));
740 if (args.buf == 0 ||
741 openfirmware((void *)argsptr) == -1) {
742 ofw_real_stop();
743 return (-1);
744 }
745 ofw_real_unmap(argsptr, &args, sizeof(args));
746 ofw_real_unmap(args.buf, buf, len);
747
748 ofw_real_stop();
749 return (args.size);
750 }
751
752 /* Call the method in the scope of a given instance. */
753 static int
754 ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method,
755 int nargs, int nreturns, cell_t *args_and_returns)
756 {
757 vm_offset_t argsptr;
758 struct {
759 cell_t name;
760 cell_t nargs;
761 cell_t nreturns;
762 cell_t method;
763 cell_t instance;
764 cell_t args_n_results[12];
765 } args;
766 cell_t *ap, *cp;
767 int n;
768
769 args.name = (cell_t)(uintptr_t)"call-method";
770 args.nargs = 2;
771 args.nreturns = 1;
772
773 if (nargs > 6)
774 return (-1);
775
776 ofw_real_start();
777 args.nargs = nargs + 2;
778 args.nreturns = nreturns + 1;
779 args.method = ofw_real_map(method, strlen(method) + 1);
780 args.instance = instance;
781
782 ap = args_and_returns;
783 for (cp = args.args_n_results + (n = nargs); --n >= 0;)
784 *--cp = *(ap++);
785 argsptr = ofw_real_map(&args, sizeof(args));
786 if (args.method == 0 ||
787 openfirmware((void *)argsptr) == -1) {
788 ofw_real_stop();
789 return (-1);
790 }
791 ofw_real_unmap(argsptr, &args, sizeof(args));
792 ofw_real_stop();
793 if (args.args_n_results[nargs])
794 return (args.args_n_results[nargs]);
795 for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
796 *(ap++) = *--cp;
797 return (0);
798 }
799
800 static int
801 ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns)
802 {
803 vm_offset_t argsptr;
804 struct {
805 cell_t name;
806 cell_t nargs;
807 cell_t nreturns;
808 cell_t slot[16];
809 } args;
810 cell_t status;
811 int i = 0, j = 0;
812
813 args.name = (cell_t)(uintptr_t)"interpret";
814 args.nargs = 1;
815
816 ofw_real_start();
817 args.nreturns = ++nreturns;
818 args.slot[i++] = ofw_real_map(cmd, strlen(cmd) + 1);
819 argsptr = ofw_real_map(&args, sizeof(args));
820 if (openfirmware((void *)argsptr) == -1) {
821 ofw_real_stop();
822 return (-1);
823 }
824 ofw_real_unmap(argsptr, &args, sizeof(args));
825 ofw_real_stop();
826 status = args.slot[i++];
827 while (i < 1 + nreturns)
828 returns[j++] = args.slot[i++];
829 return (status);
830 }
831
832 /*
833 * Device I/O functions
834 */
835
836 /* Open an instance for a device. */
837 static ihandle_t
838 ofw_real_open(ofw_t ofw, const char *device)
839 {
840 vm_offset_t argsptr;
841 struct {
842 cell_t name;
843 cell_t nargs;
844 cell_t nreturns;
845 cell_t device;
846 cell_t instance;
847 } args;
848
849 args.name = (cell_t)(uintptr_t)"open";
850 args.nargs = 1;
851 args.nreturns = 1;
852
853 ofw_real_start();
854
855 args.device = ofw_real_map(device, strlen(device) + 1);
856 argsptr = ofw_real_map(&args, sizeof(args));
857 if (args.device == 0 || openfirmware((void *)argsptr) == -1
858 || args.instance == 0) {
859 ofw_real_stop();
860 return (-1);
861 }
862 ofw_real_unmap(argsptr, &args, sizeof(args));
863 ofw_real_stop();
864 return (args.instance);
865 }
866
867 /* Close an instance. */
868 static void
869 ofw_real_close(ofw_t ofw, ihandle_t instance)
870 {
871 vm_offset_t argsptr;
872 struct {
873 cell_t name;
874 cell_t nargs;
875 cell_t nreturns;
876 cell_t instance;
877 } args;
878
879 args.name = (cell_t)(uintptr_t)"close";
880 args.nargs = 1;
881 args.nreturns = 0;
882 args.instance = instance;
883 ofw_real_start();
884 argsptr = ofw_real_map(&args, sizeof(args));
885 openfirmware((void *)argsptr);
886 ofw_real_stop();
887 }
888
889 /* Read from an instance. */
890 static ssize_t
891 ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
892 {
893 vm_offset_t argsptr;
894 struct {
895 cell_t name;
896 cell_t nargs;
897 cell_t nreturns;
898 cell_t instance;
899 cell_t addr;
900 cell_t len;
901 int32_t actual;
902 } args;
903
904 args.name = (cell_t)(uintptr_t)"read";
905 args.nargs = 3;
906 args.nreturns = 1;
907
908 ofw_real_start();
909
910 args.instance = instance;
911 args.addr = ofw_real_map(addr, len);
912 args.len = len;
913 argsptr = ofw_real_map(&args, sizeof(args));
914 if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
915 ofw_real_stop();
916 return (-1);
917 }
918 ofw_real_unmap(argsptr, &args, sizeof(args));
919 ofw_real_unmap(args.addr, addr, len);
920
921 ofw_real_stop();
922 return (args.actual);
923 }
924
925 /* Write to an instance. */
926 static ssize_t
927 ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
928 {
929 vm_offset_t argsptr;
930 struct {
931 cell_t name;
932 cell_t nargs;
933 cell_t nreturns;
934 cell_t instance;
935 cell_t addr;
936 cell_t len;
937 int32_t actual;
938 } args;
939
940 args.name = (cell_t)(uintptr_t)"write";
941 args.nargs = 3;
942 args.nreturns = 1;
943
944 ofw_real_start();
945
946 args.instance = instance;
947 args.addr = ofw_real_map(addr, len);
948 args.len = len;
949 argsptr = ofw_real_map(&args, sizeof(args));
950 if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
951 ofw_real_stop();
952 return (-1);
953 }
954 ofw_real_unmap(argsptr, &args, sizeof(args));
955 ofw_real_stop();
956 return (args.actual);
957 }
958
959 /* Seek to a position. */
960 static int
961 ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
962 {
963 vm_offset_t argsptr;
964 struct {
965 cell_t name;
966 cell_t nargs;
967 cell_t nreturns;
968 cell_t instance;
969 cell_t poshi;
970 cell_t poslo;
971 cell_t status;
972 } args;
973
974 args.name = (cell_t)(uintptr_t)"seek";
975 args.nargs = 3;
976 args.nreturns = 1;
977
978 args.instance = instance;
979 args.poshi = pos >> 32;
980 args.poslo = pos;
981 ofw_real_start();
982 argsptr = ofw_real_map(&args, sizeof(args));
983 if (openfirmware((void *)argsptr) == -1) {
984 ofw_real_stop();
985 return (-1);
986 }
987 ofw_real_unmap(argsptr, &args, sizeof(args));
988 ofw_real_stop();
989 return (args.status);
990 }
991
992 /*
993 * Memory functions
994 */
995
996 /* Claim an area of memory. */
997 static caddr_t
998 ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
999 {
1000 vm_offset_t argsptr;
1001 struct {
1002 cell_t name;
1003 cell_t nargs;
1004 cell_t nreturns;
1005 cell_t virt;
1006 cell_t size;
1007 cell_t align;
1008 cell_t baseaddr;
1009 } args;
1010
1011 args.name = (cell_t)(uintptr_t)"claim";
1012 args.nargs = 3;
1013 args.nreturns = 1;
1014
1015 args.virt = (cell_t)(uintptr_t)virt;
1016 args.size = size;
1017 args.align = align;
1018 ofw_real_start();
1019 argsptr = ofw_real_map(&args, sizeof(args));
1020 if (openfirmware((void *)argsptr) == -1) {
1021 ofw_real_stop();
1022 return ((void *)-1);
1023 }
1024 ofw_real_unmap(argsptr, &args, sizeof(args));
1025 ofw_real_stop();
1026 return ((void *)(uintptr_t)args.baseaddr);
1027 }
1028
1029 /* Release an area of memory. */
1030 static void
1031 ofw_real_release(ofw_t ofw, void *virt, size_t size)
1032 {
1033 vm_offset_t argsptr;
1034 struct {
1035 cell_t name;
1036 cell_t nargs;
1037 cell_t nreturns;
1038 cell_t virt;
1039 cell_t size;
1040 } args;
1041
1042 args.name = (cell_t)(uintptr_t)"release";
1043 args.nargs = 2;
1044 args.nreturns = 0;
1045
1046 args.virt = (cell_t)(uintptr_t)virt;
1047 args.size = size;
1048 ofw_real_start();
1049 argsptr = ofw_real_map(&args, sizeof(args));
1050 openfirmware((void *)argsptr);
1051 ofw_real_stop();
1052 }
1053
1054 /*
1055 * Control transfer functions
1056 */
1057
1058 /* Suspend and drop back to the Open Firmware interface. */
1059 static void
1060 ofw_real_enter(ofw_t ofw)
1061 {
1062 vm_offset_t argsptr;
1063 struct {
1064 cell_t name;
1065 cell_t nargs;
1066 cell_t nreturns;
1067 } args;
1068
1069 args.name = (cell_t)(uintptr_t)"enter";
1070 args.nargs = 0;
1071 args.nreturns = 0;
1072
1073 ofw_real_start();
1074 argsptr = ofw_real_map(&args, sizeof(args));
1075 openfirmware((void *)argsptr);
1076 /* We may come back. */
1077 ofw_real_stop();
1078 }
1079
1080 /* Shut down and drop back to the Open Firmware interface. */
1081 static void
1082 ofw_real_exit(ofw_t ofw)
1083 {
1084 vm_offset_t argsptr;
1085 struct {
1086 cell_t name;
1087 cell_t nargs;
1088 cell_t nreturns;
1089 } args;
1090
1091 args.name = (cell_t)(uintptr_t)"exit";
1092 args.nargs = 0;
1093 args.nreturns = 0;
1094
1095 ofw_real_start();
1096 argsptr = ofw_real_map(&args, sizeof(args));
1097 openfirmware((void *)argsptr);
1098 for (;;) /* just in case */
1099 ;
1100 ofw_real_stop();
1101 }
1102
Cache object: 52dfce3a74c88e2c8b2b0abbea643d13
|