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