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