/* $NetBSD: boot.c,v 1.13 1995/09/17 00:50:54 pk Exp $ */ /*- * Copyright (c) 1982, 1986, 1990, 1993 * The Regents of the University of California. All rights reserved. * * 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 the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS OR CONTRIBUTORS 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. * * @(#)boot.c 8.1 (Berkeley) 6/10/93 */ #include #include #include #include #include "promdev.h" static void copyunix __P((int, char *)); static void promsyms __P((int, struct exec *)); int debug; int netif_debug; /* * Boot device is derived from ROM provided information. */ #define DEFAULT_KERNEL "netbsd" extern char *version; unsigned long esym; char *strtab; int strtablen; char fbuf[80], dbuf[128]; typedef void (*entry_t)__P((caddr_t, int, int, int, long, long)); void loadfile __P((int, caddr_t)); main() { int io; char *file; prom_init(); printf(">> NetBSD BOOT [%s]\n", version); file = prom_bootfile; if (file == 0 || *file == 0) file = DEFAULT_KERNEL; for (;;) { if (prom_boothow & RB_ASKNAME) { printf("device[%s]: ", prom_bootdevice); gets(dbuf); if (dbuf[0]) prom_bootdevice = dbuf; printf("boot: "); gets(fbuf); if (fbuf[0]) file = fbuf; } if ((io = open(file, 0)) >= 0) break; printf("open: %s: %s\n", file, strerror(errno)); prom_boothow |= RB_ASKNAME; } printf("Booting %s @ 0x%x\n", file, LOADADDR); loadfile(io, LOADADDR); _rtt(); } void loadfile(io, addr) register int io; register caddr_t addr; { register entry_t entry = (entry_t)LOADADDR; struct exec x; int i; i = read(io, (char *)&x, sizeof(x)); if (i != sizeof(x) || N_BADMAG(x)) { printf("Bad format\n"); return; } printf("%d", x.a_text); if (N_GETMAGIC(x) == ZMAGIC) { entry = (entry_t)(addr+sizeof(struct exec)); addr += sizeof(struct exec); } if (read(io, (char *)addr, x.a_text) != x.a_text) goto shread; addr += x.a_text; if (N_GETMAGIC(x) == ZMAGIC || N_GETMAGIC(x) == NMAGIC) while ((int)addr & __LDPGSZ) *addr++ = 0; printf("+%d", x.a_data); if (read(io, addr, x.a_data) != x.a_data) goto shread; addr += x.a_data; printf("+%d", x.a_bss); for (i = 0; i < x.a_bss; i++) *addr++ = 0; if (x.a_syms != 0) { bcopy(&x.a_syms, addr, sizeof(x.a_syms)); addr += sizeof(x.a_syms); printf("+[%d", x.a_syms); if (read(io, addr, x.a_syms) != x.a_syms) goto shread; addr += x.a_syms; if (read(io, &strtablen, sizeof(int)) != sizeof(int)) goto shread; bcopy(&strtablen, addr, sizeof(int)); if (i = strtablen) { i -= sizeof(int); addr += sizeof(int); if (read(io, addr, i) != i) goto shread; addr += i; } printf("+%d]", i); esym = KERNBASE + (((int)addr + sizeof(int) - 1) & ~(sizeof(int) - 1)); #if 0 /* * The FORTH word `loadsyms' is mentioned in the * "Openboot command reference" book, but it seems it has * not been implemented on at least one machine.. */ promsyms(io, &x); #endif } printf("=0x%x\n", addr); close(io); /* Note: args 2-4 not used due to conflicts with SunOS loaders */ (*entry)(cputyp == CPU_SUN4 ? LOADADDR : (caddr_t)promvec, 0, 0, 0, esym, DDB_MAGIC); return; shread: printf("boot: short read\n"); return; } #if 0 struct syms { u_int32_t value; u_int32_t index; }; static void sort(syms, n) struct syms *syms; int n; { register struct syms *sj; register int i, j, k; register u_int32_t value, index; /* Insertion sort. This is O(n^2), but so what? */ for (i = 1; i < n; i++) { /* save i'th entry */ value = syms[i].value; index = syms[i].index; /* find j such that i'th entry goes before j'th */ for (j = 0, sj = syms; j < i; j++, sj++) if (value < sj->value) break; /* slide up any additional entries */ for (k = 0; k < (i - j); k++) { sj[k+1].value = sj[k].value; sj[k+1].index = sj[k].index; } sj->value = value; sj->index = index; } } void promsyms(fd, hp) int fd; struct exec *hp; { int i, n, strtablen; char *str, *p, *cp, buf[128]; struct syms *syms; lseek(fd, sizeof(*hp)+hp->a_text+hp->a_data, SEEK_SET); n = hp->a_syms/sizeof(struct nlist); if (n == 0) return; syms = (struct syms *)alloc(n * sizeof(struct syms)); printf("+[%x+", hp->a_syms); for (i = 0; i < n; i++) { struct nlist nlist; if (read(fd, &nlist, sizeof(nlist)) != sizeof(nlist)) { printf("promsyms: read failed\n"); return; } syms[i].value = nlist.n_value; syms[i].index = nlist.n_un.n_strx - sizeof(strtablen); } sort(syms, n); if (read(fd, &strtablen, sizeof(strtablen)) != sizeof(strtablen)) { printf("promsym: read failed (strtablen)\n"); return; } if (strtablen < sizeof(strtablen)) { printf("promsym: string table corrupted\n"); return; } strtablen -= sizeof(strtablen); str = (char *)alloc(strtablen); printf("%x]", strtablen); if (read(fd, str, strtablen) != strtablen) { printf("promsym: read failed (strtab)\n"); return; } sprintf(buf, "%x %d %x loadsyms", syms, n, str); (promvec->pv_fortheval.v2_eval)(buf); } #endif