disklabel64 UFS+HAMMER boot support (was previously just HAMMER boot support)
authorMatthew Dillon <dillon@apollo.backplane.com>
Mon, 2 Mar 2009 02:49:06 +0000 (18:49 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Mon, 2 Mar 2009 02:49:06 +0000 (18:49 -0800)
Create a mini-API for boot2 filesystems, split out the filesystem probe &
initialization code, and adjust boot2 to probe multiple filesystems.  While
the coding is fairly generic, only the larger boot2 area in a disklabel64
is big enough to hold a multi-filesystem boot2.  32 bit disklabels can still
only boot from UFS.

As part of this work the BTX loader offset for boot2 had to be adjusted.
boot1 used to load boot2 at 0xA000+0x4000 = 0xE000, but this left only 8KB
available before the segment would overflow in boot1's relocation code.

The BOOT2_VORIGIN was adjusted downward from 0x4000 to 0x2000, reducing
the absolute physical load address for boot2 to 0xC000 and allowing us
to load up to a 16K boot2 without overflowing the segment.

lib/libstand/hammerread.c
sys/boot/common/boot2.h [new file with mode: 0644]
sys/boot/common/dinode.h
sys/boot/common/ufsread.c
sys/boot/pc32/boot2/Makefile
sys/boot/pc32/boot2/boot1.S
sys/boot/pc32/boot2/boot2.c
sys/boot/pc32/bootasm.h
sys/sys/types.h

index b24a57b..083455f 100644 (file)
 #define        LIBSTAND        1
 #endif
 
+#ifdef BOOT2
+#include "boot2.h"
+#else
 #include <sys/param.h>
-
 #include <stddef.h>
 #include <stdint.h>
+#endif
 
 #ifdef TESTING
 #include <sys/fcntl.h>
@@ -136,12 +139,12 @@ hread(struct hfs *hfs, hammer_off_t off)
 
 #else  /* BOOT2 */
 
-struct dmadat {
-       char            secbuf[DEV_BSIZE];
+struct hammer_dmadat {
+       struct boot2_dmadat boot2;
        char            buf[HAMMER_BUFSIZE];
 };
 
-static struct dmadat *dmadat;
+#define fsdmadat       ((struct hammer_dmadat *)boot2_dmadat)
 
 struct hfs {
        hammer_off_t    root;
@@ -151,7 +154,7 @@ struct hfs {
 static void *
 hread(struct hfs *hfs, hammer_off_t off)
 {
-       char *buf = dmadat->buf;
+       char *buf = fsdmadat->buf;
 
        hammer_off_t boff = off & ~HAMMER_BUFMASK64;
        boff &= HAMMER_OFF_LONG_MASK;
@@ -755,27 +758,23 @@ hreadf(struct hfs *hfs, ino_t ino, int64_t off, int64_t len, char *buf)
 struct hfs hfs;
 
 static int
-hammerinit(void)
+boot2_hammer_init(void)
 {
-       if (dsk_meta)
-               return (0);
+       hammer_volume_ondisk_t volhead;
 
-       hammer_volume_ondisk_t volhead = hread(&hfs, HAMMER_ZONE_ENCODE(1, 0));
+       volhead = hread(&hfs, HAMMER_ZONE_ENCODE(1, 0));
        if (volhead == NULL)
                return (-1);
        if (volhead->vol_signature != HAMMER_FSBUF_VOLUME)
                return (-1);
        hfs.root = volhead->vol0_btree_root;
        hfs.buf_beg = volhead->vol_buf_beg;
-       dsk_meta++;
        return (0);
 }
 
-static ino_t
-lookup(const char *path)
+static boot2_ino_t
+boot2_hammer_lookup(const char *path)
 {
-       hammerinit();
-
        ino_t ino = hlookup(&hfs, path);
 
        if (ino == -1)
@@ -787,15 +786,20 @@ lookup(const char *path)
 }
 
 static ssize_t
-fsread(ino_t ino, void *buf, size_t len)
+boot2_hammer_read(boot2_ino_t ino, void *buf, size_t len)
 {
-       hammerinit();
-
        ssize_t rlen = hreadf(&hfs, ino, fs_off, len, buf);
        if (rlen != -1)
                fs_off += rlen;
        return (rlen);
 }
+
+const struct boot2_fsapi boot2_hammer_api = {
+       .fsinit = boot2_hammer_init,
+       .fslookup = boot2_hammer_lookup,
+       .fsread = boot2_hammer_read
+};
+
 #endif
 
 #ifndef BOOT2
diff --git a/sys/boot/common/boot2.h b/sys/boot/common/boot2.h
new file mode 100644 (file)
index 0000000..ddd9299
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ *
+ * 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. Neither the name of The DragonFly Project 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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.
+ */
+/*
+ * boot2 encapsulated ABI.  The boot2 standalone code provides these functions
+ * to the boot2 add-on modules (ufsread.c and hammerread.c).
+ */
+
+#ifndef _BOOT_COMMON_BOOT2_H_
+#define _BOOT_COMMON_BOOT2_H_
+
+
+#include <sys/param.h>
+#include <sys/dtype.h>
+#include <sys/dirent.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <machine/bootinfo.h>
+#include <machine/elf.h>
+
+/*
+ * We only need a 32 bit ino_t for UFS-only boot code.  We have to squeeze
+ * space usage, else we'd just use 64 bits across the board.
+ */
+#if defined(HAMMERFS)
+typedef uint64_t boot2_ino_t;
+#else
+typedef uint32_t boot2_ino_t;
+#endif
+
+struct boot2_fsapi {
+       int (*fsinit)(void);
+       boot2_ino_t (*fslookup)(const char *);
+       ssize_t (*fsread)(boot2_ino_t, void *, size_t);
+};
+
+struct boot2_dmadat {
+       char    secbuf[DEV_BSIZE];
+       /* extended by *fsread() modules */
+};
+
+extern uint32_t fs_off;
+extern int     ls;
+extern int     dsk_meta;
+extern struct boot2_dmadat *boot2_dmadat;
+
+extern int dskread(void *, unsigned, unsigned);
+extern void printf(const char *,...);
+extern void putchar(int);
+extern int strcmp(const char *s1, const char *s2);
+extern void memcpy(void *d, const void *s, int len);
+
+#ifdef UFS
+extern const struct boot2_fsapi boot2_ufs_api;
+#endif
+#ifdef HAMMERFS
+extern const struct boot2_fsapi boot2_hammer_api;
+#endif
+
+#endif
index e16f215..6b6a916 100644 (file)
@@ -71,6 +71,7 @@ typedef       int32_t ufs1_daddr_t;
 typedef        int64_t ufs2_daddr_t;
 typedef int64_t ufs_lbn_t;
 typedef int64_t ufs_time_t;
+typedef uint32_t ufs_ino_t;
 
 /* File permissions. */
 #define        IEXEC           0000100         /* Executable. */
index 93bd287..6b94600 100644 (file)
  * $DragonFly: src/sys/boot/common/ufsread.c,v 1.5 2008/09/13 11:46:28 corecode Exp $
  */
 
+#ifdef BOOT2
+#include "boot2.h"
+#else
+#include <sys/param.h>
+#endif
+#include <sys/dtype.h>
+#include <sys/dirent.h>
+#include <machine/bootinfo.h>
+#include <machine/elf.h>
 #include <vfs/ufs/dir.h>
 #include "dinode.h"
 #include "fs.h"
+
 #ifdef __i386__
 /* XXX: Revert to old (broken for over 1.5Tb filesystems) version of cgbase
    (see sys/ufs/ffs/fs.h rev 1.39) so that i386 boot loader (boot2) can
 #define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK)
 
 /* Buffers that must not span a 64k boundary. */
-struct dmadat {
+struct ufs_dmadat {
+       struct boot2_dmadat boot2;
        char blkbuf[VBLKSIZE];  /* filesystem blocks */
        char indbuf[VBLKSIZE];  /* indir blocks */
        char sbbuf[SBLOCKSIZE]; /* superblock */
-       char secbuf[DEV_BSIZE]; /* for MBR/disklabel */
 };
-static struct dmadat *dmadat;
 
-static ino_t lookup(const char *);
-static ssize_t fsread(ino_t, void *, size_t);
+#define fsdmadat       ((struct ufs_dmadat *)boot2_dmadat)
+
+static boot2_ino_t boot2_ufs_lookup(const char *);
+static ssize_t boot2_ufs_read(boot2_ino_t, void *, size_t);
+static int boot2_ufs_init(void);
+
+const struct boot2_fsapi boot2_ufs_api = {
+       .fsinit = boot2_ufs_init,
+       .fslookup = boot2_ufs_lookup,
+       .fsread = boot2_ufs_read
+};
 
 static __inline__ int
-fsfind(const char *name, ino_t * ino)
+fsfind(const char *name, ufs_ino_t *ino)
 {
        char buf[DEV_BSIZE];
        struct direct *d;
@@ -75,7 +93,7 @@ fsfind(const char *name, ino_t * ino)
        ssize_t n;
 
        fs_off = 0;
-       while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0)
+       while ((n = boot2_ufs_read(*ino, buf, DEV_BSIZE)) > 0)
                for (s = buf; s < buf + DEV_BSIZE;) {
                        d = (void *)s;
                        if (ls)
@@ -91,12 +109,12 @@ fsfind(const char *name, ino_t * ino)
        return 0;
 }
 
-static ino_t
-lookup(const char *path)
+static boot2_ino_t
+boot2_ufs_lookup(const char *path)
 {
        char name[MAXNAMLEN + 1];
        const char *s;
-       ino_t ino;
+       ufs_ino_t ino;
        ssize_t n;
        int dt;
 
@@ -139,8 +157,45 @@ static int sblock_try[] = SBLOCKSEARCH;
 #define DIP(field) fs->fs_magic == FS_UFS1_MAGIC ? dp1.field : dp2.field
 #endif
 
+static ufs_ino_t inomap;
+static ufs2_daddr_t blkmap, indmap;
+
+static int
+boot2_ufs_init(void)
+{
+       struct fs *fs;
+       size_t n;
+
+       fs = (struct fs *)fsdmadat->sbbuf;
+
+       for (n = 0; sblock_try[n] != -1; n++) {
+               if (dskread(fs, sblock_try[n] / DEV_BSIZE,
+                           SBLOCKSIZE / DEV_BSIZE)) {
+                       return -1;
+               }
+               if ((
+#if defined(UFS1_ONLY)
+                    fs->fs_magic == FS_UFS1_MAGIC
+#elif defined(UFS2_ONLY)
+                   (fs->fs_magic == FS_UFS2_MAGIC &&
+                   fs->fs_sblockloc == sblock_try[n])
+#else
+                    fs->fs_magic == FS_UFS1_MAGIC ||
+                   (fs->fs_magic == FS_UFS2_MAGIC &&
+                   fs->fs_sblockloc == sblock_try[n])
+#endif
+                   ) &&
+                   fs->fs_bsize <= MAXBSIZE &&
+                   fs->fs_bsize >= sizeof(struct fs))
+                       break;
+       }
+       if (sblock_try[n] == -1)
+               return -1;
+       return 0;
+}
+
 static ssize_t
-fsread(ino_t inode, void *buf, size_t nbyte)
+boot2_ufs_read(boot2_ino_t boot2_inode, void *buf, size_t nbyte)
 {
 #ifndef UFS2_ONLY
        static struct ufs1_dinode dp1;
@@ -148,7 +203,7 @@ fsread(ino_t inode, void *buf, size_t nbyte)
 #ifndef UFS1_ONLY
        static struct ufs2_dinode dp2;
 #endif
-       static ino_t inomap;
+       ufs_ino_t ufs_inode = (ufs_ino_t)boot2_inode;
        char *blkbuf;
        void *indbuf;
        struct fs *fs;
@@ -156,48 +211,19 @@ fsread(ino_t inode, void *buf, size_t nbyte)
        size_t n, nb, size, off, vboff;
        ufs_lbn_t lbn;
        ufs2_daddr_t addr, vbaddr;
-       static ufs2_daddr_t blkmap, indmap;
        u_int u;
 
+       blkbuf = fsdmadat->blkbuf;
+       indbuf = fsdmadat->indbuf;
+       fs = (struct fs *)fsdmadat->sbbuf;
 
-       blkbuf = dmadat->blkbuf;
-       indbuf = dmadat->indbuf;
-       fs = (struct fs *)dmadat->sbbuf;
-       if (!dsk_meta) {
-               inomap = 0;
-               for (n = 0; sblock_try[n] != -1; n++) {
-                       if (dskread(fs, sblock_try[n] / DEV_BSIZE,
-                           SBLOCKSIZE / DEV_BSIZE))
-                               return -1;
-                       if ((
-#if defined(UFS1_ONLY)
-                            fs->fs_magic == FS_UFS1_MAGIC
-#elif defined(UFS2_ONLY)
-                           (fs->fs_magic == FS_UFS2_MAGIC &&
-                           fs->fs_sblockloc == sblock_try[n])
-#else
-                            fs->fs_magic == FS_UFS1_MAGIC ||
-                           (fs->fs_magic == FS_UFS2_MAGIC &&
-                           fs->fs_sblockloc == sblock_try[n])
-#endif
-                           ) &&
-                           fs->fs_bsize <= MAXBSIZE &&
-                           fs->fs_bsize >= sizeof(struct fs))
-                               break;
-               }
-               if (sblock_try[n] == -1) {
-                       printf("Not ufs\n");
-                       return -1;
-               }
-               dsk_meta++;
-       }
-       if (!inode)
+       if (!ufs_inode)
                return 0;
-       if (inomap != inode) {
+       if (inomap != ufs_inode) {
                n = IPERVBLK(fs);
-               if (dskread(blkbuf, INO_TO_VBA(fs, n, inode), DBPERVBLK))
+               if (dskread(blkbuf, INO_TO_VBA(fs, n, ufs_inode), DBPERVBLK))
                        return -1;
-               n = INO_TO_VBO(n, inode);
+               n = INO_TO_VBO(n, ufs_inode);
 #if defined(UFS1_ONLY)
                dp1 = ((struct ufs1_dinode *)blkbuf)[n];
 #elif defined(UFS2_ONLY)
@@ -208,7 +234,7 @@ fsread(ino_t inode, void *buf, size_t nbyte)
                else
                        dp2 = ((struct ufs2_dinode *)blkbuf)[n];
 #endif
-               inomap = inode;
+               inomap = ufs_inode;
                fs_off = 0;
                blkmap = indmap = 0;
        }
index 2a9043a..bd61016 100644 (file)
@@ -11,6 +11,8 @@ NXCFLAGS=
 NXLDFLAGS=
 
 .PATH: ${.CURDIR}/..
+.PATH: ${.CURDIR}/../../common
+.PATH: ${.CURDIR}/../../../../lib/libstand
 
 # A value of 0x80 enables LBA support.
 B1FLAGS=       0x80
@@ -50,8 +52,7 @@ CFLAGS=       -elf -ffreestanding -Os -fno-builtin \
        -I${.CURDIR}/../btx/lib -I. \
        -Wall -Waggregate-return -Wbad-function-cast -Wcast-align \
        -Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
-       -Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \
-       -D__BOOT2_HACK
+       -Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings
 
 # Tell gcc that it shouldn't do fancy optimizations for newer processors.
 # Otherwise it winds up creating larger code and we won't be able to fit boot2.
@@ -69,8 +70,15 @@ CFLAGS+= -fno-unit-at-a-time
 CFLAGS+= -fno-stack-protector
 .endif
 
+# boot2 area in 32 bit disklabel is 16 sectors (8K)
+#
+# boot2 area in 64 bit disklabel is 64 sectors (32K).
+# However, the boot1 btx loader puts boot2 at a physical address
+# of MEM_BTX_USR+BOOT2_VORIGIN which is typically 0xC000, so we
+# cannot make boot2 any larger then 16KB or we overflow the segment.
+#
 NSECT_32?=     16
-NSECT_64?=     18
+NSECT_64?=     30
 LDFLAGS=-nostdlib -static -N --gc-sections
 
 all: boot
@@ -84,9 +92,11 @@ _ADDCFLAGS$s:= -DNSECT=${NSECT$s}
 _ts=   $s
 .if ${_ts} == "_64"
 _ADDCFLAGS$s+= -DDISKLABEL64
-_ADDCFLAGS$s+= -DHAMMERFS
+_ADDCFLAGS$s+= -DHAMMERFS -DUFS
+_ADDOBJS$s+= hammerread$s.o ufsread$s.o
 .else
-_ADDCFLAGS$s+= -DUFS1_ONLY
+_ADDCFLAGS$s+= -DUFS -DUFS1_ONLY
+_ADDOBJS$s+= ufsread$s.o
 .endif
 
 all: boot1$s boot2$s
@@ -127,14 +137,22 @@ boot2$s.ldr:
 boot2$s.bin: boot2$s.out
        objcopy -S -O binary boot2$s.out ${.TARGET}
 
-boot2$s.out: boot2$s.o sio.o
+boot2$s.out: boot2$s.o sio.o ${_ADDOBJS$s}
        ${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} \
                ${BTX}/lib/crt0.o ${.ALLSRC}
 
 boot2$s.o: boot2$s.h
 
 CLEANFILES+=   boot1$s boot1$s.out boot1$s.o \
-               boot2$s boot2$s.ldr boot2$s.bin boot2$s.ld boot2$s.out boot2$s.o boot2$s.h boot2$s.s
+               boot2$s boot2$s.ldr boot2$s.bin \
+               boot2$s.ld boot2$s.out boot2$s.o boot2$s.h boot2$s.s \
+               ${_ADDOBJS$s}
+
+hammerread$s.o: hammerread.c
+       ${CC} ${CFLAGS} ${_ADDCFLAGS$s} ${.ALLSRC} -o ${.TARGET} -c
+
+ufsread$s.o: ufsread.c
+       ${CC} ${CFLAGS} ${_ADDCFLAGS$s} ${.ALLSRC} -o ${.TARGET} -c
 
 .endfor
 
index 39cfcdf..475ffe2 100644 (file)
@@ -202,7 +202,11 @@ main.4:    xor %dx,%dx                     // Partition:drive
 //
 // Ok, we have a slice and drive in %dx now, so use that to locate and load
 // boot2.  %si references the start of the slice we are looking for, so go
-// ahead and load up the first 16 sectors (boot1 + boot2) from that.  
+// ahead and load up the first N sectors (boot1 + boot2) from that.
+//
+// N is 16 for boot1 in a disklabel32 and up to 32 in a disklabel64.  The
+// disklabel64 can hold up to 64 sectors but MEM_BTX_USR+BOOT2_VORIGIN
+// will overflow the segment if we use more then 32 sectors.
 //
 // When we read it in, we conveniently use BOOT2_LOAD_BUF (0x8c00) as our
 // transfer buffer.  Thus, boot1 ends up at 0x8c00, and boot2 starts at
index d37e751..dd0aff9 100644 (file)
@@ -47,9 +47,6 @@
  * $FreeBSD: src/sys/boot/i386/boot2/boot2.c,v 1.64 2003/08/25 23:28:31 obrien Exp $
  * $DragonFly: src/sys/boot/pc32/boot2/boot2.c,v 1.18 2008/09/13 11:45:45 corecode Exp $
  */
-#ifdef HAMMERFS
-#undef __BOOT2_HACK
-#endif
 
 #include <sys/param.h>
 #ifdef DISKLABEL64
@@ -75,7 +72,7 @@
 #else
 #include "boot2_32.h"
 #endif
-
+#include "boot2.h"
 #include "lib.h"
 #include "../bootasm.h"
 
@@ -157,21 +154,26 @@ static struct dsk {
     unsigned start;
     int init;
 } dsk;
+
 static char cmd[512];
 static char kname[1024];
-static uint32_t opts;
+static uint32_t opts = RBF_VIDEO;
 static struct bootinfo bootinfo;
 
-static int ls, dsk_meta;
-static uint32_t fs_off;
+/*
+ * boot2 encapsulated ABI elements provided to *fsread.c
+ *
+ * NOTE: boot2_dmadat is extended by per-filesystem APIs
+ */
+uint32_t fs_off;
+int    ls;
+struct boot2_dmadat *boot2_dmadat;
 
 void exit(int);
 static void load(void);
 static int parse(void);
-static int xfsread(ino_t, void *, size_t);
-static int dskread(void *, unsigned, unsigned);
-static void printf(const char *,...);
-static void putchar(int);
+static int dskprobe(void);
+static int xfsread(boot2_ino_t, void *, size_t);
 static uint32_t memsize(void);
 static int drvread(void *, unsigned, unsigned);
 static int keyhit(unsigned);
@@ -179,7 +181,7 @@ static void xputc(int);
 static int xgetc(int);
 static int getc(int);
 
-static void 
+void
 memcpy(void *d, const void *s, int len)
 {
     char *dd = d;
@@ -198,23 +200,32 @@ memcpy(void *d, const void *s, int len)
 #endif
 }
 
-static inline int
+int
 strcmp(const char *s1, const char *s2)
 {
-    for (; *s1 == *s2 && *s1; s1++, s2++);
-    return (unsigned char)*s1 - (unsigned char)*s2;
+    for (; *s1 == *s2 && *s1; s1++, s2++)
+       ;
+    return ((int)((unsigned char)*s1 - (unsigned char)*s2));
 }
 
-#if HAMMERFS
-#include "hammerread.c"
-#else
-#include "ufsread.c"
+#if defined(UFS) && defined(HAMMERFS)
+
+const struct boot2_fsapi *fsapi;
+
+#elif defined(UFS)
+
+#define fsapi  (&boot2_ufs_api)
+
+#elif defined(HAMMERFS)
+
+#define fsapi  (&boot2_hammer_api)
+
 #endif
 
 static int
-xfsread(ino_t inode, void *buf, size_t nbyte)
+xfsread(boot2_ino_t inode, void *buf, size_t nbyte)
 {
-    if ((size_t)fsread(inode, buf, nbyte) != nbyte) {
+    if ((size_t)fsapi->fsread(inode, buf, nbyte) != nbyte) {
        printf(INVALID_S, "format");
        return -1;
     }
@@ -273,9 +284,10 @@ int
 main(void)
 {
     int autoboot;
-    ino_t ino;
+    boot2_ino_t ino;
 
-    dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
+    boot2_dmadat =
+               (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
     v86.ctl = V86_FLAGS;
     dsk.drive = *(uint8_t *)PTOV(MEM_BTX_USR_ARG);
     dsk.type = dsk.drive & DRV_HARD ? TYPE_AD : TYPE_FD;
@@ -287,13 +299,20 @@ main(void)
     bootinfo.bi_extmem = memsize();
     bootinfo.bi_memsizes_valid++;
 
-    /* Process configuration file */
-
     autoboot = 1;
 
-    if ((ino = lookup(PATH_CONFIG)))
-       fsread(ino, cmd, sizeof(cmd));
+    /*
+     * Probe the default disk and process the configuration file if
+     * successful.
+     */
+    if (dskprobe() == 0) {
+       if ((ino = fsapi->fslookup(PATH_CONFIG)))
+           fsapi->fsread(ino, cmd, sizeof(cmd));
+    }
 
+    /*
+     * Parse config file if present.  parse() will re-probe if necessary.
+     */
     if (cmd[0]) {
        printf("%s: %s", PATH_CONFIG, cmd);
        if (parse())
@@ -367,11 +386,11 @@ load(void)
     Elf32_Phdr ep[2];
     Elf32_Shdr es[2];
     caddr_t p;
-    ino_t ino;
+    boot2_ino_t ino;
     uint32_t addr, x;
     int fmt, i, j;
 
-    if (!(ino = lookup(kname))) {
+    if (!(ino = fsapi->fslookup(kname))) {
        if (!ls)
            printf("No %s\n", kname);
        return;
@@ -453,7 +472,7 @@ load(void)
 }
 
 static int
-parse()
+parse(void)
 {
     char *arg = cmd;
     char *p, *q;
@@ -525,7 +544,6 @@ parse()
                    drv = dsk.unit;
                dsk.drive = (dsk.type <= TYPE_MAXHARD
                             ? DRV_HARD : 0) + drv;
-               dsk_meta = 0;
            }
            if ((i = p - arg - !*(p - 1))) {
                if ((size_t)i >= sizeof(kname))
@@ -535,11 +553,11 @@ parse()
        }
        arg = p;
     }
-    return 0;
+    return dskprobe();
 }
 
 static int
-dskread(void *buf, unsigned lba, unsigned nblk)
+dskprobe(void)
 {
     struct dos_partition *dp;
 #ifdef DISKLABEL64
@@ -550,77 +568,112 @@ dskread(void *buf, unsigned lba, unsigned nblk)
     char *sec;
     unsigned sl, i;
 
-    if (!dsk_meta) {
-       sec = dmadat->secbuf;
-       dsk.start = 0;
-       if (drvread(sec, DOSBBSECTOR, 1))
-           return -1;
-       dp = (void *)(sec + DOSPARTOFF);
-       sl = dsk.slice;
-       if (sl < BASE_SLICE) {
-           for (i = 0; i < NDOSPART; i++)
-               if (dp[i].dp_typ == DOSPTYP_386BSD &&
-                   (dp[i].dp_flag & 0x80 || sl < BASE_SLICE)) {
-                   sl = BASE_SLICE + i;
-                   if (dp[i].dp_flag & 0x80 ||
-                       dsk.slice == COMPATIBILITY_SLICE)
-                       break;
-               }
-           if (dsk.slice == WHOLE_DISK_SLICE)
-               dsk.slice = sl;
-       }
-       if (sl != WHOLE_DISK_SLICE) {
-           if (sl != COMPATIBILITY_SLICE)
-               dp += sl - BASE_SLICE;
-           if (dp->dp_typ != DOSPTYP_386BSD) {
-               printf(INVALID_S, "slice");
-               return -1;
+    /*
+     * Probe slice table
+     */
+    sec = boot2_dmadat->secbuf;
+    dsk.start = 0;
+    if (drvread(sec, DOSBBSECTOR, 1))
+       return -1;
+    dp = (void *)(sec + DOSPARTOFF);
+    sl = dsk.slice;
+    if (sl < BASE_SLICE) {
+       for (i = 0; i < NDOSPART; i++)
+           if (dp[i].dp_typ == DOSPTYP_386BSD &&
+               (dp[i].dp_flag & 0x80 || sl < BASE_SLICE)) {
+               sl = BASE_SLICE + i;
+               if (dp[i].dp_flag & 0x80 ||
+                   dsk.slice == COMPATIBILITY_SLICE)
+                   break;
            }
-           dsk.start = dp->dp_start;
+       if (dsk.slice == WHOLE_DISK_SLICE)
+           dsk.slice = sl;
+    }
+    if (sl != WHOLE_DISK_SLICE) {
+       if (sl != COMPATIBILITY_SLICE)
+           dp += sl - BASE_SLICE;
+       if (dp->dp_typ != DOSPTYP_386BSD) {
+           printf(INVALID_S, "slice");
+           return -1;
        }
+       dsk.start = dp->dp_start;
+    }
+
+    /*
+     * Probe label and partition table
+     */
 #ifdef DISKLABEL64
-       if (drvread(sec, dsk.start, (sizeof(struct disklabel64) + 511) / 512))
-               return -1;
-       d = (void *)sec;
-       if (d->d_magic != DISKMAGIC64) {
-           printf(INVALID_S, "label");
+    if (drvread(sec, dsk.start, (sizeof(struct disklabel64) + 511) / 512))
+           return -1;
+    d = (void *)sec;
+    if (d->d_magic != DISKMAGIC64) {
+       printf(INVALID_S, "label");
+       return -1;
+    } else {
+       if (dsk.part >= d->d_npartitions || d->d_partitions[dsk.part].p_bsize == 0) {
+           printf(INVALID_S, "partition");
            return -1;
-       } else {
-           if (dsk.part >= d->d_npartitions || d->d_partitions[dsk.part].p_bsize == 0) {
-               printf(INVALID_S, "partition");
-               return -1;
-           }
-           dsk.start += d->d_partitions[dsk.part].p_boffset / 512;
        }
+       dsk.start += d->d_partitions[dsk.part].p_boffset / 512;
+    }
 #else
-       if (drvread(sec, dsk.start + LABELSECTOR32, 1))
-               return -1;
-       d = (void *)(sec + LABELOFFSET32);
-       if (d->d_magic != DISKMAGIC32 || d->d_magic2 != DISKMAGIC32) {
-           if (dsk.part != RAW_PART) {
-               printf(INVALID_S, "label");
-               return -1;
-           }
-       } else {
-           if (!dsk.init) {
-               if (d->d_type == DTYPE_SCSI)
-                   dsk.type = TYPE_DA;
-               dsk.init++;
-           }
-           if (dsk.part >= d->d_npartitions ||
-               !d->d_partitions[dsk.part].p_size) {
-               printf(INVALID_S, "partition");
-               return -1;
-           }
-           dsk.start += d->d_partitions[dsk.part].p_offset;
-           dsk.start -= d->d_partitions[RAW_PART].p_offset;
+    if (drvread(sec, dsk.start + LABELSECTOR32, 1))
+           return -1;
+    d = (void *)(sec + LABELOFFSET32);
+    if (d->d_magic != DISKMAGIC32 || d->d_magic2 != DISKMAGIC32) {
+       if (dsk.part != RAW_PART) {
+           printf(INVALID_S, "label");
+           return -1;
+       }
+    } else {
+       if (!dsk.init) {
+           if (d->d_type == DTYPE_SCSI)
+               dsk.type = TYPE_DA;
+           dsk.init++;
        }
+       if (dsk.part >= d->d_npartitions ||
+           !d->d_partitions[dsk.part].p_size) {
+           printf(INVALID_S, "partition");
+           return -1;
+       }
+       dsk.start += d->d_partitions[dsk.part].p_offset;
+       dsk.start -= d->d_partitions[RAW_PART].p_offset;
+    }
 #endif
+    /*
+     * Probe filesystem
+     */
+#if defined(UFS) && defined(HAMMERFS)
+    if (boot2_hammer_api.fsinit() == 0) {
+       fsapi = &boot2_hammer_api;
+    } else if (boot2_ufs_api.fsinit() == 0) {
+       fsapi = &boot2_ufs_api;
+    } else {
+       printf("fs probe failed\n");
+       fsapi = &boot2_ufs_api;
+       return -1;
     }
+    return 0;
+#else
+    return fsapi->fsinit();
+#endif
+}
+
+
+/*
+ * Read from the probed disk.  We have established the slice and partition
+ * base sector.
+ */
+int
+dskread(void *buf, unsigned lba, unsigned nblk)
+{
     return drvread(buf, dsk.start + lba, nblk);
 }
 
-static void
+/*
+ * boot encapsulated ABI
+ */
+void
 printf(const char *fmt,...)
 {
     va_list ap;
@@ -655,10 +708,12 @@ printf(const char *fmt,...)
        putchar(c);
     }
     va_end(ap);
-    return;
 }
 
-static void
+/*
+ * boot encapsulated ABI
+ */
+void
 putchar(int c)
 {
     if (c == '\n')
@@ -666,7 +721,10 @@ putchar(int c)
     xputc(c);
 }
 
-static int
+/*
+ * boot encapsulated ABI
+ */
+int
 drvread(void *buf, unsigned lba, unsigned nblk)
 {
     static unsigned c = 0x2d5c7c2f;    /* twiddle */
index f13516d..0db08f0 100644 (file)
 /*
  * This is the origin of boot2.bin relative to the BTX user address space
  * (e.g. physical address would be MEM_BTX_USR+BOOT2_VORIGIN).
+ *
+ * The physical origin is typically around 0xC000 and limits the size of
+ * boot2 to 16K, otherwise the loader will overflow the segment in v86 mode.
  */
-#define BOOT2_VORIGIN  0x4000
+#define BOOT2_VORIGIN  0x2000
 
 /*
  * NOTE: BOOT0_ORIGIN is extracted from this file and used in boot0/Makefile
index ebb106b..12b43d1 100644 (file)
@@ -90,11 +90,7 @@ typedef      __uint32_t      gid_t;          /* group id */
 typedef __int64_t      id_t;           /* general id, can hold gid/pid/uid_t */
 typedef        __uint32_t      in_addr_t;      /* base type for internet address */
 typedef        __uint16_t      in_port_t;
-#ifdef __BOOT2_HACK
-typedef        __uint32_t      ino_t;          /* inode number */
-#else
 typedef        __uint64_t      ino_t;          /* inode number */
-#endif
 typedef        long            key_t;          /* IPC key (for Sys V IPC) */
 typedef        __uint16_t      mode_t;         /* permissions */
 typedef        __uint32_t      nlink_t;        /* link count */