xref: /netbsd-src/sys/arch/ofppc/stand/ofwboot/Locore.c (revision da1547d6be1bc48dad166f46976c33019c69217f)
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