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