Home | History | Annotate | Line # | Download | only in bootxx
bootxx.c revision 1.5.12.1
      1 /*	$NetBSD: bootxx.c,v 1.5.12.1 2002/06/20 03:39:41 nathanw 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/types.h>
     35 #include <machine/bat.h>
     36 
     37 #include <sys/bootblock.h>
     38 
     39 int (*openfirmware)(void *);
     40 
     41 				/*
     42 				 * 32 KB of stack with 32 bytes overpad
     43 				 * (see below)
     44 				 */
     45 int32_t __attribute__((aligned(16))) stack[8192 + 8];
     46 
     47 struct shared_bbinfo bbinfo = {
     48 	{ MACPPC_BBINFO_MAGIC },
     49 	0,
     50 	SHARED_BBINFO_MAXBLOCKS,
     51 	{ 0 }
     52 };
     53 
     54 #ifndef DEFAULT_ENTRY_POINT
     55 #define	DEFAULT_ENTRY_POINT	0x600000
     56 #endif
     57 
     58 void (*entry_point)(int, int, void *) = (void *)DEFAULT_ENTRY_POINT;
     59 
     60 
     61 asm("
     62 	.text
     63 	.align 2
     64 	.globl	_start
     65 _start:
     66 
     67 	lis	8,(_start)@ha
     68 	addi	8,8,(_start)@l
     69 	li	9,0x40		/* loop 64 times (for 2048 bytes of bootxx) */
     70 	mtctr	9
     71 1:
     72 	dcbf	0,8
     73 	icbi	0,8
     74 	addi	8,8,0x20
     75 	bdnz	1b
     76 	sync
     77 
     78 	li	0,0
     79 	mtdbatu	3,0
     80 	mtibatu	3,0
     81 	isync
     82 	li	8,0x1ffe	/* map the lowest 256MB */
     83 	li	9,0x22		/* BAT_I */
     84 	mtdbatl	3,9
     85 	mtdbatu	3,8
     86 	mtibatl	3,9
     87 	mtibatu	3,8
     88 	isync
     89 
     90 				/*
     91 				 * setup 32 KB of stack with 32 bytes overpad
     92 				 * (see above)
     93 				 */
     94 	lis	1,(stack  + 4 * 8192)@ha
     95 	addi	1,1,(stack+ 4 * 8192)@l
     96 	stw	0,0(1)		/* terminate the frame link chain */
     97 
     98 	b	startup
     99 ");
    100 
    101 
    102 static __inline int
    103 OF_finddevice(name)
    104 	char *name;
    105 {
    106 	static struct {
    107 		char *name;
    108 		int nargs;
    109 		int nreturns;
    110 		char *device;
    111 		int phandle;
    112 	} args = {
    113 		"finddevice",
    114 		1,
    115 		1,
    116 	};
    117 
    118 	args.device = name;
    119 	openfirmware(&args);
    120 
    121 	return args.phandle;
    122 }
    123 
    124 static __inline int
    125 OF_getprop(handle, prop, buf, buflen)
    126 	int handle;
    127 	char *prop;
    128 	void *buf;
    129 	int buflen;
    130 {
    131 	static struct {
    132 		char *name;
    133 		int nargs;
    134 		int nreturns;
    135 		int phandle;
    136 		char *prop;
    137 		void *buf;
    138 		int buflen;
    139 		int size;
    140 	} args = {
    141 		"getprop",
    142 		4,
    143 		1,
    144 	};
    145 
    146 	args.phandle = handle;
    147 	args.prop = prop;
    148 	args.buf = buf;
    149 	args.buflen = buflen;
    150 	openfirmware(&args);
    151 
    152 	return args.size;
    153 }
    154 
    155 static __inline int
    156 OF_open(dname)
    157 	char *dname;
    158 {
    159 	static struct {
    160 		char *name;
    161 		int nargs;
    162 		int nreturns;
    163 		char *dname;
    164 		int handle;
    165 	} args = {
    166 		"open",
    167 		1,
    168 		1,
    169 	};
    170 
    171 	args.dname = dname;
    172 	openfirmware(&args);
    173 
    174 	return args.handle;
    175 }
    176 
    177 static __inline int
    178 OF_read(handle, addr, len)
    179 	int handle;
    180 	void *addr;
    181 	int len;
    182 {
    183 	static struct {
    184 		char *name;
    185 		int nargs;
    186 		int nreturns;
    187 		int ihandle;
    188 		void *addr;
    189 		int len;
    190 		int actual;
    191 	} args = {
    192 		"read",
    193 		3,
    194 		1,
    195 	};
    196 
    197 	args.ihandle = handle;
    198 	args.addr = addr;
    199 	args.len = len;
    200 	openfirmware(&args);
    201 
    202 	return args.actual;
    203 }
    204 
    205 static __inline int
    206 OF_seek(handle, pos)
    207 	int handle;
    208 	u_quad_t pos;
    209 {
    210 	static struct {
    211 		char *name;
    212 		int nargs;
    213 		int nreturns;
    214 		int handle;
    215 		int poshi;
    216 		int poslo;
    217 		int status;
    218 	} args = {
    219 		"seek",
    220 		3,
    221 		1,
    222 	};
    223 
    224 	args.handle = handle;
    225 	args.poshi = (int)(pos >> 32);
    226 	args.poslo = (int)pos;
    227 	openfirmware(&args);
    228 
    229 	return args.status;
    230 }
    231 
    232 static __inline int
    233 OF_write(handle, addr, len)
    234 	int handle;
    235 	void *addr;
    236 	int len;
    237 {
    238 	static struct {
    239 		char *name;
    240 		int nargs;
    241 		int nreturns;
    242 		int ihandle;
    243 		void *addr;
    244 		int len;
    245 		int actual;
    246 	} args = {
    247 		"write",
    248 		3,
    249 		1,
    250 	};
    251 
    252 	args.ihandle = handle;
    253 	args.addr = addr;
    254 	args.len = len;
    255 	openfirmware(&args);
    256 
    257 	return args.actual;
    258 }
    259 
    260 int stdout;
    261 
    262 void
    263 putstrn(const char *s, size_t n)
    264 {
    265 	OF_write(stdout, s, n);
    266 }
    267 
    268 #define putstr(x)	putstrn((x),sizeof(x)-1)
    269 #define putc(x)		do { char __x = (x) ; putstrn(&__x, 1); } while (0)
    270 
    271 
    272 void
    273 startup(arg1, arg2, openfirm)
    274 	int arg1, arg2;
    275 	void *openfirm;
    276 {
    277 	int fd, blk, chosen, options, i;
    278 	char *addr;
    279 	char bootpath[128];
    280 
    281 	openfirmware = openfirm;
    282 
    283 	chosen = OF_finddevice("/chosen");
    284 	if (OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath)) == 1) {
    285 		/*
    286 		 * buggy firmware doesn't set bootpath...
    287 		 */
    288 		options = OF_finddevice("/options");
    289 		OF_getprop(options, "boot-device", bootpath, sizeof(bootpath));
    290 	}
    291 	if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout))
    292 	    != sizeof(stdout))
    293 		stdout = -1;
    294 
    295 	/*
    296 	 * "scsi/sd@0:0" --> "scsi/sd@0"
    297 	 */
    298 	for (i = 0; i < sizeof(bootpath); i++) {
    299 		if (bootpath[i] == ':')
    300 			bootpath[i] = 0;
    301 		if (bootpath[i] == 0)
    302 			break;
    303 	}
    304 
    305 	putstr("\r\nOF_open bootpath=");
    306 	putstrn(bootpath, i);
    307 	fd = OF_open(bootpath);
    308 
    309 	addr = (char *)entry_point;
    310 	putstr("\r\nread stage 2 blocks: ");
    311 	for (i = 0; i < bbinfo.bbi_block_count; i++) {
    312 		if ((blk = bbinfo.bbi_block_table[i]) == 0)
    313 			break;
    314 		putc('0' + i % 10);
    315 		OF_seek(fd, (u_quad_t)blk * 512);
    316 		OF_read(fd, addr, bbinfo.bbi_block_size);
    317 		addr += bbinfo.bbi_block_size;
    318 	}
    319 	putstr(". done!\r\nstarting stage 2...\r\n");
    320 
    321 	/*
    322 	 * enable D/I cache
    323 	 */
    324 	asm("
    325 		mtdbatu	3,%0
    326 		mtdbatl	3,%1
    327 		mtibatu	3,%0
    328 		mtibatl	3,%1
    329 		isync
    330 	" :: "r"(BATU(0, BAT_BL_256M, BAT_Vs)),
    331 	     "r"(BATL(0, 0, BAT_PP_RW)));
    332 
    333 	entry_point(0, 0, openfirm);
    334 	for (;;);			/* just in case */
    335 }
    336