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