Home | History | Annotate | Line # | Download | only in ofwboot
      1 /*	$NetBSD: Locore.c,v 1.23 2014/09/20 23:10:46 phx 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 
     40 static int (*openfirmware_entry)(void *);
     41 static int openfirmware(void *);
     42 
     43 void startup(void *, int, int (*)(void *), char *, int)
     44 	__attribute__((__used__));
     45 static void setup(void);
     46 
     47 /* this pad gets the rodata laignment right, don't EVER fiddle it */
     48 char *pad __attribute__((__aligned__ (8))) = "pad";
     49 int stack[0x20000/4 + 4] __attribute__((__aligned__ (4), __used__));
     50 char *heapspace __attribute__((__aligned__ (4)));
     51 char altheap[0x20000] __attribute__((__aligned__ (4)));
     52 
     53 static int
     54 openfirmware(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 
     65 void
     66 startup(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
     76 OF_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
     93 OF_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 
    111 int
    112 OF_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 
    132 int
    133 OF_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 
    153 int
    154 OF_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 */
    181 int
    182 OF_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 
    209 int
    210 OF_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 
    241 void
    242 OF_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 
    262 int
    263 OF_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 
    299 int
    300 OF_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 
    336 int
    337 OF_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 
    371 void *
    372 OF_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 
    400 void *
    401 OF_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 
    435 void
    436 OF_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 
    458 int
    459 OF_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__
    477 void
    478 OF_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
    503 void
    504 OF_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 
    516 static int stdin;
    517 static int stdout;
    518 
    519 static void
    520 setup(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 
    541 void
    542 putchar(int c)
    543 {
    544 	char ch = c;
    545 
    546 	if (c == '\n')
    547 		putchar('\r');
    548 	OF_write(stdout, &ch, 1);
    549 }
    550 
    551 int
    552 getchar(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 
    565 static int
    566 OF_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 
    586 static int
    587 OF_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 
    607 int
    608 OF_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 
    632 static int
    633 OF_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 
    661 void
    662 dump_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