1 /*        $NetBSD: Locore.c,v 1.23 2014/09/20 23:10:46 phx 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 #include "openfirm.h"
35 #include <sys/param.h>
36 #include <lib/libsa/stand.h>
37 
38 #include <machine/cpu.h>
39 
40 static int (*openfirmware_entry)(void *);
41 static int openfirmware(void *);
42 
43 void startup(void *, int, int (*)(void *), char *, int)
44           __attribute__((__used__));
45 static void setup(void);
46 
47 /* this pad gets the rodata laignment right, don't EVER fiddle it */
48 char *pad __attribute__((__aligned__ (8))) = "pad";
49 int stack[0x20000/4 + 4] __attribute__((__aligned__ (4), __used__));
50 char *heapspace __attribute__((__aligned__ (4)));
51 char altheap[0x20000] __attribute__((__aligned__ (4)));
52 
53 static int
openfirmware(void * arg)54 openfirmware(void *arg)
55 {
56           int r;
57 
58           __asm volatile ("sync; isync");
59           r = openfirmware_entry(arg);
60           __asm volatile ("sync; isync");
61 
62           return r;
63 }
64 
65 void
startup(void * vpd,int res,int (* openfirm)(void *),char * arg,int argl)66 startup(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
67 {
68 
69           openfirmware_entry = openfirm;
70           setup();
71           main();
72           OF_exit();
73 }
74 
75 __dead void
OF_exit(void)76 OF_exit(void)
77 {
78           static struct {
79                     char *name;
80                     int nargs;
81                     int nreturns;
82           } args = {
83                     "exit",
84                     0,
85                     0
86           };
87 
88           openfirmware(&args);
89           for (;;);                     /* just in case */
90 }
91 
92 __dead void
OF_boot(char * bootspec)93 OF_boot(char *bootspec)
94 {
95           static struct {
96                     char *name;
97                     int nargs;
98                     int nreturns;
99                     char *bootspec;
100           } args = {
101                     "boot",
102                     1,
103                     0,
104           };
105 
106           args.bootspec = bootspec;
107           openfirmware(&args);
108           for (;;);                     /* just in case */
109 }
110 
111 int
OF_finddevice(char * name)112 OF_finddevice(char *name)
113 {
114           static struct {
115                     char *name;
116                     int nargs;
117                     int nreturns;
118                     char *device;
119                     int phandle;
120           } args = {
121                     "finddevice",
122                     1,
123                     1,
124           };
125 
126           args.device = name;
127           if (openfirmware(&args) == -1)
128                     return -1;
129           return args.phandle;
130 }
131 
132 int
OF_instance_to_package(int ihandle)133 OF_instance_to_package(int ihandle)
134 {
135           static struct {
136                     char *name;
137                     int nargs;
138                     int nreturns;
139                     int ihandle;
140                     int phandle;
141           } args = {
142                     "instance-to-package",
143                     1,
144                     1,
145           };
146 
147           args.ihandle = ihandle;
148           if (openfirmware(&args) == -1)
149                     return -1;
150           return args.phandle;
151 }
152 
153 int
OF_getprop(int handle,char * prop,void * buf,int buflen)154 OF_getprop(int handle, char *prop, void *buf, int buflen)
155 {
156           static struct {
157                     char *name;
158                     int nargs;
159                     int nreturns;
160                     int phandle;
161                     char *prop;
162                     void *buf;
163                     int buflen;
164                     int size;
165           } args = {
166                     "getprop",
167                     4,
168                     1,
169           };
170 
171           args.phandle = handle;
172           args.prop = prop;
173           args.buf = buf;
174           args.buflen = buflen;
175           if (openfirmware(&args) == -1)
176                     return -1;
177           return args.size;
178 }
179 
180 #ifdef    __notyet__          /* Has a bug on FirePower */
181 int
OF_setprop(int handle,char * prop,void * buf,int len)182 OF_setprop(int handle, char *prop, void *buf, int len)
183 {
184           static struct {
185                     char *name;
186                     int nargs;
187                     int nreturns;
188                     int phandle;
189                     char *prop;
190                     void *buf;
191                     int len;
192                     int size;
193           } args = {
194                     "setprop",
195                     4,
196                     1,
197           };
198 
199           args.phandle = handle;
200           args.prop = prop;
201           args.buf = buf;
202           args.len = len;
203           if (openfirmware(&args) == -1)
204                     return -1;
205           return args.size;
206 }
207 #endif
208 
209 int
OF_open(char * dname)210 OF_open(char *dname)
211 {
212           static struct {
213                     char *name;
214                     int nargs;
215                     int nreturns;
216                     char *dname;
217                     int handle;
218           } args = {
219                     "open",
220                     1,
221                     1,
222           };
223 
224 #ifdef OFW_DEBUG
225           printf("OF_open(%s) -> ", dname);
226 #endif
227           args.dname = dname;
228           if (openfirmware(&args) == -1 ||
229               args.handle == 0) {
230 #ifdef OFW_DEBUG
231                     printf("lose\n");
232 #endif
233                     return -1;
234           }
235 #ifdef OFW_DEBUG
236           printf("%d\n", args.handle);
237 #endif
238           return args.handle;
239 }
240 
241 void
OF_close(int handle)242 OF_close(int handle)
243 {
244           static struct {
245                     char *name;
246                     int nargs;
247                     int nreturns;
248                     int handle;
249           } args = {
250                     "close",
251                     1,
252                     0,
253           };
254 
255 #ifdef OFW_DEBUG
256           printf("OF_close(%d)\n", handle);
257 #endif
258           args.handle = handle;
259           openfirmware(&args);
260 }
261 
262 int
OF_write(int handle,void * addr,int len)263 OF_write(int handle, void *addr, int len)
264 {
265           static struct {
266                     char *name;
267                     int nargs;
268                     int nreturns;
269                     int ihandle;
270                     void *addr;
271                     int len;
272                     int actual;
273           } args = {
274                     "write",
275                     3,
276                     1,
277           };
278 
279 #ifdef OFW_DEBUG
280           if (len != 1)
281                     printf("OF_write(%d, %p, %x) -> ", handle, addr, len);
282 #endif
283           args.ihandle = handle;
284           args.addr = addr;
285           args.len = len;
286           if (openfirmware(&args) == -1) {
287 #ifdef OFW_DEBUG
288                     printf("lose\n");
289 #endif
290                     return -1;
291           }
292 #ifdef OFW_DEBUG
293           if (len != 1)
294                     printf("%x\n", args.actual);
295 #endif
296           return args.actual;
297 }
298 
299 int
OF_read(int handle,void * addr,int len)300 OF_read(int handle, void *addr, int len)
301 {
302           static struct {
303                     char *name;
304                     int nargs;
305                     int nreturns;
306                     int ihandle;
307                     void *addr;
308                     int len;
309                     int actual;
310           } args = {
311                     "read",
312                     3,
313                     1,
314           };
315 
316 #ifdef OFW_DEBUG
317           if (len != 1)
318                     printf("OF_read(%d, %p, %x) -> ", handle, addr, len);
319 #endif
320           args.ihandle = handle;
321           args.addr = addr;
322           args.len = len;
323           if (openfirmware(&args) == -1) {
324 #ifdef OFW_DEBUG
325                     printf("lose\n");
326 #endif
327                     return -1;
328           }
329 #ifdef OFW_DEBUG
330           if (len != 1)
331                     printf("%x\n", args.actual);
332 #endif
333           return args.actual;
334 }
335 
336 int
OF_seek(int handle,u_quad_t pos)337 OF_seek(int handle, u_quad_t pos)
338 {
339           static struct {
340                     char *name;
341                     int nargs;
342                     int nreturns;
343                     int handle;
344                     int poshi;
345                     int poslo;
346                     int status;
347           } args = {
348                     "seek",
349                     3,
350                     1,
351           };
352 
353 #ifdef OFW_DEBUG
354           printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos);
355 #endif
356           args.handle = handle;
357           args.poshi = (int)(pos >> 32);
358           args.poslo = (int)pos;
359           if (openfirmware(&args) == -1) {
360 #ifdef OFW_DEBUG
361                     printf("lose\n");
362 #endif
363                     return -1;
364           }
365 #ifdef OFW_DEBUG
366           printf("%d\n", args.status);
367 #endif
368           return args.status;
369 }
370 
371 void *
OF_alloc_mem(u_int size)372 OF_alloc_mem(u_int size)
373 {
374           static struct {
375                     char *name;
376                     int nargs;
377                     int nreturns;
378                     u_int size;
379                     void *baseaddr;
380           } args = {
381                     "alloc-mem",
382                     1,
383                     1,
384           };
385 #ifdef OFW_DEBUG
386           printf("alloc-mem %x -> ", size);
387 #endif
388           if (openfirmware(&args) == -1) {
389 #ifdef OFW_DEBUG
390                     printf("lose\n");
391 #endif
392                     return (void *)-1;
393           }
394 #ifdef OFW_DEBUG
395           printf("%p\n", args.baseaddr);
396 #endif
397           return args.baseaddr;
398 }
399 
400 void *
OF_claim(void * virt,u_int size,u_int align)401 OF_claim(void *virt, u_int size, u_int align)
402 {
403           static struct {
404                     char *name;
405                     int nargs;
406                     int nreturns;
407                     void *virt;
408                     u_int size;
409                     u_int align;
410                     void *baseaddr;
411           } args = {
412                     "claim",
413                     3,
414                     1,
415           };
416 
417 #ifdef OFW_DEBUG
418           printf("OF_claim(%p, %x, %x) -> ", virt, size, align);
419 #endif
420           args.virt = virt;
421           args.size = size;
422           args.align = align;
423           if (openfirmware(&args) == -1) {
424 #ifdef OFW_DEBUG
425                     printf("lose\n");
426 #endif
427                     return (void *)-1;
428           }
429 #ifdef OFW_DEBUG
430           printf("%p\n", args.baseaddr);
431 #endif
432           return args.baseaddr;
433 }
434 
435 void
OF_release(void * virt,u_int size)436 OF_release(void *virt, u_int size)
437 {
438           static struct {
439                     char *name;
440                     int nargs;
441                     int nreturns;
442                     void *virt;
443                     u_int size;
444           } args = {
445                     "release",
446                     2,
447                     0,
448           };
449 
450 #ifdef OFW_DEBUG
451           printf("OF_release(%p, %x)\n", virt, size);
452 #endif
453           args.virt = virt;
454           args.size = size;
455           openfirmware(&args);
456 }
457 
458 int
OF_milliseconds(void)459 OF_milliseconds(void)
460 {
461           static struct {
462                     char *name;
463                     int nargs;
464                     int nreturns;
465                     int ms;
466           } args = {
467                     "milliseconds",
468                     0,
469                     1,
470           };
471 
472           openfirmware(&args);
473           return args.ms;
474 }
475 
476 #ifdef    __notyet__
477 void
OF_chain(void * virt,u_int size,void (* entry)(),void * arg,u_int len)478 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
479 {
480           static struct {
481                     char *name;
482                     int nargs;
483                     int nreturns;
484                     void *virt;
485                     u_int size;
486                     void (*entry)();
487                     void *arg;
488                     u_int len;
489           } args = {
490                     "chain",
491                     5,
492                     0,
493           };
494 
495           args.virt = virt;
496           args.size = size;
497           args.entry = entry;
498           args.arg = arg;
499           args.len = len;
500           openfirmware(&args);
501 }
502 #else
503 void
OF_chain(void * virt,u_int size,boot_entry_t entry,void * arg,u_int len)504 OF_chain(void *virt, u_int size, boot_entry_t entry, void *arg, u_int len)
505 {
506           /*
507            * This is a REALLY dirty hack till the firmware gets this going
508            */
509 #if 0
510           OF_release(virt, size);
511 #endif
512           entry(0, 0, openfirmware_entry, arg, len);
513 }
514 #endif
515 
516 static int stdin;
517 static int stdout;
518 
519 static void
setup(void)520 setup(void)
521 {
522           int chosen;
523 
524           if ((chosen = OF_finddevice("/chosen")) == -1)
525                     OF_exit();
526           if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) !=
527               sizeof(stdin) ||
528               OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) !=
529               sizeof(stdout))
530                     OF_exit();
531 
532           //printf("Allocating 0x20000 bytes of ram for boot\n");
533           heapspace = OF_claim(0, 0x20000, NBPG);
534           if (heapspace == (char *)-1) {
535                     printf("WARNING: Failed to alloc ram, using bss\n");
536                     setheap(&altheap, &altheap[0x20000]);
537           } else
538                     setheap(heapspace, heapspace+0x20000);
539 }
540 
541 void
putchar(int c)542 putchar(int c)
543 {
544           char ch = c;
545 
546           if (c == '\n')
547                     putchar('\r');
548           OF_write(stdout, &ch, 1);
549 }
550 
551 int
getchar(void)552 getchar(void)
553 {
554           unsigned char ch = '\0';
555           int l;
556 
557           while ((l = OF_read(stdin, &ch, 1)) != 1)
558                     if (l != -2 && l != 0)
559                               return -1;
560           return ch;
561 }
562 
563 #ifdef OFWDUMP
564 
565 static int
OF_peer(int phandle)566 OF_peer(int phandle)
567 {
568           static struct {
569                     const char *name;
570                     int nargs;
571                     int nreturns;
572                     int phandle;
573                     int sibling;
574           } args = {
575                     "peer",
576                               1,
577                               1,
578           };
579 
580           args.phandle = phandle;
581           if (openfirmware(&args) == -1)
582                     return 0;
583           return args.sibling;
584 }
585 
586 static int
OF_child(int phandle)587 OF_child(int phandle)
588 {
589           static struct {
590                     const char *name;
591                     int nargs;
592                     int nreturns;
593                     int phandle;
594                     int child;
595           } args = {
596                     "child",
597                               1,
598                               1,
599           };
600 
601           args.phandle = phandle;
602           if (openfirmware(&args) == -1)
603                     return 0;
604           return args.child;
605 }
606 
607 int
OF_nextprop(int handle,const char * prop,void * nextprop)608 OF_nextprop(int handle, const char *prop, void *nextprop)
609 {
610           static struct {
611                     const char *name;
612                     int nargs;
613                     int nreturns;
614                     int phandle;
615                     const char *prop;
616                     char *buf;
617                     int flag;
618           } args = {
619                     "nextprop",
620                               3,
621                               1,
622           };
623 
624           args.phandle = handle;
625           args.prop = prop;
626           args.buf = nextprop;
627           if (openfirmware(&args) == -1)
628                     return -1;
629           return args.flag;
630 }
631 
632 static int
OF_package_to_path(int phandle,char * buf,int buflen)633 OF_package_to_path(int phandle, char *buf, int buflen)
634 {
635           static struct {
636                     const char *name;
637                     int nargs;
638                     int nreturns;
639                     int phandle;
640                     char *buf;
641                     int buflen;
642                     int length;
643           } args = {
644                     "package-to-path",
645                               3,
646                               1,
647           };
648 
649           if (buflen > 4096)
650                     return -1;
651           args.phandle = phandle;
652           args.buf = buf;
653           args.buflen = buflen;
654           if (openfirmware(&args) < 0)
655                     return -1;
656           if (args.length > buflen)
657                     args.length = buflen;
658           return args.length;
659 }
660 
661 void
dump_ofwtree(int node)662 dump_ofwtree(int node)
663 {
664           int peer, child, namelen, dlen, i;
665           char namebuf[33], newnamebuf[33];
666           char path[256], data[256];
667 
668           for (peer = node; peer; peer = OF_peer(peer)) {
669                     printf("\nnode: 0x%x ", peer);
670                     if (OF_package_to_path(peer, path, 512) >= 0)
671                               printf("path=%s", path);
672                     printf("\n");
673                     namebuf[0] = '\0';
674                     namelen = OF_nextprop(peer, namebuf, &newnamebuf);
675                     while (namelen >= 0) {
676                               /*printf("namelen == %d namebuf=%s new=%s\n", namelen,
677                                 namebuf, newnamebuf);*/
678                               //newnamebuf[namelen] = '\0';
679                               strcpy(namebuf, newnamebuf);
680                               printf("  %s :", newnamebuf);
681                               dlen = OF_getprop(peer, newnamebuf, data, 256);
682                               if (dlen > 0) {
683                                         if (data[0] < 0177)
684                                                   printf(" %s\n", data);
685                                         else
686                                                   printf("\n");
687                                         printf("    ");
688                                         for (i=0; i < dlen && i < 256; i++) {
689                                                   if (data[i] < 0x10)
690                                                             printf("0");
691                                                   printf("%x", data[i]);
692                                                   if ((i+1)%4 == 0)
693                                                             printf(" ");
694                                                   if ((i+1)%32 == 0)
695                                                             printf("\n    ");
696                                         }
697                               }
698                               printf("\n");
699                               namelen = OF_nextprop(peer, namebuf, &newnamebuf);
700                               if (newnamebuf[0] == '\0' ||
701                                   strcmp(namebuf, newnamebuf) == 0)
702                                         break;
703                     }
704                     child = OF_child(peer);
705                     if (child > 0)
706                               dump_ofwtree(child);
707           }
708 }
709 
710 #endif /* OFWDUMP */
711