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