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