]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/boot/ofw/libofw/openfirm.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / boot / ofw / libofw / openfirm.c
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$");
60
61 #include <machine/stdarg.h>
62
63 #include <stand.h>
64
65 #include "openfirm.h"
66
67 int (*openfirmware)(void *);
68
69 phandle_t chosen;
70 ihandle_t mmu;
71 ihandle_t memory;
72 int       real_mode = 0;
73
74 /* Initialiser */
75
76 void
77 OF_init(int (*openfirm)(void *))
78 {
79         phandle_t options;
80         char      mode[sizeof("true")];
81
82         openfirmware = openfirm;
83
84         if ((chosen = OF_finddevice("/chosen")) == -1)
85                 OF_exit();
86         if (OF_getprop(chosen, "memory", &memory, sizeof(memory)) == -1) {
87                 memory = OF_open("/memory");
88                 if (memory == -1)
89                         memory = OF_open("/memory@0");
90                 if (memory == -1)
91                         OF_exit();
92         }
93         if (OF_getprop(chosen, "mmu", &mmu, sizeof(mmu)) == -1)
94                 OF_exit();
95
96         /*
97          * Check if we run in real mode. If so, we do not need to map
98          * memory later on.
99          */
100         options = OF_finddevice("/options");
101         if (OF_getprop(options, "real-mode?", mode, sizeof(mode)) > 0 &&
102             strcmp(mode, "true") == 0)
103                 real_mode = 1;
104 }
105
106 /*
107  * Generic functions
108  */
109
110 /* Test to see if a service exists. */
111 int
112 OF_test(char *name)
113 {
114         static struct {
115                 cell_t name;
116                 cell_t nargs;
117                 cell_t nreturns;
118                 cell_t service;
119                 cell_t missing;
120         } args = {
121                 (cell_t)"test",
122                 1,
123                 1,
124         };
125
126         args.service = (cell_t)name;
127         if (openfirmware(&args) == -1)
128                 return (-1);
129         return (args.missing);
130 }
131
132 /* Return firmware millisecond count. */
133 int
134 OF_milliseconds()
135 {
136         static struct {
137                 cell_t name;
138                 cell_t nargs;
139                 cell_t nreturns;
140                 cell_t ms;
141         } args = {
142                 (cell_t)"milliseconds",
143                 0,
144                 1,
145         };
146
147         openfirmware(&args);
148         return (args.ms);
149 }
150
151 /*
152  * Device tree functions
153  */
154
155 /* Return the next sibling of this node or 0. */
156 phandle_t
157 OF_peer(phandle_t node)
158 {
159         static struct {
160                 cell_t name;
161                 cell_t nargs;
162                 cell_t nreturns;
163                 cell_t node;
164                 cell_t next;
165         } args = {
166                 (cell_t)"peer",
167                 1,
168                 1,
169         };
170
171         args.node = node;
172         if (openfirmware(&args) == -1)
173                 return (-1);
174         return (args.next);
175 }
176
177 /* Return the first child of this node or 0. */
178 phandle_t
179 OF_child(phandle_t node)
180 {
181         static struct {
182                 cell_t name;
183                 cell_t nargs;
184                 cell_t nreturns;
185                 cell_t node;
186                 cell_t child;
187         } args = {
188                 (cell_t)"child",
189                 1,
190                 1,
191         };
192
193         args.node = node;
194         if (openfirmware(&args) == -1)
195                 return (-1);
196         return (args.child);
197 }
198
199 /* Return the parent of this node or 0. */
200 phandle_t
201 OF_parent(phandle_t node)
202 {
203         static struct {
204                 cell_t name;
205                 cell_t nargs;
206                 cell_t nreturns;
207                 cell_t node;
208                 cell_t parent;
209         } args = {
210                 (cell_t)"parent",
211                 1,
212                 1,
213         };
214
215         args.node = node;
216         if (openfirmware(&args) == -1)
217                 return (-1);
218         return (args.parent);
219 }
220
221 /* Return the package handle that corresponds to an instance handle. */
222 phandle_t
223 OF_instance_to_package(ihandle_t instance)
224 {
225         static struct {
226                 cell_t name;
227                 cell_t nargs;
228                 cell_t nreturns;
229                 cell_t instance;
230                 cell_t package;
231         } args = {
232                 (cell_t)"instance-to-package",
233                 1,
234                 1,
235         };
236
237         args.instance = instance;
238         if (openfirmware(&args) == -1)
239                 return (-1);
240         return (args.package);
241 }
242
243 /* Get the length of a property of a package. */
244 int
245 OF_getproplen(phandle_t package, char *propname)
246 {
247         static struct {
248                 cell_t name;
249                 cell_t nargs;
250                 cell_t nreturns;
251                 cell_t package;
252                 cell_t propname;
253                 cell_t proplen;
254         } args = {
255                 (cell_t)"getproplen",
256                 2,
257                 1,
258         };
259
260         args.package = package;
261         args.propname = (cell_t)propname;
262         if (openfirmware(&args) == -1)
263                 return (-1);
264         return (args.proplen);
265 }
266
267 /* Get the value of a property of a package. */
268 int
269 OF_getprop(phandle_t package, char *propname, void *buf, int buflen)
270 {
271         static struct {
272                 cell_t name;
273                 cell_t nargs;
274                 cell_t nreturns;
275                 cell_t package;
276                 cell_t propname;
277                 cell_t buf;
278                 cell_t buflen;
279                 cell_t size;
280         } args = {
281                 (cell_t)"getprop",
282                 4,
283                 1,
284         };
285
286         args.package = package;
287         args.propname = (cell_t)propname;
288         args.buf = (cell_t)buf;
289         args.buflen = buflen;
290         if (openfirmware(&args) == -1)
291                 return (-1);
292         return (args.size);
293 }
294
295 /* Get the next property of a package. */
296 int
297 OF_nextprop(phandle_t package, char *previous, char *buf)
298 {
299         static struct {
300                 cell_t name;
301                 cell_t nargs;
302                 cell_t nreturns;
303                 cell_t package;
304                 cell_t previous;
305                 cell_t buf;
306                 cell_t flag;
307         } args = {
308                 (cell_t)"nextprop",
309                 3,
310                 1,
311         };
312
313         args.package = package;
314         args.previous = (cell_t)previous;
315         args.buf = (cell_t)buf;
316         if (openfirmware(&args) == -1)
317                 return (-1);
318         return (args.flag);
319 }
320
321 /* Set the value of a property of a package. */
322 /* XXX Has a bug on FirePower */
323 int
324 OF_setprop(phandle_t package, char *propname, void *buf, int len)
325 {
326         static struct {
327                 cell_t name;
328                 cell_t nargs;
329                 cell_t nreturns;
330                 cell_t package;
331                 cell_t propname;
332                 cell_t buf;
333                 cell_t len;
334                 cell_t size;
335         } args = {
336                 (cell_t)"setprop",
337                 4,
338                 1,
339         };
340
341         args.package = package;
342         args.propname = (cell_t)propname;
343         args.buf = (cell_t)buf;
344         args.len = len;
345         if (openfirmware(&args) == -1)
346                 return (-1);
347         return (args.size);
348 }
349
350 /* Convert a device specifier to a fully qualified pathname. */
351 int
352 OF_canon(const char *device, char *buf, int len)
353 {
354         static struct {
355                 cell_t name;
356                 cell_t nargs;
357                 cell_t nreturns;
358                 cell_t device;
359                 cell_t buf;
360                 cell_t len;
361                 cell_t size;
362         } args = {
363                 (cell_t)"canon",
364                 3,
365                 1,
366         };
367
368         args.device = (cell_t)device;
369         args.buf = (cell_t)buf;
370         args.len = len;
371         if (openfirmware(&args) == -1)
372                 return (-1);
373         return (args.size);
374 }
375
376 /* Return a package handle for the specified device. */
377 phandle_t
378 OF_finddevice(const char *device)
379 {
380         static struct {
381                 cell_t name;
382                 cell_t nargs;
383                 cell_t nreturns;
384                 cell_t device;
385                 cell_t package;
386         } args = {
387                 (cell_t)"finddevice",
388                 1,
389                 1,
390         };
391
392         args.device = (cell_t)device;
393         if (openfirmware(&args) == -1)
394                 return (-1);
395         return (args.package);
396 }
397
398 /* Return the fully qualified pathname corresponding to an instance. */
399 int
400 OF_instance_to_path(ihandle_t instance, char *buf, int len)
401 {
402         static struct {
403                 cell_t name;
404                 cell_t nargs;
405                 cell_t nreturns;
406                 cell_t instance;
407                 cell_t buf;
408                 cell_t len;
409                 cell_t size;
410         } args = {
411                 (cell_t)"instance-to-path",
412                 3,
413                 1,
414         };
415
416         args.instance = instance;
417         args.buf = (cell_t)buf;
418         args.len = len;
419         if (openfirmware(&args) == -1)
420                 return (-1);
421         return (args.size);
422 }
423
424 /* Return the fully qualified pathname corresponding to a package. */
425 int
426 OF_package_to_path(phandle_t package, char *buf, int len)
427 {
428         static struct {
429                 cell_t name;
430                 cell_t nargs;
431                 cell_t nreturns;
432                 cell_t package;
433                 cell_t buf;
434                 cell_t len;
435                 cell_t size;
436         } args = {
437                 (cell_t)"package-to-path",
438                 3,
439                 1,
440         };
441
442         args.package = package;
443         args.buf = (cell_t)buf;
444         args.len = len;
445         if (openfirmware(&args) == -1)
446                 return (-1);
447         return (args.size);
448 }
449
450 /*  Call the method in the scope of a given instance. */
451 int
452 OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
453 {
454         va_list ap;
455         static struct {
456                 cell_t name;
457                 cell_t nargs;
458                 cell_t nreturns;
459                 cell_t method;
460                 cell_t instance;
461                 cell_t args_n_results[12];
462         } args = {
463                 (cell_t)"call-method",
464                 2,
465                 1,
466         };
467         cell_t *cp;
468         int n;
469
470         if (nargs > 6)
471                 return (-1);
472         args.nargs = nargs + 2;
473         args.nreturns = nreturns + 1;
474         args.method = (cell_t)method;
475         args.instance = instance;
476         va_start(ap, nreturns);
477         for (cp = (cell_t *)(args.args_n_results + (n = nargs)); --n >= 0;)
478                 *--cp = va_arg(ap, cell_t);
479         if (openfirmware(&args) == -1)
480                 return (-1);
481         if (args.args_n_results[nargs])
482                 return (args.args_n_results[nargs]);
483         for (cp = (cell_t *)(args.args_n_results + nargs + (n = args.nreturns));
484             --n > 0;)
485                 *va_arg(ap, cell_t *) = *--cp;
486         va_end(ap);
487         return (0);
488 }
489
490 /*
491  * Device I/O functions
492  */
493
494 /* Open an instance for a device. */
495 ihandle_t
496 OF_open(char *device)
497 {
498         static struct {
499                 cell_t name;
500                 cell_t nargs;
501                 cell_t nreturns;
502                 cell_t device;
503                 cell_t instance;
504         } args = {
505                 (cell_t)"open",
506                 1,
507                 1,
508         };
509
510         args.device = (cell_t)device;
511         if (openfirmware(&args) == -1 || args.instance == 0) {
512                 return (-1);
513         }
514         return (args.instance);
515 }
516
517 /* Close an instance. */
518 void
519 OF_close(ihandle_t instance)
520 {
521         static struct {
522                 cell_t name;
523                 cell_t nargs;
524                 cell_t nreturns;
525                 cell_t instance;
526         } args = {
527                 (cell_t)"close",
528                 1,
529         };
530
531         args.instance = instance;
532         openfirmware(&args);
533 }
534
535 /* Read from an instance. */
536 int
537 OF_read(ihandle_t instance, void *addr, int len)
538 {
539         static struct {
540                 cell_t name;
541                 cell_t nargs;
542                 cell_t nreturns;
543                 cell_t instance;
544                 cell_t addr;
545                 cell_t len;
546                 cell_t actual;
547         } args = {
548                 (cell_t)"read",
549                 3,
550                 1,
551         };
552
553         args.instance = instance;
554         args.addr = (cell_t)addr;
555         args.len = len;
556
557 #if defined(OPENFIRM_DEBUG)
558         printf("OF_read: called with instance=%08x, addr=%p, len=%d\n",
559             args.instance, args.addr, args.len);
560 #endif
561
562         if (openfirmware(&args) == -1)
563                 return (-1);
564
565 #if defined(OPENFIRM_DEBUG)
566         printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n",
567             args.instance, args.addr, args.len, args.actual);
568 #endif
569
570         return (args.actual);
571 }
572
573 /* Write to an instance. */
574 int
575 OF_write(ihandle_t instance, void *addr, int len)
576 {
577         static struct {
578                 cell_t name;
579                 cell_t nargs;
580                 cell_t nreturns;
581                 cell_t instance;
582                 cell_t addr;
583                 cell_t len;
584                 cell_t actual;
585         } args = {
586                 (cell_t)"write",
587                 3,
588                 1,
589         };
590
591         args.instance = instance;
592         args.addr = (cell_t)addr;
593         args.len = len;
594         if (openfirmware(&args) == -1)
595                 return (-1);
596         return (args.actual);
597 }
598
599 /* Seek to a position. */
600 int
601 OF_seek(ihandle_t instance, u_int64_t pos)
602 {
603         static struct {
604                 cell_t name;
605                 cell_t nargs;
606                 cell_t nreturns;
607                 cell_t instance;
608                 cell_t poshi;
609                 cell_t poslo;
610                 cell_t status;
611         } args = {
612                 (cell_t)"seek",
613                 3,
614                 1,
615         };
616
617         args.instance = instance;
618         args.poshi = pos >> 32;
619         args.poslo = pos;
620         if (openfirmware(&args) == -1)
621                 return (-1);
622         return (args.status);
623 }
624
625 /*
626  * Memory functions
627  */
628
629 /* Claim an area of memory. */
630 void *
631 OF_claim(void *virt, u_int size, u_int align)
632 {
633         static struct {
634                 cell_t name;
635                 cell_t nargs;
636                 cell_t nreturns;
637                 cell_t virt;
638                 cell_t size;
639                 cell_t align;
640                 cell_t baseaddr;
641         } args = {
642                 (cell_t)"claim",
643                 3,
644                 1,
645         };
646
647         args.virt = (cell_t)virt;
648         args.size = size;
649         args.align = align;
650         if (openfirmware(&args) == -1)
651                 return ((void *)-1);
652         return ((void *)args.baseaddr);
653 }
654
655 /* Release an area of memory. */
656 void
657 OF_release(void *virt, u_int size)
658 {
659         static struct {
660                 cell_t name;
661                 cell_t nargs;
662                 cell_t nreturns;
663                 cell_t virt;
664                 cell_t size;
665         } args = {
666                 (cell_t)"release",
667                 2,
668         };
669
670         args.virt = (cell_t)virt;
671         args.size = size;
672         openfirmware(&args);
673 }
674
675 /*
676  * Control transfer functions
677  */
678
679 /* Reset the system and call "boot <bootspec>". */
680 void
681 OF_boot(char *bootspec)
682 {
683         static struct {
684                 cell_t name;
685                 cell_t nargs;
686                 cell_t nreturns;
687                 cell_t bootspec;
688         } args = {
689                 (cell_t)"boot",
690                 1,
691         };
692
693         args.bootspec = (cell_t)bootspec;
694         openfirmware(&args);
695         for (;;)                        /* just in case */
696                 ;
697 }
698
699 /* Suspend and drop back to the Open Firmware interface. */
700 void
701 OF_enter()
702 {
703         static struct {
704                 cell_t name;
705                 cell_t nargs;
706                 cell_t nreturns;
707         } args = {
708                 (cell_t)"enter",
709         };
710
711         openfirmware(&args);
712         /* We may come back. */
713 }
714
715 /* Shut down and drop back to the Open Firmware interface. */
716 void
717 OF_exit()
718 {
719         static struct {
720                 cell_t name;
721                 cell_t nargs;
722                 cell_t nreturns;
723         } args = {
724                 (cell_t)"exit",
725         };
726
727         openfirmware(&args);
728         for (;;)                        /* just in case */
729                 ;
730 }
731
732 /* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
733 #if 0
734 void
735 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
736 {
737         static struct {
738                 cell_t name;
739                 cell_t nargs;
740                 cell_t nreturns;
741                 cell_t virt;
742                 cell_t size;
743                 cell_t entry;
744                 cell_t arg;
745                 cell_t len;
746         } args = {
747                 (cell_t)"chain",
748                 5,
749         };
750
751         args.virt = (cell_t)virt;
752         args.size = size;
753         args.entry = (cell_t)entry;
754         args.arg = (cell_t)arg;
755         args.len = len;
756         openfirmware(&args);
757 }
758 #else
759 void
760 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
761 {
762         /*
763          * This is a REALLY dirty hack till the firmware gets this going
764          */
765 #if 0
766         if (size > 0)
767                 OF_release(virt, size);
768 #endif
769         entry(0, 0, openfirmware, arg, len);
770 }
771 #endif