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