diff options
author | Per Fogelstrom <pefo@cvs.openbsd.org> | 1997-07-21 06:58:16 +0000 |
---|---|---|
committer | Per Fogelstrom <pefo@cvs.openbsd.org> | 1997-07-21 06:58:16 +0000 |
commit | 165d6cf5bda061baecb1399468bb228204e73e43 (patch) | |
tree | b498d0899dfe93665f8ce1ab240686f6f0e4e04d /sys/arch/wgrisc | |
parent | 7d330777bab7dbaf8003284034c688a493098134 (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.inc | 8 | ||||
-rw-r--r-- | sys/arch/wgrisc/stand/boot/Makefile | 12 | ||||
-rw-r--r-- | sys/arch/wgrisc/stand/boot/boot.c | 76 | ||||
-rw-r--r-- | sys/arch/wgrisc/stand/boot/conf.c | 37 | ||||
-rw-r--r-- | sys/arch/wgrisc/stand/boot/fl.c | 102 | ||||
-rw-r--r-- | sys/arch/wgrisc/stand/boot/sd.c | 77 | ||||
-rw-r--r-- | sys/arch/wgrisc/stand/boot/start.S | 186 | ||||
-rw-r--r-- | sys/arch/wgrisc/stand/libsa/Makefile | 10 | ||||
-rw-r--r-- | sys/arch/wgrisc/stand/libsa/devopen.c | 126 | ||||
-rw-r--r-- | sys/arch/wgrisc/stand/libsa/gets.c | 22 | ||||
-rw-r--r-- | sys/arch/wgrisc/stand/libsa/ufs.c | 762 |
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 |