1 1.35 martin /* $NetBSD: boot.c,v 1.35 2017/09/15 13:25:34 martin Exp $ */ 2 1.12 cdi 3 1.1 mrg /* 4 1.1 mrg * Copyright (c) 1997, 1999 Eduardo E. Horvath. All rights reserved. 5 1.1 mrg * Copyright (c) 1997 Jason R. Thorpe. All rights reserved. 6 1.1 mrg * Copyright (C) 1995, 1996 Wolfgang Solfrank. 7 1.1 mrg * Copyright (C) 1995, 1996 TooLs GmbH. 8 1.1 mrg * All rights reserved. 9 1.1 mrg * 10 1.1 mrg * ELF support derived from NetBSD/alpha's boot loader, written 11 1.1 mrg * by Christopher G. Demetriou. 12 1.1 mrg * 13 1.1 mrg * Redistribution and use in source and binary forms, with or without 14 1.1 mrg * modification, are permitted provided that the following conditions 15 1.1 mrg * are met: 16 1.1 mrg * 1. Redistributions of source code must retain the above copyright 17 1.1 mrg * notice, this list of conditions and the following disclaimer. 18 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright 19 1.1 mrg * notice, this list of conditions and the following disclaimer in the 20 1.1 mrg * documentation and/or other materials provided with the distribution. 21 1.1 mrg * 3. All advertising materials mentioning features or use of this software 22 1.1 mrg * must display the following acknowledgement: 23 1.1 mrg * This product includes software developed by TooLs GmbH. 24 1.1 mrg * 4. The name of TooLs GmbH may not be used to endorse or promote products 25 1.1 mrg * derived from this software without specific prior written permission. 26 1.1 mrg * 27 1.1 mrg * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 28 1.1 mrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29 1.1 mrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 30 1.1 mrg * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 1.1 mrg * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 32 1.1 mrg * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 33 1.1 mrg * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 34 1.1 mrg * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 35 1.1 mrg * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 36 1.1 mrg * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 1.1 mrg */ 38 1.1 mrg 39 1.1 mrg /* 40 1.1 mrg * First try for the boot code 41 1.1 mrg * 42 1.1 mrg * Input syntax is: 43 1.1 mrg * [promdev[{:|,}partition]]/[filename] [flags] 44 1.1 mrg */ 45 1.1 mrg 46 1.1 mrg #include <lib/libsa/stand.h> 47 1.31 rtr #include <lib/libsa/bootcfg.h> 48 1.12 cdi #include <lib/libsa/loadfile.h> 49 1.1 mrg #include <lib/libkern/libkern.h> 50 1.1 mrg 51 1.1 mrg #include <sys/param.h> 52 1.1 mrg #include <sys/reboot.h> 53 1.1 mrg #include <sys/disklabel.h> 54 1.2 jdolecek #include <sys/boot_flag.h> 55 1.1 mrg 56 1.1 mrg #include <machine/cpu.h> 57 1.12 cdi #include <machine/promlib.h> 58 1.12 cdi #include <machine/bootinfo.h> 59 1.25 christos #include <sparc/stand/common/isfloppy.h> 60 1.1 mrg 61 1.12 cdi #include "boot.h" 62 1.1 mrg #include "ofdev.h" 63 1.1 mrg #include "openfirm.h" 64 1.1 mrg 65 1.12 cdi 66 1.12 cdi #define COMPAT_BOOT(marks) (marks[MARK_START] == marks[MARK_ENTRY]) 67 1.12 cdi 68 1.12 cdi 69 1.12 cdi typedef void (*entry_t)(long o0, long bootargs, long bootsize, long o3, 70 1.12 cdi long ofw); 71 1.1 mrg 72 1.1 mrg /* 73 1.1 mrg * Boot device is derived from ROM provided information, or if there is none, 74 1.1 mrg * this list is used in sequence, to find a kernel. 75 1.1 mrg */ 76 1.12 cdi const char *kernelnames[] = { 77 1.12 cdi "netbsd", 78 1.12 cdi "netbsd.gz", 79 1.12 cdi "netbsd.old", 80 1.12 cdi "netbsd.old.gz", 81 1.12 cdi "onetbsd", 82 1.12 cdi "onetbsd.gz", 83 1.1 mrg "vmunix ", 84 1.1 mrg #ifdef notyet 85 1.1 mrg "netbsd.pl ", 86 1.1 mrg "netbsd.pl.gz ", 87 1.1 mrg "netbsd.el ", 88 1.1 mrg "netbsd.el.gz ", 89 1.1 mrg #endif 90 1.1 mrg NULL 91 1.1 mrg }; 92 1.1 mrg 93 1.12 cdi char bootdev[PROM_MAX_PATH]; 94 1.22 martin bool root_fs_quickseekable = true; /* unset for tftp boots */ 95 1.22 martin static bool bootinfo_pass_bootdev = false; 96 1.1 mrg 97 1.12 cdi int debug = 0; 98 1.12 cdi int compatmode = 0; 99 1.26 mrg extern char twiddle_toggle; 100 1.1 mrg 101 1.1 mrg #if 0 102 1.1 mrg static void 103 1.13 uwe prom2boot(char *dev) 104 1.1 mrg { 105 1.1 mrg char *cp, *lp = 0; 106 1.1 mrg int handle; 107 1.1 mrg char devtype[16]; 108 1.1 mrg 109 1.1 mrg for (cp = dev; *cp; cp++) 110 1.1 mrg if (*cp == ':') 111 1.1 mrg lp = cp; 112 1.1 mrg if (!lp) 113 1.1 mrg lp = cp; 114 1.1 mrg *lp = 0; 115 1.1 mrg } 116 1.1 mrg #endif 117 1.1 mrg 118 1.12 cdi static int 119 1.15 martin bootoptions(const char *ap, char *loaddev, char *kernel, char *options) 120 1.1 mrg { 121 1.12 cdi int v = 0; 122 1.15 martin const char *start1 = NULL, *end1 = NULL, *start2 = NULL, *end2 = NULL; 123 1.15 martin const char *path; 124 1.17 martin char partition, *pp; 125 1.12 cdi 126 1.12 cdi *kernel = '\0'; 127 1.12 cdi *options = '\0'; 128 1.12 cdi 129 1.12 cdi if (ap == NULL) { 130 1.12 cdi return (0); 131 1.12 cdi } 132 1.12 cdi 133 1.12 cdi while (*ap == ' ') { 134 1.12 cdi ap++; 135 1.12 cdi } 136 1.12 cdi 137 1.12 cdi if (*ap != '-') { 138 1.15 martin start1 = ap; 139 1.12 cdi while (*ap != '\0' && *ap != ' ') { 140 1.12 cdi ap++; 141 1.12 cdi } 142 1.15 martin end1 = ap; 143 1.1 mrg 144 1.32 martin while (*ap == ' ') { 145 1.12 cdi ap++; 146 1.12 cdi } 147 1.15 martin 148 1.15 martin if (*ap != '-') { 149 1.15 martin start2 = ap; 150 1.15 martin while (*ap != '\0' && *ap != ' ') { 151 1.15 martin ap++; 152 1.15 martin } 153 1.15 martin end2 = ap; 154 1.15 martin while (*ap != '\0' && *ap == ' ') { 155 1.15 martin ap++; 156 1.15 martin } 157 1.15 martin } 158 1.15 martin } 159 1.15 martin if (end2 == start2) { 160 1.15 martin start2 = end2 = NULL; 161 1.15 martin } 162 1.15 martin if (end1 == start1) { 163 1.15 martin start1 = end1 = NULL; 164 1.15 martin } 165 1.15 martin 166 1.15 martin if (start1 == NULL) { 167 1.15 martin /* only options */ 168 1.15 martin } else if (start2 == NULL) { 169 1.15 martin memcpy(kernel, start1, (end1 - start1)); 170 1.15 martin kernel[end1 - start1] = '\0'; 171 1.15 martin path = filename(kernel, &partition); 172 1.16 martin if (path == NULL) { 173 1.16 martin strcpy(loaddev, kernel); 174 1.16 martin kernel[0] = '\0'; 175 1.16 martin } else if (path != kernel) { 176 1.15 martin /* copy device part */ 177 1.15 martin memcpy(loaddev, kernel, path-kernel); 178 1.15 martin loaddev[path-kernel] = '\0'; 179 1.17 martin if (partition) { 180 1.17 martin pp = loaddev + strlen(loaddev); 181 1.17 martin pp[0] = ':'; 182 1.17 martin pp[1] = partition; 183 1.17 martin pp[2] = '\0'; 184 1.17 martin } 185 1.15 martin /* and kernel path */ 186 1.15 martin strcpy(kernel, path); 187 1.15 martin } 188 1.15 martin } else { 189 1.15 martin memcpy(loaddev, start1, (end1-start1)); 190 1.15 martin loaddev[end1-start1] = '\0'; 191 1.15 martin memcpy(kernel, start2, (end2 - start2)); 192 1.15 martin kernel[end2 - start2] = '\0'; 193 1.1 mrg } 194 1.12 cdi 195 1.26 mrg twiddle_toggle = 1; 196 1.12 cdi strcpy(options, ap); 197 1.12 cdi while (*ap != '\0' && *ap != ' ' && *ap != '\t' && *ap != '\n') { 198 1.12 cdi BOOT_FLAG(*ap, v); 199 1.12 cdi switch(*ap++) { 200 1.1 mrg case 'D': 201 1.1 mrg debug = 2; 202 1.1 mrg break; 203 1.12 cdi case 'C': 204 1.12 cdi compatmode = 1; 205 1.12 cdi break; 206 1.26 mrg case 'T': 207 1.26 mrg twiddle_toggle = 1 - twiddle_toggle; 208 1.26 mrg break; 209 1.2 jdolecek default: 210 1.1 mrg break; 211 1.1 mrg } 212 1.1 mrg } 213 1.12 cdi 214 1.12 cdi if (((v & RB_KDB) != 0) && (debug == 0)) { 215 1.12 cdi debug = 1; 216 1.12 cdi } 217 1.12 cdi 218 1.15 martin DPRINTF(("bootoptions: device='%s', kernel='%s', options='%s'\n", 219 1.15 martin loaddev, kernel, options)); 220 1.12 cdi return (v); 221 1.1 mrg } 222 1.1 mrg 223 1.12 cdi /* 224 1.12 cdi * The older (those relying on ofwboot v1.8 and earlier) kernels can't handle 225 1.12 cdi * ksyms information unless it resides in a dedicated memory allocated from 226 1.12 cdi * PROM and aligned on NBPG boundary. This is because the kernels calculate 227 1.12 cdi * their ends on their own, they use address of 'end[]' reference which follows 228 1.12 cdi * text segment. Ok, allocate some memory from PROM and copy symbol information 229 1.12 cdi * over there. 230 1.12 cdi */ 231 1.12 cdi static void 232 1.12 cdi ksyms_copyout(void **ssym, void **esym) 233 1.12 cdi { 234 1.28 tsutsui uint8_t *addr; 235 1.28 tsutsui int kssize = (int)(long)((char *)*esym - (char *)*ssym + 1); 236 1.12 cdi 237 1.12 cdi DPRINTF(("ksyms_copyout(): ssym = %p, esym = %p, kssize = %d\n", 238 1.12 cdi *ssym, *esym, kssize)); 239 1.1 mrg 240 1.12 cdi if ( (addr = OF_claim(0, kssize, NBPG)) == (void *)-1) { 241 1.12 cdi panic("ksyms_copyout(): no space for symbol table"); 242 1.12 cdi } 243 1.12 cdi 244 1.12 cdi memcpy(addr, *ssym, kssize); 245 1.12 cdi *ssym = addr; 246 1.12 cdi *esym = addr + kssize - 1; 247 1.12 cdi 248 1.12 cdi DPRINTF(("ksyms_copyout(): ssym = %p, esym = %p\n", *ssym, *esym)); 249 1.12 cdi } 250 1.12 cdi 251 1.12 cdi /* 252 1.12 cdi * Prepare boot information and jump directly to the kernel. 253 1.12 cdi */ 254 1.1 mrg static void 255 1.29 martin jump_to_kernel(u_long *marks, char *kernel, char *args, void *ofw, 256 1.29 martin int boothowto) 257 1.1 mrg { 258 1.1 mrg int l, machine_tag; 259 1.12 cdi long newargs[4]; 260 1.12 cdi void *ssym, *esym; 261 1.12 cdi vaddr_t bootinfo; 262 1.12 cdi struct btinfo_symtab bi_sym; 263 1.12 cdi struct btinfo_kernend bi_kend; 264 1.29 martin struct btinfo_boothowto bi_howto; 265 1.12 cdi char *cp; 266 1.12 cdi char bootline[PROM_MAX_PATH * 2]; 267 1.1 mrg 268 1.12 cdi /* Compose kernel boot line. */ 269 1.12 cdi strncpy(bootline, kernel, sizeof(bootline)); 270 1.12 cdi cp = bootline + strlen(bootline); 271 1.12 cdi if (*args) { 272 1.12 cdi *cp++ = ' '; 273 1.12 cdi strncpy(bootline, args, sizeof(bootline) - (cp - bootline)); 274 1.12 cdi } 275 1.12 cdi *cp = 0; args = bootline; 276 1.12 cdi 277 1.12 cdi /* Record symbol information in the bootinfo. */ 278 1.12 cdi bootinfo = bi_init(marks[MARK_END]); 279 1.12 cdi bi_sym.nsym = marks[MARK_NSYM]; 280 1.12 cdi bi_sym.ssym = marks[MARK_SYM]; 281 1.12 cdi bi_sym.esym = marks[MARK_END]; 282 1.12 cdi bi_add(&bi_sym, BTINFO_SYMTAB, sizeof(bi_sym)); 283 1.12 cdi bi_kend.addr= bootinfo + BOOTINFO_SIZE; 284 1.12 cdi bi_add(&bi_kend, BTINFO_KERNEND, sizeof(bi_kend)); 285 1.29 martin bi_howto.boothowto = boothowto; 286 1.29 martin bi_add(&bi_howto, BTINFO_BOOTHOWTO, sizeof(bi_howto)); 287 1.35 martin if (bootinfo_pass_bootunit) 288 1.35 martin bi_add(&bi_unit, BTINFO_BOOTDEV_UNIT, 289 1.35 martin sizeof(bi_unit)); 290 1.22 martin if (bootinfo_pass_bootdev) { 291 1.22 martin struct { 292 1.22 martin struct btinfo_common common; 293 1.22 martin char name[256]; 294 1.22 martin } info; 295 1.22 martin 296 1.22 martin strcpy(info.name, bootdev); 297 1.22 martin bi_add(&info, BTINFO_BOOTDEV, strlen(bootdev) 298 1.22 martin +sizeof(struct btinfo_bootdev)); 299 1.22 martin } 300 1.22 martin 301 1.14 martin sparc64_finalize_tlb(marks[MARK_DATA]); 302 1.12 cdi sparc64_bi_add(); 303 1.12 cdi 304 1.12 cdi ssym = (void*)(long)marks[MARK_SYM]; 305 1.12 cdi esym = (void*)(long)marks[MARK_END]; 306 1.12 cdi 307 1.12 cdi DPRINTF(("jump_to_kernel(): ssym = %p, esym = %p\n", ssym, esym)); 308 1.12 cdi 309 1.12 cdi /* Adjust ksyms pointers, if needed. */ 310 1.12 cdi if (COMPAT_BOOT(marks) || compatmode) { 311 1.12 cdi ksyms_copyout(&ssym, &esym); 312 1.12 cdi } 313 1.1 mrg 314 1.1 mrg freeall(); 315 1.1 mrg /* 316 1.1 mrg * When we come in args consists of a pointer to the boot 317 1.1 mrg * string. We need to fix it so it takes into account 318 1.1 mrg * other params such as romp. 319 1.1 mrg */ 320 1.1 mrg 321 1.1 mrg /* 322 1.1 mrg * Stash pointer to end of symbol table after the argument 323 1.1 mrg * strings. 324 1.1 mrg */ 325 1.1 mrg l = strlen(args) + 1; 326 1.20 cegger memcpy(args + l, &esym, sizeof(esym)); 327 1.1 mrg l += sizeof(esym); 328 1.1 mrg 329 1.1 mrg /* 330 1.1 mrg * Tell the kernel we're an OpenFirmware system. 331 1.1 mrg */ 332 1.1 mrg machine_tag = SPARC_MACHINE_OPENFIRMWARE; 333 1.20 cegger memcpy(args + l, &machine_tag, sizeof(machine_tag)); 334 1.1 mrg l += sizeof(machine_tag); 335 1.1 mrg 336 1.1 mrg /* 337 1.1 mrg * Since we don't need the boot string (we can get it from /chosen) 338 1.1 mrg * we won't pass it in. Just pass in esym and magic # 339 1.1 mrg */ 340 1.1 mrg newargs[0] = SPARC_MACHINE_OPENFIRMWARE; 341 1.1 mrg newargs[1] = (long)esym; 342 1.1 mrg newargs[2] = (long)ssym; 343 1.12 cdi newargs[3] = (long)(void*)bootinfo; 344 1.1 mrg args = (char *)newargs; 345 1.1 mrg l = sizeof(newargs); 346 1.1 mrg 347 1.1 mrg /* if -D is set then pause in the PROM. */ 348 1.12 cdi if (debug > 1) callrom(); 349 1.12 cdi 350 1.12 cdi /* 351 1.12 cdi * Jump directly to the kernel. Solaris kernel and Sun PROM 352 1.12 cdi * flash updates expect ROMP vector in %o0, so we do. Format 353 1.12 cdi * of other parameters and their order reflect OF_chain() 354 1.12 cdi * symantics since this is what older NetBSD kernels rely on. 355 1.12 cdi * (see sparc64/include/bootinfo.h for specification). 356 1.12 cdi */ 357 1.12 cdi DPRINTF(("jump_to_kernel(%lx, %lx, %lx, %lx, %lx) @ %p\n", (long)ofw, 358 1.12 cdi (long)args, (long)l, (long)ofw, (long)ofw, 359 1.12 cdi (void*)marks[MARK_ENTRY])); 360 1.12 cdi (*(entry_t)marks[MARK_ENTRY])((long)ofw, (long)args, (long)l, (long)ofw, 361 1.12 cdi (long)ofw); 362 1.12 cdi printf("Returned from kernel entry point!\n"); 363 1.1 mrg } 364 1.1 mrg 365 1.12 cdi static void 366 1.29 martin start_kernel(char *kernel, char *bootline, void *ofw, int isfloppy, 367 1.29 martin int boothowto) 368 1.1 mrg { 369 1.1 mrg int fd; 370 1.34 martin u_long marks[MARK_MAX] = {0}; 371 1.24 christos int flags = LOAD_ALL; 372 1.34 martin 373 1.24 christos if (isfloppy) 374 1.24 christos flags &= ~LOAD_BACKWARDS; 375 1.1 mrg 376 1.1 mrg /* 377 1.12 cdi * First, load headers using default allocator and check whether kernel 378 1.12 cdi * entry address matches kernel text load address. If yes, this is the 379 1.12 cdi * old kernel designed for ofwboot v1.8 and therefore it must be mapped 380 1.12 cdi * by PROM. Otherwise, map the kernel with 4MB permanent pages. 381 1.1 mrg */ 382 1.12 cdi loadfile_set_allocator(LOADFILE_NOP_ALLOCATOR); 383 1.12 cdi if ( (fd = loadfile(kernel, marks, LOAD_HDR|COUNT_TEXT)) != -1) { 384 1.12 cdi if (COMPAT_BOOT(marks) || compatmode) { 385 1.12 cdi (void)printf("[c] "); 386 1.12 cdi loadfile_set_allocator(LOADFILE_OFW_ALLOCATOR); 387 1.12 cdi } else { 388 1.12 cdi loadfile_set_allocator(LOADFILE_MMU_ALLOCATOR); 389 1.12 cdi } 390 1.12 cdi (void)printf("Loading %s: ", kernel); 391 1.1 mrg 392 1.23 christos if (fdloadfile(fd, marks, flags) != -1) { 393 1.21 martin close(fd); 394 1.29 martin jump_to_kernel(marks, kernel, bootline, ofw, boothowto); 395 1.1 mrg } 396 1.1 mrg } 397 1.12 cdi (void)printf("Failed to load '%s'.\n", kernel); 398 1.1 mrg } 399 1.1 mrg 400 1.15 martin static void 401 1.15 martin help(void) 402 1.15 martin { 403 1.15 martin printf( "enter a special command\n" 404 1.15 martin " halt\n" 405 1.15 martin " exit\n" 406 1.15 martin " to return to OpenFirmware\n" 407 1.15 martin " ?\n" 408 1.15 martin " help\n" 409 1.15 martin " to display this message\n" 410 1.15 martin "or a boot specification:\n" 411 1.15 martin " [device] [kernel] [options]\n" 412 1.15 martin "\n" 413 1.15 martin "for example:\n" 414 1.15 martin " disk:a netbsd -s\n"); 415 1.15 martin } 416 1.15 martin 417 1.22 martin static void 418 1.31 rtr do_config_command(const char *cmd, char *arg) 419 1.22 martin { 420 1.22 martin DPRINTF(("do_config_command: %s\n", cmd)); 421 1.22 martin if (strcmp(cmd, "bootpartition") == 0) { 422 1.22 martin char *c; 423 1.22 martin 424 1.22 martin DPRINTF(("switching boot partition to %s from %s\n", 425 1.22 martin arg, bootdev)); 426 1.22 martin c = strrchr(bootdev, ':'); 427 1.22 martin if (!c) return; 428 1.22 martin if (c[1] == 0) return; 429 1.22 martin if (strlen(arg) > strlen(c)) return; 430 1.22 martin strcpy(c, arg); 431 1.22 martin DPRINTF(("new boot device: %s\n", bootdev)); 432 1.22 martin bootinfo_pass_bootdev = true; 433 1.22 martin } 434 1.22 martin } 435 1.22 martin 436 1.22 martin static void 437 1.22 martin check_boot_config(void) 438 1.22 martin { 439 1.31 rtr if (!root_fs_quickseekable) 440 1.30 martin return; 441 1.22 martin 442 1.31 rtr perform_bootcfg(BOOTCFG_FILENAME, &do_config_command, 32768); 443 1.22 martin } 444 1.22 martin 445 1.12 cdi void 446 1.12 cdi main(void *ofw) 447 1.12 cdi { 448 1.29 martin int boothowto, i = 0, isfloppy, kboothowto; 449 1.1 mrg 450 1.12 cdi char kernel[PROM_MAX_PATH]; 451 1.12 cdi char bootline[PROM_MAX_PATH]; 452 1.1 mrg 453 1.12 cdi /* Initialize OpenFirmware */ 454 1.12 cdi romp = ofw; 455 1.12 cdi prom_init(); 456 1.1 mrg 457 1.7 martin printf("\r>> %s, Revision %s\n", bootprog_name, bootprog_rev); 458 1.1 mrg 459 1.12 cdi /* Figure boot arguments */ 460 1.12 cdi strncpy(bootdev, prom_getbootpath(), sizeof(bootdev) - 1); 461 1.29 martin kboothowto = boothowto = 462 1.29 martin bootoptions(prom_getbootargs(), bootdev, kernel, bootline); 463 1.25 christos isfloppy = bootdev_isfloppy(bootdev); 464 1.12 cdi 465 1.12 cdi for (;; *kernel = '\0') { 466 1.1 mrg if (boothowto & RB_ASKNAME) { 467 1.28 tsutsui char cmdline[PROM_MAX_PATH]; 468 1.12 cdi 469 1.1 mrg printf("Boot: "); 470 1.33 dholland kgets(cmdline, sizeof(cmdline)); 471 1.12 cdi 472 1.15 martin if (!strcmp(cmdline,"exit") || 473 1.15 martin !strcmp(cmdline,"halt")) { 474 1.12 cdi prom_halt(); 475 1.15 martin } else if (!strcmp(cmdline, "?") || 476 1.15 martin !strcmp(cmdline, "help")) { 477 1.15 martin help(); 478 1.15 martin continue; 479 1.12 cdi } 480 1.15 martin 481 1.15 martin boothowto = bootoptions(cmdline, bootdev, kernel, 482 1.15 martin bootline); 483 1.15 martin boothowto |= RB_ASKNAME; 484 1.15 martin i = 0; 485 1.1 mrg } 486 1.12 cdi 487 1.12 cdi if (*kernel == '\0') { 488 1.12 cdi if (kernelnames[i] == NULL) { 489 1.12 cdi boothowto |= RB_ASKNAME; 490 1.12 cdi continue; 491 1.12 cdi } 492 1.12 cdi strncpy(kernel, kernelnames[i++], PROM_MAX_PATH); 493 1.12 cdi } else if (i == 0) { 494 1.12 cdi /* 495 1.12 cdi * Kernel name was passed via command line -- ask user 496 1.12 cdi * again if requested image fails to boot. 497 1.12 cdi */ 498 1.12 cdi boothowto |= RB_ASKNAME; 499 1.12 cdi } 500 1.12 cdi 501 1.22 martin check_boot_config(); 502 1.29 martin start_kernel(kernel, bootline, ofw, isfloppy, kboothowto); 503 1.12 cdi 504 1.1 mrg /* 505 1.12 cdi * Try next name from kernel name list if not in askname mode, 506 1.12 cdi * enter askname on reaching list's end. 507 1.1 mrg */ 508 1.12 cdi if ((boothowto & RB_ASKNAME) == 0 && (kernelnames[i] != NULL)) { 509 1.12 cdi printf(": trying %s...\n", kernelnames[i]); 510 1.1 mrg } else { 511 1.1 mrg printf("\n"); 512 1.1 mrg boothowto |= RB_ASKNAME; 513 1.1 mrg } 514 1.1 mrg } 515 1.1 mrg 516 1.12 cdi (void)printf("Boot failed! Exiting to the Firmware.\n"); 517 1.12 cdi prom_halt(); 518 1.1 mrg } 519