diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /sys/arch/sparc/stand |
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/sparc/stand')
-rw-r--r-- | sys/arch/sparc/stand/Makefile | 36 | ||||
-rw-r--r-- | sys/arch/sparc/stand/Makefile.inc | 30 | ||||
-rw-r--r-- | sys/arch/sparc/stand/binstall.sh | 120 | ||||
-rw-r--r-- | sys/arch/sparc/stand/boot.c | 261 | ||||
-rw-r--r-- | sys/arch/sparc/stand/boot/Makefile | 18 | ||||
-rw-r--r-- | sys/arch/sparc/stand/bootxx.c | 125 | ||||
-rw-r--r-- | sys/arch/sparc/stand/bootxx/Makefile | 24 | ||||
-rw-r--r-- | sys/arch/sparc/stand/conf.c | 46 | ||||
-rw-r--r-- | sys/arch/sparc/stand/dvma.c | 119 | ||||
-rw-r--r-- | sys/arch/sparc/stand/installboot.8 | 140 | ||||
-rw-r--r-- | sys/arch/sparc/stand/installboot.c | 389 | ||||
-rw-r--r-- | sys/arch/sparc/stand/installboot/Makefile | 11 | ||||
-rw-r--r-- | sys/arch/sparc/stand/net.c | 157 | ||||
-rw-r--r-- | sys/arch/sparc/stand/netif_sun.c | 219 | ||||
-rw-r--r-- | sys/arch/sparc/stand/promdev.c | 792 | ||||
-rw-r--r-- | sys/arch/sparc/stand/promdev.h | 82 | ||||
-rw-r--r-- | sys/arch/sparc/stand/srt0.S | 188 | ||||
-rw-r--r-- | sys/arch/sparc/stand/version.c | 41 |
18 files changed, 2798 insertions, 0 deletions
diff --git a/sys/arch/sparc/stand/Makefile b/sys/arch/sparc/stand/Makefile new file mode 100644 index 00000000000..5d3bd616240 --- /dev/null +++ b/sys/arch/sparc/stand/Makefile @@ -0,0 +1,36 @@ +# $NetBSD: Makefile,v 1.10 1995/10/09 23:25:54 pk Exp $ + +SUBDIR= boot bootxx installboot + +### find out what to use for libkern and libsa +SAREL= +KERNREL= +.include "Makefile.inc" +.include "$S/lib/libsa/Makefile.inc" +.include "$S/lib/libkern/Makefile.inc" + +all: ${SALIB} ${KERNLIB} _SUBDIRUSE + +libdep: + @echo ${.OBJDIR}/${SALIB} ${.OBJDIR}/${KERNLIB} + +sadep: + @echo ${.OBJDIR}/${SALIB} + +kernlibdir: + @echo ${.OBJDIR}/${KERNDST} + +salibdir: + @echo ${.OBJDIR}/${SADST} + +clean:: _SUBDIRUSE + +cleandir: _SUBDIRUSE + +BINDIR=/usr/mdec + +afterinstall: + install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ + ${.CURDIR}/binstall.sh ${DESTDIR}${BINDIR}/binstall + +.include <bsd.subdir.mk> diff --git a/sys/arch/sparc/stand/Makefile.inc b/sys/arch/sparc/stand/Makefile.inc new file mode 100644 index 00000000000..a083047b0d1 --- /dev/null +++ b/sys/arch/sparc/stand/Makefile.inc @@ -0,0 +1,30 @@ +# $NetBSD: Makefile.inc,v 1.4 1995/10/09 23:25:55 pk Exp $ + +.if !defined(__stand_makefile_inc) +__stand_makefile_inc=1 + +S= ${.CURDIR}/../../../${R} + +.if !make(libdep) && !make(sadep) && !make(salibdir) && !make(kernlibdir) +.BEGIN: + @([ -h machine ] || ln -s ${S}/arch/${MACHINE}/include machine) +.endif + +RELOC_SUN4= 0x240000 +RELOC_SUN4C= 0x340000 +RELOC_SUN4M= 0x440000 + +# Note: a `RELOC' value of 0x340000 seems to work on most machines +RELOC?= ${RELOC_SUN4C} + +INCLUDES+= -I. -I${.CURDIR}/.. -I${S}/arch -I${S} -I${S}/lib/libsa +DEFS+= -DSTANDALONE -DRELOC=${RELOC} -DSUN4 -DSUN4C -DSUN_BOOTPARAMS +CFLAGS+= -O2 ${INCLUDES} ${DEFS} + +srt0.o: srt0.S + ${CC} ${CFLAGS} -DLOCORE -c ${.IMPSRC} + +cleandir: + rm -rf lib machine + +.endif diff --git a/sys/arch/sparc/stand/binstall.sh b/sys/arch/sparc/stand/binstall.sh new file mode 100644 index 00000000000..d3fcad7caa6 --- /dev/null +++ b/sys/arch/sparc/stand/binstall.sh @@ -0,0 +1,120 @@ +#!/bin/sh +# $NetBSD: binstall.sh,v 1.1.2.1 1995/10/13 19:55:03 pk Exp $ +# + +vecho () { +# echo if VERBOSE on + if [ "$VERBOSE" = "1" ]; then + echo "$@" 1>&2 + fi + return 0 +} + +Usage () { + echo "Usage: $0 [-hvt] [-m<path>] net|ffs directory" + exit 1 +} + +Help () { + echo "This script copies the boot programs to one of several" + echo "commonly used places. It takes care of stripping the" + echo "a.out(5) header off the installed boot program on sun4 machines." + echo "When installing an \"ffs\" boot program, this script also runs" + echo "installboot(8) which installs the default proto bootblocks into" + echo "the appropriate filesystem partition." + echo "Options:" + echo " -h - display this message" + echo " -m<path> - Look for boot programs in <path> (default: /usr/mdec)" + echo " -v - verbose mode" + echo " -t - test mode (implies -v)" + exit 0 +} + + +PATH=/bin:/usr/bin:/sbin:/usr/sbin +MDEC=${MDEC:-/usr/mdec} + +set -- `getopt "hm:tv" "$@"` +if [ $? -gt 0 ]; then + Usage +fi + +for a in $* +do + case $1 in + -h) Help; shift ;; + -m) MDEC=$2; shift 2 ;; + -t) TEST=1; VERBOSE=1; shift ;; + -v) VERBOSE=1; shift ;; + --) shift; break ;; + esac +done + +DOIT=${TEST:+echo "=>"} + +if [ $# != 2 ]; then + Usage +fi + +WHAT=$1 +DEST=$2 + +if [ "`sysctl -n hw.model | cut -b1-5`" = "SUN/4" ]; then + KARCH=sun4 +else + KARCH=sun4c +fi +vecho "Kernel architecture: $KARCH" + +if [ ! -d $DEST ]; then + echo "$DEST: not a directory" + Usage +fi + + +if [ $KARCH = sun4 ]; then SKIP=1; else SKIP=0; fi + + +case $WHAT in +"ffs") + DEV=`mount | while read line; do + set -- $line + vecho "Inspecting \"$line\"" + if [ "$2" = "on" -a "$3" = "$DEST" ]; then + if [ ! -b $1 ]; then + continue + fi + RAW=\`echo -n "$1" | sed -e 's;/dev/;/dev/r;'\` + if [ ! -c \$RAW ]; then + continue + fi + echo -n $RAW + break; + fi + done` + if [ "$DEV" = "" ]; then + echo "Cannot find \"$DEST\" in mount table" + exit 1 + fi + TARGET=$DEST/boot + vecho Boot device: $DEV + vecho Target: $TARGET + $DOIT dd if=${MDEC}/boot of=$TARGET skip=$SKIP bs=32 + sync; sync; sync + vecho installboot ${VERBOSE:+-v} $TARGET ${MDEC}/bootxx $DEV + $DOIT installboot ${VERBOSE:+-v} $TARGET ${MDEC}/bootxx $DEV + ;; + +"net") + TARGET=$DEST/boot.sparc.netbsd.$KARCH + vecho Target: $TARGET + $DOIT dd if=${MDEC}/boot of=$TARGET skip=$SKIP bs=32 + ;; + +*) + echo "$WHAT: not recognised" + exit 1 + ;; +esac + +exit $? diff --git a/sys/arch/sparc/stand/boot.c b/sys/arch/sparc/stand/boot.c new file mode 100644 index 00000000000..5b423db0ad2 --- /dev/null +++ b/sys/arch/sparc/stand/boot.c @@ -0,0 +1,261 @@ +/* $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 <sys/param.h> +#include <sys/reboot.h> +#include <a.out.h> +#include <stand.h> + +#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 diff --git a/sys/arch/sparc/stand/boot/Makefile b/sys/arch/sparc/stand/boot/Makefile new file mode 100644 index 00000000000..f135f55abc5 --- /dev/null +++ b/sys/arch/sparc/stand/boot/Makefile @@ -0,0 +1,18 @@ +# $NetBSD: Makefile,v 1.2 1995/09/30 21:43:38 pk Exp $ + +R= .. +.PATH: ${.CURDIR}/${R} +PROG= boot +SRCS= srt0.S boot.c promdev.c dvma.c net.c netif_sun.c conf.c version.c +NOMAN= 1 +BINDIR= /usr/mdec +LIBS!= cd ${.CURDIR}/${R}; ${MAKE} libdep + +${PROG}:${OBJS} ${LIBS} + ${LD} -N -T ${RELOC} -e start ${OBJS} ${LIBS} + # convert to Sun magic + (echo -n 01 | tr 01 '\01\03'; tail +3c a.out) > ${.TARGET} + @rm a.out + @size ${.TARGET} + +.include <bsd.prog.mk> diff --git a/sys/arch/sparc/stand/bootxx.c b/sys/arch/sparc/stand/bootxx.c new file mode 100644 index 00000000000..4ad862e991e --- /dev/null +++ b/sys/arch/sparc/stand/bootxx.c @@ -0,0 +1,125 @@ +/* $NetBSD: bootxx.c,v 1.7 1995/09/27 09:03:13 pk Exp $ */ + +/* + * Copyright (c) 1994 Paul Kranenburg + * 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 Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <sys/param.h> +#include <sys/time.h> +#include <a.out.h> + +#include <stand.h> +#include "promdev.h" + +int debug; +int netif_debug; + +/* + * Boot device is derived from ROM provided information. + */ +const char progname[] = "bootxx"; +struct open_file io; + +/* + * The contents of the block_* variables below is set by installboot(8) + * to hold the the filesystem data of the second-stage boot program + * (typically `/boot'): filesystem block size, # of filesystem blocks and + * the block numbers themselves. + */ +#define MAXBLOCKNUM 256 /* enough for a 2MB boot program (bs 8K) */ +int32_t block_size = 0; +int32_t block_count = MAXBLOCKNUM; +daddr_t block_table[MAXBLOCKNUM] = { 0 }; + + +void loadboot __P((struct open_file *, caddr_t)); + +int +main() +{ + char *dummy; + size_t n; + register void (*entry)__P((caddr_t)) = (void (*)__P((caddr_t)))LOADADDR; + + prom_init(); + io.f_flags = F_RAW; + if (devopen(&io, 0, &dummy)) { + panic("%s: can't open device", progname); + } + + (void)loadboot(&io, LOADADDR); + (*entry)(cputyp == CPU_SUN4 ? LOADADDR : (caddr_t)promvec); + _rtt(); +} + +void +loadboot(f, addr) + register struct open_file *f; + register char *addr; +{ + register int i; + register char *buf; + size_t n; + daddr_t blk; + + /* + * Allocate a buffer that we can map into DVMA space; only + * needed for sun4 architecture, but use it for all machines + * to keep code size down as much as possible. + */ + buf = alloc(block_size); + if (buf == NULL) + panic("%s: alloc failed", progname); + + for (i = 0; i < block_count; i++) { + if ((blk = block_table[i]) == 0) + panic("%s: block table corrupt", progname); + +#ifdef DEBUG + printf("%s: block # %d = %d\n", progname, i, blk); +#endif + if ((f->f_dev->dv_strategy)(f->f_devdata, F_READ, + blk, block_size, buf, &n)) { + panic("%s: read failure", progname); + } + bcopy(buf, addr, block_size); + if (n != block_size) + panic("%s: short read", progname); + if (i == 0) { + register int m = N_GETMAGIC(*(struct exec *)addr); + if (m == ZMAGIC || m == NMAGIC || m == OMAGIC) { + /* Move exec header out of the way */ + bcopy(addr, addr - sizeof(struct exec), n); + addr -= sizeof(struct exec); + } + } + addr += n; + } + +} diff --git a/sys/arch/sparc/stand/bootxx/Makefile b/sys/arch/sparc/stand/bootxx/Makefile new file mode 100644 index 00000000000..7769be5223b --- /dev/null +++ b/sys/arch/sparc/stand/bootxx/Makefile @@ -0,0 +1,24 @@ +# $NetBSD: Makefile,v 1.4.2.1 1995/10/13 19:55:36 pk Exp $ + +R= .. +.PATH: ${.CURDIR}/${R} +PROG= bootxx +SRCS= srt0.S bootxx.c promdev.c dvma.c +KOBJS= __main.o bzero.o urem.o udiv.o +NOMAN= 1 +STRIP= +BINDIR= /usr/mdec +CFLAGS= -DBOOTXX + +LIBS!= cd ${.CURDIR}/${R}; ${MAKE} sadep +KOBJDIR!= cd ${.CURDIR}/${R}; ${MAKE} kernlibdir +_KOBJS=${KOBJS:S,^,${KOBJDIR}/,g} + +${PROG}:${OBJS} ${_KOBJS} ${LIBS} + ${LD} -N -T ${RELOC} -e start ${OBJS} ${_KOBJS} ${LIBS} + # convert to Sun magic + (echo -n 01 | tr 01 '\01\03'; tail +3c a.out) > ${.TARGET} + @rm a.out + @size ${.TARGET} + +.include <bsd.prog.mk> diff --git a/sys/arch/sparc/stand/conf.c b/sys/arch/sparc/stand/conf.c new file mode 100644 index 00000000000..b03b9998977 --- /dev/null +++ b/sys/arch/sparc/stand/conf.c @@ -0,0 +1,46 @@ +/* $NetBSD: conf.c,v 1.2 1995/09/18 21:31:45 pk Exp $ */ + +/* + * Copyright (c) 1993 Philip A. Nelson. + * 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 Philip A. Nelson. + * 4. The name of Philip A. Nelson may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY PHILIP NELSON ``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 PHILIP NELSON 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 <stand.h> +#include <ufs.h> +#include <netinet/in.h> +#include <nfs.h> + +struct fs_ops file_system_ufs[] = { + { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat }, +}; +struct fs_ops file_system_nfs[] = { + { nfs_open, nfs_close, nfs_read, nfs_write, nfs_seek, nfs_stat }, +}; +struct fs_ops file_system[1]; +int nfsys = sizeof(file_system)/sizeof(struct fs_ops); diff --git a/sys/arch/sparc/stand/dvma.c b/sys/arch/sparc/stand/dvma.c new file mode 100644 index 00000000000..ffa50eef23f --- /dev/null +++ b/sys/arch/sparc/stand/dvma.c @@ -0,0 +1,119 @@ +/* $NetBSD: dvma.c,v 1.2 1995/09/17 00:50:56 pk Exp $ */ +/* + * Copyright (c) 1995 Gordon W. Ross + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * 4. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Gordon Ross + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +/* + * The easiest way to deal with the need for DVMA mappings is + * to just map the entire third megabyte of RAM into DVMA space. + * That way, dvma_mapin can just compute the DVMA alias address, + * and dvma_mapout does nothing. Note that this assumes all + * standalone programs stay in the range SA_MIN_VA .. SA_MAX_VA + */ + +#include <sys/param.h> +#include <machine/pte.h> +#include <machine/ctlreg.h> +#include "promdev.h" + +#define DVMA_BASE 0xFFF00000 +#define DVMA_MAPLEN 0xE0000 /* 1 MB - 128K (save MONSHORTSEG) */ + +#define SA_MIN_VA (RELOC - 0x40000) /* XXX - magic constant */ +#define SA_MAX_VA (SA_MIN_VA + DVMA_MAPLEN) + +void +dvma_init() +{ + register int segva, dmava; + + dmava = DVMA_BASE; + for (segva = SA_MIN_VA; segva < SA_MAX_VA; segva += NBPSG) { + setsegmap(dmava, getsegmap(segva)); + dmava += NBPSG; + } +} + +/* + * Convert a local address to a DVMA address. + */ +char * +dvma_mapin(char *addr, size_t len) +{ + register int va = (int)addr; + + /* Make sure the address is in the DVMA map. */ + if ((va < SA_MIN_VA) || (va >= SA_MAX_VA)) + panic("dvma_mapin"); + + va += DVMA_BASE - SA_MIN_VA; + + return ((char *)va); +} + +/* + * Convert a DVMA address to a local address. + */ +char * +dvma_mapout(char *addr, size_t len) +{ + int va = (int)addr; + + /* Make sure the address is in the DVMA map. */ + if ((va < DVMA_BASE) || (va >= (DVMA_BASE + DVMA_MAPLEN))) + panic("dvma_mapout"); + + va -= DVMA_BASE - SA_MIN_VA; + + return ((char *)va); +} + +extern char *alloc __P((int)); + +char * +dvma_alloc(int len) +{ + char *mem; + + mem = alloc(len); + if (!mem) + return (mem); + return (dvma_mapin(mem, len)); +} + +extern void free(void *ptr, int len); +void +dvma_free(char *dvma, int len) +{ + char *mem; + + mem = dvma_mapout(dvma, len); + if (mem) + free(mem, len); +} diff --git a/sys/arch/sparc/stand/installboot.8 b/sys/arch/sparc/stand/installboot.8 new file mode 100644 index 00000000000..c2cfeef3be0 --- /dev/null +++ b/sys/arch/sparc/stand/installboot.8 @@ -0,0 +1,140 @@ +.\" $NetBSD: installboot.8,v 1.1 1995/09/30 21:32:14 pk Exp $ +.\" +.\" Copyright (c) 1995 Paul Kranenburg +.\" 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 Paul Kranenburg. +.\" 3. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +.\" +.Dd September 29, 1995 +.Dt INSTALLBOOT 8 +.Os +.Sh NAME +.Nm installboot +.Nd install a bootstrap on an FFS filesystem partition +.Sh SYNOPSIS +.Nm installboot +.Op Fl nvh +.Ar boot +.Ar bootxx +.Ar device +.Sh DESCRIPTION +.Nm installboot +prepares a FFS filesystem partition for boot-strapping from the PROM. +The sparc bootblocks are split into two parts: a small first-stage program that +is written into the superblock area in a partition +.Po +and hence is limited in size to SBSIZE - DEV_BSIZE bytes +.Pc , +and a second-stage program that resides in the filesystem proper. +The first-stage program is loaded into memory by the PROM. After it receiving +control, it loads the second stage program from a set of filesystem block +numbers that have been hard-coded into it by the +.Nm installboot +program. The second-stage boot program uses the device driver interface to +the PROM and the stand-alone filesystem code in +.Dq libsa.a +to locate and load the kernel. +The second-stage boot program and the prototype code for the +first-stage bootprogram can be found in +.Pa /usr/mdec/boot +and +.Pa /usr/mdec/bootxx +respectively. The second-stage program commonly resides in the root directory +as +.Pa /boot . +The utility +.Pa /usr/mdec/binstall +can be used to properly copy the a second-stage bootprogram to its +destination. This script takes care of post-processing that is required +on non- +.Tn Openboot +machines. +.Pp +The options are as follows: +.Bl -tag -width flag +.It Fl n +Do not actually write anything on the disk. +.It Fl v +Verbose mode. +.It Fl h +Leave the +.Xr a.out 5 +header on the installed +.Ar bootxx +program. +Sun 4c models with +.Tn Openboot +PROMs need the header to be present, while Sun 4 systems with the +.Dq old monitor +interface require the header to be stripped off. This is normally taken +care of by +.Nm +automatically. +.El +.Pp +The arguments are: +.Bl -tag -width bootxx +.It Ar boot +the name of the second-stage boot program in the file system +where the first-stage boot program is to be installed. +.It Ar bootxx +the name of the prototype file for the first stage boot program. +.It Ar device +the name of the raw device in which the first-stage boot program +is to be installed. This should correspond to the block device +on which the file system containing +.Ar boot +is mounted. +.El +.Sh EXAMPLES +The following command will install the first-stage bootblocks in the +root filesystem +.Pq assumed to be mounted on Dq sd0a +using the file +.Pa /boot +as the second-level boot program: +.Bd -literal -offset indent +installboot /boot /usr/mdec/bootxx /dev/rsd0a +.Ed +.Sh BUGS +.Nm +requires simultaneous access to the mounted file system and +the raw device, but that is not allowed with the kernel +.Dv securelevel +variable set to a value greater than zero +.Pq the default , +so +.Nm installboot +only works in single-user mode +.Pq or insecure mode - see Xr init 8 . +.Sh "SEE ALSO" +.Xr disklabel 8 , +.Xr init 8 +.Sh HISTORY +The +.Nm +first appeared in +.Nx 1.1 diff --git a/sys/arch/sparc/stand/installboot.c b/sys/arch/sparc/stand/installboot.c new file mode 100644 index 00000000000..badac63ddd4 --- /dev/null +++ b/sys/arch/sparc/stand/installboot.c @@ -0,0 +1,389 @@ +/* $NetBSD: installboot.c,v 1.9 1995/09/27 09:03:15 pk Exp $ */ + +/* + * Copyright (c) 1994 Paul Kranenburg + * 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 Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <sys/param.h> +#include <sys/mount.h> +#include <sys/time.h> +#include <sys/stat.h> +#include <sys/sysctl.h> +#include <ufs/ufs/dinode.h> +#include <ufs/ufs/dir.h> +#include <ufs/ffs/fs.h> +#include <err.h> +#include <a.out.h> +#include <fcntl.h> +#include <nlist.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +int verbose, nowrite, hflag; +char *boot, *proto, *dev; + +struct nlist nl[] = { +#define X_BLOCKTABLE 0 + {"_block_table"}, +#define X_BLOCKCOUNT 1 + {"_block_count"}, +#define X_BLOCKSIZE 2 + {"_block_size"}, + {NULL} +}; +daddr_t *block_table; /* block number array in prototype image */ +int32_t *block_count_p; /* size of this array */ +int32_t *block_size_p; /* filesystem block size */ +int32_t max_block_count; + +char cpumodel[100]; + + +char *loadprotoblocks __P((char *, long *)); +int loadblocknums __P((char *, int)); +static void devread __P((int, void *, daddr_t, size_t, char *)); +static void usage __P((void)); +int main __P((int, char *[])); + + +static void +usage() +{ + fprintf(stderr, + "usage: installboot [-n] [-v] [-h] <boot> <proto> <device>\n"); + exit(1); +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int c; + int devfd; + char *protostore; + long protosize; + int mib[2]; + size_t size; + + while ((c = getopt(argc, argv, "vnh")) != EOF) { + switch (c) { + case 'h': + /* Don't strip a.out header */ + hflag = 1; + break; + case 'n': + /* Do not actually write the bootblock to disk */ + nowrite = 1; + break; + case 'v': + /* Chat */ + verbose = 1; + break; + default: + usage(); + } + } + + if (argc - optind < 3) { + usage(); + } + + boot = argv[optind]; + proto = argv[optind + 1]; + dev = argv[optind + 2]; + + if (verbose) { + printf("boot: %s\n", boot); + printf("proto: %s\n", proto); + printf("device: %s\n", dev); + } + + mib[0] = CTL_HW; + mib[1] = HW_MODEL; + size = sizeof(cpumodel); + if (sysctl(mib, 2, cpumodel, &size, NULL, 0) == -1) + err(1, "sysctl"); + + if (size < 5 || strncmp(cpumodel, "SUN/4", 5) != 0) /*XXX*/ + /* Assume a sun4c/sun4m */ + hflag = 1; + + /* Load proto blocks into core */ + if ((protostore = loadprotoblocks(proto, &protosize)) == NULL) + exit(1); + + /* Open and check raw disk device */ + if ((devfd = open(dev, O_RDONLY, 0)) < 0) + err(1, "open: %s", dev); + + /* Extract and load block numbers */ + if (loadblocknums(boot, devfd) != 0) + exit(1); + + (void)close(devfd); + + if (nowrite) + return 0; + + /* Write patched proto bootblocks into the superblock */ + if (protosize > SBSIZE - DEV_BSIZE) + errx(1, "proto bootblocks too big"); + + if ((devfd = open(dev, O_RDWR, 0)) < 0) + err(1, "open: %s", dev); + + if (lseek(devfd, DEV_BSIZE, SEEK_SET) != DEV_BSIZE) + err(1, "lseek bootstrap"); + + /* Sync filesystems (to clean in-memory superblock?) */ + sync(); + + if (write(devfd, protostore, protosize) != protosize) + err(1, "write bootstrap"); + (void)close(devfd); + return 0; +} + +char * +loadprotoblocks(fname, size) + char *fname; + long *size; +{ + int fd, sz; + char *bp; + struct stat statbuf; + struct exec *hp; + long off; + + /* Locate block number array in proto file */ + if (nlist(fname, nl) != 0) { + warnx("nlist: %s: symbols not found", fname); + return NULL; + } + if (nl[X_BLOCKTABLE].n_type != N_DATA + N_EXT) { + warnx("nlist: %s: wrong type", nl[X_BLOCKTABLE].n_un.n_name); + return NULL; + } + if (nl[X_BLOCKCOUNT].n_type != N_DATA + N_EXT) { + warnx("nlist: %s: wrong type", nl[X_BLOCKCOUNT].n_un.n_name); + return NULL; + } + if (nl[X_BLOCKSIZE].n_type != N_DATA + N_EXT) { + warnx("nlist: %s: wrong type", nl[X_BLOCKSIZE].n_un.n_name); + return NULL; + } + + if ((fd = open(fname, O_RDONLY)) < 0) { + warn("open: %s", fname); + return NULL; + } + if (fstat(fd, &statbuf) != 0) { + warn("fstat: %s", fname); + close(fd); + return NULL; + } + if ((bp = calloc(roundup(statbuf.st_size, DEV_BSIZE), 1)) == NULL) { + warnx("malloc: %s: no memory", fname); + close(fd); + return NULL; + } + if (read(fd, bp, statbuf.st_size) != statbuf.st_size) { + warn("read: %s", fname); + free(bp); + close(fd); + return NULL; + } + close(fd); + + hp = (struct exec *)bp; + sz = (hflag ? sizeof(*hp) : 0) + hp->a_text + hp->a_data; + sz = roundup(sz, DEV_BSIZE); + + /* Calculate the symbols' location within the proto file */ + off = N_DATOFF(*hp) - N_DATADDR(*hp) - (hp->a_entry - N_TXTADDR(*hp)); + block_table = (daddr_t *) (bp + nl[X_BLOCKTABLE].n_value + off); + block_count_p = (int32_t *)(bp + nl[X_BLOCKCOUNT].n_value + off); + block_size_p = (int32_t *) (bp + nl[X_BLOCKSIZE].n_value + off); + if ((int)block_table & 3) { + warn("%s: invalid address: block_table = %x", + fname, block_table); + free(bp); + close(fd); + return NULL; + } + if ((int)block_count_p & 3) { + warn("%s: invalid address: block_count_p = %x", + fname, block_count_p); + free(bp); + close(fd); + return NULL; + } + if ((int)block_size_p & 3) { + warn("%s: invalid address: block_size_p = %x", + fname, block_size_p); + free(bp); + close(fd); + return NULL; + } + max_block_count = *block_count_p; + + if (verbose) { + printf("%s: entry point %#x\n", fname, hp->a_entry); + printf("%s: a.out header %s\n", fname, + hflag?"left on":"stripped off"); + printf("proto bootblock size %ld\n", sz); + printf("room for %d filesystem blocks at %#x\n", + max_block_count, nl[X_BLOCKTABLE].n_value); + } + + *size = sz; + return (hflag ? bp : (bp + sizeof(struct exec))); +} + +static void +devread(fd, buf, blk, size, msg) + int fd; + void *buf; + daddr_t blk; + size_t size; + char *msg; +{ + if (lseek(fd, dbtob(blk), SEEK_SET) != dbtob(blk)) + err(1, "%s: devread: lseek", msg); + + if (read(fd, buf, size) != size) + err(1, "%s: devread: read", msg); +} + +static char sblock[SBSIZE]; + +int +loadblocknums(boot, devfd) +char *boot; +int devfd; +{ + int i, fd; + struct stat statbuf; + struct statfs statfsbuf; + struct fs *fs; + char *buf; + daddr_t blk, *ap; + struct dinode *ip; + int ndb; + + /* + * Open 2nd-level boot program and record the block numbers + * it occupies on the filesystem represented by `devfd'. + */ + if ((fd = open(boot, O_RDONLY)) < 0) + err(1, "open: %s", boot); + + if (fstatfs(fd, &statfsbuf) != 0) + err(1, "statfs: %s", boot); + + if (strncmp(statfsbuf.f_fstypename, "ufs", MFSNAMELEN)) + errx(1, "%s: must be on a UFS filesystem", boot); + + if (fsync(fd) != 0) + err(1, "fsync: %s", boot); + + if (fstat(fd, &statbuf) != 0) + err(1, "fstat: %s", boot); + + close(fd); + + /* Read superblock */ + devread(devfd, sblock, btodb(SBOFF), SBSIZE, "superblock"); + fs = (struct fs *)sblock; + + /* Read inode */ + if ((buf = malloc(fs->fs_bsize)) == NULL) + errx(1, "No memory for filesystem block"); + + blk = fsbtodb(fs, ino_to_fsba(fs, statbuf.st_ino)); + devread(devfd, buf, blk, fs->fs_bsize, "inode"); + ip = (struct dinode *)(buf) + ino_to_fsbo(fs, statbuf.st_ino); + + /* + * Register filesystem block size. + */ + *block_size_p = fs->fs_bsize; + + /* + * Get the block numbers; we don't handle fragments + */ + ndb = howmany(ip->di_size, fs->fs_bsize); + if (ndb > max_block_count) + errx(1, "%s: Too many blocks", boot); + + /* + * Register block count. + */ + *block_count_p = ndb; + + if (verbose) + printf("%s: block numbers: ", boot); + ap = ip->di_db; + for (i = 0; i < NDADDR && *ap && ndb; i++, ap++, ndb--) { + blk = fsbtodb(fs, *ap); + block_table[i] = blk; + if (verbose) + printf("%d ", blk); + } + if (verbose) + printf("\n"); + + if (ndb == 0) + return 0; + + /* + * Just one level of indirections; there isn't much room + * for more in the 1st-level bootblocks anyway. + */ + if (verbose) + printf("%s: block numbers (indirect): ", boot); + blk = ip->di_ib[0]; + devread(devfd, buf, blk, fs->fs_bsize, "indirect block"); + ap = (daddr_t *)buf; + for (; i < NINDIR(fs) && *ap && ndb; i++, ap++, ndb--) { + blk = fsbtodb(fs, *ap); + block_table[i] = blk; + if (verbose) + printf("%d ", blk); + } + if (verbose) + printf("\n"); + + if (ndb) + errx(1, "%s: Too many blocks", boot); + return 0; +} diff --git a/sys/arch/sparc/stand/installboot/Makefile b/sys/arch/sparc/stand/installboot/Makefile new file mode 100644 index 00000000000..0662608f1dc --- /dev/null +++ b/sys/arch/sparc/stand/installboot/Makefile @@ -0,0 +1,11 @@ +# $NetBSD: Makefile,v 1.3 1995/09/30 21:43:41 pk Exp $ + +.PATH: ${.CURDIR}/.. +PROG= installboot +MAN= installboot.8 +BINDIR=/usr/sbin + +# XXX - prevent sa clutter +__stand_makefile_inc=1 + +.include <bsd.prog.mk> diff --git a/sys/arch/sparc/stand/net.c b/sys/arch/sparc/stand/net.c new file mode 100644 index 00000000000..f70c1834793 --- /dev/null +++ b/sys/arch/sparc/stand/net.c @@ -0,0 +1,157 @@ +/* $NetBSD: net.c,v 1.2 1995/09/18 21:31:46 pk Exp $ */ + +/* + * Copyright (c) 1995 Gordon W. Ross + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * 4. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Gordon W. Ross + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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() + * RARP for IP address - rarp_getipaddress() + * RPC/bootparams - callrpc(d, RPC_BOOTPARAMS, ...) + * RPC/mountd - nfs_mount(sock, ip, path) + * + * the root file handle from mountd is saved in a global + * for use by the NFS open code (NFS/lookup). + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <netinet/if_ether.h> +#include <netinet/in_systm.h> + +#include "stand.h" +#include "net.h" +#include "netif.h" +#include "bootparam.h" + +char rootpath[FNAME_SIZE]; + +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(pd) + struct promdata *pd; +{ + int error = 0; + + /* On first open, do netif open, mount, etc. */ + if (open_count == 0) { + /* Find network interface. */ + if ((netdev_sock = netif_open(pd)) < 0) { + error = errno; + goto bad; + } + if ((error = net_mountroot()) != 0) + goto bad; + } + open_count++; +bad: + return (error); +} + +int +net_close(pd) + struct promdata *pd; +{ + /* On last close, do netif close, etc. */ + if (open_count > 0) + if (--open_count == 0) + netif_close(netdev_sock); +} + +int +net_mountroot() +{ + +#ifdef DEBUG + printf("net_mountroot\n"); +#endif + + /* + * Get info for NFS boot: our IP address, our hostname, + * server IP address, and our root path on the server. + * There are two ways to do this: The old, Sun way, + * and the more modern, BOOTP way. (RFC951, RFC1048) + */ + +#ifdef SUN_BOOTPARAMS + /* Get boot info using RARP and Sun bootparams. */ + + /* Get our IP address. (rarp.c) */ + if (rarp_getipaddress(netdev_sock) == -1) + return errno; + + printf("boot: client IP address: %s\n", inet_ntoa(myip)); + + /* Get our hostname, server IP address. */ + if (bp_whoami(netdev_sock)) + return (errno); + + printf("boot: client name: %s\n", hostname); + + /* Get the root pathname. */ + if (bp_getfile(netdev_sock, "root", &rootip, rootpath)) + return (errno); + +#else + + /* Get boot info using BOOTP way. (RFC951, RFC1048) */ + bootp(netdev_sock); + + printf("Using IP address: %s\n", inet_ntoa(myip)); + + printf("myip: %s (%s)", hostname, inet_ntoa(myip)); + if (gateip) + 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). */ + return nfs_mount(netdev_sock, rootip, rootpath); +} diff --git a/sys/arch/sparc/stand/netif_sun.c b/sys/arch/sparc/stand/netif_sun.c new file mode 100644 index 00000000000..930d5d9659b --- /dev/null +++ b/sys/arch/sparc/stand/netif_sun.c @@ -0,0 +1,219 @@ +/* $NetBSD: netif_sun.c,v 1.2 1995/09/18 21:31:48 pk Exp $ */ + +/* + * Copyright (c) 1995 Gordon W. Ross + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * 4. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Gordon W. Ross + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +/* + * The Sun PROM has a fairly general set of network drivers, + * so it is easiest to just replace the netif module with + * this adaptation to the PROM network interface. + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <string.h> +#include <time.h> + +#include <net/if.h> + +#include <netinet/in.h> +#include <netinet/if_ether.h> +#include <netinet/in_systm.h> + +#include "stand.h" +#include "net.h" +#include "netif.h" + +#include "promdev.h" + +static struct netif netif_prom; + +#ifdef NETIF_DEBUG +int netif_debug; +#endif + +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 promdata *pd = machdep_hint; + struct iodesc *io; + int fd, error; + + /* find a free socket */ + io = sockets; + if (io->io_netif) { +#ifdef DEBUG + printf("netif_open: device busy\n"); +#endif + errno = ENFILE; + return (-1); + } + bzero(io, sizeof(*io)); + + netif_prom.nif_devdata = pd; + io->io_netif = &netif_prom; + + /* Put our ethernet address in io->myea */ + prom_getether(pd->fd, io->myea); + + return(0); +} + +int +netif_close(fd) + int fd; +{ + struct iodesc *io; + struct netif *ni; + + if (fd != 0) { + errno = EBADF; + return(-1); + } + + io = &sockets[fd]; + ni = io->io_netif; + if (ni != NULL) { + ni->nif_devdata = NULL; + io->io_netif = NULL; + } + 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 promdata *pd; + ssize_t rv; + size_t sendlen; + + pd = (struct promdata *)desc->io_netif->nif_devdata; + +#ifdef NETIF_DEBUG + if (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 = (*pd->xmit)(pd, pkt, sendlen); + +#ifdef NETIF_DEBUG + if (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 promdata *pd; + int tick0, tmo_ticks; + ssize_t len; + + pd = (struct promdata *)desc->io_netif->nif_devdata; + +#ifdef NETIF_DEBUG + if (netif_debug) + printf("netif_get: pkt=0x%x, maxlen=%d, tmo=%d\n", + pkt, maxlen, timo); +#endif + + tmo_ticks = timo * hz; + tick0 = getticks(); + + do { + len = (*pd->recv)(pd, pkt, maxlen); + } while ((len == 0) && ((getticks() - tick0) < tmo_ticks)); + +#ifdef NETIF_DEBUG + if (netif_debug) + printf("netif_get: received len=%d\n", len); +#endif + + if (len < 12) + return -1; + +#ifdef NETIF_DEBUG + if (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; +} diff --git a/sys/arch/sparc/stand/promdev.c b/sys/arch/sparc/stand/promdev.c new file mode 100644 index 00000000000..1dd56840038 --- /dev/null +++ b/sys/arch/sparc/stand/promdev.c @@ -0,0 +1,792 @@ +/* $NetBSD: promdev.c,v 1.14.2.1 1995/10/13 19:53:55 pk Exp $ */ + +/* + * Copyright (c) 1993 Paul Kranenburg + * Copyright (c) 1995 Gordon W. Ross + * 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 Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +/* + * Note: the `#ifndef BOOTXX' in here serve to queeze the code size + * of the 1st-stage boot program. + */ +#include <sys/param.h> +#include <sys/reboot.h> +#include <machine/idprom.h> +#include <machine/oldmon.h> +#include <machine/ctlreg.h> + +#include <stand.h> + +#include "promdev.h" + + +int obp_close __P((struct open_file *)); +int obp_strategy __P((void *, int, daddr_t, size_t, void *, size_t *)); +ssize_t obp_xmit __P((struct promdata *, void *, size_t)); +ssize_t obp_recv __P((struct promdata *, void *, size_t)); +int prom0_close __P((struct open_file *)); +int prom0_strategy __P((void *, int, daddr_t, size_t, void *, size_t *)); +void prom0_iclose __P((struct saioreq *)); +int prom0_iopen __P((struct promdata *)); +ssize_t prom0_xmit __P((struct promdata *, void *, size_t)); +ssize_t prom0_recv __P((struct promdata *, void *, size_t)); + +static char *prom_mapin __P((u_long, int, int)); + +int getdevtype __P((int, char *)); +int getprop __P((int, char *, void *, int)); +char *getpropstring __P((int, char *)); + +static void prom0_fake __P((void)); + +extern struct filesystem file_system_nfs[]; +extern struct filesystem file_system_ufs[]; + +int prom_open __P((struct open_file *f, ...)) { return 0; } +int prom_ioctl __P((struct open_file *f, u_long c, void *d)) { return EIO; } + +struct devsw devsw[] = { + { "prom0", prom0_strategy, prom_open, prom0_close, prom_ioctl }, + { "prom", obp_strategy, prom_open, obp_close, prom_ioctl } +}; + +int ndevs = (sizeof(devsw)/sizeof(devsw[0])); + +char *prom_bootdevice; +char *prom_bootfile; +int prom_boothow; + +struct promvec *promvec; +static int saveecho; + +void +prom_init() +{ + register char *ap, *cp, *dp; + + if (cputyp == CPU_SUN4) + prom0_fake(); + + if (promvec->pv_romvec_vers >= 2) { + static char filestore[16]; + + prom_bootdevice = *promvec->pv_v2bootargs.v2_bootpath; + +#ifndef BOOTXX + cp = *promvec->pv_v2bootargs.v2_bootargs; + dp = prom_bootfile = filestore; + while (*cp && *cp != '-') + *dp++ = *cp++; + while (dp > prom_bootfile && *--dp == ' '); + *++dp = '\0'; + ap = cp; +#endif + } else { + static char bootstore[16]; + dp = prom_bootdevice = bootstore; + cp = (*promvec->pv_v0bootargs)->ba_argv[0]; + while (*cp) { + *dp++ = *cp; + if (*cp++ == ')') + break; + } + *dp = '\0'; +#ifndef BOOTXX + prom_bootfile = (*promvec->pv_v0bootargs)->ba_kernel; + ap = (*promvec->pv_v0bootargs)->ba_argv[1]; +#endif + } + +#ifndef BOOTXX + if (ap == NULL || *ap != '-') + return; + + while (*ap) { + switch (*ap++) { + case 'a': + prom_boothow |= RB_ASKNAME; + break; + case 's': + prom_boothow |= RB_SINGLE; + break; + case 'd': + prom_boothow |= RB_KDB; + debug = 1; + break; + } + } +#endif +} + +int +devopen(f, fname, file) + struct open_file *f; + const char *fname; + char **file; +{ + int error = 0, fd; + struct promdata *pd; + + pd = (struct promdata *)alloc(sizeof *pd); + + if (cputyp == CPU_SUN4) { + error = prom0_iopen(pd); +#ifndef BOOTXX + pd->xmit = prom0_xmit; + pd->recv = prom0_recv; +#endif + } else { + fd = (promvec->pv_romvec_vers >= 2) + ? (*promvec->pv_v2devops.v2_open)(prom_bootdevice) + : (*promvec->pv_v0devops.v0_open)(prom_bootdevice); + if (fd == 0) { + error = ENXIO; + } else { + pd->fd = fd; +#ifndef BOOTXX + pd->xmit = obp_xmit; + pd->recv = obp_recv; +#endif + } + } + + if (error) { + printf("Can't open device `%s'\n", prom_bootdevice); + return (error); + } + +#ifdef BOOTXX + pd->devtype = DT_BLOCK; +#else /* BOOTXX */ + pd->devtype = getdevtype(fd, prom_bootdevice); + /* Assume type BYTE is a raw device */ + if (pd->devtype != DT_BYTE) + *file = (char *)fname; + + if (pd->devtype == DT_NET) { + bcopy(file_system_nfs, file_system, sizeof(struct fs_ops)); + if ((error = net_open(pd)) != 0) { + printf("Can't open network device `%s'\n", + prom_bootdevice); + return error; + } + } else + bcopy(file_system_ufs, file_system, sizeof(struct fs_ops)); +#endif /* BOOTXX */ + + f->f_dev = &devsw[cputyp == CPU_SUN4 ? 0 : 1]; + f->f_devdata = (void *)pd; + return 0; +} + +int +obp_strategy(devdata, flag, dblk, size, buf, rsize) + void *devdata; + int flag; + daddr_t dblk; + size_t size; + void *buf; + size_t *rsize; +{ + int error = 0; + struct promdata *pd = (struct promdata *)devdata; + int fd = pd->fd; + +#ifdef DEBUG_PROM + printf("promstrategy: size=%d dblk=%d\n", size, dblk); +#endif + + if (promvec->pv_romvec_vers >= 2) { + if (pd->devtype == DT_BLOCK) + (*promvec->pv_v2devops.v2_seek)(fd, 0, dbtob(dblk)); + + *rsize = (*((flag == F_READ) + ? (u_int (*)())promvec->pv_v2devops.v2_read + : (u_int (*)())promvec->pv_v2devops.v2_write + ))(fd, buf, size); + } else { + int n = (*((flag == F_READ) + ? (u_int (*)())promvec->pv_v0devops.v0_rbdev + : (u_int (*)())promvec->pv_v0devops.v0_wbdev + ))(fd, btodb(size), dblk, buf); + *rsize = dbtob(n); + } + +#ifdef DEBUG_PROM + printf("rsize = %x\n", *rsize); +#endif + return error; +} + +/* + * On old-monitor machines, things work differently. + */ +int +prom0_strategy(devdata, flag, dblk, size, buf, rsize) + void *devdata; + int flag; + daddr_t dblk; + size_t size; + void *buf; + size_t *rsize; +{ + struct promdata *pd = devdata; + struct saioreq *si; + struct om_boottable *ops; + char *dmabuf; + int si_flag; + size_t xcnt; + + si = pd->si; + ops = si->si_boottab; + +#ifdef DEBUG_PROM + printf("prom_strategy: size=%d dblk=%d\n", size, dblk); +#endif + + dmabuf = dvma_mapin(buf, size); + + si->si_bn = dblk; + si->si_ma = dmabuf; + si->si_cc = size; + + si_flag = (flag == F_READ) ? SAIO_F_READ : SAIO_F_WRITE; + xcnt = (*ops->b_strategy)(si, si_flag); + dvma_mapout(dmabuf, size); + +#ifdef DEBUG_PROM + printf("disk_strategy: xcnt = %x\n", xcnt); +#endif + + if (xcnt <= 0) + return (EIO); + + *rsize = xcnt; + return (0); +} + +int +obp_close(f) + struct open_file *f; +{ + struct promdata *pd = f->f_devdata; + register int fd = pd->fd; + +#ifndef BOOTXX + if (pd->devtype == DT_NET) + net_close(pd); +#endif + if (promvec->pv_romvec_vers >= 2) + (void)(*promvec->pv_v2devops.v2_close)(fd); + else + (void)(*promvec->pv_v0devops.v0_close)(fd); + return 0; +} + +int +prom0_close(f) + struct open_file *f; +{ + struct promdata *pd = f->f_devdata; + +#ifndef BOOTXX + if (pd->devtype == DT_NET) + net_close(pd); +#endif + prom0_iclose(pd->si); + pd->si = NULL; + *romp->echo = saveecho; /* Hmm, probably must go somewhere else */ + return 0; +} + +#ifndef BOOTXX +ssize_t +obp_xmit(pd, buf, len) + struct promdata *pd; + void *buf; + size_t len; +{ + return (promvec->pv_romvec_vers >= 2 + ? (*promvec->pv_v2devops.v2_write)(pd->fd, buf, len) + : (*promvec->pv_v0devops.v0_wnet)(pd->fd, len, buf)); +} + +ssize_t +obp_recv(pd, buf, len) + struct promdata *pd; + void *buf; + size_t len; +{ + int n; + + n = (promvec->pv_romvec_vers >= 2 + ? (*promvec->pv_v2devops.v2_read)(pd->fd, buf, len) + : (*promvec->pv_v0devops.v0_rnet)(pd->fd, len, buf)); + return (n == -2 ? 0 : n); +} + +ssize_t +prom0_xmit(pd, buf, len) + struct promdata *pd; + void *buf; + size_t len; +{ + struct saioreq *si; + struct saif *sif; + char *dmabuf; + int rv; + + si = pd->si; + sif = si->si_sif; + if (sif == NULL) { + printf("xmit: not a network device\n"); + return (-1); + } + dmabuf = dvma_mapin(buf, len); + rv = sif->sif_xmit(si->si_devdata, dmabuf, len); + dvma_mapout(dmabuf, len); + + return (ssize_t)(rv ? -1 : len); +} + +ssize_t +prom0_recv(pd, buf, len) + struct promdata *pd; + void *buf; + size_t len; +{ + struct saioreq *si; + struct saif *sif; + char *dmabuf; + int rv; + + si = pd->si; + sif = si->si_sif; + dmabuf = dvma_mapin(buf, len); + rv = sif->sif_poll(si->si_devdata, dmabuf); + dvma_mapout(dmabuf, len); + + return (ssize_t)rv; +} + +int +getchar() +{ + char c; + register int n; + + if (promvec->pv_romvec_vers > 2) + while ((n = (*promvec->pv_v2devops.v2_read) + (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1)) != 1); + else + c = (*promvec->pv_getchar)(); + + if (c == '\r') + c = '\n'; + return (c); +} + +int +peekchar() +{ + char c; + register int n; + + if (promvec->pv_romvec_vers > 2) { + n = (*promvec->pv_v2devops.v2_read) + (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1); + if (n < 0) + return -1; + } else + c = (*promvec->pv_nbgetchar)(); + + if (c == '\r') + c = '\n'; + return (c); +} +#endif + +static void +pv_putchar(c) + int c; +{ + char c0 = c; + + if (promvec->pv_romvec_vers > 2) + (*promvec->pv_v2devops.v2_write) + (*promvec->pv_v2bootargs.v2_fd1, &c0, 1); + else + (*promvec->pv_putchar)(c); +} + +void +putchar(c) + int c; +{ + + if (c == '\n') + pv_putchar('\r'); + pv_putchar(c); +} + +void +_rtt() +{ + promvec->pv_halt(); +} + +#ifndef BOOTXX +int hz = 1000; + +time_t +getsecs() +{ + register int ticks = getticks(); + return ((time_t)(ticks / hz)); +} + +int +getticks() +{ + if (promvec->pv_romvec_vers >= 2) { + char c; + (void)(*promvec->pv_v2devops.v2_read) + (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 0); + } else { + (void)(*promvec->pv_nbgetchar)(); + } + return *(promvec->pv_ticks); +} + +void +prom_getether(fd, ea) + u_char *ea; +{ + if (cputyp == CPU_SUN4) { + static struct idprom sun4_idprom; + u_char *src, *dst; + int len, x; + + if (sun4_idprom.id_format == 0) { + dst = (char*)&sun4_idprom; + src = (char*)AC_IDPROM; + len = sizeof(struct idprom); + do { + x = lduba(src++, ASI_CONTROL); + *dst++ = x; + } while (--len > 0); + } + bcopy(sun4_idprom.id_ether, ea, 6); + } else if (promvec->pv_romvec_vers < 2) { + (void)(*promvec->pv_enaddr)(fd, (char *)ea); + } else { + char buf[64]; + sprintf(buf, "%x mac-address drop swap 6 cmove", ea); + promvec->pv_fortheval.v2_eval(buf); + } +} + + +/* + * A number of well-known devices on sun4s. + */ +static struct dtab { + char *name; + int type; +} dtab[] = { + { "sd", DT_BLOCK }, + { "st", DT_BLOCK }, + { "xd", DT_BLOCK }, + { "xy", DT_BLOCK }, + { "fd", DT_BLOCK }, + { "le", DT_NET }, + { "ie", DT_NET }, + { NULL, 0 } +}; + +int +getdevtype(fd, name) + int fd; + char *name; +{ + if (promvec->pv_romvec_vers >= 2) { + int node = (*promvec->pv_v2devops.v2_fd_phandle)(fd); + char *cp = getpropstring(node, "device_type"); + if (strcmp(cp, "block") == 0) + return DT_BLOCK; + else if (strcmp(cp, "network") == 0) + return DT_NET; + else if (strcmp(cp, "byte") == 0) + return DT_BYTE; + } else { + struct dtab *dp; + for (dp = dtab; dp->name; dp++) { + if (name[0] == dp->name[0] && + name[1] == dp->name[1]) + return dp->type; + } + } + return 0; +} + +/* + * OpenPROM nodes & property routines (from <sparc/autoconf.c>). + */ +int +getprop(node, name, buf, bufsiz) + int node; + char *name; + void *buf; + register int bufsiz; +{ + register struct nodeops *no; + register int len; + + no = promvec->pv_nodeops; + len = no->no_proplen(node, name); + if (len > bufsiz) { + printf("node %x property %s length %d > %d\n", + node, name, len, bufsiz); + return (0); + } + no->no_getprop(node, name, buf); + return (len); +} + +/* + * Return a string property. There is a (small) limit on the length; + * the string is fetched into a static buffer which is overwritten on + * subsequent calls. + */ +char * +getpropstring(node, name) + int node; + char *name; +{ + register int len; + static char stringbuf[64]; + + len = getprop(node, name, (void *)stringbuf, sizeof stringbuf - 1); + if (len == -1) + len = 0; + stringbuf[len] = '\0'; /* usually unnecessary */ + return (stringbuf); +} +#endif /* BOOTXX */ + +/* + * Old monitor routines + */ + +#include <machine/pte.h> + +struct saioreq prom_si; +static int promdev_inuse; + +int +prom0_iopen(pd) + struct promdata *pd; +{ + struct om_bootparam *bp; + struct om_boottable *ops; + struct devinfo *dip; + struct saioreq *si; + int error; + + if (promdev_inuse) + return(EMFILE); + + bp = *romp->bootParam; + ops = bp->bootTable; + dip = ops->b_devinfo; + +#ifdef DEBUG_PROM + printf("Boot device type: %s\n", ops->b_desc); + printf("d_devbytes=%d\n", dip->d_devbytes); + printf("d_dmabytes=%d\n", dip->d_dmabytes); + printf("d_localbytes=%d\n", dip->d_localbytes); + printf("d_stdcount=%d\n", dip->d_stdcount); + printf("d_stdaddrs[%d]=%x\n", bp->ctlrNum, dip->d_stdaddrs[bp->ctlrNum]); + printf("d_devtype=%d\n", dip->d_devtype); + printf("d_maxiobytes=%d\n", dip->d_maxiobytes); +#endif + + dvma_init(); + + si = &prom_si; + bzero((caddr_t)si, sizeof(*si)); + si->si_boottab = ops; + si->si_ctlr = bp->ctlrNum; + si->si_unit = bp->unitNum; + si->si_boff = bp->partNum; + + if (si->si_ctlr > dip->d_stdcount) { + printf("Invalid controller number\n"); + return(ENXIO); + } + + if (dip->d_devbytes) { + si->si_devaddr = prom_mapin(dip->d_stdaddrs[si->si_ctlr], + dip->d_devbytes, dip->d_devtype); +#ifdef DEBUG_PROM + printf("prom_iopen: devaddr=0x%x pte=0x%x\n", + si->si_devaddr, + getpte((u_long)si->si_devaddr & ~PGOFSET)); +#endif + } + + if (dip->d_dmabytes) { + si->si_dmaaddr = dvma_alloc(dip->d_dmabytes); +#ifdef DEBUG_PROM + printf("prom_iopen: dmaaddr=0x%x\n", si->si_dmaaddr); +#endif + } + + if (dip->d_localbytes) { + si->si_devdata = alloc(dip->d_localbytes); +#ifdef DEBUG_PROM + printf("prom_iopen: devdata=0x%x\n", si->si_devdata); +#endif + } + + /* OK, call the PROM device open routine. */ + error = (*ops->b_open)(si); + if (error != 0) { + printf("prom_iopen: \"%s\" error=%d\n", + ops->b_desc, error); + return (ENXIO); + } +#ifdef DEBUG_PROM + printf("prom_iopen: succeeded, error=%d\n", error); +#endif + + pd->si = si; + promdev_inuse++; + return (0); +} + +void +prom0_iclose(si) + struct saioreq *si; +{ + struct om_boottable *ops; + struct devinfo *dip; + + if (promdev_inuse == 0) + return; + + ops = si->si_boottab; + dip = ops->b_devinfo; + + (*ops->b_close)(si); + + if (si->si_dmaaddr) { + dvma_free(si->si_dmaaddr, dip->d_dmabytes); + si->si_dmaaddr = NULL; + } + + promdev_inuse = 0; +} + +static struct mapinfo { + int maptype; + int pgtype; + int base; +} prom_mapinfo[] = { + { MAP_MAINMEM, PG_OBMEM, 0 }, + { MAP_OBIO, PG_OBIO, 0 }, + { MAP_MBMEM, PG_VME16, 0xFF000000 }, + { MAP_MBIO, PG_VME16, 0xFFFF0000 }, + { MAP_VME16A16D, PG_VME16, 0xFFFF0000 }, + { MAP_VME16A32D, PG_VME32, 0xFFFF0000 }, + { MAP_VME24A16D, PG_VME16, 0xFF000000 }, + { MAP_VME24A32D, PG_VME32, 0xFF000000 }, + { MAP_VME32A16D, PG_VME16, 0 }, + { MAP_VME32A32D, PG_VME32, 0 }, +}; +static prom_mapinfo_cnt = sizeof(prom_mapinfo) / sizeof(prom_mapinfo[0]); + +/* The virtual address we will use for PROM device mappings. */ +static u_long prom_devmap = MONSHORTSEG; + +static char * +prom_mapin(physaddr, length, maptype) + u_long physaddr; + int length, maptype; +{ + int i, pa, pte, va; + + if (length > (4*NBPG)) + panic("prom_mapin: length=%d\n", length); + + for (i = 0; i < prom_mapinfo_cnt; i++) + if (prom_mapinfo[i].maptype == maptype) + goto found; + panic("prom_mapin: invalid maptype %d\n", maptype); +found: + + pte = prom_mapinfo[i].pgtype; + pte |= (PG_V|PG_W|PG_S|PG_NC); + pa = prom_mapinfo[i].base; + pa += physaddr; + pte |= ((pa >> PGSHIFT) & PG_PFNUM); + + va = prom_devmap; + do { + setpte(va, pte); + va += NBPG; + pte += 1; + length -= NBPG; + } while (length > 0); + return ((char*)(prom_devmap | (pa & PGOFSET))); +} + +void +prom0_fake() +{ +static struct promvec promvecstore; + + promvec = &promvecstore; + + promvec->pv_stdin = romp->inSource; + promvec->pv_stdout = romp->outSink; + promvec->pv_putchar = romp->putChar; + promvec->pv_putstr = romp->fbWriteStr; + promvec->pv_nbgetchar = romp->mayGet; + promvec->pv_getchar = romp->getChar; + promvec->pv_romvec_vers = 0; /* eek! */ + promvec->pv_reboot = romp->reBoot; + promvec->pv_abort = romp->abortEntry; + promvec->pv_setctxt = romp->setcxsegmap; + promvec->pv_v0bootargs = (struct v0bootargs **)(romp->bootParam); + promvec->pv_halt = romp->exitToMon; + promvec->pv_ticks = romp->nmiClock; + saveecho = *romp->echo; + *romp->echo = 0; +} diff --git a/sys/arch/sparc/stand/promdev.h b/sys/arch/sparc/stand/promdev.h new file mode 100644 index 00000000000..a3bede11f2c --- /dev/null +++ b/sys/arch/sparc/stand/promdev.h @@ -0,0 +1,82 @@ +/* $NetBSD: promdev.h,v 1.3 1995/09/18 21:31:50 pk Exp $ */ + +/* + * Copyright (c) 1993 Paul Kranenburg + * 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 Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <machine/bsd_openprom.h> + +struct promdata { + int fd; /* Openboot descriptor */ + struct saioreq *si; /* Oldmon IO request */ + int devtype; /* Kind of device we're booting from */ +#define DT_BLOCK 1 +#define DT_NET 2 +#define DT_BYTE 3 + /* Hooks for netif.c */ + int (*xmit) __P((struct promdata *, void *, size_t)); + int (*recv) __P((struct promdata *, void *, size_t)); +}; + +#define LOADADDR ((caddr_t)0x4000) +#define DDB_MAGIC ( ('D'<<24) | ('D'<<16) | ('B'<<8) | ('0') ) + +extern struct promvec *promvec; +extern char *prom_bootdevice; +extern char *prom_bootfile; +extern int prom_boothow; +extern int hz; +extern int cputyp, nbpg, pgofset, pgshift; +extern int debug; + +extern void prom_init __P((void)); + +/* Note: dvma_*() routines are for "oldmon" machines only */ +extern char *dvma_mapin __P((char *, size_t)); +extern char *dvma_mapout __P((char *, size_t)); +extern char *dvma_alloc __P((int)); + +/* + * duplicates from pmap.c for mapping device on "oldmon" machines. + */ +#include <sparc/sparc/asm.h> + +#define getcontext() lduba(AC_CONTEXT, ASI_CONTROL) +#define setcontext(c) stba(AC_CONTEXT, ASI_CONTROL, c) +#define getsegmap(va) (cputyp == CPU_SUN4C \ + ? lduba(va, ASI_SEGMAP) \ + : lduha(va, ASI_SEGMAP)) +#define setsegmap(va, pmeg) (cputyp == CPU_SUN4C \ + ? stba(va, ASI_SEGMAP, pmeg) \ + : stha(va, ASI_SEGMAP, pmeg)) +#define getregmap(va) ((unsigned)lduha(va+2, ASI_REGMAP) >> 8) +#define setregmap(va, smeg) stha(va+2, ASI_REGMAP, (smeg << 8)) + +#define getpte(va) lda(va, ASI_PTE) +#define setpte(va, pte) sta(va, ASI_PTE, pte) diff --git a/sys/arch/sparc/stand/srt0.S b/sys/arch/sparc/stand/srt0.S new file mode 100644 index 00000000000..6a8d538cb90 --- /dev/null +++ b/sys/arch/sparc/stand/srt0.S @@ -0,0 +1,188 @@ +/* $NetBSD: srt0.S,v 1.4 1995/09/16 23:20:37 pk Exp $ */ + +/* + * Copyright (c) 1994 Paul Kranenburg + * 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 Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <machine/param.h> +#include <machine/psl.h> + +#define CCFSZ 96 + + .file "str0.s" + + .data + .global _cputyp, _nbpg, _pgofset, _pgshift +_cputyp: + .word 1 +_nbpg: + .word 1 +_pgofset: + .word 1 +_pgshift: + .word 1 + + .text + .globl start + +start: + /* + * Set up a stack. + */ + set start, %o1 + save %o1, -CCFSZ, %sp + + /* + * Relocate. + */ +1: call 2f + nop +2: add %o7, (start-1b), %l0 + set start, %l1 + set _end, %o0 + sub %o0, %l1, %l2 ! length +3: ld [%l0], %o0 + add %l0, 4, %l0 + st %o0, [%l1] + subcc %l2, 4, %l2 + bg 3b + add %l1, 4, %l1 + + set 4f, %g1 + jmp %g1 + nop + +4: +#ifdef notyet + /* + * Enable traps + */ + wr %g0, 0, %wim ! make sure we can set psr + nop; nop; nop + wr %g0, PSR_S|PSR_PS|PSR_PIL, %psr ! set initial psr + nop; nop; nop + wr %g0, 2, %wim ! set initial %wim (w1 invalid) + + rd %psr, %l0 + wr %l0, PSR_ET, %psr + nop; nop; nop +#endif + + /* + * Clear BSS + */ + set _edata, %o0 ! bzero(edata, end - edata) + set _end, %o1 + call _bzero + sub %o1, %o0, %o1 + + /* + * Set CPU type that we are running on. + */ + sethi %hi(_cputyp), %o0 + set 0x4000, %g7 + cmp %i0, %g7 + beq 5f + nop + + /* + * Save address of PROM vector (passed in %i0). + */ + sethi %hi(_promvec), %o1 + st %i0, [%o1 + %lo(_promvec)] + + mov CPU_SUN4C, %g4 + mov SUN4CM_PGSHIFT, %g5 + b,a 6f + +5: + mov CPU_SUN4, %g4 + mov SUN4_PGSHIFT, %g5 + +6: + st %g4, [%o0 + %lo(_cputyp)] + sethi %hi(_pgshift), %o0 ! pgshift = log2(nbpg) + st %g5, [%o0 + %lo(_pgshift)] + + mov 1, %o0 ! nbpg = 1 << pgshift + sll %o0, %g5, %g5 + sethi %hi(_nbpg), %o0 ! nbpg = bytes in a page + st %g5, [%o0 + %lo(_nbpg)] + + sub %g5, 1, %g5 + sethi %hi(_pgofset), %o0 ! page offset = bytes in a page - 1 + st %g5, [%o0 + %lo(_pgofset)] + + call _main + mov %i0, %o0 + + ret + restore + + +#ifdef TIGHT + +/* + * XXX - Space saving .div & .rem routines (small & non-negative numbres only) + */ + .align 4 + .global .div, .udiv +! int n = 0; while (a >= b) { a -= b; n++; }; return n; +.div: +.udiv: + cmp %o0, %o1 + bl 2f + mov 0, %o5 +1: + sub %o0, %o1, %o0 + cmp %o0, %o1 + bge 1b + add %o5, 1, %o5 +2: + retl + mov %o5, %o0 + + .align 4 + .global .rem, .urem +! while (a>=b) a -= b; return a; +.rem: +.urem: + cmp %o0, %o1 + bl 2f + nop + sub %o0, %o1, %o0 +1: + cmp %o0, %o1 + bge,a 1b + sub %o0, %o1, %o0 +2: + retl + nop + +#endif /* TIGHT */ diff --git a/sys/arch/sparc/stand/version.c b/sys/arch/sparc/stand/version.c new file mode 100644 index 00000000000..f288f3059da --- /dev/null +++ b/sys/arch/sparc/stand/version.c @@ -0,0 +1,41 @@ +/* $NetBSD: version.c,v 1.4 1995/09/16 23:20:39 pk Exp $ */ + +/* + * Copyright (c) 1993 Paul Kranenburg + * 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 Paul Kranenburg. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +/* + * NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. + * + * 1.1 + * 1.2 get it to work with V0 bootproms. + * 1.4 add oldmon support and network support. + */ + +char *version = "$Revision: 1.1 $"; |