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