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