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