1 /* $NetBSD: bootxx.c,v 1.9 2002/05/18 04:24:22 lukem 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