Home | History | Annotate | Line # | Download | only in ofwboot
      1 /*	$NetBSD: Locore.c,v 1.4 2009/03/14 15:36:14 dsl 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 <arm/armreg.h>
     39 
     40 #include "cache.h"
     41 #include "extern.h"
     42 #include "openfirm.h"
     43 
     44 static int (*openfirmware_entry)(void *);
     45 static int openfirmware(void *);
     46 
     47 void startup(int (*)(void *), char *, int);
     48 static void setup(void);
     49 
     50 void (*cache_syncI)(void);
     51 
     52 void abort(void);
     53 void abort(void)
     54 {
     55 
     56 	/* Stupid compiler (__dead). */
     57 	for (;;)
     58 		continue;
     59 }
     60 
     61 static int
     62 openfirmware(void *arg)
     63 {
     64 
     65 	(*openfirmware_entry)(arg);
     66 	return 0;
     67 }
     68 
     69 static vaddr_t
     70 ofw_getcleaninfo(void)
     71 {
     72 	int cpu, vclean;
     73 
     74 	if ((cpu = OF_finddevice("/cpu")) == -1)
     75 		panic("no /cpu from OFW");
     76 
     77 	if (OF_getprop(cpu, "d-cache-flush-address", &vclean,
     78 		       sizeof(vclean)) != sizeof(vclean)) {
     79 		printf("WARNING: no OFW d-cache-flush-address property\n");
     80 		return (RELOC);
     81 	}
     82 
     83 	return (of_decode_int((unsigned char *)&vclean));
     84 }
     85 
     86 void
     87 startup(int (*openfirm)(void *), char *arg, int argl)
     88 {
     89 	u_int cputype = cpufunc_id() & CPU_ID_CPU_MASK;
     90 
     91 	openfirmware_entry = openfirm;
     92 	setup();
     93 
     94 	/*
     95 	 * Determine the CPU type, and set up the appropriate
     96 	 * I$ sync routine.
     97 	 */
     98 	if (cputype == CPU_ID_SA110 || cputype == CPU_ID_SA1100 ||
     99 	    cputype == CPU_ID_SA1110) {
    100 		extern vaddr_t sa110_cache_clean_addr;
    101 		cache_syncI = sa110_cache_syncI;
    102 		sa110_cache_clean_addr = ofw_getcleaninfo();
    103 	} else {
    104 		printf("WARNING: no I$ sync routine for CPU 0x%x\n",
    105 		    cputype);
    106 	}
    107 
    108 	main();
    109 	OF_exit();
    110 }
    111 
    112 int
    113 of_decode_int(const u_char *p)
    114 {
    115 	unsigned int i = *p++ << 8;
    116 	i = (i + *p++) << 8;
    117 	i = (i + *p++) << 8;
    118 	return (i + *p);
    119 }
    120 
    121 __dead void
    122 OF_exit(void)
    123 {
    124 	static struct {
    125 		const char *name;
    126 		int nargs;
    127 		int nreturns;
    128 	} args = {
    129 		"exit",
    130 		0,
    131 		0
    132 	};
    133 
    134 	openfirmware(&args);
    135 	for (;;);			/* just in case */
    136 }
    137 
    138 int
    139 OF_finddevice(const char *name)
    140 {
    141 	static struct {
    142 		const char *name;
    143 		int nargs;
    144 		int nreturns;
    145 		const char *device;
    146 		int phandle;
    147 	} args = {
    148 		"finddevice",
    149 		1,
    150 		1,
    151 	};
    152 
    153 	args.device = name;
    154 	if (openfirmware(&args) == -1)
    155 		return -1;
    156 	return args.phandle;
    157 }
    158 
    159 int
    160 OF_instance_to_package(int ihandle)
    161 {
    162 	static struct {
    163 		const char *name;
    164 		int nargs;
    165 		int nreturns;
    166 		int ihandle;
    167 		int phandle;
    168 	} args = {
    169 		"instance-to-package",
    170 		1,
    171 		1,
    172 	};
    173 
    174 	args.ihandle = ihandle;
    175 	if (openfirmware(&args) == -1)
    176 		return -1;
    177 	return args.phandle;
    178 }
    179 
    180 int
    181 OF_getprop(int handle, const char *prop, void *buf, int buflen)
    182 {
    183 	static struct {
    184 		const char *name;
    185 		int nargs;
    186 		int nreturns;
    187 		int phandle;
    188 		const char *prop;
    189 		void *buf;
    190 		int buflen;
    191 		int size;
    192 	} args = {
    193 		"getprop",
    194 		4,
    195 		1,
    196 	};
    197 
    198 	args.phandle = handle;
    199 	args.prop = prop;
    200 	args.buf = buf;
    201 	args.buflen = buflen;
    202 	if (openfirmware(&args) == -1)
    203 		return -1;
    204 	return args.size;
    205 }
    206 
    207 #ifdef	__notyet__	/* Has a bug on FirePower */
    208 int
    209 OF_setprop(int handle, const char *prop, void *buf, int len)
    210 {
    211 	static struct {
    212 		const char *name;
    213 		int nargs;
    214 		int nreturns;
    215 		int phandle;
    216 		const char *prop;
    217 		void *buf;
    218 		int len;
    219 		int size;
    220 	} args = {
    221 		"setprop",
    222 		4,
    223 		1,
    224 	};
    225 
    226 	args.phandle = handle;
    227 	args.prop = prop;
    228 	args.buf = buf;
    229 	args.len = len;
    230 	if (openfirmware(&args) == -1)
    231 		return -1;
    232 	return args.size;
    233 }
    234 #endif
    235 
    236 int
    237 OF_open(char *dname)
    238 {
    239 	static struct {
    240 		const char *name;
    241 		int nargs;
    242 		int nreturns;
    243 		char *dname;
    244 		int handle;
    245 	} args = {
    246 		"open",
    247 		1,
    248 		1,
    249 	};
    250 
    251 #ifdef OFW_DEBUG
    252 	printf("OF_open(%s) -> ", dname);
    253 #endif
    254 	args.dname = dname;
    255 	if (openfirmware(&args) == -1 ||
    256 	    args.handle == 0) {
    257 #ifdef OFW_DEBUG
    258 		printf("lose\n");
    259 #endif
    260 		return -1;
    261 	}
    262 #ifdef OFW_DEBUG
    263 	printf("%d\n", args.handle);
    264 #endif
    265 	return args.handle;
    266 }
    267 
    268 void
    269 OF_close(int handle)
    270 {
    271 	static struct {
    272 		const char *name;
    273 		int nargs;
    274 		int nreturns;
    275 		int handle;
    276 	} args = {
    277 		"close",
    278 		1,
    279 		0,
    280 	};
    281 
    282 #ifdef OFW_DEBUG
    283 	printf("OF_close(%d)\n", handle);
    284 #endif
    285 	args.handle = handle;
    286 	openfirmware(&args);
    287 }
    288 
    289 int
    290 OF_write(int handle, void *addr, int len)
    291 {
    292 	static struct {
    293 		const char *name;
    294 		int nargs;
    295 		int nreturns;
    296 		int ihandle;
    297 		void *addr;
    298 		int len;
    299 		int actual;
    300 	} args = {
    301 		"write",
    302 		3,
    303 		1,
    304 	};
    305 
    306 #ifdef OFW_DEBUG
    307 	if (len != 1)
    308 		printf("OF_write(%d, %x, %x) -> ", handle, addr, len);
    309 #endif
    310 	args.ihandle = handle;
    311 	args.addr = addr;
    312 	args.len = len;
    313 	if (openfirmware(&args) == -1) {
    314 #ifdef OFW_DEBUG
    315 		printf("lose\n");
    316 #endif
    317 		return -1;
    318 	}
    319 #ifdef OFW_DEBUG
    320 	if (len != 1)
    321 		printf("%x\n", args.actual);
    322 #endif
    323 	return args.actual;
    324 }
    325 
    326 int
    327 OF_read(int handle, void *addr, int len)
    328 {
    329 	static struct {
    330 		const char *name;
    331 		int nargs;
    332 		int nreturns;
    333 		int ihandle;
    334 		void *addr;
    335 		int len;
    336 		int actual;
    337 	} args = {
    338 		"read",
    339 		3,
    340 		1,
    341 	};
    342 
    343 #ifdef OFW_DEBUG
    344 	if (len != 1)
    345 		printf("OF_read(%d, %x, %x) -> ", handle, addr, len);
    346 #endif
    347 	args.ihandle = handle;
    348 	args.addr = addr;
    349 	args.len = len;
    350 	if (openfirmware(&args) == -1) {
    351 #ifdef OFW_DEBUG
    352 		printf("lose\n");
    353 #endif
    354 		return -1;
    355 	}
    356 #ifdef OFW_DEBUG
    357 	if (len != 1)
    358 		printf("%x\n", args.actual);
    359 #endif
    360 	return args.actual;
    361 }
    362 
    363 int
    364 OF_seek(int handle, u_quad_t pos)
    365 {
    366 	static struct {
    367 		const char *name;
    368 		int nargs;
    369 		int nreturns;
    370 		int handle;
    371 		int poshi;
    372 		int poslo;
    373 		int status;
    374 	} args = {
    375 		"seek",
    376 		3,
    377 		1,
    378 	};
    379 
    380 #ifdef OFW_DEBUG
    381 	printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos);
    382 #endif
    383 	args.handle = handle;
    384 	args.poshi = (int)(pos >> 32);
    385 	args.poslo = (int)pos;
    386 	if (openfirmware(&args) == -1) {
    387 #ifdef OFW_DEBUG
    388 		printf("lose\n");
    389 #endif
    390 		return -1;
    391 	}
    392 #ifdef OFW_DEBUG
    393 	printf("%d\n", args.status);
    394 #endif
    395 	return args.status;
    396 }
    397 
    398 void *
    399 OF_claim(void *virt, u_int size, u_int align)
    400 {
    401 	static struct {
    402 		const char *name;
    403 		int nargs;
    404 		int nreturns;
    405 		void *virt;
    406 		u_int size;
    407 		u_int align;
    408 		void *baseaddr;
    409 	} args = {
    410 		"claim",
    411 		3,
    412 		1,
    413 	};
    414 
    415 #ifdef OFW_DEBUG
    416 	printf("OF_claim(%x, %x, %x) -> ", virt, size, align);
    417 #endif
    418 	args.virt = virt;
    419 	args.size = size;
    420 	args.align = align;
    421 	if (openfirmware(&args) == -1) {
    422 #ifdef OFW_DEBUG
    423 		printf("lose\n");
    424 #endif
    425 		return (void *)-1;
    426 	}
    427 #ifdef OFW_DEBUG
    428 	printf("%x\n", args.baseaddr);
    429 #endif
    430 	return args.baseaddr;
    431 }
    432 
    433 void
    434 OF_release(void *virt, u_int size)
    435 {
    436 	static struct {
    437 		const char *name;
    438 		int nargs;
    439 		int nreturns;
    440 		void *virt;
    441 		u_int size;
    442 	} args = {
    443 		"release",
    444 		2,
    445 		0,
    446 	};
    447 
    448 #ifdef OFW_DEBUG
    449 	printf("OF_release(%x, %x)\n", virt, size);
    450 #endif
    451 	args.virt = virt;
    452 	args.size = size;
    453 	openfirmware(&args);
    454 }
    455 
    456 int
    457 OF_milliseconds(void)
    458 {
    459 	static struct {
    460 		const char *name;
    461 		int nargs;
    462 		int nreturns;
    463 		int ms;
    464 	} args = {
    465 		"milliseconds",
    466 		0,
    467 		1,
    468 	};
    469 
    470 	openfirmware(&args);
    471 	return args.ms;
    472 }
    473 
    474 void
    475 OF_chain(void *virt, u_int size, void (*entry)(int (*)(void *), void *, u_int),
    476     void *arg, u_int len)
    477 {
    478 	struct {
    479 		const char *name;
    480 		int nargs;
    481 		int nreturns;
    482 		void *virt;
    483 		u_int size;
    484 		void (*entry)(int (*)(void *), void *, u_int);
    485 		void *arg;
    486 		u_int len;
    487 	} args;
    488 
    489 	args.name = "chain";
    490 	args.nargs = 5;
    491 	args.nreturns = 0;
    492 	args.virt = virt;
    493 	args.size = size;
    494 	args.entry = entry;
    495 	args.arg = arg;
    496 	args.len = len;
    497 #if 1
    498 	openfirmware(&args);
    499 #else
    500 	entry(openfirmware_entry, arg, len);
    501 #endif
    502 }
    503 
    504 static int stdin;
    505 static int stdout;
    506 
    507 static void
    508 setup(void)
    509 {
    510 	u_char buf[sizeof(int)];
    511 	int chosen;
    512 
    513 	if ((chosen = OF_finddevice("/chosen")) == -1)
    514 		OF_exit();
    515 
    516 	if (OF_getprop(chosen, "stdin", buf, sizeof(buf)) != sizeof(buf))
    517 		OF_exit();
    518 	stdin = of_decode_int(buf);
    519 
    520 	if (OF_getprop(chosen, "stdout", buf, sizeof(buf)) != sizeof(buf))
    521 		OF_exit();
    522 	stdout = of_decode_int(buf);
    523 }
    524 
    525 void
    526 putchar(int c)
    527 {
    528 	char ch = c;
    529 
    530 	if (c == '\n')
    531 		putchar('\r');
    532 	OF_write(stdout, &ch, 1);
    533 }
    534 
    535 int
    536 getchar(void)
    537 {
    538 	unsigned char ch = '\0';
    539 	int l;
    540 
    541 	while ((l = OF_read(stdin, &ch, 1)) != 1)
    542 		if (l != -2 && l != 0)
    543 			return -1;
    544 	return ch;
    545 }
    546