1 #define DEBUG 2 /* $NetBSD: boot.c,v 1.7 2011/01/22 19:19:23 joerg Exp $ */ 3 4 /*- 5 * Copyright (c) 1997 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jason R. Thorpe. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 35 * Copyright (C) 1995, 1996 TooLs GmbH. 36 * All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed by TooLs GmbH. 49 * 4. The name of TooLs GmbH may not be used to endorse or promote products 50 * derived from this software without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 53 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 54 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 55 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 56 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 */ 63 64 /* 65 * First try for the boot code 66 * 67 * Input syntax is: 68 * [promdev[{:|,}partition]]/[filename] [flags] 69 */ 70 71 #define ELFSIZE 32 /* We use 32-bit ELF. */ 72 73 #include <sys/param.h> 74 #include <sys/exec.h> 75 #include <sys/exec_elf.h> 76 #include <sys/reboot.h> 77 #include <sys/disklabel.h> 78 #include <sys/boot_flag.h> 79 80 #include <lib/libsa/stand.h> 81 #include <lib/libsa/loadfile.h> 82 #include <lib/libkern/libkern.h> 83 84 #include <machine/cpu.h> 85 86 #include "cache.h" 87 #include "extern.h" 88 #include "ofdev.h" 89 #include "openfirm.h" 90 91 #ifdef DEBUG 92 # define DPRINTF printf 93 #else 94 # define DPRINTF while (/*CONSTCOND*/0) printf 95 #endif 96 97 char bootdev[128]; 98 char bootfile[128]; 99 int boothowto; 100 int debug; 101 102 #ifdef notyet 103 static int ofw_version = 0; 104 #endif 105 static const char *kernels[] = { 106 "/netbsd", "/netbsd.gz", "/netbsd.shark", NULL 107 }; 108 109 static void 110 prom2boot(char *dev) 111 { 112 char *cp, *ocp; 113 114 ocp = dev; 115 cp = dev + strlen(dev) - 1; 116 for (; cp >= ocp; cp--) { 117 if (*cp == ':') { 118 *cp = '\0'; 119 return; 120 } 121 } 122 } 123 124 static void 125 parseargs(char *str, int *howtop) 126 { 127 char *cp; 128 129 /* Allow user to drop back to the PROM. */ 130 if (strcmp(str, "exit") == 0) 131 OF_exit(); 132 133 *howtop = 0; 134 135 for (cp = str; *cp; cp++) 136 if (*cp == ' ' || *cp == '-') 137 goto found; 138 139 return; 140 141 found: 142 *cp++ = '\0'; 143 while (*cp) 144 BOOT_FLAG(*cp++, *howtop); 145 } 146 147 static void 148 chain(void (*entry)(int (*)(void *), void *, u_int), char *args, void *ssym, 149 void *esym) 150 { 151 extern char end[]; 152 u_int l, magic = 0x19730224; 153 154 freeall(); 155 156 /* 157 * Stash pointer to start and end of symbol table after the argument 158 * strings. 159 */ 160 l = strlen(args) + 1; 161 l = (l + 3) & ~3; /* align */ 162 DPRINTF("magic @ %p\n", args + l); 163 memcpy(args + l, &magic, sizeof(magic)); 164 l += sizeof(magic); 165 DPRINTF("ssym @ %p\n", args + l); 166 memcpy(args + l, &ssym, sizeof(ssym)); 167 l += sizeof(ssym); 168 DPRINTF("esym @ %p\n", args + l); 169 memcpy(args + l, &esym, sizeof(esym)); 170 l += sizeof(esym); 171 DPRINTF("args + l -> %p\n", args + l); 172 173 DPRINTF("Calling OF_chain(%p, %tx, %p, %p, %u)\n", 174 (void *)RELOC, end - (char *)RELOC, entry, args, l); 175 OF_chain((void *)RELOC, end - (char *)RELOC, entry, args, l); 176 panic("chain"); 177 } 178 179 __dead void 180 _rtt(void) 181 { 182 183 OF_exit(); 184 } 185 186 void 187 main(void) 188 { 189 extern char bootprog_name[], bootprog_rev[]; 190 int chosen; 191 char bootline[512]; /* Should check size? */ 192 char *cp, *startbuf, *endbuf; 193 u_long marks[MARK_MAX], size; 194 u_int32_t entry; 195 void *ssym, *esym; 196 197 printf("\n"); 198 printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev); 199 200 /* 201 * Get the boot arguments from Openfirmware 202 */ 203 if ((chosen = OF_finddevice("/chosen")) == -1 || 204 OF_getprop(chosen, "bootpath", bootdev, sizeof bootdev) < 0 || 205 OF_getprop(chosen, "bootargs", bootline, sizeof bootline) < 0) { 206 printf("Invalid Openfirmware environment\n"); 207 OF_exit(); 208 } 209 210 prom2boot(bootdev); 211 parseargs(bootline, &boothowto); 212 DPRINTF("bootline=%s\n", bootline); 213 214 /* 215 * Per the ARM OpenFirmware bindings, the firmware must 216 * allocate and map at least 6MB of physical memory starting 217 * at VA 0xf0000000. We have been loaded at 0xf0000000, 218 * and the memory after us has been unmapped and freed. 219 * We expect to load the kernel at 0xf0100000, so we will 220 * allocate 5MB of virtual memory starting there, and 221 * unmap/free what we don't use. 222 */ 223 startbuf = OF_claim((void *) 0xf0100000, (5 * 1024 * 1024), 0); 224 if (startbuf != (void *) 0xf0100000) { 225 printf("Unable to claim buffer for kernel\n"); 226 OF_exit(); 227 } 228 endbuf = startbuf + (5 * 1024 * 1024); 229 230 for (;;) { 231 int i; 232 233 if (boothowto & RB_ASKNAME) { 234 printf("Boot: "); 235 gets(bootline); 236 parseargs(bootline, &boothowto); 237 } 238 239 if (bootline[0]) { 240 kernels[0] = bootline; 241 kernels[1] = NULL; 242 } 243 244 for (i = 0; kernels[i]; i++) { 245 DPRINTF("Trying %s\n", kernels[i]); 246 247 marks[MARK_START] = 0xf0100000; 248 if (loadfile(kernels[i], marks, LOAD_KERNEL) >= 0) 249 goto loaded; 250 } 251 252 boothowto |= RB_ASKNAME; 253 } 254 loaded: 255 /* 256 * Okay, kernel is loaded, free the extra memory at the end. 257 * Round to the ARM OpenFirmare page size (4k). 258 */ 259 cp = (char *) ((marks[MARK_END] + 0xfff) & ~0xfff); 260 size = (u_long) (endbuf - cp); 261 if (size) 262 OF_release(cp, size); 263 264 #ifdef __notyet__ 265 OF_setprop(chosen, "bootpath", opened_name, strlen(opened_name) + 1); 266 cp = bootline; 267 #else 268 strcpy(bootline, opened_name); 269 cp = bootline + strlen(bootline); 270 *cp++ = ' '; 271 #endif 272 *cp = '-'; 273 if (boothowto & RB_ASKNAME) 274 *++cp = 'a'; 275 if (boothowto & RB_SINGLE) 276 *++cp = 's'; 277 if (boothowto & RB_KDB) 278 *++cp = 'd'; 279 if (*cp == '-') 280 #ifdef __notyet__ 281 *cp = 0; 282 #else 283 *--cp = 0; 284 #endif 285 else 286 *++cp = 0; 287 #ifdef __notyet__ 288 OF_setprop(chosen, "bootargs", bootline, strlen(bootline) + 1); 289 #endif 290 291 entry = marks[MARK_ENTRY]; 292 ssym = (void *)marks[MARK_SYM]; 293 esym = (void *)marks[MARK_END]; 294 295 printf(" start=0x%x\n", entry); 296 297 if (cache_syncI != NULL) { 298 DPRINTF("Syncing I$...\n"); 299 (*cache_syncI)(); 300 } 301 302 chain((void *)entry, bootline, ssym, esym); 303 304 OF_exit(); 305 } 306