summaryrefslogtreecommitdiff
path: root/sys/arch/sparc/stand
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /sys/arch/sparc/stand
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/sparc/stand')
-rw-r--r--sys/arch/sparc/stand/Makefile36
-rw-r--r--sys/arch/sparc/stand/Makefile.inc30
-rw-r--r--sys/arch/sparc/stand/binstall.sh120
-rw-r--r--sys/arch/sparc/stand/boot.c261
-rw-r--r--sys/arch/sparc/stand/boot/Makefile18
-rw-r--r--sys/arch/sparc/stand/bootxx.c125
-rw-r--r--sys/arch/sparc/stand/bootxx/Makefile24
-rw-r--r--sys/arch/sparc/stand/conf.c46
-rw-r--r--sys/arch/sparc/stand/dvma.c119
-rw-r--r--sys/arch/sparc/stand/installboot.8140
-rw-r--r--sys/arch/sparc/stand/installboot.c389
-rw-r--r--sys/arch/sparc/stand/installboot/Makefile11
-rw-r--r--sys/arch/sparc/stand/net.c157
-rw-r--r--sys/arch/sparc/stand/netif_sun.c219
-rw-r--r--sys/arch/sparc/stand/promdev.c792
-rw-r--r--sys/arch/sparc/stand/promdev.h82
-rw-r--r--sys/arch/sparc/stand/srt0.S188
-rw-r--r--sys/arch/sparc/stand/version.c41
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 $";