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