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