summaryrefslogtreecommitdiff
path: root/sys/arch/wgrisc
diff options
context:
space:
mode:
authorPer Fogelstrom <pefo@cvs.openbsd.org>1997-07-21 06:58:16 +0000
committerPer Fogelstrom <pefo@cvs.openbsd.org>1997-07-21 06:58:16 +0000
commit165d6cf5bda061baecb1399468bb228204e73e43 (patch)
treeb498d0899dfe93665f8ce1ab240686f6f0e4e04d /sys/arch/wgrisc
parent7d330777bab7dbaf8003284034c688a493098134 (diff)
New boot code that fits into the boot record with embedded label.
Diffstat (limited to 'sys/arch/wgrisc')
-rw-r--r--sys/arch/wgrisc/stand/Makefile.inc8
-rw-r--r--sys/arch/wgrisc/stand/boot/Makefile12
-rw-r--r--sys/arch/wgrisc/stand/boot/boot.c76
-rw-r--r--sys/arch/wgrisc/stand/boot/conf.c37
-rw-r--r--sys/arch/wgrisc/stand/boot/fl.c102
-rw-r--r--sys/arch/wgrisc/stand/boot/sd.c77
-rw-r--r--sys/arch/wgrisc/stand/boot/start.S186
-rw-r--r--sys/arch/wgrisc/stand/libsa/Makefile10
-rw-r--r--sys/arch/wgrisc/stand/libsa/devopen.c126
-rw-r--r--sys/arch/wgrisc/stand/libsa/gets.c22
-rw-r--r--sys/arch/wgrisc/stand/libsa/ufs.c762
11 files changed, 1163 insertions, 255 deletions
diff --git a/sys/arch/wgrisc/stand/Makefile.inc b/sys/arch/wgrisc/stand/Makefile.inc
index 5c847e9f9e6..6134f2b753e 100644
--- a/sys/arch/wgrisc/stand/Makefile.inc
+++ b/sys/arch/wgrisc/stand/Makefile.inc
@@ -1,10 +1,8 @@
-# $OpenBSD: Makefile.inc,v 1.1 1997/05/11 16:17:48 pefo Exp $
+# $OpenBSD: Makefile.inc,v 1.2 1997/07/21 06:58:11 pefo Exp $
CPPFLAGS+=-Wall -Werror -I. -Imachine
-CPPFLAGS+=-D_STANDALONE -DSTRIPPED
-CFLAGS+=-mno-abicalls -mips1 -mcpu=r3000
-START=0x10000
-HEAP_LIMIT=0x50000
+CPPFLAGS+=-D_STANDALONE -DSTRIPPED -DALLOC_FIRST_FIT -DNO_SYM_LINKS
+CFLAGS+=-O2 -mno-abicalls -mips1 -mcpu=r3000
BOOTREL=0x3000
BOOTMAGIC=0xdeadbeef
diff --git a/sys/arch/wgrisc/stand/boot/Makefile b/sys/arch/wgrisc/stand/boot/Makefile
index 9979ff28502..06c3d12b698 100644
--- a/sys/arch/wgrisc/stand/boot/Makefile
+++ b/sys/arch/wgrisc/stand/boot/Makefile
@@ -1,8 +1,8 @@
-# $OpenBSD: Makefile,v 1.1 1997/05/11 16:17:51 pefo Exp $
+# $OpenBSD: Makefile,v 1.2 1997/07/21 06:58:11 pefo Exp $
PROG=boot
SADIR=${.CURDIR}/..
-SRCS=start.S boot.c filesystem.c conf.c sd.c
+SRCS=start.S boot.c filesystem.c conf.c sd.c fl.c
CFLAGS+=$(SACFLAGS) -I${.CURDIR}/../../../../lib/libsa -I${.CURDIR}/../libsa
CFLAGS+=-D__INTERNAL_LIBSA_CREAD
@@ -17,13 +17,15 @@ machine-links:
@ln -fs ${.CURDIR}/../.. wgrisc
@ln -fs ${.CURDIR}/../../include machine
-${PROG}: $(OBJS) $(DPADD)
+${PROG}: $(OBJS) $(LDADD)
$(LD) $(LDFLAGS) -o $(PROG) $(OBJS) $(LDADD)
-${PROG}.bin: ${PROG}
+${PROG}.bin: ${PROG}
cp ${PROG} ${PROG}.tmp
strip -s ${PROG}.tmp
- dd if=${PROG}.tmp of=${PROG}.bin bs=4096 skip=1
+ dd if=${PROG}.tmp of=${PROG}.bin bs=512 skip=8 count=1
+ dd if=/dev/zero of=${PROG}.bin bs=512 seek=1 count=1
+ dd if=${PROG}.tmp of=${PROG}.bin bs=512 skip=9 seek=2 count=14
rm ${PROG}.tmp
.include <bsd.prog.mk>
diff --git a/sys/arch/wgrisc/stand/boot/boot.c b/sys/arch/wgrisc/stand/boot/boot.c
index 6892d6a6a23..2e7cf0742ff 100644
--- a/sys/arch/wgrisc/stand/boot/boot.c
+++ b/sys/arch/wgrisc/stand/boot/boot.c
@@ -1,12 +1,8 @@
-/* $NetBSD: boot.c,v 1.6 1995/06/28 10:22:32 jonathan Exp $ */
+/* $OpenBSD: boot.c,v 1.2 1997/07/21 06:58:12 pefo Exp $ */
/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Ralph Campbell.
- *
+ * Copyright (c) 1997 Per Fogelstrom
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,17 +13,16 @@
* 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 product includes software developed under OpenBSD by
+ * Per Fogelstrom.
+ * 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 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
+ * 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
@@ -35,7 +30,6 @@
* 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>
@@ -46,29 +40,24 @@
#include <errno.h>
-char line[1024];
void gets __P((char *));
ssize_t read __P((int, void *, size_t));
int close __P((int));
void prom_write __P((int, char *, int));
-int main __P((int, char **));
+void main __P((int, char **));
int loadfile __P((char *));
/*
- * This gets arguments from the PROM, calls other routines to open
- * and load the program to boot, and then transfers execution to that
- * new program.
- * Argv[0] should be something like "rz(0,0,0)vmunix" on a DECstation 3100.
- * Argv[0,1] should be something like "boot 5/rz0/vmunix" on a DECstation 5000.
- * The argument "-a" means vmunix should do an automatic reboot.
*/
-int
+void
main(argc, argv)
int argc;
char **argv;
{
- char *cp = 0;
+static char boot[] = {"Boot:"};
+ char *cp = boot;
int ask, entry;
+ char line[1024];
ask = 1;
@@ -78,23 +67,22 @@ main(argc, argv)
}
while(1) {
do {
- printf("Boot: ");
+ printf("%s\n", cp);
if (ask) {
gets(line);
cp = line;
argv[0] = cp;
argc = 1;
- } else
- printf("%s\n", cp);
+ }
} while(ask && line[0] == '\0');
entry = loadfile(cp);
if (entry != -1) {
- printf("Starting at 0x%x\n\n", entry);
((void (*)())entry)(argc, argv, 0, 0);
}
+ ask = 1;
+ cp = boot;
}
- return(0);
}
/*
@@ -108,9 +96,10 @@ loadfile(fname)
Elf32_Ehdr eh;
Elf32_Phdr *ph;
u_long phsize;
+ char *errs = 0;
if ((fd = oopen(fname, 0)) < 0) {
- printf("open(%s) failed: %d\n", fname, errno);
+ errs="open(%s) err: %d\n";
goto err;
}
@@ -126,24 +115,19 @@ loadfile(fname)
goto serr;
}
- for(i = 0; i < eh.e_phnum; i++) {
- switch (ph[i].p_type) {
- case PT_LOAD:
- olseek(fd, ph[i].p_offset, 0);
- if(oread(fd, (char *)ph[i].p_paddr, ph[i].p_filesz) != ph[i].p_filesz) {
+ for(i = 0; i < eh.e_phnum; i++, ph++) {
+ if(ph->p_type == PT_LOAD) {
+ olseek(fd, ph->p_offset, 0);
+ if(oread(fd, (char *)ph->p_paddr, ph->p_filesz) != ph->p_filesz) {
goto serr;
}
- break;
- default:
- break;
}
}
- (void) oclose(fd);
return(eh.e_entry);
serr:
- printf("Read size error\n");
+ errs = "rd(%s) sz err\n";
err:
- printf("Can't boot '%s'\n", fname);
- (void) oclose(fd);
+ printf(errs, fname, errno);
return (-1);
}
+
diff --git a/sys/arch/wgrisc/stand/boot/conf.c b/sys/arch/wgrisc/stand/boot/conf.c
index fa2b4cb730c..3c991b8edbe 100644
--- a/sys/arch/wgrisc/stand/boot/conf.c
+++ b/sys/arch/wgrisc/stand/boot/conf.c
@@ -1,12 +1,8 @@
-/* $NetBSD: conf.c,v 1.5 1995/01/18 06:53:39 mellon Exp $ */
+/* $OpenBSD: conf.c,v 1.2 1997/07/21 06:58:12 pefo Exp $ */
/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Ralph Campbell.
- *
+ * Copyright (c) 1997 Per Fogelstrom
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,17 +13,16 @@
* 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 product includes software developed under OpenBSD by
+ * Per Fogelstrom.
+ * 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 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
+ * 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
@@ -35,9 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)conf.c 8.1 (Berkeley) 6/10/93
*/
-
#include <stand.h>
int errno;
@@ -50,10 +43,16 @@ int sdstrategy __P((void *, int, daddr_t, size_t, void *, size_t *));
int sdopen __P((struct open_file *, ...));
int sdclose __P((struct open_file *));
+int flstrategy __P((void *, int, daddr_t, size_t, void *, size_t *));
+int flopen __P((struct open_file *, ...));
+int flclose __P((struct open_file *));
+
#define sdioctl noioctl
+#define flioctl noioctl
struct devsw devsw[] = {
{ "sd", sdstrategy, sdopen, sdclose, sdioctl }, /*0*/
+ { "fl", flstrategy, flopen, flclose, flioctl }, /*1*/
};
int ndevs = (sizeof(devsw)/sizeof(devsw[0]));
diff --git a/sys/arch/wgrisc/stand/boot/fl.c b/sys/arch/wgrisc/stand/boot/fl.c
new file mode 100644
index 00000000000..02459551ff7
--- /dev/null
+++ b/sys/arch/wgrisc/stand/boot/fl.c
@@ -0,0 +1,102 @@
+/* $OpenBSD: fl.c,v 1.1 1997/07/21 06:58:13 pefo Exp $ */
+
+/*
+ * Copyright (c) 1997 Per Fogelstrom
+ *
+ * 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 under OpenBSD by
+ * Per Fogelstrom.
+ * 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 <stdarg.h>
+
+#include <stand.h>
+#include <sys/param.h>
+
+int prom_seek __P((int, long, int));
+int disk_read __P((int, char *, int, int));
+int disk_open __P((char *, int));
+
+struct fl_softc {
+ int sc_fd; /* PROM file id */
+};
+
+int
+flstrategy(devdata, rw, bn, reqcnt, addr, cnt)
+ void *devdata;
+ int rw;
+ daddr_t bn;
+ u_int reqcnt;
+ char *addr;
+ u_int *cnt; /* out: number of bytes transfered */
+{
+ struct fl_softc *sc = (struct fl_softc *)devdata;
+ int s;
+ long offset;
+
+ offset = bn * DEV_BSIZE;
+
+ s = disk_read(sc->sc_fd, addr, offset, reqcnt);
+ if (s < 0)
+ return (-s);
+ *cnt = s;
+ return (0);
+}
+
+/*
+ * We only deal with flash 0 here. We need to be small.
+ */
+int
+flopen(struct open_file *f, ...)
+{
+ struct fl_softc *sc;
+ int fd;
+ static char device[] = "fl(0)";
+
+ fd = disk_open(device, 0);
+ if (fd < 0) {
+ return (ENXIO);
+ }
+
+ sc = alloc(sizeof(struct fl_softc));
+ f->f_devdata = (void *)sc;
+
+ sc->sc_fd = fd;
+
+ return (0);
+}
+
+int
+flclose(f)
+ struct open_file *f;
+{
+#ifdef FANCY
+ free(f->f_devdata, sizeof(struct fl_softc));
+ f->f_devdata = (void *)0;
+#endif
+ return (0);
+}
diff --git a/sys/arch/wgrisc/stand/boot/sd.c b/sys/arch/wgrisc/stand/boot/sd.c
index 34f8068e14a..dfc9b51317e 100644
--- a/sys/arch/wgrisc/stand/boot/sd.c
+++ b/sys/arch/wgrisc/stand/boot/sd.c
@@ -50,8 +50,6 @@ int disk_open __P((char *, int));
struct sd_softc {
int sc_fd; /* PROM file id */
- int sc_ctlr; /* controller number */
- int sc_unit; /* disk unit number */
int sc_part; /* disk partition number */
struct disklabel sc_label; /* disk label for this disk */
};
@@ -66,30 +64,16 @@ sdstrategy(devdata, rw, bn, reqcnt, addr, cnt)
u_int *cnt; /* out: number of bytes transfered */
{
struct sd_softc *sc = (struct sd_softc *)devdata;
- int part = sc->sc_part;
- struct partition *pp = &sc->sc_label.d_partitions[part];
+ struct partition *pp = &sc->sc_label.d_partitions[sc->sc_part];
int s;
long offset;
- offset = bn * DEV_BSIZE;
-
- /*
- * Partial-block transfers not handled.
- */
- if (reqcnt & (DEV_BSIZE - 1)) {
- *cnt = 0;
- return (EINVAL);
- }
-
- offset += pp->p_offset * DEV_BSIZE;
+ offset = (pp->p_offset + bn) * DEV_BSIZE;
s = disk_read(sc->sc_fd, addr, offset, reqcnt);
-#if 0 /* XXX error code not returned yet... */
- if (s <= 0)
- return (EIO);
-#endif
-
- *cnt = reqcnt;
+ if (s < 0)
+ return (-s);
+ *cnt = s;
return (0);
}
@@ -100,9 +84,8 @@ sdopen(struct open_file *f, ...)
struct sd_softc *sc;
struct disklabel *lp;
- struct dos_partition dp, *dp2;
int i, fd;
- char *msg;
+ char *msg = "rd err";
char buf[DEV_BSIZE];
int cnt;
daddr_t labelsector;
@@ -128,8 +111,6 @@ sdopen(struct open_file *f, ...)
f->f_devdata = (void *)sc;
sc->sc_fd = fd;
- sc->sc_ctlr = ctlr;
- sc->sc_unit = unit;
sc->sc_part = part;
lp = &sc->sc_label;
@@ -137,48 +118,46 @@ sdopen(struct open_file *f, ...)
lp->d_secpercyl = 1;
lp->d_npartitions = MAXPARTITIONS;
lp->d_partitions[part].p_offset = 0;
- lp->d_partitions[part].p_size = 0x7fffffff;
+ lp->d_partitions[part].p_size = 0x7fff0000;
+
+ labelsector = LABELSECTOR;
+#ifdef USE_DOSBBSECTOR
/* First check for any DOS partition table */
i = sdstrategy(sc, F_READ, (daddr_t)DOSBBSECTOR, DEV_BSIZE, buf, &cnt);
- if (i || cnt != DEV_BSIZE) {
- printf("sd%d: error reading disk label\n", unit);
- goto bad;
- }
- labelsector = 0;
- bcopy(buf + DOSPARTOFF, &dp, NDOSPART * sizeof(dp));
- for (dp2=&dp, i=0; i < NDOSPART; i++, dp2++) {
- if (dp2->dp_size && dp2->dp_typ == DOSPTYP_OPENBSD) {
- labelsector = dp2->dp_start;
- break;
+ if (!(i || cnt != DEV_BSIZE)) {
+ struct dos_partition dp, *dp2;
+ bcopy(buf + DOSPARTOFF, &dp, NDOSPART * sizeof(dp));
+ for (dp2=&dp, i=0; i < NDOSPART; i++, dp2++) {
+ if (dp2->dp_size) {
+ if((dp2->dp_typ == DOSPTYP_386BSD) ||
+ (dp2->dp_typ == DOSPTYP_OPENBSD)) {
+ labelsector += dp2->dp_start;
+ break;
+ }
+ }
}
}
- for (dp2=&dp, i=0; i < NDOSPART; i++, dp2++) {
- if (dp2->dp_size && dp2->dp_typ == DOSPTYP_386BSD) {
- labelsector = dp2->dp_start;
- break;
- }
+ else {
+ goto bad;
}
+#endif
/* try to read disk label and partition table information */
- labelsector += LABELSECTOR;
i = sdstrategy(sc, F_READ, (daddr_t)labelsector, DEV_BSIZE, buf, &cnt);
if (i || cnt != DEV_BSIZE) {
- printf("sd%d: error reading disk label\n", unit);
goto bad;
}
msg = getdisklabel(buf, lp);
if (msg) {
- printf("sd%d: %s\n", unit, msg);
goto bad;
}
if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) {
- bad:
-#ifndef SMALL
- free(sc, sizeof(struct sd_softc));
-#endif
+ msg = "no part";
+bad:
+ printf("sd%d: %s\n", unit, msg);
return (ENXIO);
}
return (0);
@@ -188,7 +167,9 @@ int
sdclose(f)
struct open_file *f;
{
+#ifdef FANCY
free(f->f_devdata, sizeof(struct sd_softc));
f->f_devdata = (void *)0;
+#endif
return (0);
}
diff --git a/sys/arch/wgrisc/stand/boot/start.S b/sys/arch/wgrisc/stand/boot/start.S
index 70535726c56..a3aa0f0ebb9 100644
--- a/sys/arch/wgrisc/stand/boot/start.S
+++ b/sys/arch/wgrisc/stand/boot/start.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: start.S,v 1.1 1997/05/11 16:17:54 pefo Exp $ */
+/* $OpenBSD: start.S,v 1.2 1997/07/21 06:58:13 pefo Exp $ */
/*
* Copyright (c) 1997 Per Fogelstrom
@@ -52,6 +52,11 @@ __start:
move s0, a0 # save argc
move s1, a1 # save argv
+ la a0, __start+512 # Merge together from
+ la a1, __start+1024 # disklabel split.
+ jal memcpy
+ li a2, 8192 - 1024
+
la a0, edata # clear BSS
li a1, 0
la a2, end
@@ -61,15 +66,101 @@ __start:
move a0, s0 # restore argc
jal main # main(argc, argv)
move a1, s1 # restore argv
+/* MAIN NEVER RETURNS */
- j restart # restart...
- nop
-/* dummy routine for gcc2 */
-LEAF(__main)
+/* dummy routines return 0 */
+ .globl getenv
+ .globl __main
+getenv:
+__main:
+ .set noreorder
j ra
+ li v0, 0
+
+ .globl strcmp
+strcmp:
+ .set noreorder
+1:
+ lbu v0, 0(a0)
+ lbu v1, 0(a1)
+ beqz v0, 2f
+ addu a0, a0, 1
+ beq v0, v1, 1b
+ addu a1, a1, 1
+2:
+ jr ra
+ subu v0, v0, v1
+
+ .globl strlen
+strlen:
+ .set noreorder
+ li v0, 0
+1:
+ lbu v1, 0(a0)
+ addu a0, a0, 1
+ bnez v1, 1b
+ addu v0, v0, 1
+
+ jr ra
+ addu v0, v0, -1
+
+ .globl memset
+memset:
+ .set noreorder
+ move v0, a0
+1:
+ beqz a2, 2f
+ addu a2, a2, -1
+
+ sb a1, 0(a0)
+ b 1b
+ addu a0, a0, 1
+2:
+ jr ra
+ nop
+
+ .globl memcpy
+memcpy:
+ .set noreorder
+ beqz a2, 3f
+ move v0, a0
+ sltu v1, a1, a0
+ beqz v1, 1f
+ li a3, 1 /* Forward copy */
+
+ li a3, -1 /* Backwrads copy */
+ addu a0, a2
+ b 2f
+ addu a1, a2
+
+1:
+ lbu v1, 0(a1)
+ addu a2, a2, -1
+ sb v1, 0(a0)
+2:
+ addu a0, a0, a3
+ bnez a2, 1b
+ addu a1, a1, a3
+
+3:
+ jr ra
nop
-END(__main)
+
+ .globl twiddle
+twiddle:
+ .set noreorder
+ la v0, twc+4
+ lw a0, -4(v0)
+ li a1, 7
+ addu a0, a0, 2
+ sw a0, -4(v0)
+ and a1, a0, a1
+ add a1, a1, v0
+
+ li a0, 1 /* Stdout */
+ b prom_write
+ li a2, 2
/*
* Boot rom entrypoints.
@@ -77,54 +168,71 @@ END(__main)
#define BOOTVEC 0xbfc00500 /* Address of boot vector table */
-NON_LEAF(getchar, STAND_FRAME_SIZE, ra)
- .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
- subu sp, sp, STAND_FRAME_SIZE
- sw ra, STAND_RA_OFFSET(sp)
+ .globl getchar
+getchar:
+ .set noreorder
+ sw ra, 4(sp)
move a1, sp
li a0, 0
- li a2, 1
jal prom_read
+ li a2, 1
+ lw ra, 4(sp)
lbu v0, 0(sp)
- lw ra, STAND_RA_OFFSET(sp)
- addu sp, sp, STAND_FRAME_SIZE
jr ra
-END(getchar)
+ nop
+
+ .globl disk_open
+disk_open:
+ .set noreorder
+ b __go
+ li v0, 96
-LEAF(putchar)
+ .globl disk_read
+disk_read:
+ .set noreorder
+ b __go
+ li v0, 100
+
+ .globl prom_read
+prom_read:
+ .set noreorder
+ b __go
+ li v0, 0
+
+ .globl putchar
+putchar:
+ .set noreorder
sb a0, 0(sp)
move a1, sp
li a0, 1 /* Stdout */
li a2, 1
- b prom_write
-
-END(putchar)
-
-LEAF(restart)
-END(restart)
+/* -- fall through -- */
+ .globl prom_write
+prom_write:
+ .set noreorder
+ b __go
+ li v0, 4
-LEAF(panic)
-END(panic)
+ .globl printf
+printf:
+ .set noreorder
+ b __go
+ li v0, 20
-LEAF(disk_open)
- lw v0, BOOTVEC+96
- jr v0
-END(disk_open)
+ .globl panic
+panic:
-LEAF(disk_read)
- lw v0, BOOTVEC+100
+__go:
+ .set noreorder
+ lw v0, BOOTVEC(v0)
+ nop
jr v0
-END(disk_read)
+ nop
+ .align 2
+ .globl twc
+twc: .word 0
+tws: .ascii "\\\b-\b/\b-\b"
-LEAF(prom_read)
- lw v0, BOOTVEC+0
- jr v0
-END(prom_read)
-
-LEAF(prom_write)
- lw v0, BOOTVEC+4
- jr v0
-END(prom_write)
diff --git a/sys/arch/wgrisc/stand/libsa/Makefile b/sys/arch/wgrisc/stand/libsa/Makefile
index f0ba65b1c51..e93b5a2df4a 100644
--- a/sys/arch/wgrisc/stand/libsa/Makefile
+++ b/sys/arch/wgrisc/stand/libsa/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.2 1997/05/11 16:17:55 pefo Exp $
+# $OpenBSD: Makefile,v 1.3 1997/07/21 06:58:14 pefo Exp $
LIB= sa
@@ -6,14 +6,14 @@ S=${.CURDIR}/../../../..
DIR_SA= $S/lib/libsa
DIR_KERN=$S/lib/libkern
-CFLAGS+=$(SACFLAGS) -D__INTERNAL_LIBSA_CREAD
-CFLAGS+=-DSTART=$(START) -DHEAP_LIMIT=$(HEAP_LIMIT)
+CFLAGS+=$(SACFLAGS) -D__INTERNAL_LIBSA_CREAD -DNO_READDIR -fno-inline
+CFLAGS+=-DSTART=$(START)
CFLAGS+=${DEBUGFLAGS} -I${.CURDIR} -I${.CURDIR}/..
CFLAGS+=-I$(S)/lib/libsa -I$(S)
SRCS= alloc.c close.c dev.c disklabel.c dkcksum.c getfile.c ioctl.c \
- lseek.c open.c printf.c read.c ufs.c write.c devopen.c getenv.c \
- gets.c memcmp.c memcpy.c memset.c strcat.c strcmp.c strcpy.c strlen.c \
+ lseek.c open.c read.c ufs.c write.c devopen.c \
+ gets.c memcpy.c memset.c strcat.c strlen.c \
strncpy.c
.PATH: ${DIR_SA} ${DIR_KERN}
diff --git a/sys/arch/wgrisc/stand/libsa/devopen.c b/sys/arch/wgrisc/stand/libsa/devopen.c
index 32eef0c79cd..0c1c68f36b6 100644
--- a/sys/arch/wgrisc/stand/libsa/devopen.c
+++ b/sys/arch/wgrisc/stand/libsa/devopen.c
@@ -1,12 +1,8 @@
-/* $NetBSD: devopen.c,v 1.5 1995/01/18 06:53:54 mellon Exp $ */
+/* $OpenBSD: devopen.c,v 1.3 1997/07/21 06:58:14 pefo Exp $ */
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Ralph Campbell.
- *
+/*
+ * Copyright (c) 1997 Per Fogelstrom
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,17 +13,16 @@
* 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 product includes software developed under OpenBSD by
+ * Per Fogelstrom.
+ * 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 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
+ * 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
@@ -35,15 +30,22 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)devopen.c 8.1 (Berkeley) 6/10/93
*/
#include <lib/libsa/stand.h>
-/*
- * Decode the string 'fname', open the device and return the remaining
- * file name if any.
- */
+static int
+a2i(ch)
+ char *ch;
+{
+ unsigned int v;
+
+ v = *ch - '0';
+ if(v > 9)
+ v = 0;
+ return(v);
+}
+
int
devopen(f, fname, file)
struct open_file *f;
@@ -53,64 +55,46 @@ devopen(f, fname, file)
const char *cp;
char *ncp;
struct devsw *dp;
- int c, i;
+ unsigned int c;
int ctlr = 0, unit = 0, part = 0;
char namebuf[20];
- int rc;
+ int rc, n;
cp = fname;
ncp = namebuf;
- /* expect a string like 'sd(0,0,0)vmunix' */
- while ((c = *cp) != '\0') {
- if (c == '(') {
- cp++;
- break;
- }
- if (ncp < namebuf + sizeof(namebuf) - 1)
- *ncp++ = c;
- cp++;
- }
+ while ((c = *cp++) != '\0' && c != '(') {
+ *ncp++ = c;
+ }
+ *ncp = '\0';
+ if(c == '(') {
/* get controller number */
- if ((c = *cp) >= '0' && c <= '9') {
- ctlr = c - '0';
- c = *++cp;
- }
-
- if (c == ',') {
- /* get SCSI device number */
- if ((c = *++cp) >= '0' && c <= '9') {
- unit = c - '0';
- c = *++cp;
- }
+ ctlr = a2i(cp);
+ cp += 2;
+ /* get SCSI device number */
+ unit = a2i(cp);
+ cp += 2;
+ /* get partition number */
+ part = a2i(cp);
+ cp += 2;
+ if (cp[-1] != ')')
+ return (ENXIO);
+ }
- if (c == ',') {
- /* get partition number */
- if ((c = *++cp) >= '0' && c <= '9') {
- part = c - '0';
- c = *++cp;
- }
+ dp = devsw;
+ n = ndevs;
+ while(n--) {
+ if (strcmp (namebuf, dp->dv_name) == 0) {
+ rc = (dp->dv_open)(f, ctlr, unit, part);
+ if (!rc) {
+ f->f_dev = dp;
+ if (file && *cp != '\0')
+ *file = (char *)cp;
}
+ return (rc);
}
- if (c != ')')
- return (ENXIO);
- cp++;
- *ncp = '\0';
-
- if (strcmp (namebuf, "sd")) {
- printf ("Unknown device: %s\n", namebuf);
- return ENXIO;
+ dp++;
}
- dp = devsw;
- i = 0;
-
- rc = (dp->dv_open)(f, ctlr, unit, part);
- if (rc)
- return (rc);
-
- f->f_dev = dp;
- if (file && *cp != '\0')
- *file = (char *)cp;
- return (0);
+ return ENXIO;
}
diff --git a/sys/arch/wgrisc/stand/libsa/gets.c b/sys/arch/wgrisc/stand/libsa/gets.c
index 841dd048915..359e40d988a 100644
--- a/sys/arch/wgrisc/stand/libsa/gets.c
+++ b/sys/arch/wgrisc/stand/libsa/gets.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gets.c,v 1.1 1997/05/11 16:17:56 pefo Exp $ */
+/* $OpenBSD: gets.c,v 1.2 1997/07/21 06:58:15 pefo Exp $ */
/* $NetBSD: gets.c,v 1.5.2.1 1995/10/13 19:54:26 pk Exp $ */
/*-
@@ -42,8 +42,8 @@ void
gets(buf)
char *buf;
{
- register int c;
- register char *lp;
+ int c;
+ char *lp;
for (lp = buf;;)
switch (c = getchar() & 0177) {
@@ -60,21 +60,9 @@ gets(buf)
putchar('\b');
}
break;
- case 'r'&037: {
- register char *p;
-
- putchar('\n');
- for (p = buf; p < lp; ++p)
- putchar(*p);
- break;
- }
- case 'u'&037:
- case 'w'&037:
- lp = buf;
- putchar('\n');
- break;
default:
- *lp++ = c;
+ *lp = c;
+ lp++;
}
/*NOTREACHED*/
}
diff --git a/sys/arch/wgrisc/stand/libsa/ufs.c b/sys/arch/wgrisc/stand/libsa/ufs.c
new file mode 100644
index 00000000000..bfd995db942
--- /dev/null
+++ b/sys/arch/wgrisc/stand/libsa/ufs.c
@@ -0,0 +1,762 @@
+/* $OpenBSD: ufs.c,v 1.1 1997/07/21 06:58:15 pefo Exp $ */
+/* $NetBSD: ufs.c,v 1.16 1996/09/30 16:01:22 ws Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * 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.
+ *
+ *
+ * Copyright (c) 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: David Golub
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * Stand-alone file reading package.
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <ufs/ffs/fs.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ufs/dir.h>
+#include <lib/libkern/libkern.h>
+
+#include "stand.h"
+
+/*
+ * In-core open file.
+ */
+struct file {
+ off_t f_seekp; /* seek pointer */
+ struct fs *f_fs; /* pointer to super-block */
+ struct dinode f_di; /* copy of on-disk inode */
+ int f_nindir[NIADDR];
+ /* number of blocks mapped by
+ indirect block at level i */
+ char *f_blk[NIADDR]; /* buffer for indirect block at
+ level i */
+ size_t f_blksize[NIADDR];
+ /* size of buffer */
+ daddr_t f_blkno[NIADDR];/* disk address of block in buffer */
+ char *f_buf; /* buffer for data block */
+ size_t f_buf_size; /* size of data block */
+ daddr_t f_buf_blkno; /* block number of data block */
+};
+
+static int read_inode __P((ino_t, struct open_file *));
+static int block_map __P((struct open_file *, daddr_t, daddr_t *));
+static int buf_read_file __P((struct open_file *, char **, size_t *));
+static int search_directory __P((char *, struct open_file *, ino_t *));
+#ifdef COMPAT_UFS
+static void ffs_oldfscompat __P((struct fs *));
+#endif
+
+/*
+ * Read a new inode into a file structure.
+ */
+static int
+read_inode(inumber, f)
+ ino_t inumber;
+ struct open_file *f;
+{
+ register struct file *fp = (struct file *)f->f_fsdata;
+ register struct fs *fs = fp->f_fs;
+ char *buf;
+ size_t rsize;
+ int rc;
+
+ /*
+ * Read inode and save it.
+ */
+ buf = alloc(fs->fs_bsize);
+ twiddle();
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize,
+ buf, &rsize);
+ if (rc)
+ goto out;
+ if (rsize != fs->fs_bsize) {
+ rc = EIO;
+ goto out;
+ }
+
+ {
+ register struct dinode *dp;
+
+ dp = (struct dinode *)buf;
+ fp->f_di = dp[ino_to_fsbo(fs, inumber)];
+ }
+
+ /*
+ * Clear out the old buffers
+ */
+ {
+ register int level;
+
+ for (level = 0; level < NIADDR; level++)
+ fp->f_blkno[level] = -1;
+ fp->f_buf_blkno = -1;
+ }
+out:
+ free(buf, fs->fs_bsize);
+ return (rc);
+}
+
+/*
+ * Given an offset in a file, find the disk block number that
+ * contains that block.
+ */
+static int
+block_map(f, file_block, disk_block_p)
+ struct open_file *f;
+ daddr_t file_block;
+ daddr_t *disk_block_p; /* out */
+{
+ register struct file *fp = (struct file *)f->f_fsdata;
+ register struct fs *fs = fp->f_fs;
+ int level;
+ int idx;
+ daddr_t ind_block_num;
+ daddr_t *ind_p;
+ int rc;
+
+ /*
+ * Index structure of an inode:
+ *
+ * di_db[0..NDADDR-1] hold block numbers for blocks
+ * 0..NDADDR-1
+ *
+ * di_ib[0] index block 0 is the single indirect block
+ * holds block numbers for blocks
+ * NDADDR .. NDADDR + NINDIR(fs)-1
+ *
+ * di_ib[1] index block 1 is the double indirect block
+ * holds block numbers for INDEX blocks for blocks
+ * NDADDR + NINDIR(fs) ..
+ * NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
+ *
+ * di_ib[2] index block 2 is the triple indirect block
+ * holds block numbers for double-indirect
+ * blocks for blocks
+ * NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
+ * NDADDR + NINDIR(fs) + NINDIR(fs)**2
+ * + NINDIR(fs)**3 - 1
+ */
+
+ if (file_block < NDADDR) {
+ /* Direct block. */
+ *disk_block_p = fp->f_di.di_db[file_block];
+ return (0);
+ }
+
+ file_block -= NDADDR;
+
+ /*
+ * nindir[0] = NINDIR
+ * nindir[1] = NINDIR**2
+ * nindir[2] = NINDIR**3
+ * etc
+ */
+ for (level = 0; level < NIADDR; level++) {
+ if (file_block < fp->f_nindir[level])
+ break;
+ file_block -= fp->f_nindir[level];
+ }
+ if (level == NIADDR) {
+ /* Block number too high */
+ return (EFBIG);
+ }
+
+ ind_block_num = fp->f_di.di_ib[level];
+
+ for (; level >= 0; level--) {
+ if (ind_block_num == 0) {
+ *disk_block_p = 0; /* missing */
+ return (0);
+ }
+
+ if (fp->f_blkno[level] != ind_block_num) {
+ if (fp->f_blk[level] == (char *)0)
+ fp->f_blk[level] =
+ alloc(fs->fs_bsize);
+ twiddle();
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ fsbtodb(fp->f_fs, ind_block_num),
+ fs->fs_bsize,
+ fp->f_blk[level],
+ &fp->f_blksize[level]);
+ if (rc)
+ return (rc);
+ if (fp->f_blksize[level] != fs->fs_bsize)
+ return (EIO);
+ fp->f_blkno[level] = ind_block_num;
+ }
+
+ ind_p = (daddr_t *)fp->f_blk[level];
+
+ if (level > 0) {
+ idx = file_block / fp->f_nindir[level - 1];
+ file_block %= fp->f_nindir[level - 1];
+ } else
+ idx = file_block;
+
+ ind_block_num = ind_p[idx];
+ }
+
+ *disk_block_p = ind_block_num;
+
+ return (0);
+}
+
+/*
+ * Read a portion of a file into an internal buffer. Return
+ * the location in the buffer and the amount in the buffer.
+ */
+static int
+buf_read_file(f, buf_p, size_p)
+ struct open_file *f;
+ char **buf_p; /* out */
+ size_t *size_p; /* out */
+{
+ register struct file *fp = (struct file *)f->f_fsdata;
+ register struct fs *fs = fp->f_fs;
+ long off;
+ register daddr_t file_block;
+ daddr_t disk_block;
+ size_t block_size;
+ int rc;
+
+ off = blkoff(fs, fp->f_seekp);
+ file_block = lblkno(fs, fp->f_seekp);
+ block_size = dblksize(fs, &fp->f_di, file_block);
+
+ if (file_block != fp->f_buf_blkno) {
+ rc = block_map(f, file_block, &disk_block);
+ if (rc)
+ return (rc);
+
+ if (fp->f_buf == (char *)0)
+ fp->f_buf = alloc(fs->fs_bsize);
+
+ if (disk_block == 0) {
+ bzero(fp->f_buf, block_size);
+ fp->f_buf_size = block_size;
+ } else {
+ twiddle();
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ fsbtodb(fs, disk_block),
+ 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 = block_size - off;
+
+ /*
+ * But truncate buffer at end of file.
+ */
+ if (*size_p > fp->f_di.di_size - fp->f_seekp)
+ *size_p = fp->f_di.di_size - fp->f_seekp;
+
+ return (0);
+}
+
+/*
+ * Search a directory for a name and return its
+ * i_number.
+ */
+static int
+search_directory(name, f, inumber_p)
+ char *name;
+ struct open_file *f;
+ ino_t *inumber_p; /* out */
+{
+ register struct file *fp = (struct file *)f->f_fsdata;
+ register struct direct *dp;
+ struct direct *edp;
+ char *buf;
+ size_t buf_size;
+ int namlen, length;
+ int rc;
+
+ length = strlen(name);
+
+ fp->f_seekp = 0;
+ while (fp->f_seekp < fp->f_di.di_size) {
+ rc = buf_read_file(f, &buf, &buf_size);
+ if (rc)
+ return (rc);
+
+ dp = (struct direct *)buf;
+ edp = (struct direct *)(buf + buf_size);
+ while (dp < edp) {
+ if (dp->d_ino == (ino_t)0)
+ goto next;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ if (fp->f_fs->fs_maxsymlinklen <= 0)
+ namlen = dp->d_type;
+ else
+#endif
+ namlen = dp->d_namlen;
+ if (namlen == length &&
+ !strcmp(name, dp->d_name)) {
+ /* found entry */
+ *inumber_p = dp->d_ino;
+ return (0);
+ }
+ next:
+ dp = (struct direct *)((char *)dp + dp->d_reclen);
+ }
+ fp->f_seekp += buf_size;
+ }
+ return (ENOENT);
+}
+
+/*
+ * Open a file.
+ */
+int
+ufs_open(path, f)
+ char *path;
+ struct open_file *f;
+{
+ register char *cp, *ncp;
+ register int c;
+ ino_t inumber, parent_inumber;
+ struct file *fp;
+ struct fs *fs;
+ int rc;
+ size_t buf_size;
+#ifndef NO_SYM_LINKS
+ int nlinks = 0;
+ char namebuf[MAXPATHLEN+1];
+#endif
+ char *buf = NULL;
+
+ /* allocate file system specific data structure */
+ fp = alloc(sizeof(struct file));
+ bzero(fp, sizeof(struct file));
+ f->f_fsdata = (void *)fp;
+
+ /* allocate space and read super block */
+ fs = alloc(SBSIZE);
+ fp->f_fs = fs;
+ twiddle();
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ SBLOCK, SBSIZE, (char *)fs, &buf_size);
+ if (rc)
+ goto out;
+
+ if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC ||
+ fs->fs_bsize > MAXBSIZE || fs->fs_bsize < sizeof(struct fs)) {
+ rc = EINVAL;
+ goto out;
+ }
+#ifdef COMPAT_UFS
+ ffs_oldfscompat(fs);
+#endif
+
+ /*
+ * Calculate indirect block levels.
+ */
+ {
+ register int mult;
+ register int level;
+
+ mult = 1;
+ for (level = 0; level < NIADDR; level++) {
+ mult *= NINDIR(fs);
+ fp->f_nindir[level] = mult;
+ }
+ }
+
+ inumber = ROOTINO;
+ if ((rc = read_inode(inumber, f)) != 0)
+ goto out;
+
+ cp = path;
+ while (*cp) {
+
+ /*
+ * Remove extra separators
+ */
+ while (*cp == '/')
+ cp++;
+ if (*cp == '\0')
+ break;
+
+ /*
+ * Check that current node is a directory.
+ */
+ if ((fp->f_di.di_mode & IFMT) != IFDIR) {
+ rc = ENOTDIR;
+ goto out;
+ }
+
+ /*
+ * Get next component of path name.
+ */
+ {
+ register int len = 0;
+
+ ncp = cp;
+ while ((c = *cp) != '\0' && c != '/') {
+ if (++len > MAXNAMLEN) {
+ rc = ENOENT;
+ goto out;
+ }
+ cp++;
+ }
+ *cp = '\0';
+ }
+
+ /*
+ * Look up component in current directory.
+ * Save directory inumber in case we find a
+ * symbolic link.
+ */
+ parent_inumber = inumber;
+ rc = search_directory(ncp, f, &inumber);
+ *cp = c;
+ if (rc)
+ goto out;
+
+ /*
+ * Open next component.
+ */
+ if ((rc = read_inode(inumber, f)) != 0)
+ goto out;
+
+#ifndef NO_SYM_LINKS
+ /*
+ * Check for symbolic link.
+ */
+ if ((fp->f_di.di_mode & IFMT) == IFLNK) {
+ int link_len = fp->f_di.di_size;
+ int len;
+
+ len = strlen(cp);
+
+ if (link_len + len > MAXPATHLEN ||
+ ++nlinks > MAXSYMLINKS) {
+ rc = ENOENT;
+ goto out;
+ }
+
+ bcopy(cp, &namebuf[link_len], len + 1);
+
+ if (link_len < fs->fs_maxsymlinklen) {
+ bcopy(fp->f_di.di_shortlink, namebuf,
+ (unsigned) link_len);
+ } else {
+ /*
+ * Read file for symbolic link
+ */
+ size_t buf_size;
+ daddr_t disk_block;
+ register struct fs *fs = fp->f_fs;
+
+ if (!buf)
+ buf = alloc(fs->fs_bsize);
+ rc = block_map(f, (daddr_t)0, &disk_block);
+ if (rc)
+ goto out;
+
+ twiddle();
+ rc = (f->f_dev->dv_strategy)(f->f_devdata,
+ F_READ, fsbtodb(fs, disk_block),
+ fs->fs_bsize, buf, &buf_size);
+ if (rc)
+ goto out;
+
+ bcopy((char *)buf, namebuf, (unsigned)link_len);
+ }
+
+ /*
+ * If relative pathname, restart at parent directory.
+ * If absolute pathname, restart at root.
+ */
+ cp = namebuf;
+ if (*cp != '/')
+ inumber = parent_inumber;
+ else
+ inumber = (ino_t)ROOTINO;
+
+ if ((rc = read_inode(inumber, f)) != 0)
+ goto out;
+ }
+#endif /* NO_SYM_LINKS */
+ }
+
+ /*
+ * Found terminal component.
+ */
+ rc = 0;
+out:
+ if (buf)
+ free(buf, fs->fs_bsize);
+ if (rc) {
+ free(fp->f_fs, SBSIZE);
+ free(fp, sizeof(struct file));
+ }
+ return (rc);
+}
+
+int
+ufs_close(f)
+ struct open_file *f;
+{
+ register struct file *fp = (struct file *)f->f_fsdata;
+ int level;
+
+ f->f_fsdata = (void *)0;
+ if (fp == (struct file *)0)
+ return (0);
+
+ for (level = 0; level < NIADDR; level++) {
+ if (fp->f_blk[level])
+ free(fp->f_blk[level], fp->f_fs->fs_bsize);
+ }
+ if (fp->f_buf)
+ free(fp->f_buf, fp->f_fs->fs_bsize);
+ free(fp->f_fs, SBSIZE);
+ free(fp, sizeof(struct file));
+ return (0);
+}
+
+/*
+ * Copy a portion of a file into kernel memory.
+ * Cross block boundaries when necessary.
+ */
+int
+ufs_read(f, start, size, resid)
+ struct open_file *f;
+ void *start;
+ size_t size;
+ size_t *resid; /* out */
+{
+ register struct file *fp = (struct file *)f->f_fsdata;
+ register size_t csize;
+ char *buf;
+ size_t buf_size;
+ int rc = 0;
+ register char *addr = start;
+
+ while (size != 0) {
+ if (fp->f_seekp >= fp->f_di.di_size)
+ break;
+
+ rc = buf_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
+ufs_write(f, start, size, resid)
+ struct open_file *f;
+ void *start;
+ size_t size;
+ size_t *resid; /* out */
+{
+
+ return (EROFS);
+}
+
+off_t
+ufs_seek(f, offset, where)
+ struct open_file *f;
+ off_t offset;
+ int where;
+{
+ register struct file *fp = (struct 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:
+ fp->f_seekp = fp->f_di.di_size - offset;
+ break;
+ default:
+ return (-1);
+ }
+ return (fp->f_seekp);
+}
+
+int
+ufs_stat(f, sb)
+ struct open_file *f;
+ struct stat *sb;
+{
+#if 0
+ register struct file *fp = (struct file *)f->f_fsdata;
+
+ /* only important stuff */
+ sb->st_mode = fp->f_di.di_mode;
+ sb->st_uid = fp->f_di.di_uid;
+ sb->st_gid = fp->f_di.di_gid;
+ sb->st_size = fp->f_di.di_size;
+#endif
+ return (0);
+}
+
+#ifndef NO_READDIR
+int
+ufs_readdir(f, name)
+ struct open_file *f;
+ char *name;
+{
+ register struct file *fp = (struct file *)f->f_fsdata;
+ char *buf;
+ size_t buf_size;
+ register struct direct *dp, *edp;
+ int rc, namlen;
+
+ if (name == NULL)
+ fp->f_seekp = 0;
+ else {
+ /* end of dir */
+ if (fp->f_seekp >= fp->f_di.di_size) {
+ *name = '\0';
+ return -1;
+ }
+
+ do {
+ if ((rc = buf_read_file(f, &buf, &buf_size)) != 0)
+ return rc;
+
+ dp = (struct direct *)buf;
+ edp = (struct direct *)(buf + buf_size);
+ while (dp < edp && dp->d_ino == (ino_t)0)
+ dp = (struct direct *)((char *)dp + dp->d_reclen);
+ fp->f_seekp += buf_size -
+ ((u_int8_t *)edp - (u_int8_t *)dp);
+ } while (dp >= edp);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ if (fp->f_fs->fs_maxsymlinklen <= 0)
+ namlen = dp->d_type;
+ else
+#endif
+ namlen = dp->d_namlen;
+ strncpy(name, dp->d_name, namlen + 1);
+
+ fp->f_seekp += dp->d_reclen;
+ }
+
+ return 0;
+}
+#endif
+
+#ifdef COMPAT_UFS
+/*
+ * Sanity checks for old file systems.
+ *
+ * XXX - goes away some day.
+ */
+static void
+ffs_oldfscompat(fs)
+ struct fs *fs;
+{
+ int i;
+
+ fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
+ fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
+ if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
+ fs->fs_nrpos = 8; /* XXX */
+ if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
+ quad_t sizepb = fs->fs_bsize; /* XXX */
+ /* XXX */
+ fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
+ for (i = 0; i < NIADDR; i++) { /* XXX */
+ sizepb *= NINDIR(fs); /* XXX */
+ fs->fs_maxfilesize += sizepb; /* XXX */
+ } /* XXX */
+ fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
+ fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
+ } /* XXX */
+}
+#endif