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