1 /* $NetBSD: boot.c,v 1.13 2002/12/11 10:35:06 pk Exp $ */ 2 3 /*- 4 * Copyright (c) 1982, 1986, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)boot.c 8.1 (Berkeley) 6/10/93 36 */ 37 38 #include <sys/param.h> 39 #include <sys/reboot.h> 40 #include <sys/boot_flag.h> 41 #include <sys/exec.h> 42 43 #include <lib/libsa/stand.h> 44 #include <lib/libsa/loadfile.h> 45 46 #include <machine/promlib.h> 47 #include <sparc/stand/common/promdev.h> 48 49 #include "bootinfo.h" 50 51 extern void prom_patch __P((void)); /* prompatch.c */ 52 53 static int bootoptions __P((char *)); 54 #if 0 55 static void promsyms __P((int, struct exec *)); 56 #endif 57 58 int debug; 59 int netif_debug; 60 61 extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[]; 62 unsigned long esym; 63 char *strtab; 64 int strtablen; 65 char fbuf[80], dbuf[128]; 66 67 int main __P((void)); 68 typedef void (*entry_t)__P((caddr_t, int, int, int, long, long)); 69 70 /* 71 * Boot device is derived from ROM provided information, or if there is none, 72 * this list is used in sequence, to find a kernel. 73 */ 74 char *kernels[] = { 75 "netbsd", 76 "netbsd.gz", 77 "netbsd.old", 78 "netbsd.old.gz", 79 "onetbsd", 80 "onetbsd.gz", 81 "vmunix", 82 #ifdef notyet 83 "netbsd.pl", 84 "netbsd.pl.gz", 85 "netbsd.el", 86 "netbsd.el.gz", 87 #endif 88 NULL 89 }; 90 91 int 92 bootoptions(ap) 93 char *ap; 94 { 95 int v = 0; 96 if (ap == NULL || *ap++ != '-') 97 return (0); 98 99 while (*ap != '\0' && *ap != ' ' && *ap != '\t' && *ap != '\n') { 100 BOOT_FLAG(*ap, v); 101 ap++; 102 } 103 104 if ((v & RB_KDB) != 0) 105 debug = 1; 106 107 return (v); 108 } 109 110 int 111 main() 112 { 113 int io, i; 114 char *kernel; 115 int how; 116 u_long marks[MARK_MAX], bootinfo; 117 struct btinfo_symtab bi_sym; 118 void *arg; 119 u_long maxkernsize; 120 121 #ifdef HEAP_VARIABLE 122 { 123 extern char end[]; 124 setheap((void *)ALIGN(end), (void *)0xffffffff); 125 } 126 #endif 127 { 128 /* 129 * Find maximum the kernel size that we can handle. 130 * Our stack grows down from label `start'; assume 131 * we need no more that 16K of stack space. 132 */ 133 extern char start[]; /* top of stack (see srt0.S) */ 134 maxkernsize = (u_long)start - (16*1024) - PROM_LOADADDR; 135 136 } 137 prom_init(); 138 139 printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev); 140 printf(">> (%s, %s)\n", bootprog_maker, bootprog_date); 141 142 /* massage machine prom */ 143 prom_patch(); 144 145 /* 146 * get default kernel. 147 */ 148 prom_bootdevice = prom_getbootpath(); 149 kernel = prom_getbootfile(); 150 how = bootoptions(prom_getbootargs()); 151 152 if (kernel != NULL && *kernel != '\0') { 153 i = -1; /* not using the kernels */ 154 } else { 155 i = 0; 156 kernel = kernels[i]; 157 } 158 159 for (;;) { 160 /* 161 * ask for a kernel first .. 162 */ 163 if (how & RB_ASKNAME) { 164 printf("device[%s] (\"halt\" to halt): ", 165 prom_bootdevice); 166 gets(dbuf); 167 if (strcmp(dbuf, "halt") == 0) 168 _rtt(); 169 if (dbuf[0]) 170 prom_bootdevice = dbuf; 171 printf("boot (press RETURN to try default list): "); 172 gets(fbuf); 173 if (fbuf[0]) 174 kernel = fbuf; 175 else { 176 how &= ~RB_ASKNAME; 177 i = 0; 178 kernel = kernels[i]; 179 } 180 } 181 182 marks[MARK_START] = 0; 183 printf("Booting %s\n", kernel); 184 if ((io = loadfile(kernel, marks, COUNT_KERNEL)) != -1) { 185 close(io); 186 if (marks[MARK_END] - marks[MARK_START] > maxkernsize) { 187 printf("kernel too large: %lu" 188 " (maximum kernel size is %lu)\n", 189 marks[MARK_END] - marks[MARK_START], 190 maxkernsize); 191 how |= RB_ASKNAME; 192 continue; 193 } 194 marks[MARK_START] = 0; 195 if ((io = loadfile(kernel, marks, LOAD_KERNEL)) != -1) { 196 close(io); 197 break; 198 } 199 } 200 201 /* 202 * if we have are not in askname mode, and we aren't using the 203 * prom bootfile, try the next one (if it exits). otherwise, 204 * go into askname mode. 205 */ 206 if ((how & RB_ASKNAME) == 0 && 207 i != -1 && kernels[++i]) { 208 kernel = kernels[i]; 209 printf(": trying %s...\n", kernel); 210 } else { 211 printf("\n"); 212 how |= RB_ASKNAME; 213 } 214 } 215 216 marks[MARK_END] = (((u_long)marks[MARK_END] + sizeof(int) - 1)) & 217 (-sizeof(int)); 218 arg = (prom_version() == PROM_OLDMON) ? (caddr_t)PROM_LOADADDR : romp; 219 #if 0 220 /* Old style cruft; works only with a.out */ 221 marks[MARK_END] |= 0xf0000000; 222 (*(entry_t)marks[MARK_ENTRY])(arg, 0, 0, 0, marks[MARK_END], 223 DDB_MAGIC1); 224 #else 225 /* Should work with both a.out and ELF, but somehow ELF is busted */ 226 bootinfo = bi_init(marks[MARK_END]); 227 228 bi_sym.nsym = marks[MARK_NSYM]; 229 bi_sym.ssym = marks[MARK_SYM]; 230 bi_sym.esym = marks[MARK_END]; 231 bi_add(&bi_sym, BTINFO_SYMTAB, sizeof(bi_sym)); 232 233 /* 234 * Add kernel path to bootinfo 235 */ 236 i = sizeof(struct btinfo_common) + strlen(kernel) + 1; 237 /* Impose limit (somewhat arbitrary) */ 238 if (i < BOOTINFO_SIZE / 2) { 239 union { 240 struct btinfo_kernelfile bi_file; 241 char x[i]; 242 } U; 243 strcpy(U.bi_file.name, kernel); 244 bi_add(&U.bi_file, BTINFO_KERNELFILE, i); 245 } 246 247 (*(entry_t)marks[MARK_ENTRY])(arg, 0, 0, 0, bootinfo, DDB_MAGIC2); 248 #endif 249 250 _rtt(); 251 } 252