AMD64 - Fix native-built sys/boot install
[dragonfly.git] / sys / boot / pc32 / boot2 / boot2.c
index e283e7f..34bddfb 100644 (file)
  * purpose.
  *
  * $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.16 2007/06/18 05:13:42 dillon Exp $
+ * $DragonFly: src/sys/boot/pc32/boot2/boot2.c,v 1.18 2008/09/13 11:45:45 corecode Exp $
  */
+
+#define AOUT_H_FORCE32
 #include <sys/param.h>
+#ifdef DISKLABEL64
+#include <sys/disklabel64.h>
+#else
 #include <sys/disklabel32.h>
+#endif
 #include <sys/diskslice.h>
 #include <sys/diskmbr.h>
 #include <sys/dtype.h>
 
 #include <btxv86.h>
 
+#ifdef DISKLABEL64
+#include "boot2_64.h"
+#else
+#include "boot2_32.h"
+#endif
 #include "boot2.h"
 #include "lib.h"
 #include "../bootasm.h"
 #define RBX_MASK       0x2005ffff
 
 #define PATH_CONFIG    "/boot.config"
-#define PATH_BOOT3     "/boot/loader"
+#define PATH_BOOT3     "/boot/loader"          /* /boot in root */
+#define PATH_BOOT3_ALT "/loader"               /* /boot partition */
 #define PATH_KERNEL    "/kernel"
 
 #define NDEV           3
@@ -143,18 +155,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;
 
+/*
+ * 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);
@@ -162,7 +182,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;
@@ -181,19 +201,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));
 }
 
-#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;
     }
@@ -252,9 +285,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;
@@ -266,13 +300,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())
@@ -297,11 +338,15 @@ main(void)
     /*
      * Try to exec stage 3 boot loader. If interrupted by a keypress,
      * or in case of failure, try to load a kernel directly instead.
+     *
+     * We have to try boot /boot/loader and /loader to support booting
+     * from a /boot partition instead of a root partition.
      */
-
     if (autoboot && !*kname) {
        memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3));
        if (!keyhit(3*SECOND)) {
+           load();
+           memcpy(kname, PATH_BOOT3_ALT, sizeof(PATH_BOOT3_ALT));
            load();
            memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL));
        }
@@ -342,11 +387,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;
@@ -428,7 +473,7 @@ load(void)
 }
 
 static int
-parse()
+parse(void)
 {
     char *arg = cmd;
     char *p, *q;
@@ -500,7 +545,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))
@@ -510,72 +554,127 @@ parse()
        }
        arg = p;
     }
-    return 0;
+    return dskprobe();
 }
 
 static int
-dskread(void *buf, unsigned lba, unsigned nblk)
+dskprobe(void)
 {
     struct dos_partition *dp;
+#ifdef DISKLABEL64
+    struct disklabel64 *d;
+#else
     struct disklabel32 *d;
+#endif
     char *sec;
     unsigned sl, i;
 
-    if (!dsk_meta) {
-       sec = dmadat->secbuf;
-       dsk.start = 0;
-       if (drvread(sec, DOSBBSECTOR, 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;
+           }
+       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;
-       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;
-           }
-           dsk.start = dp->dp_start;
+       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");
+       return -1;
+    } else {
+       if (dsk.part >= d->d_npartitions || d->d_partitions[dsk.part].p_bsize == 0) {
+           printf(INVALID_S, "partition");
+           return -1;
        }
-       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;
+       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;
+    }
+#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;
@@ -610,10 +709,12 @@ printf(const char *fmt,...)
        putchar(c);
     }
     va_end(ap);
-    return;
 }
 
-static void
+/*
+ * boot encapsulated ABI
+ */
+void
 putchar(int c)
 {
     if (c == '\n')
@@ -621,7 +722,10 @@ putchar(int c)
     xputc(c);
 }
 
-static int
+/*
+ * boot encapsulated ABI
+ */
+int
 drvread(void *buf, unsigned lba, unsigned nblk)
 {
     static unsigned c = 0x2d5c7c2f;    /* twiddle */