/* $OpenBSD: boot.c,v 1.10 2003/10/16 04:30:09 drahn Exp $ */ /* $NetBSD: boot.c,v 1.1 1997/04/16 20:29:17 thorpej Exp $ */ /* * Copyright (c) 1997 Jason R. Thorpe. All rights reserved. * Copyright (C) 1995, 1996 Wolfgang Solfrank. * Copyright (C) 1995, 1996 TooLs GmbH. * All rights reserved. * * ELF support derived from NetBSD/alpha's boot loader, written * by Christopher G. Demetriou. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by TooLs GmbH. * 4. The name of TooLs GmbH may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * First try for the boot code * * Input syntax is: * [promdev[{:|,}partition]]/[filename] [flags] */ #define ELFSIZE 32 /* We use 32-bit ELF. */ #include #include #include #include #include #include #include #include #include #include #include char bootdev[128]; char bootfile[128]; int boothowto; int debug; extern int ConfigPPCCache(u_int32_t); // L2Config.c static void prom2boot(char *bootpath, char *bootargs, char *bootdev) { char *cp, *bd, *lp = 0; int len, inst; char buf[128]; bd = buf; // might need to canonicalize the name for (cp = bootargs; *cp; cp++) { if (*cp == ':') { lp = cp; // full path specified break; } else *bd++ = *cp; } *bd = 0; if (lp) { // OF's canon (OF_canon) will drop device nodes (grrr...) inst = OF_finddevice("/aliases"); len = OF_getprop(inst, buf, bootdev, 128); } if (!lp) { // path given is relative to bootloader bd = bootdev; // copy into bootdev for (cp = bootpath; *cp; cp++) { if (*cp == ':') { lp = cp; break; } else *bd++ = *cp; } *bd = 0; } printf("bootdev: %s\n",bootdev); printf("bootpath: %s\n",bootpath); printf("bootargs: %s\n",bootargs); } static void parseargs(char *str, int *howtop) { char *cp; /* Allow user to drop back to the PROM. */ if (strcmp(str, "exit") == 0) _rtt(); *howtop = 0; if (str[0] == '\0') return; cp = str; while (*cp != 0) { /* check for - */ if (*cp == '-') break; /* start of options found */ while (*cp != 0 && *cp != ' ') cp++; /* character in the middle of the name, skip */ while (*cp == ' ') *cp++ = 0; } if (!*cp) return; *cp++ = 0; while (*cp) { switch (*cp++) { case 'a': *howtop |= RB_ASKNAME; break; case 'c': *howtop |= RB_CONFIG; break; case 's': *howtop |= RB_SINGLE; break; case 'd': *howtop |= RB_KDB; debug = 1; break; } } } static void chain(void (*entry)(), char *args, void *ssym, void *esym) { extern char end[]; int l, machine_tag; u_long kernsize; freeall(); /* * Stash pointer to end of symbol table after the argument * strings. */ l = strlen(args) + 1; bcopy(&ssym, args + l, sizeof(ssym)); l += sizeof(ssym); bcopy(&esym, args + l, sizeof(esym)); l += sizeof(esym); #ifdef __notyet__ /* * Tell the kernel we're an OpenFirmware system. */ machine_tag = POWERPC_MACHINE_OPENFIRMWARE; bcopy(&machine_tag, args + l, sizeof(machine_tag)); l += sizeof(machine_tag); #endif // if we're here, OF let us write into the space, // so claim it for region allocations kernsize = roundup(((char *)esym - (char *)entry), 1024); if (OF_claim((void *)entry, kernsize, 0) == -1) { ofw_panic("\nmemory claim failed in boot.c: chain, kernsize: %lu, esym: %x, entry: %x", kernsize, esym, entry); } printf("\nchaining (args: %s)...", args); // legacy OpenBSD code that's wrong - // ummm...RELOC and end are relative to boot.mac // so passing these values to Open Firmware is // useless. OF initiated the bootloader and knows how to // free its space. What OF needs is to know how much // to claim for the kernel. However, there are still // reasons to keep the bootloader around so OF_chain // jumping to the start of the kernel manually suits us OF_chain((void *)RELOC, end - (char *)RELOC, entry, args, l); panic("chain"); } int main() { int chosen; char bootargs[512], bootpath[512]; /* Should check size? */ char *cp; u_long marks[MARK_MAX]; u_int32_t entry; u_int32_t pvr, vers; void *ssym, *esym; int fd, err; printf("\nBoot25c.xcf, enhanced *BSD XCOFF bootloader\n"); printf("configuring L1/L2/L3 caches..."); pvr = ppc_mfpvr(); vers = pvr >> 16; err = ConfigPPCCache(vers); if (err == -1) printf("caches preconfigured.\n"); else if (err == 0) printf("unable to determine proper L2 cache value.\n"); else printf("L2 cache value: %x\n", err); printf("\n"); /* * Get the boot arguments from Openfirmware */ if ((chosen = OF_finddevice("/chosen")) == -1 || OF_getprop(chosen, "bootpath", bootpath, sizeof bootpath) < 0 || OF_getprop(chosen, "bootargs", bootargs, sizeof bootargs) < 0) { printf("Invalid Openfirmware environment\n"); exit(); } prom2boot(bootpath, bootargs, bootdev); parseargs(bootargs, &boothowto); for (;;) { if (boothowto & RB_ASKNAME) { printf("Boot (or \"exit\"): "); gets(bootargs); parseargs(bootargs, &boothowto); } marks[MARK_START] = 0; if (loadfile(bootargs, marks, LOAD_ALL) >= 0) break; if (errno) printf("open %s: %s\n", opened_name, strerror(errno)); boothowto |= RB_ASKNAME; } #ifdef __notyet__ OF_setprop(chosen, "bootpath", opened_name, strlen(opened_name) + 1); cp = bootargs; #else strlcpy(bootargs, opened_name, sizeof bootargs); cp = bootargs + strlen(bootargs); *cp++ = ' '; #endif *cp = '-'; if (boothowto & RB_ASKNAME) *++cp = 'a'; if (boothowto & RB_CONFIG) *++cp = 'c'; if (boothowto & RB_SINGLE) *++cp = 's'; if (boothowto & RB_KDB) *++cp = 'd'; if (*cp == '-') #ifdef __notyet__ *cp = 0; #else *--cp = 0; #endif else *++cp = 0; #ifdef __notyet__ OF_setprop(chosen, "bootargs", bootargs, strlen(bootargs) + 1); #endif entry = marks[MARK_ENTRY]; ssym = (void *)marks[MARK_SYM]; esym = (void *)marks[MARK_END]; chain((void *)entry, bootargs, ssym, esym); _rtt(); return 0; }