xref: /netbsd-src/sys/arch/ofppc/stand/ofwboot/Locore.c (revision e5548b402ae4c44fb816de42c7bba9581ce23ef5)
1 /*	$NetBSD: Locore.c,v 1.12 2005/12/11 12:18:30 christos 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 "openfirm.h"
35 
36 #include <lib/libsa/stand.h>
37 
38 #include <machine/cpu.h>
39 
40 static int (*openfirmware_entry)(void *);
41 static int openfirmware(void *);
42 
43 static void setup(void);
44 
45 static int stack[8192/4 + 4];
46 
47 asm(
48 "	.text					\n"
49 "	.globl	_start				\n"
50 "_start:					\n"
51 "	li	8,0				\n"
52 "	li	9,0x100				\n"
53 "	mtctr	9				\n"
54 "1:						\n"
55 "	dcbf	0,8				\n"
56 "	icbi	0,8				\n"
57 "	addi	8,8,0x20			\n"
58 "	bdnz	1b				\n"
59 "	sync					\n"
60 "	isync					\n"
61 
62 "	lis	1,stack@ha			\n"
63 "	addi	1,1,stack@l			\n"
64 "	addi	1,1,8192			\n"
65 "	b	startup				\n"
66 );
67 
68 static int
69 openfirmware(void *arg)
70 {
71 	int r;
72 
73 	asm volatile ("sync; isync");
74 	r = openfirmware_entry(arg);
75 	asm volatile ("sync; isync");
76 
77 	return r;
78 }
79 
80 static void
81 startup(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
82 {
83 	extern char _end[], _edata[];
84 
85 	memset(_edata, 0, (_end - _edata));
86 	openfirmware_entry = openfirm;
87 	setup();
88 	main();
89 	OF_exit();
90 }
91 
92 __dead void
93 OF_exit(void)
94 {
95 	static struct {
96 		char *name;
97 		int nargs;
98 		int nreturns;
99 	} args = {
100 		"exit",
101 		0,
102 		0
103 	};
104 
105 	openfirmware(&args);
106 	for (;;);			/* just in case */
107 }
108 
109 __dead void
110 OF_boot(char *bootspec)
111 {
112 	static struct {
113 		char *name;
114 		int nargs;
115 		int nreturns;
116 		char *bootspec;
117 	} args = {
118 		"boot",
119 		1,
120 		0,
121 	};
122 
123 	args.bootspec = bootspec;
124 	openfirmware(&args);
125 	for (;;);			/* just is case */
126 }
127 
128 int
129 OF_finddevice(char *name)
130 {
131 	static struct {
132 		char *name;
133 		int nargs;
134 		int nreturns;
135 		char *device;
136 		int phandle;
137 	} args = {
138 		"finddevice",
139 		1,
140 		1,
141 	};
142 
143 	args.device = name;
144 	if (openfirmware(&args) == -1)
145 		return -1;
146 	return args.phandle;
147 }
148 
149 int
150 OF_instance_to_package(int ihandle)
151 {
152 	static struct {
153 		char *name;
154 		int nargs;
155 		int nreturns;
156 		int ihandle;
157 		int phandle;
158 	} args = {
159 		"instance-to-package",
160 		1,
161 		1,
162 	};
163 
164 	args.ihandle = ihandle;
165 	if (openfirmware(&args) == -1)
166 		return -1;
167 	return args.phandle;
168 }
169 
170 int
171 OF_getprop(int handle, char *prop, void *buf, int buflen)
172 {
173 	static struct {
174 		char *name;
175 		int nargs;
176 		int nreturns;
177 		int phandle;
178 		char *prop;
179 		void *buf;
180 		int buflen;
181 		int size;
182 	} args = {
183 		"getprop",
184 		4,
185 		1,
186 	};
187 
188 	args.phandle = handle;
189 	args.prop = prop;
190 	args.buf = buf;
191 	args.buflen = buflen;
192 	if (openfirmware(&args) == -1)
193 		return -1;
194 	return args.size;
195 }
196 
197 #ifdef	__notyet__	/* Has a bug on FirePower */
198 int
199 OF_setprop(int handle, char *prop, void *buf, int len)
200 {
201 	static struct {
202 		char *name;
203 		int nargs;
204 		int nreturns;
205 		int phandle;
206 		char *prop;
207 		void *buf;
208 		int len;
209 		int size;
210 	} args = {
211 		"setprop",
212 		4,
213 		1,
214 	};
215 
216 	args.phandle = handle;
217 	args.prop = prop;
218 	args.buf = buf;
219 	args.len = len;
220 	if (openfirmware(&args) == -1)
221 		return -1;
222 	return args.size;
223 }
224 #endif
225 
226 int
227 OF_open(char *dname)
228 {
229 	static struct {
230 		char *name;
231 		int nargs;
232 		int nreturns;
233 		char *dname;
234 		int handle;
235 	} args = {
236 		"open",
237 		1,
238 		1,
239 	};
240 
241 #ifdef OFW_DEBUG
242 	printf("OF_open(%s) -> ", dname);
243 #endif
244 	args.dname = dname;
245 	if (openfirmware(&args) == -1 ||
246 	    args.handle == 0) {
247 #ifdef OFW_DEBUG
248 		printf("lose\n");
249 #endif
250 		return -1;
251 	}
252 #ifdef OFW_DEBUG
253 	printf("%d\n", args.handle);
254 #endif
255 	return args.handle;
256 }
257 
258 void
259 OF_close(int handle)
260 {
261 	static struct {
262 		char *name;
263 		int nargs;
264 		int nreturns;
265 		int handle;
266 	} args = {
267 		"close",
268 		1,
269 		0,
270 	};
271 
272 #ifdef OFW_DEBUG
273 	printf("OF_close(%d)\n", handle);
274 #endif
275 	args.handle = handle;
276 	openfirmware(&args);
277 }
278 
279 int
280 OF_write(int handle, void *addr, int len)
281 {
282 	static struct {
283 		char *name;
284 		int nargs;
285 		int nreturns;
286 		int ihandle;
287 		void *addr;
288 		int len;
289 		int actual;
290 	} args = {
291 		"write",
292 		3,
293 		1,
294 	};
295 
296 #ifdef OFW_DEBUG
297 	if (len != 1)
298 		printf("OF_write(%d, %p, %x) -> ", handle, addr, len);
299 #endif
300 	args.ihandle = handle;
301 	args.addr = addr;
302 	args.len = len;
303 	if (openfirmware(&args) == -1) {
304 #ifdef OFW_DEBUG
305 		printf("lose\n");
306 #endif
307 		return -1;
308 	}
309 #ifdef OFW_DEBUG
310 	if (len != 1)
311 		printf("%x\n", args.actual);
312 #endif
313 	return args.actual;
314 }
315 
316 int
317 OF_read(int handle, void *addr, int len)
318 {
319 	static struct {
320 		char *name;
321 		int nargs;
322 		int nreturns;
323 		int ihandle;
324 		void *addr;
325 		int len;
326 		int actual;
327 	} args = {
328 		"read",
329 		3,
330 		1,
331 	};
332 
333 #ifdef OFW_DEBUG
334 	if (len != 1)
335 		printf("OF_read(%d, %p, %x) -> ", handle, addr, len);
336 #endif
337 	args.ihandle = handle;
338 	args.addr = addr;
339 	args.len = len;
340 	if (openfirmware(&args) == -1) {
341 #ifdef OFW_DEBUG
342 		printf("lose\n");
343 #endif
344 		return -1;
345 	}
346 #ifdef OFW_DEBUG
347 	if (len != 1)
348 		printf("%x\n", args.actual);
349 #endif
350 	return args.actual;
351 }
352 
353 int
354 OF_seek(int handle, u_quad_t pos)
355 {
356 	static struct {
357 		char *name;
358 		int nargs;
359 		int nreturns;
360 		int handle;
361 		int poshi;
362 		int poslo;
363 		int status;
364 	} args = {
365 		"seek",
366 		3,
367 		1,
368 	};
369 
370 #ifdef OFW_DEBUG
371 	printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos);
372 #endif
373 	args.handle = handle;
374 	args.poshi = (int)(pos >> 32);
375 	args.poslo = (int)pos;
376 	if (openfirmware(&args) == -1) {
377 #ifdef OFW_DEBUG
378 		printf("lose\n");
379 #endif
380 		return -1;
381 	}
382 #ifdef OFW_DEBUG
383 	printf("%d\n", args.status);
384 #endif
385 	return args.status;
386 }
387 
388 void *
389 OF_claim(void *virt, u_int size, u_int align)
390 {
391 	static struct {
392 		char *name;
393 		int nargs;
394 		int nreturns;
395 		void *virt;
396 		u_int size;
397 		u_int align;
398 		void *baseaddr;
399 	} args = {
400 		"claim",
401 		3,
402 		1,
403 	};
404 
405 #ifdef OFW_DEBUG
406 	printf("OF_claim(%p, %x, %x) -> ", virt, size, align);
407 #endif
408 	args.virt = virt;
409 	args.size = size;
410 	args.align = align;
411 	if (openfirmware(&args) == -1) {
412 #ifdef OFW_DEBUG
413 		printf("lose\n");
414 #endif
415 		return (void *)-1;
416 	}
417 #ifdef OFW_DEBUG
418 	printf("%p\n", args.baseaddr);
419 #endif
420 	return args.baseaddr;
421 }
422 
423 void
424 OF_release(void *virt, u_int size)
425 {
426 	static struct {
427 		char *name;
428 		int nargs;
429 		int nreturns;
430 		void *virt;
431 		u_int size;
432 	} args = {
433 		"release",
434 		2,
435 		0,
436 	};
437 
438 #ifdef OFW_DEBUG
439 	printf("OF_release(%p, %x)\n", virt, size);
440 #endif
441 	args.virt = virt;
442 	args.size = size;
443 	openfirmware(&args);
444 }
445 
446 int
447 OF_milliseconds(void)
448 {
449 	static struct {
450 		char *name;
451 		int nargs;
452 		int nreturns;
453 		int ms;
454 	} args = {
455 		"milliseconds",
456 		0,
457 		1,
458 	};
459 
460 	openfirmware(&args);
461 	return args.ms;
462 }
463 
464 #ifdef	__notyet__
465 void
466 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
467 {
468 	static struct {
469 		char *name;
470 		int nargs;
471 		int nreturns;
472 		void *virt;
473 		u_int size;
474 		void (*entry)();
475 		void *arg;
476 		u_int len;
477 	} args = {
478 		"chain",
479 		5,
480 		0,
481 	};
482 
483 	args.virt = virt;
484 	args.size = size;
485 	args.entry = entry;
486 	args.arg = arg;
487 	args.len = len;
488 	openfirmware(&args);
489 }
490 #else
491 void
492 OF_chain(void *virt, u_int size, boot_entry_t entry, void *arg, u_int len)
493 {
494 	/*
495 	 * This is a REALLY dirty hack till the firmware gets this going
496 	 */
497 #if 1
498 	OF_release(virt, size);
499 #endif
500 	entry(0, 0, openfirmware_entry, arg, len);
501 }
502 #endif
503 
504 static int stdin;
505 static int stdout;
506 
507 static void
508 setup(void)
509 {
510 	int chosen;
511 
512 	if ((chosen = OF_finddevice("/chosen")) == -1)
513 		OF_exit();
514 	if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) !=
515 	    sizeof(stdin) ||
516 	    OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) !=
517 	    sizeof(stdout))
518 		OF_exit();
519 }
520 
521 void
522 putchar(int c)
523 {
524 	char ch = c;
525 
526 	if (c == '\n')
527 		putchar('\r');
528 	OF_write(stdout, &ch, 1);
529 }
530 
531 int
532 getchar(void)
533 {
534 	unsigned char ch = '\0';
535 	int l;
536 
537 	while ((l = OF_read(stdin, &ch, 1)) != 1)
538 		if (l != -2 && l != 0)
539 			return -1;
540 	return ch;
541 }
542