1 /* $NetBSD: boot.c,v 1.2 1997/10/05 18:20:21 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 41 * Copyright (C) 1995, 1996 TooLs GmbH. 42 * All rights reserved. 43 * 44 * ELF support derived from NetBSD/alpha's boot loader, written 45 * by Christopher G. Demetriou. 46 * 47 * Redistribution and use in source and binary forms, with or without 48 * modification, are permitted provided that the following conditions 49 * are met: 50 * 1. Redistributions of source code must retain the above copyright 51 * notice, this list of conditions and the following disclaimer. 52 * 2. Redistributions in binary form must reproduce the above copyright 53 * notice, this list of conditions and the following disclaimer in the 54 * documentation and/or other materials provided with the distribution. 55 * 3. All advertising materials mentioning features or use of this software 56 * must display the following acknowledgement: 57 * This product includes software developed by TooLs GmbH. 58 * 4. The name of TooLs GmbH may not be used to endorse or promote products 59 * derived from this software without specific prior written permission. 60 * 61 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 62 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 63 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 64 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 65 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 66 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 67 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 68 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 69 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 70 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 71 */ 72 73 /* 74 * First try for the boot code 75 * 76 * Input syntax is: 77 * [promdev[{:|,}partition]]/[filename] [flags] 78 */ 79 80 #define ELFSIZE 32 /* We use 32-bit ELF. */ 81 82 #include <lib/libsa/stand.h> 83 #include <lib/libkern/libkern.h> 84 85 #include <sys/param.h> 86 #include <sys/exec.h> 87 #include <sys/exec_elf.h> 88 #include <sys/reboot.h> 89 #include <sys/disklabel.h> 90 91 #include <machine/cpu.h> 92 #include <machine/machine_type.h> 93 94 #include <powerpc/stand/ofwboot/ofdev.h> 95 #include <powerpc/stand/ofwboot/openfirm.h> 96 97 char bootdev[128]; 98 char bootfile[128]; 99 int boothowto; 100 int debug; 101 102 #ifdef POWERPC_BOOT_ELF 103 int elf_exec __P((int, Elf_Ehdr *, u_int32_t *, void **)); 104 #endif 105 106 #ifdef POWERPC_BOOT_AOUT 107 int aout_exec __P((int, struct exec *, u_int32_t *, void **)); 108 #endif 109 110 static void 111 prom2boot(dev) 112 char *dev; 113 { 114 char *cp, *lp = 0; 115 int handle; 116 char devtype[16]; 117 118 for (cp = dev; *cp; cp++) 119 if (*cp == ':') 120 lp = cp; 121 if (!lp) 122 lp = cp; 123 *lp = 0; 124 } 125 126 static void 127 parseargs(str, howtop) 128 char *str; 129 int *howtop; 130 { 131 char *cp; 132 133 /* Allow user to drop back to the PROM. */ 134 if (strcmp(str, "exit") == 0) 135 _rtt(); 136 137 *howtop = 0; 138 for (cp = str; *cp; cp++) 139 if (*cp == ' ' || *cp == '-') 140 break; 141 if (!*cp) 142 return; 143 144 *cp++ = 0; 145 while (*cp) { 146 switch (*cp++) { 147 case 'a': 148 *howtop |= RB_ASKNAME; 149 break; 150 case 's': 151 *howtop |= RB_SINGLE; 152 break; 153 case 'd': 154 *howtop |= RB_KDB; 155 debug = 1; 156 break; 157 } 158 } 159 } 160 161 static void 162 chain(entry, args, esym) 163 void (*entry)(); 164 char *args; 165 void *esym; 166 { 167 extern char end[]; 168 int l, machine_tag; 169 170 freeall(); 171 172 /* 173 * Stash pointer to end of symbol table after the argument 174 * strings. 175 */ 176 l = strlen(args) + 1; 177 bcopy(&esym, args + l, sizeof(esym)); 178 l += sizeof(esym); 179 180 /* 181 * Tell the kernel we're an OpenFirmware system. 182 */ 183 machine_tag = POWERPC_MACHINE_OPENFIRMWARE; 184 bcopy(&machine_tag, args + l, sizeof(machine_tag)); 185 l += sizeof(machine_tag); 186 187 OF_chain((void *)RELOC, end - (char *)RELOC, entry, args, l); 188 panic("chain"); 189 } 190 191 int 192 loadfile(fd, args) 193 int fd; 194 char *args; 195 { 196 union { 197 #ifdef POWERPC_BOOT_AOUT 198 struct exec aout; 199 #endif 200 #ifdef POWERPC_BOOT_ELF 201 Elf_Ehdr elf; 202 #endif 203 } hdr; 204 int rval; 205 u_int32_t entry; 206 void *esym; 207 208 rval = 1; 209 esym = NULL; 210 211 /* Load the header. */ 212 if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { 213 printf("read header: %s\n", strerror(errno)); 214 goto err; 215 } 216 217 /* Determine file type, load kernel. */ 218 #ifdef POWERPC_BOOT_AOUT 219 if (N_BADMAG(hdr.aout) == 0 && N_GETMID(hdr.aout) == MID_POWERPC) { 220 rval = aout_exec(fd, &hdr.aout, &entry, &esym); 221 } else 222 #endif 223 #ifdef POWERPC_BOOT_ELF 224 if (memcmp(Elf_e_ident, hdr.elf.e_ident, Elf_e_siz) == 0) { 225 rval = elf_exec(fd, &hdr.elf, &entry, &esym); 226 } else 227 #endif 228 { 229 printf("unknown executable format\n"); 230 } 231 232 if (rval) 233 goto err; 234 235 printf(" start=0x%x\n", entry); 236 237 close(fd); 238 239 /* XXX this should be replaced w/ a mountroothook. */ 240 if (floppyboot) { 241 printf("Please insert root disk and press ENTER "); 242 getchar(); 243 printf("\n"); 244 } 245 246 chain((void *)entry, args, esym); 247 /* NOTREACHED */ 248 249 err: 250 close(fd); 251 return (rval); 252 } 253 254 #ifdef POWERPC_BOOT_AOUT 255 int 256 aout_exec(fd, hdr, entryp, esymp) 257 int fd; 258 struct exec *hdr; 259 u_int32_t *entryp; 260 void **esymp; 261 { 262 void *addr; 263 int n, *paddr; 264 265 /* Display the load address (entry point) for a.out. */ 266 printf("Booting %s @ 0x%lx\n", opened_name, hdr->a_entry); 267 addr = (void *)(hdr->a_entry); 268 269 /* 270 * Determine memory needed for kernel and allocate it from 271 * the firmware. 272 */ 273 n = hdr->a_text + hdr->a_data + hdr->a_bss + hdr->a_syms + sizeof(int); 274 if ((paddr = OF_claim(addr, n, 0)) == (int *)-1) 275 panic("cannot claim memory"); 276 277 /* Load text. */ 278 lseek(fd, N_TXTOFF(*hdr), SEEK_SET); 279 printf("%lu", hdr->a_text); 280 if (read(fd, paddr, hdr->a_text) != hdr->a_text) { 281 printf("read text: %s\n", strerror(errno)); 282 return (1); 283 } 284 syncicache((void *)paddr, hdr->a_text); 285 286 /* Load data. */ 287 printf("+%lu", hdr->a_data); 288 if (read(fd, (void *)paddr + hdr->a_text, hdr->a_data) != hdr->a_data) { 289 printf("read data: %s\n", strerror(errno)); 290 return (1); 291 } 292 293 /* Zero BSS. */ 294 printf("+%lu", hdr->a_bss); 295 bzero((void *)paddr + hdr->a_text + hdr->a_data, hdr->a_bss); 296 297 /* Symbols. */ 298 *esymp = paddr; 299 paddr = (int *)((void *)paddr + hdr->a_text + hdr->a_data + hdr->a_bss); 300 *paddr++ = hdr->a_syms; 301 if (hdr->a_syms) { 302 printf(" [%lu", hdr->a_syms); 303 if (read(fd, paddr, hdr->a_syms) != hdr->a_syms) { 304 printf("read symbols: %s\n", strerror(errno)); 305 return (1); 306 } 307 paddr = (int *)((void *)paddr + hdr->a_syms); 308 if (read(fd, &n, sizeof(int)) != sizeof(int)) { 309 printf("read symbols: %s\n", strerror(errno)); 310 return (1); 311 } 312 if (OF_claim((void *)paddr, n + sizeof(int), 0) == (void *)-1) 313 panic("cannot claim memory"); 314 *paddr++ = n; 315 if (read(fd, paddr, n - sizeof(int)) != n - sizeof(int)) { 316 printf("read symbols: %s\n", strerror(errno)); 317 return (1); 318 } 319 printf("+%d]", n - sizeof(int)); 320 *esymp = paddr + (n - sizeof(int)); 321 } 322 323 *entryp = hdr->a_entry; 324 return (0); 325 } 326 #endif /* POWERPC_BOOT_AOUT */ 327 328 #ifdef POWERPC_BOOT_ELF 329 int 330 elf_exec(fd, elf, entryp, esymp) 331 int fd; 332 Elf_Ehdr *elf; 333 u_int32_t *entryp; 334 void **esymp; 335 { 336 Elf32_Shdr *shp; 337 Elf32_Off off; 338 void *addr; 339 size_t size; 340 int i, first = 1; 341 int n; 342 343 /* 344 * Don't display load address for ELF; it's encoded in 345 * each section. 346 */ 347 printf("Booting %s\n", opened_name); 348 349 for (i = 0; i < elf->e_phnum; i++) { 350 Elf_Phdr phdr; 351 (void)lseek(fd, elf->e_phoff + sizeof(phdr) * i, SEEK_SET); 352 if (read(fd, (void *)&phdr, sizeof(phdr)) != sizeof(phdr)) { 353 printf("read phdr: %s\n", strerror(errno)); 354 return (1); 355 } 356 if (phdr.p_type != Elf_pt_load || 357 (phdr.p_flags & (Elf_pf_w|Elf_pf_x)) == 0) 358 continue; 359 360 /* Read in segment. */ 361 printf("%s%lu@0x%lx", first ? "" : "+", phdr.p_filesz, 362 (u_long)phdr.p_vaddr); 363 (void)lseek(fd, phdr.p_offset, SEEK_SET); 364 if (OF_claim((void *)phdr.p_vaddr, phdr.p_memsz, 0) == 365 (void *)-1) 366 panic("cannot claim memory"); 367 if (read(fd, (void *)phdr.p_vaddr, phdr.p_filesz) != 368 phdr.p_filesz) { 369 printf("read segment: %s\n", strerror(errno)); 370 return (1); 371 } 372 syncicache((void *)phdr.p_vaddr, phdr.p_filesz); 373 374 /* Zero BSS. */ 375 if (phdr.p_filesz < phdr.p_memsz) { 376 printf("+%lu@0x%lx", phdr.p_memsz - phdr.p_filesz, 377 (u_long)(phdr.p_vaddr + phdr.p_filesz)); 378 bzero(phdr.p_vaddr + phdr.p_filesz, 379 phdr.p_memsz - phdr.p_filesz); 380 } 381 first = 0; 382 } 383 384 printf(" \n"); 385 386 #if 0 /* I want to rethink this... --thorpej@netbsd.org */ 387 /* 388 * Compute the size of the symbol table. 389 */ 390 size = sizeof(Elf_Ehdr) + (elf->e_shnum * sizeof(Elf32_Shdr)); 391 shp = addr = alloc(elf->e_shnum * sizeof(Elf32_Shdr)); 392 (void)lseek(fd, elf->e_shoff, SEEK_SET); 393 if (read(fd, addr, elf->e_shnum * sizeof(Elf32_Shdr)) != 394 elf->e_shnum * sizeof(Elf32_Shdr)) { 395 printf("read section headers: %s\n", strerror(errno)); 396 return (1); 397 } 398 for (i = 0; i < elf->e_shnum; i++, shp++) { 399 if (shp->sh_type == Elf_sht_null) 400 continue; 401 if (shp->sh_type != Elf_sht_symtab 402 && shp->sh_type != Elf_sht_strtab) { 403 shp->sh_offset = 0; 404 shp->sh_type = Elf_sht_nobits; 405 continue; 406 } 407 size += shp->sh_size; 408 } 409 shp = addr; 410 411 /* 412 * Reserve memory for the symbols. 413 */ 414 if ((addr = OF_claim(0, size, NBPG)) == (void *)-1) 415 panic("no space for symbol table"); 416 417 /* 418 * Copy the headers. 419 */ 420 elf->e_phoff = 0; 421 elf->e_shoff = sizeof(Elf_Ehdr); 422 elf->e_phentsize = 0; 423 elf->e_phnum = 0; 424 bcopy(elf, addr, sizeof(Elf_Ehdr)); 425 bcopy(shp, addr + sizeof(Elf_Ehdr), elf->e_shnum * sizeof(Elf32_Shdr)); 426 free(shp, elf->e_shnum * sizeof(Elf32_Shdr)); 427 *ssymp = addr; 428 429 /* 430 * Now load the symbol sections themselves. 431 */ 432 shp = addr + sizeof(Elf_Ehdr); 433 addr += sizeof(Elf_Ehdr) + (elf->e_shnum * sizeof(Elf32_Shdr)); 434 off = sizeof(Elf_Ehdr) + (elf->e_shnum * sizeof(Elf32_Shdr)); 435 for (first = 1, i = 0; i < elf->e_shnum; i++, shp++) { 436 if (shp->sh_type == Elf_sht_symtab 437 || shp->sh_type == Elf_sht_strtab) { 438 if (first) 439 printf("symbols @ 0x%lx ", (u_long)addr); 440 printf("%s%d", first ? "" : "+", shp->sh_size); 441 (void)lseek(fd, shp->sh_offset, SEEK_SET); 442 if (read(fd, addr, shp->sh_size) != shp->sh_size) { 443 printf("read symbols: %s\n", strerror(errno)); 444 return (1); 445 } 446 addr += shp->sh_size; 447 shp->sh_offset = off; 448 off += shp->sh_size; 449 first = 0; 450 } 451 } 452 *esymp = addr; 453 #endif /* 0 */ 454 455 *entryp = elf->e_entry; 456 return (0); 457 } 458 #endif /* POWERPC_BOOT_ELF */ 459 460 void 461 main() 462 { 463 extern char bootprog_name[], bootprog_rev[], 464 bootprog_maker[], bootprog_date[]; 465 int chosen; 466 char bootline[512]; /* Should check size? */ 467 char *cp; 468 int fd; 469 470 printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev); 471 printf(">> (%s, %s)\n", bootprog_maker, bootprog_date); 472 473 /* 474 * Get the boot arguments from Openfirmware 475 */ 476 if ((chosen = OF_finddevice("/chosen")) == -1 477 || OF_getprop(chosen, "bootpath", bootdev, sizeof bootdev) < 0 478 || OF_getprop(chosen, "bootargs", bootline, sizeof bootline) < 0) { 479 printf("Invalid Openfirmware environment\n"); 480 exit(); 481 } 482 prom2boot(bootdev); 483 parseargs(bootline, &boothowto); 484 for (;;) { 485 if (boothowto & RB_ASKNAME) { 486 printf("Boot: "); 487 gets(bootline); 488 parseargs(bootline, &boothowto); 489 } 490 if ((fd = open(bootline, 0)) >= 0) 491 break; 492 if (errno) 493 printf("open %s: %s\n", opened_name, strerror(errno)); 494 boothowto |= RB_ASKNAME; 495 } 496 #ifdef __notyet__ 497 OF_setprop(chosen, "bootpath", opened_name, strlen(opened_name) + 1); 498 cp = bootline; 499 #else 500 strcpy(bootline, opened_name); 501 cp = bootline + strlen(bootline); 502 *cp++ = ' '; 503 #endif 504 *cp = '-'; 505 if (boothowto & RB_ASKNAME) 506 *++cp = 'a'; 507 if (boothowto & RB_SINGLE) 508 *++cp = 's'; 509 if (boothowto & RB_KDB) 510 *++cp = 'd'; 511 if (*cp == '-') 512 #ifdef __notyet__ 513 *cp = 0; 514 #else 515 *--cp = 0; 516 #endif 517 else 518 *++cp = 0; 519 #ifdef __notyet__ 520 OF_setprop(chosen, "bootargs", bootline, strlen(bootline) + 1); 521 #endif 522 /* XXX void, for now */ 523 (void)loadfile(fd, bootline); 524 525 _rtt(); 526 } 527