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