1 /*        $NetBSD: openfirm.c,v 1.11 2021/02/07 13:59:36 martin Exp $ */
2 
3 /*
4  * Copyright 1997
5  * Digital Equipment Corporation. All rights reserved.
6  *
7  * This software is furnished under license and may be used and
8  * copied only in accordance with the following terms and conditions.
9  * Subject to these conditions, you may download, copy, install,
10  * use, modify and distribute this software in source and/or binary
11  * form. No title or ownership is transferred hereby.
12  *
13  * 1) Any source code used, modified or distributed must reproduce
14  *    and retain this copyright notice and list of conditions as
15  *    they appear in the source file.
16  *
17  * 2) No right is granted to use any trade name, trademark, or logo of
18  *    Digital Equipment Corporation. Neither the "Digital Equipment
19  *    Corporation" name nor any trademark or logo of Digital Equipment
20  *    Corporation may be used to endorse or promote products derived
21  *    from this software without the prior written permission of
22  *    Digital Equipment Corporation.
23  *
24  * 3) This software is provided "AS-IS" and any express or implied
25  *    warranties, including but not limited to, any implied warranties
26  *    of merchantability, fitness for a particular purpose, or
27  *    non-infringement are disclaimed. In no event shall DIGITAL be
28  *    liable for any damages whatsoever, and in particular, DIGITAL
29  *    shall not be liable for special, indirect, consequential, or
30  *    incidental damages or damages for lost profits, loss of
31  *    revenue or loss of use, whether such damages arise in contract,
32  *    negligence, tort, under statute, in equity, at law or otherwise,
33  *    even if advised of the possibility of such damage.
34  */
35 
36 /*
37  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
38  * Copyright (C) 1995, 1996 TooLs GmbH.
39  * All rights reserved.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. All advertising materials mentioning features or use of this software
50  *    must display the following acknowledgement:
51  *        This product includes software developed by TooLs GmbH.
52  * 4. The name of TooLs GmbH may not be used to endorse or promote products
53  *    derived from this software without specific prior written permission.
54  *
55  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
56  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
57  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
58  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
59  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
60  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
61  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
62  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
63  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
64  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
65  */
66 
67 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: openfirm.c,v 1.11 2021/02/07 13:59:36 martin Exp $");
69 
70 #include <sys/param.h>
71 
72 #include <dev/ofw/openfirm.h>
73 
74 
75 /*
76  *  Wrapper routines for OFW client services.
77  *
78  *  This code was adapted from the PowerPC version done by
79  *  Wolfgang Solfrank.  The main difference is that we don't
80  *  do the silly "ofw_stack" dance to convert the OS's real-
81  *  mode view of OFW to virtual-mode.  We don't need to do
82  *  that because our NetBSD port assumes virtual-mode OFW.
83  *
84  *  We should work with Wolfgang to turn this into a MI file. -JJK
85  */
86 
87 
88 int
OF_peer(int phandle)89 OF_peer(int phandle)
90 {
91           static struct {
92                     const char *name;
93                     int nargs;
94                     int nreturns;
95                     int phandle;
96                     int sibling;
97           } args = {
98                     "peer",
99                     1,
100                     1,
101           };
102 
103           args.phandle = phandle;
104           if (openfirmware(&args) == -1)
105                     return 0;
106           return args.sibling;
107 }
108 
109 int
OF_child(int phandle)110 OF_child(int phandle)
111 {
112           static struct {
113                     const char *name;
114                     int nargs;
115                     int nreturns;
116                     int phandle;
117                     int child;
118           } args = {
119                     "child",
120                     1,
121                     1,
122           };
123 
124           args.phandle = phandle;
125           if (openfirmware(&args) == -1)
126                     return 0;
127           return args.child;
128 }
129 
130 int
OF_parent(int phandle)131 OF_parent(int phandle)
132 {
133           static struct {
134                     const char *name;
135                     int nargs;
136                     int nreturns;
137                     int phandle;
138                     int parent;
139           } args = {
140                     "parent",
141                     1,
142                     1,
143           };
144 
145           args.phandle = phandle;
146           if (openfirmware(&args) == -1)
147                     return 0;
148           return args.parent;
149 }
150 
151 int
OF_instance_to_package(int ihandle)152 OF_instance_to_package(int ihandle)
153 {
154           static struct {
155                     const char *name;
156                     int nargs;
157                     int nreturns;
158                     int ihandle;
159                     int phandle;
160           } args = {
161                     "instance-to-package",
162                     1,
163                     1,
164           };
165 
166           args.ihandle = ihandle;
167           if (openfirmware(&args) == -1)
168                     return -1;
169           return args.phandle;
170 }
171 
172 int
OF_nextprop(int handle,const char * prop,void * nextprop)173 OF_nextprop(int handle, const char *prop, void *nextprop)
174 {
175           static struct {
176                     const char *name;
177                     int nargs;
178                     int nreturns;
179                     int phandle;
180                     const char *prop;
181                     void *nextprop;
182                     int flags;
183           } args = {
184                     "nextprop",
185                     3,
186                     1,
187           };
188 
189           args.phandle = handle;
190           args.prop = prop;
191           args.nextprop = nextprop;
192 
193           if (openfirmware(&args) == -1)
194                     return -1;
195           return args.flags;
196 }
197 
198 int
OF_getprop(int handle,const char * prop,void * buf,int buflen)199 OF_getprop(int handle, const char *prop, void *buf, int buflen)
200 {
201           static struct {
202                     const char *name;
203                     int nargs;
204                     int nreturns;
205                     int phandle;
206                     const char *prop;
207                     void *buf;
208                     int buflen;
209                     int size;
210           } args = {
211                     "getprop",
212                     4,
213                     1,
214           };
215 
216           args.phandle = handle;
217           args.prop = prop;
218           args.buf = buf;
219           args.buflen = buflen;
220 
221 
222           if (openfirmware(&args) == -1)
223                     return -1;
224           return args.size;
225 }
226 
227 int
OF_setprop(int handle,const char * prop,const void * buf,int buflen)228 OF_setprop(int handle, const char *prop, const void *buf, int buflen)
229 {
230           static struct {
231                     const char *name;
232                     int nargs;
233                     int nreturns;
234                     int phandle;
235                     const char *prop;
236                     const void *buf;
237                     int buflen;
238                     int size;
239           } args = {
240                     "setprop",
241                     4,
242                     1,
243           };
244 
245           args.phandle = handle;
246           args.prop = prop;
247           args.buf = buf;
248           args.buflen = buflen;
249 
250 
251           if (openfirmware(&args) == -1)
252                     return -1;
253           return args.size;
254 }
255 
256 int
OF_getproplen(int handle,const char * prop)257 OF_getproplen(int handle, const char *prop)
258 {
259           static struct {
260                     const char *name;
261                     int nargs;
262                     int nreturns;
263                     int phandle;
264                     const char *prop;
265                     int size;
266           } args = {
267                     "getproplen",
268                     2,
269                     1,
270           };
271 
272           args.phandle = handle;
273           args.prop = prop;
274           if (openfirmware(&args) == -1)
275                     return -1;
276           return args.size;
277 }
278 
279 int
OF_finddevice(const char * name)280 OF_finddevice(const char *name)
281 {
282           static struct {
283                     const char *name;
284                     int nargs;
285                     int nreturns;
286                     const char *device;
287                     int phandle;
288           } args = {
289                     "finddevice",
290                     1,
291                     1,
292           };
293 
294           args.device = name;
295           if (openfirmware(&args) == -1)
296                     return -1;
297           return args.phandle;
298 }
299 
300 int
OF_instance_to_path(int ihandle,char * buf,int buflen)301 OF_instance_to_path(int ihandle, char *buf, int buflen)
302 {
303           static struct {
304                     const char *name;
305                     int nargs;
306                     int nreturns;
307                     int ihandle;
308                     char *buf;
309                     int buflen;
310                     int length;
311           } args = {
312                     "instance-to-path",
313                     3,
314                     1,
315           };
316 
317           args.ihandle = ihandle;
318           args.buf = buf;
319           args.buflen = buflen;
320           if (openfirmware(&args) < 0)
321                     return -1;
322           return args.length;
323 }
324 
325 int
OF_package_to_path(int phandle,char * buf,int buflen)326 OF_package_to_path(int phandle, char *buf, int buflen)
327 {
328           static struct {
329                     const char *name;
330                     int nargs;
331                     int nreturns;
332                     int phandle;
333                     char *buf;
334                     int buflen;
335                     int length;
336           } args = {
337                     "package-to-path",
338                     3,
339                     1,
340           };
341 
342           args.phandle = phandle;
343           args.buf = buf;
344           args.buflen = buflen;
345           if (openfirmware(&args) < 0)
346                     return -1;
347           return args.length;
348 }
349 
350 int
351 #ifdef    __STDC__
OF_call_method(const char * method,int ihandle,int nargs,int nreturns,...)352 OF_call_method(const char *method, int ihandle, int nargs, int nreturns, ...)
353 #else
354 OF_call_method(method, ihandle, nargs, nreturns, va_alist)
355           const char *method;
356           int ihandle;
357           int nargs;
358           int nreturns;
359           va_dcl
360 #endif
361 {
362           va_list ap;
363           static struct {
364                     const char *name;
365                     int nargs;
366                     int nreturns;
367                     const char *method;
368                     int ihandle;
369                     int args_n_results[12];
370           } args = {
371                     "call-method",
372                     2,
373                     1,
374           };
375           int *ip, n;
376 
377           if (nargs > 6)
378                     return -1;
379           args.nargs = nargs + 2;
380           args.nreturns = nreturns + 1;
381           args.method = method;
382           args.ihandle = ihandle;
383           va_start(ap, nreturns);
384           for (ip = args.args_n_results + (n = nargs); --n >= 0;)
385                     *--ip = va_arg(ap, int);
386           if (openfirmware(&args) == -1) {
387                     va_end(ap);
388                     return -1;
389           }
390 /*
391           {
392               int i, res;
393 
394               printf("call_method(%s): ihandle = %x, nargs = %d, nreturns = %d -- ",
395                        method, ihandle, nargs, nreturns);
396               res = openfirmware(&args);
397               printf("res = %x\n", res);
398               printf("\targs_n_results = ");
399               for (i = 0; i < nargs + nreturns + 1; i++)
400                     printf("%x ", args.args_n_results[i]);
401               printf("\n");
402               if (res == -1) return -1;
403           }
404 */
405           if (args.args_n_results[nargs]) {
406                     va_end(ap);
407                     return args.args_n_results[nargs];
408           }
409           for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
410                     *va_arg(ap, int *) = *--ip;
411           va_end(ap);
412           return 0;
413 }
414 
415 int
416 #ifdef    __STDC__
OF_call_method_1(const char * method,int ihandle,int nargs,...)417 OF_call_method_1(const char *method, int ihandle, int nargs, ...)
418 #else
419 OF_call_method_1(method, ihandle, nargs, va_alist)
420           const char *method;
421           int ihandle;
422           int nargs;
423           va_dcl
424 #endif
425 {
426           va_list ap;
427           static struct {
428                     const char *name;
429                     int nargs;
430                     int nreturns;
431                     const char *method;
432                     int ihandle;
433                     int args_n_results[8];
434           } args = {
435                     "call-method",
436                     2,
437                     2,
438           };
439           int *ip, n;
440 
441           if (nargs > 6)
442                     return -1;
443           args.nargs = nargs + 2;
444           args.method = method;
445           args.ihandle = ihandle;
446           va_start(ap, nargs);
447           for (ip = args.args_n_results + (n = nargs); --n >= 0;)
448                     *--ip = va_arg(ap, int);
449           va_end(ap);
450           if (openfirmware(&args) == -1)
451                     return -1;
452 /*
453           {
454               int i, res;
455 
456               printf("call_method_1(%s): ihandle = %x, nargs = %d -- ",
457                        method, ihandle, nargs);
458               res = openfirmware(&args);
459               printf("res = %x\n", res);
460               printf("\targs_n_results = ");
461               for (i = 0; i < nargs + 2; i++)
462                     printf("%x ", args.args_n_results[i]);
463               printf("\n");
464               if (res == -1) return -1;
465           }
466 */
467           if (args.args_n_results[nargs])
468                     return -1;
469           return args.args_n_results[nargs + 1];
470 }
471 
472 int
OF_open(const char * dname)473 OF_open(const char *dname)
474 {
475           static struct {
476                     const char *name;
477                     int nargs;
478                     int nreturns;
479                     const char *dname;
480                     int handle;
481           } args = {
482                     "open",
483                     1,
484                     1,
485           };
486 
487           args.dname = dname;
488           if (openfirmware(&args) == -1)
489                     return -1;
490           return args.handle;
491 }
492 
493 void
OF_close(int handle)494 OF_close(int handle)
495 {
496           static struct {
497                     const char *name;
498                     int nargs;
499                     int nreturns;
500                     int handle;
501           } args = {
502                     "close",
503                     1,
504                     0,
505           };
506 
507           args.handle = handle;
508           openfirmware(&args);
509 }
510 
511 int
OF_read(int handle,void * addr,int len)512 OF_read(int handle, void *addr, int len)
513 {
514           static struct {
515                     const char *name;
516                     int nargs;
517                     int nreturns;
518                     int ihandle;
519                     void *addr;
520                     int len;
521                     int actual;
522           } args = {
523                     "read",
524                     3,
525                     1,
526           };
527 
528           args.ihandle = handle;
529           args.addr = addr;
530           args.len = len;
531           if (openfirmware(&args) == -1)
532                     return -1;
533           return args.actual;
534 }
535 
536 int
OF_write(int handle,const void * addr,int len)537 OF_write(int handle, const void *addr, int len)
538 {
539           static struct {
540                     const char *name;
541                     int nargs;
542                     int nreturns;
543                     int ihandle;
544                     const void *addr;
545                     int len;
546                     int actual;
547           } args = {
548                     "write",
549                     3,
550                     1,
551           };
552 
553           args.ihandle = handle;
554           args.addr = addr;
555           args.len = len;
556           if (openfirmware(&args) == -1)
557                     return -1;
558           return args.actual;
559 }
560 
561 int
OF_seek(int handle,u_quad_t pos)562 OF_seek(int handle, u_quad_t pos)
563 {
564           static struct {
565                     const char *name;
566                     int nargs;
567                     int nreturns;
568                     int handle;
569                     int poshi;
570                     int poslo;
571                     int status;
572           } args = {
573                     "seek",
574                     3,
575                     1,
576           };
577 
578           args.handle = handle;
579           args.poshi = (int)(pos >> 32);
580           args.poslo = (int)pos;
581           if (openfirmware(&args) == -1)
582                     return -1;
583           return args.status;
584 }
585 
586 void *
OF_claim(void * virt,u_int size,u_int align)587 OF_claim(void *virt, u_int size, u_int align)
588 {
589         static struct {
590                 const char *name;
591                 int nargs;
592                 int nreturns;
593                 void *virt;
594                 u_int size;
595                 u_int align;
596                 void *baseaddr;
597         } args = {
598                 "claim",
599                 3,
600                 1,
601         };
602 
603         args.virt = virt;
604         args.size = size;
605         args.align = align;
606         if (openfirmware(&args) == -1)
607                 return (void *)-1;
608         return args.baseaddr;
609 }
610 
611 void
OF_release(void * virt,u_int size)612 OF_release(void *virt, u_int size)
613 {
614         static struct {
615                 const char *name;
616                 int nargs;
617                 int nreturns;
618                 void *virt;
619                 u_int size;
620         } args = {
621                 "release",
622                 2,
623                 0,
624         };
625 
626         args.virt = virt;
627         args.size = size;
628         openfirmware(&args);
629 }
630 
631 int
OF_milliseconds(void)632 OF_milliseconds(void)
633 {
634         static struct {
635                 const char *name;
636                 int nargs;
637                 int nreturns;
638                 int ms;
639         } args = {
640                 "milliseconds",
641                 0,
642                 1,
643         };
644 
645         openfirmware(&args);
646         return args.ms;
647 }
648 
649 void
OF_boot(const char * btspec)650 OF_boot(const char *btspec)
651 {
652           static struct {
653                     const char *name;
654                     int nargs;
655                     int nreturns;
656                     const char *bootspec;
657           } args = {
658                     "boot",
659                     1,
660                     0,
661           };
662 
663           args.bootspec = btspec;
664           openfirmware(&args);
665           while (1);                              /* just in case */
666 }
667 
668 void
OF_enter(void)669 OF_enter(void)
670 {
671           static struct {
672                     const char *name;
673                     int nargs;
674                     int nreturns;
675           } args = {
676                     "enter",
677                     0,
678                     0,
679           };
680 
681           openfirmware(&args);
682 }
683 
684 void
OF_exit(void)685 OF_exit(void)
686 {
687           static struct {
688                     const char *name;
689                     int nargs;
690                     int nreturns;
691           } args = {
692                     "exit",
693                     0,
694                     0,
695           };
696 
697           openfirmware(&args);
698           while (1);                              /* just in case */
699 }
700 
701 typedef void (*of_callback_t)(void *);
702 
703 of_callback_t
OF_set_callback(of_callback_t newfunc)704 OF_set_callback(of_callback_t newfunc)
705 {
706           static struct {
707                     const char *name;
708                     int nargs;
709                     int nreturns;
710                     of_callback_t newfunc;
711                     of_callback_t oldfunc;
712           } args = {
713                     "set-callback",
714                     1,
715                     1,
716           };
717 
718           args.newfunc = newfunc;
719           if (openfirmware(&args) == -1)
720                     return 0;
721           return args.oldfunc;
722 }
723