1/*	$NetBSD: Locore.c,v 1.21 2008/02/12 04:27:46 garbled 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#include <sys/param.h>
36#include <lib/libsa/stand.h>
37
38#include <machine/cpu.h>
39
40static int (*openfirmware_entry)(void *);
41static int openfirmware(void *);
42
43void startup(void *, int, int (*)(void *), char *, int)
44	__attribute__((__used__));
45static void setup(void);
46
47/* this pad gets the rodata laignment right, don't EVER fiddle it */
48char *pad __attribute__((__aligned__ (8))) = "pad";
49int stack[8192/4 + 4] __attribute__((__aligned__ (4), __used__));
50char *heapspace __attribute__((__aligned__ (4)));
51char altheap[0x20000] __attribute__((__aligned__ (4)));
52
53static int
54openfirmware(void *arg)
55{
56	int r;
57
58	__asm volatile ("sync; isync");
59	r = openfirmware_entry(arg);
60	__asm volatile ("sync; isync");
61
62	return r;
63}
64
65void
66startup(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
67{
68
69	openfirmware_entry = openfirm;
70	setup();
71	main();
72	OF_exit();
73}
74
75__dead void
76OF_exit(void)
77{
78	static struct {
79		char *name;
80		int nargs;
81		int nreturns;
82	} args = {
83		"exit",
84		0,
85		0
86	};
87
88	openfirmware(&args);
89	for (;;);			/* just in case */
90}
91
92__dead void
93OF_boot(char *bootspec)
94{
95	static struct {
96		char *name;
97		int nargs;
98		int nreturns;
99		char *bootspec;
100	} args = {
101		"boot",
102		1,
103		0,
104	};
105
106	args.bootspec = bootspec;
107	openfirmware(&args);
108	for (;;);			/* just in case */
109}
110
111int
112OF_finddevice(char *name)
113{
114	static struct {
115		char *name;
116		int nargs;
117		int nreturns;
118		char *device;
119		int phandle;
120	} args = {
121		"finddevice",
122		1,
123		1,
124	};
125
126	args.device = name;
127	if (openfirmware(&args) == -1)
128		return -1;
129	return args.phandle;
130}
131
132int
133OF_instance_to_package(int ihandle)
134{
135	static struct {
136		char *name;
137		int nargs;
138		int nreturns;
139		int ihandle;
140		int phandle;
141	} args = {
142		"instance-to-package",
143		1,
144		1,
145	};
146
147	args.ihandle = ihandle;
148	if (openfirmware(&args) == -1)
149		return -1;
150	return args.phandle;
151}
152
153int
154OF_getprop(int handle, char *prop, void *buf, int buflen)
155{
156	static struct {
157		char *name;
158		int nargs;
159		int nreturns;
160		int phandle;
161		char *prop;
162		void *buf;
163		int buflen;
164		int size;
165	} args = {
166		"getprop",
167		4,
168		1,
169	};
170
171	args.phandle = handle;
172	args.prop = prop;
173	args.buf = buf;
174	args.buflen = buflen;
175	if (openfirmware(&args) == -1)
176		return -1;
177	return args.size;
178}
179
180#ifdef	__notyet__	/* Has a bug on FirePower */
181int
182OF_setprop(int handle, char *prop, void *buf, int len)
183{
184	static struct {
185		char *name;
186		int nargs;
187		int nreturns;
188		int phandle;
189		char *prop;
190		void *buf;
191		int len;
192		int size;
193	} args = {
194		"setprop",
195		4,
196		1,
197	};
198
199	args.phandle = handle;
200	args.prop = prop;
201	args.buf = buf;
202	args.len = len;
203	if (openfirmware(&args) == -1)
204		return -1;
205	return args.size;
206}
207#endif
208
209int
210OF_open(char *dname)
211{
212	static struct {
213		char *name;
214		int nargs;
215		int nreturns;
216		char *dname;
217		int handle;
218	} args = {
219		"open",
220		1,
221		1,
222	};
223
224#ifdef OFW_DEBUG
225	printf("OF_open(%s) -> ", dname);
226#endif
227	args.dname = dname;
228	if (openfirmware(&args) == -1 ||
229	    args.handle == 0) {
230#ifdef OFW_DEBUG
231		printf("lose\n");
232#endif
233		return -1;
234	}
235#ifdef OFW_DEBUG
236	printf("%d\n", args.handle);
237#endif
238	return args.handle;
239}
240
241void
242OF_close(int handle)
243{
244	static struct {
245		char *name;
246		int nargs;
247		int nreturns;
248		int handle;
249	} args = {
250		"close",
251		1,
252		0,
253	};
254
255#ifdef OFW_DEBUG
256	printf("OF_close(%d)\n", handle);
257#endif
258	args.handle = handle;
259	openfirmware(&args);
260}
261
262int
263OF_write(int handle, void *addr, int len)
264{
265	static struct {
266		char *name;
267		int nargs;
268		int nreturns;
269		int ihandle;
270		void *addr;
271		int len;
272		int actual;
273	} args = {
274		"write",
275		3,
276		1,
277	};
278
279#ifdef OFW_DEBUG
280	if (len != 1)
281		printf("OF_write(%d, %p, %x) -> ", handle, addr, len);
282#endif
283	args.ihandle = handle;
284	args.addr = addr;
285	args.len = len;
286	if (openfirmware(&args) == -1) {
287#ifdef OFW_DEBUG
288		printf("lose\n");
289#endif
290		return -1;
291	}
292#ifdef OFW_DEBUG
293	if (len != 1)
294		printf("%x\n", args.actual);
295#endif
296	return args.actual;
297}
298
299int
300OF_read(int handle, void *addr, int len)
301{
302	static struct {
303		char *name;
304		int nargs;
305		int nreturns;
306		int ihandle;
307		void *addr;
308		int len;
309		int actual;
310	} args = {
311		"read",
312		3,
313		1,
314	};
315
316#ifdef OFW_DEBUG
317	if (len != 1)
318		printf("OF_read(%d, %p, %x) -> ", handle, addr, len);
319#endif
320	args.ihandle = handle;
321	args.addr = addr;
322	args.len = len;
323	if (openfirmware(&args) == -1) {
324#ifdef OFW_DEBUG
325		printf("lose\n");
326#endif
327		return -1;
328	}
329#ifdef OFW_DEBUG
330	if (len != 1)
331		printf("%x\n", args.actual);
332#endif
333	return args.actual;
334}
335
336int
337OF_seek(int handle, u_quad_t pos)
338{
339	static struct {
340		char *name;
341		int nargs;
342		int nreturns;
343		int handle;
344		int poshi;
345		int poslo;
346		int status;
347	} args = {
348		"seek",
349		3,
350		1,
351	};
352
353#ifdef OFW_DEBUG
354	printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos);
355#endif
356	args.handle = handle;
357	args.poshi = (int)(pos >> 32);
358	args.poslo = (int)pos;
359	if (openfirmware(&args) == -1) {
360#ifdef OFW_DEBUG
361		printf("lose\n");
362#endif
363		return -1;
364	}
365#ifdef OFW_DEBUG
366	printf("%d\n", args.status);
367#endif
368	return args.status;
369}
370
371void *
372OF_alloc_mem(u_int size)
373{
374	static struct {
375		char *name;
376		int nargs;
377		int nreturns;
378		u_int size;
379		void *baseaddr;
380	} args = {
381		"alloc-mem",
382		1,
383		1,
384	};
385#ifdef OFW_DEBUG
386	printf("alloc-mem %x -> ", size);
387#endif
388	if (openfirmware(&args) == -1) {
389#ifdef OFW_DEBUG
390		printf("lose\n");
391#endif
392		return (void *)-1;
393	}
394#ifdef OFW_DEBUG
395	printf("%p\n", args.baseaddr);
396#endif
397	return args.baseaddr;
398}
399
400void *
401OF_claim(void *virt, u_int size, u_int align)
402{
403	static struct {
404		char *name;
405		int nargs;
406		int nreturns;
407		void *virt;
408		u_int size;
409		u_int align;
410		void *baseaddr;
411	} args = {
412		"claim",
413		3,
414		1,
415	};
416
417#ifdef OFW_DEBUG
418	printf("OF_claim(%p, %x, %x) -> ", virt, size, align);
419#endif
420	args.virt = virt;
421	args.size = size;
422	args.align = align;
423	if (openfirmware(&args) == -1) {
424#ifdef OFW_DEBUG
425		printf("lose\n");
426#endif
427		return (void *)-1;
428	}
429#ifdef OFW_DEBUG
430	printf("%p\n", args.baseaddr);
431#endif
432	return args.baseaddr;
433}
434
435void
436OF_release(void *virt, u_int size)
437{
438	static struct {
439		char *name;
440		int nargs;
441		int nreturns;
442		void *virt;
443		u_int size;
444	} args = {
445		"release",
446		2,
447		0,
448	};
449
450#ifdef OFW_DEBUG
451	printf("OF_release(%p, %x)\n", virt, size);
452#endif
453	args.virt = virt;
454	args.size = size;
455	openfirmware(&args);
456}
457
458int
459OF_milliseconds(void)
460{
461	static struct {
462		char *name;
463		int nargs;
464		int nreturns;
465		int ms;
466	} args = {
467		"milliseconds",
468		0,
469		1,
470	};
471
472	openfirmware(&args);
473	return args.ms;
474}
475
476#ifdef	__notyet__
477void
478OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
479{
480	static struct {
481		char *name;
482		int nargs;
483		int nreturns;
484		void *virt;
485		u_int size;
486		void (*entry)();
487		void *arg;
488		u_int len;
489	} args = {
490		"chain",
491		5,
492		0,
493	};
494
495	args.virt = virt;
496	args.size = size;
497	args.entry = entry;
498	args.arg = arg;
499	args.len = len;
500	openfirmware(&args);
501}
502#else
503void
504OF_chain(void *virt, u_int size, boot_entry_t entry, void *arg, u_int len)
505{
506	/*
507	 * This is a REALLY dirty hack till the firmware gets this going
508	 */
509#if 0
510	OF_release(virt, size);
511#endif
512	entry(0, 0, openfirmware_entry, arg, len);
513}
514#endif
515
516static int stdin;
517static int stdout;
518
519static void
520setup(void)
521{
522	int chosen;
523
524	if ((chosen = OF_finddevice("/chosen")) == -1)
525		OF_exit();
526	if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) !=
527	    sizeof(stdin) ||
528	    OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) !=
529	    sizeof(stdout))
530		OF_exit();
531
532	//printf("Allocating 0x20000 bytes of ram for boot\n");
533	heapspace = OF_claim(0, 0x20000, NBPG);
534	if (heapspace == (char *)-1) {
535		printf("WARNING: Failed to alloc ram, using bss\n");
536		setheap(&altheap, &altheap[0x20000]);
537	} else
538		setheap(heapspace, heapspace+0x20000);
539}
540
541void
542putchar(int c)
543{
544	char ch = c;
545
546	if (c == '\n')
547		putchar('\r');
548	OF_write(stdout, &ch, 1);
549}
550
551int
552getchar(void)
553{
554	unsigned char ch = '\0';
555	int l;
556
557	while ((l = OF_read(stdin, &ch, 1)) != 1)
558		if (l != -2 && l != 0)
559			return -1;
560	return ch;
561}
562
563#ifdef OFWDUMP
564
565static int
566OF_peer(int phandle)
567{
568	static struct {
569		const char *name;
570		int nargs;
571		int nreturns;
572		int phandle;
573		int sibling;
574	} args = {
575		"peer",
576			1,
577			1,
578	};
579
580	args.phandle = phandle;
581	if (openfirmware(&args) == -1)
582		return 0;
583	return args.sibling;
584}
585
586static int
587OF_child(int phandle)
588{
589	static struct {
590		const char *name;
591		int nargs;
592		int nreturns;
593		int phandle;
594		int child;
595	} args = {
596		"child",
597			1,
598			1,
599	};
600
601	args.phandle = phandle;
602	if (openfirmware(&args) == -1)
603		return 0;
604	return args.child;
605}
606
607int
608OF_nextprop(int handle, const char *prop, void *nextprop)
609{
610	static struct {
611		const char *name;
612		int nargs;
613		int nreturns;
614		int phandle;
615		const char *prop;
616		char *buf;
617		int flag;
618	} args = {
619		"nextprop",
620			3,
621			1,
622	};
623
624	args.phandle = handle;
625	args.prop = prop;
626	args.buf = nextprop;
627	if (openfirmware(&args) == -1)
628		return -1;
629	return args.flag;
630}
631
632static int
633OF_package_to_path(int phandle, char *buf, int buflen)
634{
635	static struct {
636		const char *name;
637		int nargs;
638		int nreturns;
639		int phandle;
640		char *buf;
641		int buflen;
642		int length;
643	} args = {
644		"package-to-path",
645			3,
646			1,
647	};
648
649	if (buflen > 4096)
650		return -1;
651	args.phandle = phandle;
652	args.buf = buf;
653	args.buflen = buflen;
654	if (openfirmware(&args) < 0)
655		return -1;
656	if (args.length > buflen)
657		args.length = buflen;
658	return args.length;
659}
660
661void
662dump_ofwtree(int node)
663{
664	int peer, child, namelen, dlen, i;
665	char namebuf[33], newnamebuf[33];
666	char path[256], data[256];
667
668	for (peer = node; peer; peer = OF_peer(peer)) {
669		printf("\nnode: 0x%x ", peer);
670		if (OF_package_to_path(peer, path, 512) >= 0)
671			printf("path=%s", path);
672		printf("\n");
673		namebuf[0] = '\0';
674		namelen = OF_nextprop(peer, namebuf, &newnamebuf);
675		while (namelen >= 0) {
676			/*printf("namelen == %d namebuf=%s new=%s\n", namelen,
677			  namebuf, newnamebuf);*/
678			//newnamebuf[namelen] = '\0';
679			strcpy(namebuf, newnamebuf);
680			printf("  %s :", newnamebuf);
681			dlen = OF_getprop(peer, newnamebuf, data, 256);
682			if (dlen > 0) {
683				if (data[0] < 0177)
684					printf(" %s\n", data);
685				else
686					printf("\n");
687				printf("    ");
688				for (i=0; i < dlen && i < 256; i++) {
689					if (data[i] < 0x10)
690						printf("0");
691					printf("%x", data[i]);
692					if ((i+1)%4 == 0)
693						printf(" ");
694					if ((i+1)%32 == 0)
695						printf("\n    ");
696				}
697			}
698			printf("\n");
699			namelen = OF_nextprop(peer, namebuf, &newnamebuf);
700			if (newnamebuf[0] == '\0' ||
701			    strcmp(namebuf, newnamebuf) == 0)
702				break;
703		}
704		child = OF_child(peer);
705		if (child > 0)
706			dump_ofwtree(child);
707	}
708}
709
710#endif /* OFWDUMP */
711