From a5179592ba50b7e5080adebb1be07ce96a3dc2ac Mon Sep 17 00:00:00 2001 From: rahnds Date: Wed, 30 Apr 1997 14:33:59 +0000 Subject: [PATCH] Newer bootloader from netbsd. This should work with non MCG Firmworks openfirmware. --- sys/arch/powerpc/stand/ofwboot/Locore.c | 477 +++++++++++++++++++++ sys/arch/powerpc/stand/ofwboot/Makefile | 54 +++ sys/arch/powerpc/stand/ofwboot/alloc.c | 217 ++++++++++ sys/arch/powerpc/stand/ofwboot/boot.c | 492 ++++++++++++++++++++++ sys/arch/powerpc/stand/ofwboot/cache.c | 22 + sys/arch/powerpc/stand/ofwboot/net.c | 152 +++++++ sys/arch/powerpc/stand/ofwboot/netif_of.c | 244 +++++++++++ sys/arch/powerpc/stand/ofwboot/ofdev.c | 339 +++++++++++++++ sys/arch/powerpc/stand/ofwboot/ofdev.h | 52 +++ sys/arch/powerpc/stand/ofwboot/ofwmagic.S | 74 ++++ sys/arch/powerpc/stand/ofwboot/openfirm.h | 55 +++ sys/arch/powerpc/stand/ofwboot/version | 5 + 12 files changed, 2183 insertions(+) create mode 100644 sys/arch/powerpc/stand/ofwboot/Locore.c create mode 100644 sys/arch/powerpc/stand/ofwboot/Makefile create mode 100644 sys/arch/powerpc/stand/ofwboot/alloc.c create mode 100644 sys/arch/powerpc/stand/ofwboot/boot.c create mode 100644 sys/arch/powerpc/stand/ofwboot/cache.c create mode 100644 sys/arch/powerpc/stand/ofwboot/net.c create mode 100644 sys/arch/powerpc/stand/ofwboot/netif_of.c create mode 100644 sys/arch/powerpc/stand/ofwboot/ofdev.c create mode 100644 sys/arch/powerpc/stand/ofwboot/ofdev.h create mode 100644 sys/arch/powerpc/stand/ofwboot/ofwmagic.S create mode 100644 sys/arch/powerpc/stand/ofwboot/openfirm.h create mode 100644 sys/arch/powerpc/stand/ofwboot/version diff --git a/sys/arch/powerpc/stand/ofwboot/Locore.c b/sys/arch/powerpc/stand/ofwboot/Locore.c new file mode 100644 index 00000000000..4887605d145 --- /dev/null +++ b/sys/arch/powerpc/stand/ofwboot/Locore.c @@ -0,0 +1,477 @@ +/* $NetBSD: Locore.c,v 1.1 1997/04/16 20:29:11 thorpej Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * 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 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. + */ + +#include +#include + +/* +#include "machine/cpu.h" +*/ + +static int (*openfirmware)(void *); + +static void setup __P((void)); + +#ifdef XCOFF_GLUE +asm (".text; .globl _entry; _entry: .long _start,0,0"); +#endif + +__dead void +_start(vpd, res, openfirm, arg, argl) + void *vpd; + int res; + int (*openfirm)(void *); + char *arg; + int argl; +{ + extern char etext[]; + +#ifdef FIRMWORKSBUGS + syncicache((void *)RELOC, etext - (char *)RELOC); +#endif + openfirmware = openfirm; /* Save entry to Open Firmware */ + setup(); + main(arg, argl); + exit(); +} + +__dead void +_rtt() +{ + static struct { + char *name; + int nargs; + int nreturns; + } args = { + "exit", + 0, + 0 + }; + + openfirmware(&args); + while (1); /* just in case */ +} + +int +OF_finddevice(name) + char *name; +{ + static struct { + char *name; + int nargs; + int nreturns; + char *device; + int phandle; + } args = { + "finddevice", + 1, + 1, + }; + + args.device = name; + if (openfirmware(&args) == -1) + return -1; + return args.phandle; +} + +int +OF_instance_to_package(ihandle) + int ihandle; +{ + static struct { + char *name; + int nargs; + int nreturns; + int ihandle; + int phandle; + } args = { + "instance-to-package", + 1, + 1, + }; + + args.ihandle = ihandle; + if (openfirmware(&args) == -1) + return -1; + return args.phandle; +} + +int +OF_getprop(handle, prop, buf, buflen) + int handle; + char *prop; + void *buf; + int buflen; +{ + static struct { + char *name; + int nargs; + int nreturns; + int phandle; + char *prop; + void *buf; + int buflen; + int size; + } args = { + "getprop", + 4, + 1, + }; + + args.phandle = handle; + args.prop = prop; + args.buf = buf; + args.buflen = buflen; + if (openfirmware(&args) == -1) + return -1; + return args.size; +} + +#ifdef __notyet__ /* Has a bug on FirePower */ +int +OF_setprop(handle, prop, buf, len) + int handle; + char *prop; + void *buf; + int len; +{ + static struct { + char *name; + int nargs; + int nreturns; + int phandle; + char *prop; + void *buf; + int len; + int size; + } args = { + "setprop", + 4, + 1, + }; + + args.phandle = handle; + args.prop = prop; + args.buf = buf; + args.len = len; + if (openfirmware(&args) == -1) + return -1; + return args.size; +} +#endif + +int +OF_open(dname) + char *dname; +{ + static struct { + char *name; + int nargs; + int nreturns; + char *dname; + int handle; + } args = { + "open", + 1, + 1, + }; + + args.dname = dname; + if (openfirmware(&args) == -1) + return -1; + return args.handle; +} + +void +OF_close(handle) + int handle; +{ + static struct { + char *name; + int nargs; + int nreturns; + int handle; + } args = { + "close", + 1, + 0, + }; + + args.handle = handle; + openfirmware(&args); +} + +int +OF_write(handle, addr, len) + int handle; + void *addr; + int len; +{ + static struct { + char *name; + int nargs; + int nreturns; + int ihandle; + void *addr; + int len; + int actual; + } args = { + "write", + 3, + 1, + }; + + args.ihandle = handle; + args.addr = addr; + args.len = len; + if (openfirmware(&args) == -1) + return -1; + return args.actual; +} + +int +OF_read(handle, addr, len) + int handle; + void *addr; + int len; +{ + static struct { + char *name; + int nargs; + int nreturns; + int ihandle; + void *addr; + int len; + int actual; + } args = { + "read", + 3, + 1, + }; + + args.ihandle = handle; + args.addr = addr; + args.len = len; + if (openfirmware(&args) == -1) + return -1; + return args.actual; +} + +int +OF_seek(handle, pos) + int handle; + u_quad_t pos; +{ + static struct { + char *name; + int nargs; + int nreturns; + int handle; + int poshi; + int poslo; + int status; + } args = { + "seek", + 3, + 1, + }; + + args.handle = handle; + args.poshi = (int)(pos >> 32); + args.poslo = (int)pos; + if (openfirmware(&args) == -1) + return -1; + return args.status; +} + +void * +OF_claim(virt, size, align) + void *virt; + u_int size; + u_int align; +{ + static struct { + char *name; + int nargs; + int nreturns; + void *virt; + u_int size; + u_int align; + void *baseaddr; + } args = { + "claim", + 3, + 1, + }; + +#ifdef FIRMWORKSBUGS + /* + * Bug with Firmworks OFW + */ + if (virt) + return virt; +#endif + args.virt = virt; + args.size = size; + args.align = align; + if (openfirmware(&args) == -1) + return (void *)-1; + return args.baseaddr; +} + +void +OF_release(virt, size) + void *virt; + u_int size; +{ + static struct { + char *name; + int nargs; + int nreturns; + void *virt; + u_int size; + } args = { + "release", + 2, + 0, + }; + + args.virt = virt; + args.size = size; + openfirmware(&args); +} + +int +OF_milliseconds() +{ + static struct { + char *name; + int nargs; + int nreturns; + int ms; + } args = { + "milliseconds", + 0, + 1, + }; + + openfirmware(&args); + return args.ms; +} + +#ifdef __notyet__ +void +OF_chain(virt, size, entry, arg, len) + void *virt; + u_int size; + void (*entry)(); + void *arg; + u_int len; +{ + static struct { + char *name; + int nargs; + int nreturns; + void *virt; + u_int size; + void (*entry)(); + void *arg; + u_int len; + } args = { + "chain", + 5, + 0, + }; + + args.virt = virt; + args.size = size; + args.entry = entry; + args.arg = arg; + args.len = len; + openfirmware(&args); +} +#else +void +OF_chain(virt, size, entry, arg, len) + void *virt; + u_int size; + void (*entry)(); + void *arg; + u_int len; +{ + /* + * This is a REALLY dirty hack till the firmware gets this going + */ + OF_release(virt, size); + entry(0, 0, openfirmware, arg, len); +} +#endif + +static int stdin; +static int stdout; + +static void +setup() +{ + int chosen; + + if ((chosen = OF_finddevice("/chosen")) == -1) + _rtt(); + if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != sizeof(stdin) + || OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != + sizeof(stdout)) + _rtt(); +} + +void +putchar(c) + int c; +{ + char ch = c; + + if (c == '\n') + putchar('\r'); + OF_write(stdout, &ch, 1); +} + +int +getchar() +{ + unsigned char ch; + int l; + + while ((l = OF_read(stdin, &ch, 1)) != 1) + if (l != -2) + return -1; + return ch; +} diff --git a/sys/arch/powerpc/stand/ofwboot/Makefile b/sys/arch/powerpc/stand/ofwboot/Makefile new file mode 100644 index 00000000000..9cc424b1083 --- /dev/null +++ b/sys/arch/powerpc/stand/ofwboot/Makefile @@ -0,0 +1,54 @@ +# $NetBSD: Makefile,v 1.2 1997/04/17 07:46:24 thorpej Exp $ + +S= ${.CURDIR}/../../../.. +R=../ + +PROG= ofwboot +SRCS= Locore.c boot.c ofdev.c net.c netif_of.c alloc.c cache.c +.PATH: ${S}/arch/powerpc/powerpc +SRCS+= ofwmagic.S +#CFLAGS+= -DDEBUG -DNETIF_DEBUG +NOMAN= +STRIPFLAG= +BINMODE= 444 +OBJCOPY?= objcopy +SAREL= +BINDIR= /usr/mdec + +NEWVERSWHAT= "OpenFirmware Boot" + +# For now... +RELOC= 20000 + +ENTRY= _start + +CPPFLAGS+= -I. -I${.CURDIR}/../../.. -I${.CURDIR}/../../../.. +CPPFLAGS+= -DRELOC=0x${RELOC} +CPPFLAGS+= -DFIRMWORKSBUGS +CPPFLAGS+= -DPOWERPC_BOOT_ELF +CPPFLAGS+= -DXCOFF_GLUE # for booting PCI Powermacs + +### find out what to use for libkern +KERN_AS= library +.include "${S}/lib/libkern/Makefile.inc" +LIBKERN= ${KERNLIB} + +### find out what to use for libz +Z_AS= library +.include "${S}/lib/libz/Makefile.inc" +LIBZ= ${ZLIB} + +### find out what to use for libsa +SA_AS= library +SAMISCMAKEFLAGS= SA_USE_CREAD=yes +.include "${S}/lib/libsa/Makefile.inc" +LIBSA= ${SALIB} + +${PROG}: ${OBJS} ${LIBSA} ${LIBZ} ${LIBKERN} + ${LD} -X -Ttext ${RELOC} -e ${ENTRY} -o ${PROG} \ + ${OBJS} ${LIBSA} ${LIBZ} ${LIBKERN} +# mv ${PROG} ${PROG}.elf +# ${OBJCOPY} --input-target=elf32-powerpc \ +# --output-target=xcoff-powermac ${PROG}.elf ${PROG}.xcf + +.include diff --git a/sys/arch/powerpc/stand/ofwboot/alloc.c b/sys/arch/powerpc/stand/ofwboot/alloc.c new file mode 100644 index 00000000000..23498613f48 --- /dev/null +++ b/sys/arch/powerpc/stand/ofwboot/alloc.c @@ -0,0 +1,217 @@ +/* $NetBSD: alloc.c,v 1.1 1997/04/16 20:29:16 thorpej Exp $ */ + +/* + * Copyright (c) 1997 Jason R. Thorpe. All rights reserved. + * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * 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 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. + */ + +/* + * Dynamic memory allocator suitable for use with OpenFirmware. + * + * Compile options: + * + * ALLOC_TRACE enable tracing of allocations/deallocations + * + * ALLOC_FIRST_FIT use a first-fit allocation algorithm, rather than + * the default best-fit algorithm. + * + * DEBUG enable debugging sanity checks. + */ + +#include +#include + +#include + +#include + +/* + * Each block actually has ALIGN(struct ml) + ALIGN(size) bytes allocated + * to it, as follows: + * + * 0 ... (sizeof(struct ml) - 1) + * allocated or unallocated: holds size of user-data part of block. + * + * sizeof(struct ml) ... (ALIGN(sizeof(struct ml)) - 1) + * allocated: unused + * unallocated: depends on packing of struct fl + * + * ALIGN(sizeof(struct ml)) ... (ALIGN(sizeof(struct ml)) + + * ALIGN(data size) - 1) + * allocated: user data + * unallocated: depends on packing of struct fl + * + * 'next' is only used when the block is unallocated (i.e. on the free list). + * However, note that ALIGN(sizeof(struct ml)) + ALIGN(data size) must + * be at least 'sizeof(struct fl)', so that blocks can be used as structures + * when on the free list. + */ + +/* + * Memory lists. + */ +struct ml { + unsigned size; + LIST_ENTRY(ml) list; +}; + +/* XXX - this is from NetBSD */ +#define LIST_HEAD_INITIALIZER(head) { NULL } + +LIST_HEAD(, ml) freelist = LIST_HEAD_INITIALIZER(freelist); +LIST_HEAD(, ml) allocatedlist = LIST_HEAD_INITIALIZER(allocatedlist); + +#define OVERHEAD ALIGN(sizeof (struct ml)) /* shorthand */ + +void * +alloc(size) + unsigned size; +{ + struct ml *f, *bestf; + unsigned bestsize = 0xffffffff; /* greater than any real size */ + char *help; + int failed; + +#ifdef ALLOC_TRACE + printf("alloc(%u)", size); +#endif + + /* + * Account for overhead now, so that we don't get an + * "exact fit" which doesn't have enough space. + */ + size = ALIGN(size) + OVERHEAD; + +#ifdef ALLOC_FIRST_FIT + /* scan freelist */ + for (f = freelist.lh_first; f != NULL && f->size < size; + f = f->list.le_next) + /* noop */ ; + bestf = f; + failed = (bestf == (struct fl *)0); +#else + /* scan freelist */ + f = freelist.lh_first; + while (f != NULL) { + if (f->size >= size) { + if (f->size == size) /* exact match */ + goto found; + + if (f->size < bestsize) { + /* keep best fit */ + bestf = f; + bestsize = f->size; + } + } + f = f->list.le_next; + } + + /* no match in freelist if bestsize unchanged */ + failed = (bestsize == 0xffffffff); +#endif + + if (failed) { /* nothing found */ + /* + * Allocate memory from the OpenFirmware, rounded + * to page size, and record the chunk size. + */ + size = roundup(size, NBPG); + help = OF_claim(0, size, NBPG); + if (help == (char *)-1) + panic("alloc: out of memory"); + + f = (struct ml *)help; + f->size = size; +#ifdef ALLOC_TRACE + printf("=%lx (new chunk size %u)\n", + (u_long)(help + OVERHEAD), f->f_size); +#endif + goto out; + } + + /* we take the best fit */ + f = bestf; + + found: + /* remove from freelist */ + LIST_REMOVE(f, list); + help = (char *)f; +#ifdef ALLOC_TRACE + printf("=%lx (origsize %u)\n", (u_long)(help + OVERHEAD), f->size); +#endif + out: + /* place on allocated list */ + LIST_INSERT_HEAD(&allocatedlist, f, list); + return (help + OVERHEAD); +} + +void +free(ptr, size) + void *ptr; + unsigned size; /* only for consistenct check */ +{ + register struct ml *a = (struct ml *)((char*)ptr - OVERHEAD); + +#ifdef ALLOC_TRACE + printf("free(%lx, %u) (origsize %u)\n", (u_long)ptr, size, a->size); +#endif +#ifdef DEBUG + if (size > a->size) + printf("free %u bytes @%lx, should be <=%u\n", + size, (u_long)ptr, a->size); +#endif + + /* Remove from allocated list, place on freelist. */ + LIST_REMOVE(a, list); + LIST_INSERT_HEAD(&freelist, a, list); +} + +void +freeall() +{ +#ifdef __notyet__ /* Firmware bug ?! */ + struct ml *m; + + /* Release chunks on freelist... */ + while ((m = freelist.lh_first) != NULL) { + LIST_REMOVE(m, list); + OF_release(m, m->size); + } + + /* ...and allocated list. */ + while ((m = allocatedlist.lh_first) != NULL) { + LIST_REMOVE(m, list); + OF_release(m, m->size); + } +#endif /* __notyet__ */ +} diff --git a/sys/arch/powerpc/stand/ofwboot/boot.c b/sys/arch/powerpc/stand/ofwboot/boot.c new file mode 100644 index 00000000000..2da4a5fe93b --- /dev/null +++ b/sys/arch/powerpc/stand/ofwboot/boot.c @@ -0,0 +1,492 @@ +/* $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; + +#ifdef POWERPC_BOOT_ELF +int elf_exec __P((int, Elf32_Ehdr *, u_int32_t *, void **)); +#endif + +#ifdef POWERPC_BOOT_AOUT +int aout_exec __P((int, struct exec *, u_int32_t *, void **)); +#endif + +static void +prom2boot(dev) + char *dev; +{ + char *cp, *lp = 0; + int handle; + char devtype[16]; + + for (cp = dev; *cp; cp++) + if (*cp == ':') + lp = cp; + if (!lp) + lp = cp; + *lp = 0; +} + +static void +parseargs(str, howtop) + char *str; + int *howtop; +{ + char *cp; + + /* Allow user to drop back to the PROM. */ + if (strcmp(str, "exit") == 0) + _rtt(); + + *howtop = 0; + for (cp = str; *cp; cp++) + if (*cp == ' ' || *cp == '-') + break; + if (!*cp) + return; + + *cp++ = 0; + while (*cp) { + switch (*cp++) { + case 'a': + *howtop |= RB_ASKNAME; + break; + case 's': + *howtop |= RB_SINGLE; + break; + case 'd': + *howtop |= RB_KDB; + debug = 1; + break; + } + } +} + +static void +chain(entry, args, esym) + void (*entry)(); + char *args; + void *esym; +{ + extern char end[]; + int l, machine_tag; + + freeall(); + + /* + * Stash pointer to end of symbol table after the argument + * strings. + */ + l = strlen(args) + 1; + 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 + + OF_chain((void *)RELOC, end - (char *)RELOC, entry, args, l); + panic("chain"); +} + +int +loadfile(fd, args) + int fd; + char *args; +{ + union { +#ifdef POWERPC_BOOT_AOUT + struct exec aout; +#endif +#ifdef POWERPC_BOOT_ELF + Elf32_Ehdr elf; +#endif + } hdr; + int rval; + u_int32_t entry; + void *esym; + + rval = 1; + esym = NULL; + + /* Load the header. */ + if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { + printf("read header: %s\n", strerror(errno)); + goto err; + } + + /* Determine file type, load kernel. */ +#ifdef POWERPC_BOOT_AOUT + if (N_BADMAG(hdr.aout) == 0 && N_GETMID(hdr.aout) == MID_POWERPC) { + rval = aout_exec(fd, &hdr.aout, &entry, &esym); + } else +#endif +#ifdef POWERPC_BOOT_ELF + if (IS_ELF(hdr.elf)) { + rval = elf_exec(fd, &hdr.elf, &entry, &esym); + } else +#endif + { + printf("unknown executable format\n"); + } + + if (rval) + goto err; + + printf(" start=0x%x\n", entry); + + close(fd); + + /* XXX this should be replaced w/ a mountroothook. */ + if (floppyboot) { + printf("Please insert root disk and press ENTER "); + getchar(); + printf("\n"); + } + + chain((void *)entry, args, esym); + /* NOTREACHED */ + + err: + close(fd); + return (rval); +} + +#ifdef POWERPC_BOOT_AOUT +int +aout_exec(fd, hdr, entryp, esymp) + int fd; + struct exec *hdr; + u_int32_t *entryp; + void **esymp; +{ + void *addr; + int n, *paddr; + + /* Display the load address (entry point) for a.out. */ + printf("Booting %s @ 0x%lx\n", opened_name, hdr->a_entry); + addr = (void *)(hdr->a_entry); + + /* + * Determine memory needed for kernel and allocate it from + * the firmware. + */ + n = hdr->a_text + hdr->a_data + hdr->a_bss + hdr->a_syms + sizeof(int); + if ((paddr = OF_claim(addr, n, 0)) == (int *)-1) + panic("cannot claim memory"); + + /* Load text. */ + lseek(fd, N_TXTOFF(*hdr), SEEK_SET); + printf("%lu", hdr->a_text); + if (read(fd, paddr, hdr->a_text) != hdr->a_text) { + printf("read text: %s\n", strerror(errno)); + return (1); + } + syncicache((void *)paddr, hdr->a_text); + + /* Load data. */ + printf("+%lu", hdr->a_data); + if (read(fd, (void *)paddr + hdr->a_text, hdr->a_data) != hdr->a_data) { + printf("read data: %s\n", strerror(errno)); + return (1); + } + + /* Zero BSS. */ + printf("+%lu", hdr->a_bss); + bzero((void *)paddr + hdr->a_text + hdr->a_data, hdr->a_bss); + + /* Symbols. */ + *esymp = paddr; + paddr = (int *)((void *)paddr + hdr->a_text + hdr->a_data + hdr->a_bss); + *paddr++ = hdr->a_syms; + if (hdr->a_syms) { + printf(" [%lu", hdr->a_syms); + if (read(fd, paddr, hdr->a_syms) != hdr->a_syms) { + printf("read symbols: %s\n", strerror(errno)); + return (1); + } + paddr = (int *)((void *)paddr + hdr->a_syms); + if (read(fd, &n, sizeof(int)) != sizeof(int)) { + printf("read symbols: %s\n", strerror(errno)); + return (1); + } + if (OF_claim((void *)paddr, n + sizeof(int), 0) == (void *)-1) + panic("cannot claim memory"); + *paddr++ = n; + if (read(fd, paddr, n - sizeof(int)) != n - sizeof(int)) { + printf("read symbols: %s\n", strerror(errno)); + return (1); + } + printf("+%d]", n - sizeof(int)); + *esymp = paddr + (n - sizeof(int)); + } + + *entryp = hdr->a_entry; + return (0); +} +#endif /* POWERPC_BOOT_AOUT */ + +#ifdef POWERPC_BOOT_ELF +int +elf_exec(fd, elf, entryp, esymp) + int fd; + Elf32_Ehdr *elf; + u_int32_t *entryp; + void **esymp; +{ + Elf32_Shdr *shp; + Elf32_Off off; + void *addr; + size_t size; + int i, first = 1; + int n; + + /* + * Don't display load address for ELF; it's encoded in + * each section. + */ + printf("Booting %s\n", opened_name); + + for (i = 0; i < elf->e_phnum; i++) { + Elf32_Phdr phdr; + (void)lseek(fd, elf->e_phoff + sizeof(phdr) * i, SEEK_SET); + if (read(fd, (void *)&phdr, sizeof(phdr)) != sizeof(phdr)) { + printf("read phdr: %s\n", strerror(errno)); + return (1); + } + if (phdr.p_type != PT_LOAD || + (phdr.p_flags & (PF_W|PF_X)) == 0) + continue; + + /* Read in segment. */ + printf("%s%lu@0x%lx", first ? "" : "+", phdr.p_filesz, + (u_long)phdr.p_vaddr); + (void)lseek(fd, phdr.p_offset, SEEK_SET); + if (OF_claim((void *)phdr.p_vaddr, phdr.p_memsz, 0) == + (void *)-1) + panic("cannot claim memory"); + if (read(fd, (void *)phdr.p_vaddr, phdr.p_filesz) != + phdr.p_filesz) { + printf("read segment: %s\n", strerror(errno)); + return (1); + } + syncicache((void *)phdr.p_vaddr, phdr.p_filesz); + + /* Zero BSS. */ + if (phdr.p_filesz < phdr.p_memsz) { + printf("+%lu@0x%lx", phdr.p_memsz - phdr.p_filesz, + (u_long)(phdr.p_vaddr + phdr.p_filesz)); + bzero(phdr.p_vaddr + phdr.p_filesz, + phdr.p_memsz - phdr.p_filesz); + } + first = 0; + } + + printf(" \n"); + +#if 0 /* I want to rethink this... --thorpej@netbsd.org */ + /* + * Compute the size of the symbol table. + */ + size = sizeof(Elf32_Ehdr) + (elf->e_shnum * sizeof(Elf32_Shdr)); + shp = addr = alloc(elf->e_shnum * sizeof(Elf32_Shdr)); + (void)lseek(fd, elf->e_shoff, SEEK_SET); + if (read(fd, addr, elf->e_shnum * sizeof(Elf32_Shdr)) != + elf->e_shnum * sizeof(Elf32_Shdr)) { + printf("read section headers: %s\n", strerror(errno)); + return (1); + } + for (i = 0; i < elf->e_shnum; i++, shp++) { + if (shp->sh_type == Elf32_sht_null) + continue; + if (shp->sh_type != Elf32_sht_symtab + && shp->sh_type != Elf32_sht_strtab) { + shp->sh_offset = 0; + shp->sh_type = Elf32_sht_nobits; + continue; + } + size += shp->sh_size; + } + shp = addr; + + /* + * Reserve memory for the symbols. + */ + if ((addr = OF_claim(0, size, NBPG)) == (void *)-1) + panic("no space for symbol table"); + + /* + * Copy the headers. + */ + elf->e_phoff = 0; + elf->e_shoff = sizeof(Elf32_Ehdr); + elf->e_phentsize = 0; + elf->e_phnum = 0; + bcopy(elf, addr, sizeof(Elf32_Ehdr)); + bcopy(shp, addr + sizeof(Elf32_Ehdr), elf->e_shnum * sizeof(Elf32_Shdr)); + free(shp, elf->e_shnum * sizeof(Elf32_Shdr)); + *ssymp = addr; + + /* + * Now load the symbol sections themselves. + */ + shp = addr + sizeof(Elf32_Ehdr); + addr += sizeof(Elf32_Ehdr) + (elf->e_shnum * sizeof(Elf32_Shdr)); + off = sizeof(Elf32_Ehdr) + (elf->e_shnum * sizeof(Elf32_Shdr)); + for (first = 1, i = 0; i < elf->e_shnum; i++, shp++) { + if (shp->sh_type == Elf32_sht_symtab + || shp->sh_type == Elf32_sht_strtab) { + if (first) + printf("symbols @ 0x%lx ", (u_long)addr); + printf("%s%d", first ? "" : "+", shp->sh_size); + (void)lseek(fd, shp->sh_offset, SEEK_SET); + if (read(fd, addr, shp->sh_size) != shp->sh_size) { + printf("read symbols: %s\n", strerror(errno)); + return (1); + } + addr += shp->sh_size; + shp->sh_offset = off; + off += shp->sh_size; + first = 0; + } + } + *esymp = addr; +#endif /* 0 */ + + *entryp = elf->e_entry; + return (0); +} +#endif /* POWERPC_BOOT_ELF */ + +void +main() +{ + int chosen; + char bootline[512]; /* Should check size? */ + char *cp; + int fd; + + printf("\n>> OpenBSD/powerpc Boot\n"); + + /* + * Get the boot arguments from Openfirmware + */ + if ((chosen = OF_finddevice("/chosen")) == -1 + || OF_getprop(chosen, "bootpath", bootdev, sizeof bootdev) < 0 + || OF_getprop(chosen, "bootargs", bootline, sizeof bootline) < 0) { + printf("Invalid Openfirmware environment\n"); + exit(); + } + prom2boot(bootdev); + parseargs(bootline, &boothowto); + for (;;) { + if (boothowto & RB_ASKNAME) { + printf("Boot: "); + gets(bootline); + parseargs(bootline, &boothowto); + } + if ((fd = open(bootline, 0)) >= 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 = bootline; +#else + strcpy(bootline, opened_name); + cp = bootline + strlen(bootline); + *cp++ = ' '; +#endif + *cp = '-'; + if (boothowto & RB_ASKNAME) + *++cp = 'a'; + 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", bootline, strlen(bootline) + 1); +#endif + /* XXX void, for now */ + (void)loadfile(fd, bootline); + + _rtt(); +} diff --git a/sys/arch/powerpc/stand/ofwboot/cache.c b/sys/arch/powerpc/stand/ofwboot/cache.c new file mode 100644 index 00000000000..c40dead4394 --- /dev/null +++ b/sys/arch/powerpc/stand/ofwboot/cache.c @@ -0,0 +1,22 @@ +#define CACHELINESIZE 32 /* For now XXX */ + +void +syncicache(from, len) + void *from; + int len; +{ + int l = len; + void *p = from; + + do { + asm volatile ("dcbst 0,%0" :: "r"(p)); + p += CACHELINESIZE; + } while ((l -= CACHELINESIZE) > 0); + asm volatile ("sync"); + do { + asm volatile ("icbi 0,%0" :: "r"(from)); + from += CACHELINESIZE; + } while ((len -= CACHELINESIZE) > 0); + asm volatile ("isync"); +} + diff --git a/sys/arch/powerpc/stand/ofwboot/net.c b/sys/arch/powerpc/stand/ofwboot/net.c new file mode 100644 index 00000000000..247598e7624 --- /dev/null +++ b/sys/arch/powerpc/stand/ofwboot/net.c @@ -0,0 +1,152 @@ +/* $NetBSD: net.c,v 1.1 1997/04/16 20:29:18 thorpej Exp $ */ + +/* + * Copyright (C) 1995 Wolfgang Solfrank. + * Copyright (C) 1995 TooLs GmbH. + * 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 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. + */ + +/* + * This module implements a "raw device" interface suitable for + * use by the stand-alone I/O library NFS code. This interface + * does not support any "block" access, and exists only for the + * purpose of initializing the network interface, getting boot + * parameters, and performing the NFS mount. + * + * At open time, this does: + * + * find interface - netif_open() + * BOOTP - bootp() + * RPC/mountd - nfs_mount() + * + * The root file handle from mountd is saved in a global + * for use by the NFS open code (NFS/lookup). + * + * Note: this is based in part on sys/arch/sparc/stand/net.c + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +char rootpath[FNAME_SIZE]; + +static int netdev_sock = -1; +static int open_count; + +/* + * Called by devopen after it sets f->f_dev to our devsw entry. + * This opens the low-level device and sets f->f_devdata. + */ +int +net_open(op) + struct of_dev *op; +{ + int error = 0; + + /* + * On first open, do netif open, mount, etc. + */ + if (open_count == 0) { + /* Find network interface. */ + if ((netdev_sock = netif_open(op)) < 0) { + error = errno; + goto bad; + } + if ((error = net_mountroot()) != 0) + goto bad; + } + open_count++; +bad: + if (netdev_sock >= 0 && open_count == 0) { + netif_close(netdev_sock); + netdev_sock = -1; + } + return error; +} + +int +net_close(op) + struct of_dev *op; +{ + /* + * On last close, do netif close, etc. + */ + if (open_count > 0) + if (--open_count == 0) { + netif_close(netdev_sock); + netdev_sock = -1; + } +} + +int +net_mountroot() +{ + +#ifdef DEBUG + printf("net_mountroot\n"); +#endif + + /* + * Get info for NFS boot: our IP address, out hostname, + * server IP address, and our root path on the server. + * We use BOOTP (RFC951, RFC1532) exclusively as mandated + * by PowerPC Reference Platform Specification I.4.2 + */ + + bootp(netdev_sock); + + if (myip.s_addr == 0) + return ETIMEDOUT; + + printf("Using IP address: %s\n", inet_ntoa(myip)); + +#ifdef DEBUG + printf("myip: %s (%s)", hostname, inet_ntoa(myip)); + if (gateip.s_addr) + printf(", gateip: %s", inet_ntoa(gateip)); + if (netmask) + printf(", netmask: %s", intoa(netmask)); + printf("\n"); +#endif + printf("root addr=%s path=%s\n", inet_ntoa(rootip), rootpath); + + /* + * Get the NFS file handle (mount). + */ + if (nfs_mount(netdev_sock, rootip, rootpath) < 0) + return errno; + return 0; +} diff --git a/sys/arch/powerpc/stand/ofwboot/netif_of.c b/sys/arch/powerpc/stand/ofwboot/netif_of.c new file mode 100644 index 00000000000..27df48e0eb0 --- /dev/null +++ b/sys/arch/powerpc/stand/ofwboot/netif_of.c @@ -0,0 +1,244 @@ +/* $NetBSD: netif_of.c,v 1.1 1997/04/16 20:29:19 thorpej Exp $ */ + +/* + * Copyright (C) 1995 Wolfgang Solfrank. + * Copyright (C) 1995 TooLs GmbH. + * 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 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. + */ + +/* + * Open Firmware does most of the job for interfacing to the hardware, + * so it is easiest to just replace the netif module with + * this adaptation to the PROM network interface. + * + * Note: this is based in part on sys/arch/sparc/stand/netif_sun.c + */ + +#include +#include + +#if 0 /* XXX thorpej */ +#include +#include +#endif + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +static struct netif netif_of; + +struct iodesc sockets[SOPEN_MAX]; + +struct iodesc * +socktodesc(sock) + int sock; +{ + if (sock != 0) + return NULL; + return sockets; +} + +int +netif_open(machdep_hint) + void *machdep_hint; +{ + struct of_dev *op = machdep_hint; + struct iodesc *io; + int fd, error; + char addr[32]; + +#ifdef NETIF_DEBUG + printf("netif_open..."); +#endif + /* find a free socket */ + io = sockets; + if (io->io_netif) { +#ifdef NETIF_DEBUG + printf("device busy\n"); +#endif + errno = ENFILE; + return -1; + } + bzero(io, sizeof *io); + + netif_of.nif_devdata = op; + io->io_netif = &netif_of; + + /* Put our ethernet address in io->myea */ + OF_getprop(OF_instance_to_package(op->handle), + "mac-address", io->myea, sizeof io->myea); + +#ifdef NETIF_DEBUG + printf("OK\n"); +#endif + return 0; +} + +int +netif_close(fd) + int fd; +{ + struct iodesc *io; + struct netif *ni; + +#ifdef NETIF_DEBUG + printf("netif_close(%x)...", fd); +#endif + if (fd != 0) { +#ifdef NETIF_DEBUG + printf("EBADF\n"); +#endif + errno = EBADF; + return -1; + } + + io = &sockets[fd]; + ni = io->io_netif; + if (ni != NULL) { + ni->nif_devdata = NULL; + io->io_netif = NULL; + } +#ifdef NETIF_DEBUG + printf("OK\n"); +#endif + return 0; +} + +/* + * Send a packet. The ether header is already there. + * Return the length sent (or -1 on error). + */ +ssize_t +netif_put(desc, pkt, len) + struct iodesc *desc; + void *pkt; + size_t len; +{ + struct of_dev *op; + ssize_t rv; + size_t sendlen; + + op = desc->io_netif->nif_devdata; + +#ifdef NETIF_DEBUG + { + struct ether_header *eh; + + printf("netif_put: desc=0x%x pkt=0x%x len=%d\n", + desc, pkt, len); + eh = pkt; + printf("dst: %s ", ether_sprintf(eh->ether_dhost)); + printf("src: %s ", ether_sprintf(eh->ether_shost)); + printf("type: 0x%x\n", eh->ether_type & 0xFFFF); + } +#endif + + sendlen = len; + if (sendlen < 60) { + sendlen = 60; +#ifdef NETIF_DEBUG + printf("netif_put: length padded to %d\n", sendlen); +#endif + } + + rv = OF_write(op->handle, pkt, sendlen); + +#ifdef NETIF_DEBUG + printf("netif_put: xmit returned %d\n", rv); +#endif + + return rv; +} + +/* + * Receive a packet, including the ether header. + * Return the total length received (or -1 on error). + */ +ssize_t +netif_get(desc, pkt, maxlen, timo) + struct iodesc *desc; + void *pkt; + size_t maxlen; + time_t timo; +{ + struct of_dev *op; + int tick0, tmo_ms; + int len; + + op = desc->io_netif->nif_devdata; + +#ifdef NETIF_DEBUG + printf("netif_get: pkt=0x%x, maxlen=%d, tmo=%d\n", + pkt, maxlen, timo); +#endif + + tmo_ms = timo * 1000; + tick0 = OF_milliseconds(); + + do { + len = OF_read(op->handle, pkt, maxlen); + } while ((len == -2) && ((OF_milliseconds() - tick0) < tmo_ms)); + +#ifdef NETIF_DEBUG + printf("netif_get: received len=%d\n", len); +#endif + + if (len < 12) + return -1; + +#ifdef NETIF_DEBUG + { + struct ether_header *eh = pkt; + + printf("dst: %s ", ether_sprintf(eh->ether_dhost)); + printf("src: %s ", ether_sprintf(eh->ether_shost)); + printf("type: 0x%x\n", eh->ether_type & 0xFFFF); + } +#endif + + return len; +} + +/* + * Shouldn't really be here, but is used solely for networking, so... + */ +time_t +getsecs() +{ + return OF_milliseconds() / 1000; +} diff --git a/sys/arch/powerpc/stand/ofwboot/ofdev.c b/sys/arch/powerpc/stand/ofwboot/ofdev.c new file mode 100644 index 00000000000..5f6bebab1df --- /dev/null +++ b/sys/arch/powerpc/stand/ofwboot/ofdev.c @@ -0,0 +1,339 @@ +/* $NetBSD: ofdev.c,v 1.1 1997/04/16 20:29:20 thorpej Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * 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 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. + */ +/* + * Device I/O routines using Open Firmware + */ +#include +#include +#include + +#include +#include +#include +#include + +#include + +extern char bootdev[]; + +static char * +filename(str, ppart) + char *str; + char *ppart; +{ + char *cp, *lp; + char savec; + int dhandle; + char devtype[16]; + + lp = str; + devtype[0] = 0; + *ppart = 0; + for (cp = str; *cp; lp = cp) { + /* For each component of the path name... */ + while (*++cp && *cp != '/'); + savec = *cp; + *cp = 0; + /* ...look whether there is a device with this name */ + dhandle = OF_finddevice(str); + *cp = savec; + if (dhandle == -1) { + /* if not, lp is the delimiter between device and path */ + /* if the last component was a block device... */ + if (!strcmp(devtype, "block")) { + /* search for arguments */ + for (cp = lp; + --cp >= str && *cp != '/' && *cp != ':';); + if (cp >= str && *cp == ':') { + /* found arguments, make firmware ignore them */ + *cp = 0; + for (cp = lp; *--cp && *cp != ',';); + if (*++cp >= 'a' && *cp <= 'a' + MAXPARTITIONS) + *ppart = *cp; + } + } + return lp; + } else if (OF_getprop(dhandle, "device_type", devtype, sizeof devtype) < 0) + devtype[0] = 0; + } + return 0; +} + +static int +strategy(devdata, rw, blk, size, buf, rsize) + void *devdata; + int rw; + daddr_t blk; + size_t size; + void *buf; + size_t *rsize; +{ + struct of_dev *dev = devdata; + u_quad_t pos; + int n; + + if (rw != F_READ) + return EPERM; + if (dev->type != OFDEV_DISK) + panic("strategy"); + + pos = (u_quad_t)(blk + dev->partoff) * dev->bsize; + + for (;;) { + if (OF_seek(dev->handle, pos) < 0) + break; + n = OF_read(dev->handle, buf, size); + if (n == -2) + continue; + if (n < 0) + break; + *rsize = n; + return 0; + } + return EIO; +} + +static int +devclose(of) + struct open_file *of; +{ + struct of_dev *op = of->f_devdata; + + if (op->type == OFDEV_NET) + net_close(op); + OF_close(op->handle); + op->handle = -1; +} + +static struct devsw devsw[1] = { + "OpenFirmware", + strategy, + (int (*)__P((struct open_file *, ...)))nodev, + devclose, + noioctl +}; +int ndevs = sizeof devsw / sizeof devsw[0]; + +static struct fs_ops file_system_ufs = { + ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat +}; +static struct fs_ops file_system_cd9660 = { + cd9660_open, cd9660_close, cd9660_read, cd9660_write, cd9660_seek, + cd9660_stat +}; +static struct fs_ops file_system_nfs = { + nfs_open, nfs_close, nfs_read, nfs_write, nfs_seek, nfs_stat +}; + +struct fs_ops file_system[3]; +int nfsys; + +static struct of_dev ofdev = { + -1, +}; + +char opened_name[256]; +int floppyboot; + +static u_long +get_long(p) + const void *p; +{ + const unsigned char *cp = p; + + return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24); +} + +/* + * Find a valid disklabel. + */ +static int +search_label(devp, off, buf, lp, off0) + struct of_dev *devp; + u_long off; + char *buf; + struct disklabel *lp; + u_long off0; +{ + size_t read; + struct mbr_partition *p; + int i; + u_long poff; + static int recursion; + + if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read) + || read != DEV_BSIZE) + return ERDLAB; + + if (buf[510] != 0x55 || buf[511] != 0xaa) + return ERDLAB; + + if (recursion++ <= 1) + off0 += off; + for (p = (struct mbr_partition *)(buf + MBRPARTOFF), i = 4; + --i >= 0; p++) { + if (p->mbr_type == MBR_NETBSD) { + poff = get_long(&p->mbr_start) + off0; + if (strategy(devp, F_READ, poff + LABELSECTOR, + DEV_BSIZE, buf, &read) == 0 + && read == DEV_BSIZE) { + if (!getdisklabel(buf, lp)) { + recursion--; + return 0; + } + } + if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read) + || read != DEV_BSIZE) { + recursion--; + return ERDLAB; + } + } else if (p->mbr_type == MBR_EXTENDED) { + poff = get_long(&p->mbr_start); + if (!search_label(devp, poff, buf, lp, off0)) { + recursion--; + return 0; + } + if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read) + || read != DEV_BSIZE) { + recursion--; + return ERDLAB; + } + } + } + recursion--; + return ERDLAB; +} + +int +devopen(of, name, file) + struct open_file *of; + const char *name; + char **file; +{ + char *cp; + char partition; + char fname[256]; + char buf[DEV_BSIZE]; + struct disklabel label; + int handle, part; + size_t read; + int error = 0; + + if (ofdev.handle != -1) + panic("devopen"); + if (of->f_flags != F_READ) + return EPERM; + strcpy(fname, name); + cp = filename(fname, &partition); + if (cp) { + strcpy(buf, cp); + *cp = 0; + } + if (!cp || !*buf) + strcpy(buf, DEFAULT_KERNEL); + if (!*fname) + strcpy(fname, bootdev); + strcpy(opened_name, fname); + if (partition) { + cp = opened_name + strlen(opened_name); + *cp++ = ':'; + *cp++ = partition; + *cp = 0; + } + if (*buf != '/') + strcat(opened_name, "/"); + strcat(opened_name, buf); + *file = opened_name + strlen(fname) + 1; + if ((handle = OF_finddevice(fname)) == -1) + return ENOENT; + if (OF_getprop(handle, "name", buf, sizeof buf) < 0) + return ENXIO; + floppyboot = !strcmp(buf, "floppy"); + if (OF_getprop(handle, "device_type", buf, sizeof buf) < 0) + return ENXIO; + if (!strcmp(buf, "block")) + /* For block devices, indicate raw partition (:0 in OpenFirmware) */ + strcat(fname, ":0"); + if ((handle = OF_open(fname)) == -1) + return ENXIO; + bzero(&ofdev, sizeof ofdev); + ofdev.handle = handle; + if (!strcmp(buf, "block")) { + ofdev.type = OFDEV_DISK; + ofdev.bsize = DEV_BSIZE; + /* First try to find a disklabel without MBR partitions */ + if (strategy(&ofdev, F_READ, + LABELSECTOR, DEV_BSIZE, buf, &read) != 0 + || read != DEV_BSIZE + || getdisklabel(buf, &label)) { + /* Else try MBR partitions */ + error = search_label(&ofdev, 0, buf, &label, 0); + if (error && error != ERDLAB) + goto bad; + } + + if (error == ERDLAB) { + if (partition) + /* User specified a parititon, but there is none */ + goto bad; + /* No, label, just use complete disk */ + ofdev.partoff = 0; + } else { + part = partition ? partition - 'a' : 0; + ofdev.partoff = label.d_partitions[part].p_offset; + } + + of->f_dev = devsw; + of->f_devdata = &ofdev; + bcopy(&file_system_ufs, file_system, sizeof file_system[0]); + bcopy(&file_system_cd9660, file_system + 1, + sizeof file_system[0]); + nfsys = 2; + return 0; + } + if (!strcmp(buf, "network")) { + ofdev.type = OFDEV_NET; + of->f_dev = devsw; + of->f_devdata = &ofdev; + bcopy(&file_system_nfs, file_system, sizeof file_system[0]); + nfsys = 1; + if (error = net_open(&ofdev)) + goto bad; + return 0; + } + error = EFTYPE; +bad: + OF_close(handle); + ofdev.handle = -1; + return error; +} diff --git a/sys/arch/powerpc/stand/ofwboot/ofdev.h b/sys/arch/powerpc/stand/ofwboot/ofdev.h new file mode 100644 index 00000000000..63349eaad03 --- /dev/null +++ b/sys/arch/powerpc/stand/ofwboot/ofdev.h @@ -0,0 +1,52 @@ +/* $NetBSD: ofdev.h,v 1.1 1997/04/16 20:29:22 thorpej Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * 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 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. + */ +#ifndef _STAND_DEV_H_ +#define _STAND_DEV_H_ + +struct of_dev { + int handle; + int type; + u_long partoff; + int bsize; +}; + +/* Known types: */ +#define OFDEV_NET 1 +#define OFDEV_DISK 2 + +#define DEFAULT_KERNEL "/bsd" + +extern char opened_name[]; +extern int floppyboot; + +#endif diff --git a/sys/arch/powerpc/stand/ofwboot/ofwmagic.S b/sys/arch/powerpc/stand/ofwboot/ofwmagic.S new file mode 100644 index 00000000000..4851e50eb99 --- /dev/null +++ b/sys/arch/powerpc/stand/ofwboot/ofwmagic.S @@ -0,0 +1,74 @@ +/* $NetBSD: ofwmagic.S,v 1.1 1997/04/16 21:19:00 thorpej Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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. + */ + +/* + * Magic note section used by OpenFirmware. + */ + + .section ".note" + + # note header + + # length of name + .long 8 + + # note descriptor size + .long 20 + + # note type (IEEE 1275) + .long 0x1275 + + # name of owner + .asciz "PowerPC" + .balign 4 + + + # note descriptor + + # real mode (-1) or virtual mode (0) + .long 0 + + # real-base + .long -1 + # real-size + .long -1 + + # virt-base + .long -1 + # virt-size + .long -1 diff --git a/sys/arch/powerpc/stand/ofwboot/openfirm.h b/sys/arch/powerpc/stand/ofwboot/openfirm.h new file mode 100644 index 00000000000..3bbcd737378 --- /dev/null +++ b/sys/arch/powerpc/stand/ofwboot/openfirm.h @@ -0,0 +1,55 @@ +/* $NetBSD: openfirm.h,v 1.1 1997/04/16 20:29:23 thorpej Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * 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 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. + */ +/* + * Prototypes for Openfirmware Interface Routines + */ + +#include +#include + +int OF_finddevice __P((char *name)); +int OF_instance_to_package __P((int ihandle)); +int OF_getprop __P((int handle, char *prop, void *buf, int buflen)); +#ifdef __notyet__ +int OF_setprop __P((int handle, char *prop, void *buf, int len)); +#endif +int OF_open __P((char *dname)); +void OF_close __P((int handle)); +int OF_write __P((int handle, void *addr, int len)); +int OF_read __P((int handle, void *addr, int len)); +int OF_seek __P((int handle, u_quad_t pos)); +void *OF_claim __P((void *virt, u_int size, u_int align)); +void OF_release __P((void *virt, u_int size)); +int OF_milliseconds __P((void)); +void OF_chain __P((void *addr, u_int size, void (*entry)(), void *parm, u_int parmlen)); + diff --git a/sys/arch/powerpc/stand/ofwboot/version b/sys/arch/powerpc/stand/ofwboot/version new file mode 100644 index 00000000000..9c0dad2a0c6 --- /dev/null +++ b/sys/arch/powerpc/stand/ofwboot/version @@ -0,0 +1,5 @@ +$NetBSD: version,v 1.3 1997/04/19 01:40:08 thorpej Exp $ + +1.1: Boot program for OpenFirmware; initial revision +1.2: Boot program rearrangement +1.3: Added support for loading ELF kernels -- 2.20.1