summaryrefslogtreecommitdiff
path: root/sys/arch/sgi
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2012-03-19 17:38:32 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2012-03-19 17:38:32 +0000
commit227e066fd9009304a6c891f3cb9faf2854a5ece1 (patch)
treeb8c52235f5a79e4ba42e7efbf3ffa12f32b30de6 /sys/arch/sgi
parent5f9c7bf79f6f68b257dd9c5b019b47217ab87267 (diff)
Teach the bootblocks how to load kernel from tftp (i.e. when OSLoadPartition
is bootp() instead of a disk). Kind of ugly because of the usual `can't seek' problem causing kernels with symbols to be read from the network twice. While there, add a 32 bit ECOFF boot block, not hooked to the build yet, to be used shortly.
Diffstat (limited to 'sys/arch/sgi')
-rw-r--r--sys/arch/sgi/stand/Makefile3
-rw-r--r--sys/arch/sgi/stand/boot/Makefile5
-rw-r--r--sys/arch/sgi/stand/boot/arcbios.c15
-rw-r--r--sys/arch/sgi/stand/boot/boot.c6
-rw-r--r--sys/arch/sgi/stand/boot/conf.c11
-rw-r--r--sys/arch/sgi/stand/boot/diskio.c4
-rw-r--r--sys/arch/sgi/stand/boot/filesystem.c4
-rw-r--r--sys/arch/sgi/stand/boot/netfs.c291
-rw-r--r--sys/arch/sgi/stand/boot/netfs.h43
-rw-r--r--sys/arch/sgi/stand/boot/netio.c84
-rw-r--r--sys/arch/sgi/stand/bootecoff/Makefile19
-rw-r--r--sys/arch/sgi/stand/bootecoff/ld.script71
12 files changed, 541 insertions, 15 deletions
diff --git a/sys/arch/sgi/stand/Makefile b/sys/arch/sgi/stand/Makefile
index 86aed86675b..62a19908f9c 100644
--- a/sys/arch/sgi/stand/Makefile
+++ b/sys/arch/sgi/stand/Makefile
@@ -1,10 +1,11 @@
-# $OpenBSD: Makefile,v 1.6 2009/05/14 18:57:41 miod Exp $
+# $OpenBSD: Makefile,v 1.7 2012/03/19 17:38:29 miod Exp $
SUBDIR= sgivol
.if ${MACHINE} == "sgi"
SUBDIR+= libsa libsa32 libz libz32
SUBDIR+= boot64 boot32
+#SUBDIR+= bootecoff
.endif
.include <bsd.subdir.mk>
diff --git a/sys/arch/sgi/stand/boot/Makefile b/sys/arch/sgi/stand/boot/Makefile
index 2774eb6009c..d27ca2d696f 100644
--- a/sys/arch/sgi/stand/boot/Makefile
+++ b/sys/arch/sgi/stand/boot/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.11 2009/05/14 18:57:43 miod Exp $
+# $OpenBSD: Makefile,v 1.12 2012/03/19 17:38:31 miod Exp $
NOMAN= noman
@@ -11,7 +11,8 @@ CFLAGS+= -D__INTERNAL_LIBSA_CREAD ${STANDALONE}
AFLAGS+= ${SAABI}
S= ${.CURDIR}/../../../..
-SRCS= start.S boot.c filesystem.c conf.c diskio.c arcbios.c strstr.c
+SRCS= start.S arcbios.c boot.c conf.c diskio.c filesystem.c \
+ netfs.c netio.c strstr.c
.PATH: ${S}/lib/libsa
SRCS+= loadfile.c
diff --git a/sys/arch/sgi/stand/boot/arcbios.c b/sys/arch/sgi/stand/boot/arcbios.c
index 3c67a23dffc..ed7e32951c2 100644
--- a/sys/arch/sgi/stand/boot/arcbios.c
+++ b/sys/arch/sgi/stand/boot/arcbios.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: arcbios.c,v 1.14 2011/04/09 20:46:33 miod Exp $ */
+/* $OpenBSD: arcbios.c,v 1.15 2012/03/19 17:38:31 miod Exp $ */
/*-
* Copyright (c) 1996 M. Warner Losh. All rights reserved.
* Copyright (c) 1996-2004 Opsycon AB. All rights reserved.
@@ -47,6 +47,8 @@ static const struct systypes {
char *sys_name;
int sys_ip;
} sys_types[] = {
+ { "SGI-IP20", 20 },
+ { "SGI-IP22", 22 },
{ "SGI-IP30", 30 },
{ "SGI-IP32", 32 }
};
@@ -244,11 +246,15 @@ devopen(struct open_file *f, const char *fname, char **file)
int rc, i, n;
ecp = cp = fname;
+ namebuf[0] = '\0';
/*
* Scan the component list and find device and partition.
*/
- if (strncmp(cp, "dksc(", 5) == 0) {
+ if (strncmp(cp, "bootp()", 7) == 0) {
+ strlcpy(devname, "bootp", sizeof(devname));
+ strlcpy(namebuf, cp, sizeof(namebuf));
+ } else if (strncmp(cp, "dksc(", 5) == 0) {
strncpy(devname, "scsi", sizeof(devname));
cp += 5;
cp = boot_getnr(cp, &i);
@@ -257,7 +263,6 @@ devopen(struct open_file *f, const char *fname, char **file)
cp = boot_getnr(cp, &i);
/* i = target id */
if (*cp++ == ',') {
-
memcpy(namebuf, fname, cp - fname);
namebuf[cp - fname] = '\0';
strlcat(namebuf, "0)", sizeof namebuf);
@@ -291,10 +296,10 @@ devopen(struct open_file *f, const char *fname, char **file)
*/
dp = devsw;
n = ndevs;
- while(n--) {
+ while (n--) {
if (strcmp(devname, dp->dv_name) == 0) {
rc = (dp->dv_open)(f, namebuf, partition, 0);
- if (!rc) {
+ if (rc == 0) {
f->f_dev = dp;
if (file && *cp != '\0')
*file = (char *)cp;
diff --git a/sys/arch/sgi/stand/boot/boot.c b/sys/arch/sgi/stand/boot/boot.c
index 8af5f540b7b..89d99cf33b5 100644
--- a/sys/arch/sgi/stand/boot/boot.c
+++ b/sys/arch/sgi/stand/boot/boot.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: boot.c,v 1.18 2011/04/09 20:46:33 miod Exp $ */
+/* $OpenBSD: boot.c,v 1.19 2012/03/19 17:38:31 miod Exp $ */
/*
* Copyright (c) 2004 Opsycon AB, www.opsycon.se.
@@ -187,6 +187,10 @@ check_phdr(void *v)
uint64_t addr;
switch (IP) {
+ case 20:
+ case 22:
+ addr = 0xffffffff88000000ULL >> 28;
+ break;
case 27:
addr = 0xa800000000000000ULL >> 28;
break;
diff --git a/sys/arch/sgi/stand/boot/conf.c b/sys/arch/sgi/stand/boot/conf.c
index caa763f7b8f..b8c70ac1a01 100644
--- a/sys/arch/sgi/stand/boot/conf.c
+++ b/sys/arch/sgi/stand/boot/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.4 2011/03/13 00:13:53 deraadt Exp $ */
+/* $OpenBSD: conf.c,v 1.5 2012/03/19 17:38:31 miod Exp $ */
/*
* Copyright (c) 1997 Per Fogelstrom
@@ -34,11 +34,16 @@ extern int noioctl();
int diostrategy(void *, int, daddr32_t, size_t, void *, size_t *);
int dioopen(struct open_file *, ...);
int dioclose(struct open_file *);
-
#define dioioctl noioctl
+int netstrategy(void *, int, daddr32_t, size_t, void *, size_t *);
+int netopen(struct open_file *, ...);
+int netclose(struct open_file *);
+#define netioctl noioctl
+
struct devsw devsw[] = {
- { "scsi", diostrategy, dioopen, dioclose, dioioctl }
+ { "scsi", diostrategy, dioopen, dioclose, dioioctl },
+ { "bootp", netstrategy, netopen, netclose, netioctl }
};
int ndevs = (sizeof(devsw)/sizeof(devsw[0]));
diff --git a/sys/arch/sgi/stand/boot/diskio.c b/sys/arch/sgi/stand/boot/diskio.c
index e1bc49c51df..5768439a799 100644
--- a/sys/arch/sgi/stand/boot/diskio.c
+++ b/sys/arch/sgi/stand/boot/diskio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: diskio.c,v 1.6 2011/03/13 00:13:53 deraadt Exp $ */
+/* $OpenBSD: diskio.c,v 1.7 2012/03/19 17:38:31 miod Exp $ */
/*
* Copyright (c) 2000 Opsycon AB (www.opsycon.se)
@@ -45,7 +45,7 @@ struct dio_softc {
};
int
-diostrategy(void *devdata, int rw, daddr32_t bn, u_int reqcnt, void *addr,
+diostrategy(void *devdata, int rw, daddr32_t bn, size_t reqcnt, void *addr,
size_t *cnt)
{
struct dio_softc *sc = (struct dio_softc *)devdata;
diff --git a/sys/arch/sgi/stand/boot/filesystem.c b/sys/arch/sgi/stand/boot/filesystem.c
index e4f0fce6f00..c8c6efcffad 100644
--- a/sys/arch/sgi/stand/boot/filesystem.c
+++ b/sys/arch/sgi/stand/boot/filesystem.c
@@ -35,9 +35,11 @@
#include <stand.h>
#include <ufs.h>
+#include "netfs.h"
struct fs_ops file_system[] = {
- { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat }
+ { netfs_open, netfs_close, netfs_read, netfs_write, netfs_seek, netfs_stat },
+ { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat },
};
int nfsys = sizeof(file_system)/sizeof(struct fs_ops);
diff --git a/sys/arch/sgi/stand/boot/netfs.c b/sys/arch/sgi/stand/boot/netfs.c
new file mode 100644
index 00000000000..07d61b352d8
--- /dev/null
+++ b/sys/arch/sgi/stand/boot/netfs.c
@@ -0,0 +1,291 @@
+/* $OpenBSD: netfs.c,v 1.1 2012/03/19 17:38:31 miod Exp $ */
+
+/*-
+ * Copyright (c) 2001 Steve Murphree, Jr.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * TFTP file system.
+ */
+
+#include <sys/param.h>
+#include <lib/libkern/libkern.h>
+#include <stand.h>
+
+#include <sys/stat.h>
+
+#include "netfs.h"
+
+/*
+ * In-core open file.
+ */
+struct tftp_file {
+ char filename[128];
+ off_t f_seekp; /* seek pointer */
+ char *f_buf; /* buffer for data block */
+ off_t f_off; /* index into buffer for data block */
+ daddr32_t f_buf_blkno; /* block number of data block */
+ size_t f_buf_size;
+};
+
+#define TFTP_BLOCK_SHIFT 9
+#define TFTP_BLOCK_SIZE (1<<TFTP_BLOCK_SHIFT) /* 512 by tftp convention */
+#define TFTP_BLOCK_NO(x) ((x >> TFTP_BLOCK_SHIFT) + 1)
+#define TFTP_BLOCK_OFF(x) (x % TFTP_BLOCK_SIZE)
+
+static int tftp_read_file(struct open_file *, char **, size_t *);
+
+/*
+ * Read a portion of a file into an internal buffer. Return
+ * the location in the buffer and the amount in the buffer.
+ */
+
+char tftp_buf[TFTP_BLOCK_SIZE]; /* static */
+struct tftp_file tftp_ctrl;
+
+static int
+tftp_read_file(f, buf_p, size_p)
+ struct open_file *f;
+ char **buf_p; /* out */
+ size_t *size_p; /* out */
+{
+ struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
+ long off;
+ daddr32_t file_block;
+ size_t block_size;
+ int i, rc;
+
+ off = TFTP_BLOCK_OFF(fp->f_seekp);
+ file_block = TFTP_BLOCK_NO(fp->f_seekp);
+ block_size = TFTP_BLOCK_SIZE;
+
+ if (file_block == fp->f_buf_blkno + 1) {
+ /*
+ * Normal, incremental block transfer.
+ */
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ file_block, block_size, fp->f_buf, &fp->f_buf_size);
+ if (rc)
+ return (rc);
+ if (!(file_block % 4)) /* twiddle every 4 blocks */
+ twiddle();
+ fp->f_buf_blkno = file_block;
+ } else if (file_block > fp->f_buf_blkno + 1) {
+ /*
+ * Read ahead to the requested block; If we need
+ * those we skipped, see below.
+ */
+ for (i = (fp->f_buf_blkno + 1); i <= file_block; i++) {
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ i, block_size, fp->f_buf, &fp->f_buf_size);
+ if (rc)
+ return (rc);
+ }
+ fp->f_buf_blkno = file_block;
+ } else if (file_block < fp->f_buf_blkno) {
+ /*
+ * Uh oh... We can't rewind. Reopen the file
+ * and start again.
+ */
+ char filename[128];
+
+ strlcpy(filename, fp->filename, sizeof filename);
+ netfs_close(f);
+ netfs_open(filename, f);
+
+ /* restore f_seekp reset by netfs_open() */
+ fp->f_seekp = (file_block - 1) * TFTP_BLOCK_SIZE + off;
+ for (i = 1; i <= file_block; i++) {
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ i, block_size, fp->f_buf, &fp->f_buf_size);
+ if (rc)
+ return (rc);
+ }
+ fp->f_buf_blkno = file_block;
+ }
+
+ /*
+ * Return address of byte in buffer corresponding to
+ * offset, and size of remainder of buffer after that
+ * byte.
+ */
+ *buf_p = fp->f_buf + off;
+ *size_p = fp->f_buf_size - off;
+
+ /*
+ * But truncate buffer at end of file.
+ */
+ if (fp->f_buf_size > block_size){
+ twiddle();
+ return(EIO);
+ }
+
+
+ return (0);
+}
+
+/*
+ * Open a file.
+ */
+int
+netfs_open(path, f)
+ char *path;
+ struct open_file *f;
+{
+ struct tftp_file *fp;
+ int rc = 0;
+extern int netstrategy(void *, int, daddr32_t, size_t, void *, size_t *);
+
+ if (f->f_dev->dv_strategy != netstrategy)
+ return EINVAL;
+
+ /* locate file system specific data structure and zero it.*/
+ fp = &tftp_ctrl;
+ bzero(fp, sizeof(struct tftp_file));
+ f->f_fsdata = (void *)fp;
+ fp->f_seekp = 0;
+ fp->f_buf = tftp_buf;
+ bzero(fp->f_buf, TFTP_BLOCK_SIZE);
+ fp->f_buf_size = 0;
+
+ strlcpy(fp->filename, path, sizeof fp->filename);
+
+ twiddle();
+ rc = (f->f_dev->dv_open)(f, path);
+ return (rc);
+}
+
+int
+netfs_close(f)
+ struct open_file *f;
+{
+ struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
+
+ fp->f_buf = (void *)0;
+ f->f_fsdata = (void *)0;
+ (f->f_dev->dv_close)(f);
+ return (0);
+}
+
+/*
+ * Copy a portion of a file into kernel memory.
+ * Cross block boundaries when necessary.
+ */
+int
+netfs_read(f, start, size, resid)
+ struct open_file *f;
+ void *start;
+ size_t size;
+ size_t *resid; /* out */
+{
+ struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
+ size_t csize;
+ char *buf;
+ size_t buf_size;
+ int rc = 0;
+ char *addr = start;
+
+ while (size != 0) {
+ rc = tftp_read_file(f, &buf, &buf_size);
+ if (rc)
+ break;
+
+ csize = size;
+ if (csize > buf_size)
+ csize = buf_size;
+
+ bcopy(buf, addr, csize);
+
+ fp->f_seekp += csize;
+ addr += csize;
+ size -= csize;
+ }
+ if (resid)
+ *resid = size;
+ return (rc);
+}
+
+/*
+ * Not implemented.
+ */
+int
+netfs_write(f, start, size, resid)
+ struct open_file *f;
+ void *start;
+ size_t size;
+ size_t *resid; /* out */
+{
+
+ return (EROFS);
+}
+
+/*
+ * We only see forward. We can't rewind.
+ */
+off_t
+netfs_seek(f, offset, where)
+ struct open_file *f;
+ off_t offset;
+ int where;
+{
+ struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
+
+ switch (where) {
+ case SEEK_SET:
+ fp->f_seekp = offset;
+ break;
+ case SEEK_CUR:
+ fp->f_seekp += offset;
+ break;
+ case SEEK_END:
+ errno = EIO;
+ return (-1);
+ break;
+ default:
+ return (-1);
+ }
+ return (fp->f_seekp);
+}
+
+int
+netfs_stat(f, sb)
+ struct open_file *f;
+ struct stat *sb;
+{
+ return EIO;
+}
+
+#ifndef NO_READDIR
+int
+netfs_readdir (struct open_file *f, char *name)
+{
+ return EIO;
+}
+#endif
+
diff --git a/sys/arch/sgi/stand/boot/netfs.h b/sys/arch/sgi/stand/boot/netfs.h
new file mode 100644
index 00000000000..f6e1c4b44da
--- /dev/null
+++ b/sys/arch/sgi/stand/boot/netfs.h
@@ -0,0 +1,43 @@
+/* $OpenBSD: netfs.h,v 1.1 2012/03/19 17:38:31 miod Exp $ */
+
+/*-
+ * Copyright (c) 2001 Steve Murphree, Jr.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+int netfs_open(char *path, struct open_file *f);
+int netfs_close(struct open_file *f);
+int netfs_read(struct open_file *f, void *buf,
+ size_t size, size_t *resid);
+int netfs_write(struct open_file *f, void *buf,
+ size_t size, size_t *resid);
+off_t netfs_seek(struct open_file *f, off_t offset, int where);
+int netfs_stat(struct open_file *f, struct stat *sb);
+#ifndef NO_READDIR
+int netfs_readdir(struct open_file *f, char *name);
+#endif
diff --git a/sys/arch/sgi/stand/boot/netio.c b/sys/arch/sgi/stand/boot/netio.c
new file mode 100644
index 00000000000..2a25d7f8aa0
--- /dev/null
+++ b/sys/arch/sgi/stand/boot/netio.c
@@ -0,0 +1,84 @@
+/* $OpenBSD: netio.c,v 1.1 2012/03/19 17:38:31 miod Exp $ */
+
+/*
+ * Copyright (c) 2012 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#include <sys/param.h>
+#include <lib/libkern/libkern.h>
+#include <stand.h>
+
+#include <mips64/arcbios.h>
+
+int
+netstrategy(void *devdata, int rw, daddr32_t bn, size_t reqcnt, void *addr,
+ size_t *cnt)
+{
+ long fd = (long)devdata;
+ long result;
+ int rc;
+
+ rc = Bios_Read(fd, addr, reqcnt, &result);
+ if (rc != 0)
+ return (EIO);
+
+ *cnt = result;
+ return 0;
+}
+
+int
+netopen(struct open_file *f, ...)
+{
+ char *path;
+ long fd;
+ int rc;
+ va_list ap;
+
+ va_start(ap, f);
+ path = va_arg(ap, char *);
+ va_end(ap);
+
+ /* to match netfs.c filename buffers... */
+ if (strlen(path) > 128 - 1)
+ return ENAMETOOLONG;
+
+ rc = Bios_Open(path, 0, &fd);
+ if (rc != 0) {
+ switch (rc) {
+ case arc_EACCES:
+ return EACCES;
+ case arc_EISDIR:
+ return EISDIR;
+ case arc_ENOENT:
+ return ENOENT;
+ default:
+ return ENXIO;
+ }
+ }
+
+ f->f_devdata = (void *)fd;
+
+ return 0;
+}
+
+int
+netclose(struct open_file *f)
+{
+ long fd = (long)f->f_devdata;
+
+ (void)Bios_Close(fd);
+ return 0;
+}
diff --git a/sys/arch/sgi/stand/bootecoff/Makefile b/sys/arch/sgi/stand/bootecoff/Makefile
new file mode 100644
index 00000000000..10feda4723c
--- /dev/null
+++ b/sys/arch/sgi/stand/bootecoff/Makefile
@@ -0,0 +1,19 @@
+# $OpenBSD: Makefile,v 1.1 2012/03/19 17:38:31 miod Exp $
+
+.include "${.CURDIR}/../Makefile32.inc"
+STRIP?= strip
+LDSCRIPT= ${.CURDIR}/ld.script
+LDFLAGS+= ${SALDFLAGS} -T ${LDSCRIPT} -e __start -N -s
+PROG= bootecoff
+.PATH: ${.CURDIR}/../boot
+.include "${.CURDIR}/../boot/Makefile"
+
+SRCS+= ashrdi3.c moddi3.c udivdi3.c umoddi3.c qdivrem.c
+
+${PROG}: $(OBJS) $(LDADD)
+ $(LD) $(LDFLAGS) -o ${PROG} $(OBJS) -L${LIBSADIR} ${LIBSA} \
+ -L${LIBZDIR} ${LIBZ}
+
+LINKS= ${BINDIR}/${PROG} ${BINDIR}/boot-IP22
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/sgi/stand/bootecoff/ld.script b/sys/arch/sgi/stand/bootecoff/ld.script
new file mode 100644
index 00000000000..deee3ac2bf1
--- /dev/null
+++ b/sys/arch/sgi/stand/bootecoff/ld.script
@@ -0,0 +1,71 @@
+OUTPUT_FORMAT("ecoff-bigmips", "ecoff-bigmips",
+ "ecoff-littlemips")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0x88002000 + SIZEOF_HEADERS;
+ .text :
+ {
+ _ftext = . ;
+ *(.text)
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.reginfo)
+ *(.init)
+ *(.stub)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ } =0
+ _etext = .;
+ PROVIDE (etext = .);
+ .fini : { *(.fini) } =0
+ .data :
+ {
+ _fdata = . ;
+ *(.data)
+ CONSTRUCTORS
+ }
+ .data1 : { *(.data1) }
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+ _gp = ALIGN(16) + 0x7ff0;
+ .got :
+ {
+ *(.got.plt) *(.got)
+ }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : { *(.sdata) }
+ .lit8 : { *(.lit8) }
+ .lit4 : { *(.lit4) }
+ _edata = .;
+ PROVIDE (edata = .);
+ __bss_start = .;
+ _fbss = .;
+ .sbss : { *(.sbss) *(.scommon) }
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+ /DISCARD/ : {
+ *(.pdr)
+ *(.mdebug.abi32)
+ *(.comment)
+ *(.stab)
+ *(.stabstr)
+ *(.debug)
+ *(.debug_srcinfo)
+ *(.debug_aranges)
+ *(.debug_pubnames)
+ *(.debug_sfnames)
+ *(.line)
+ }
+}