From d64b2e330d33214f962ba88400ebbf8d11c18ef4 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sun, 1 Mar 2009 18:49:06 -0800 Subject: [PATCH] disklabel64 UFS+HAMMER boot support (was previously just HAMMER boot support) 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 | 38 ++++--- sys/boot/common/boot2.h | 91 ++++++++++++++++ sys/boot/common/dinode.h | 1 + sys/boot/common/ufsread.c | 124 +++++++++++++--------- sys/boot/pc32/boot2/Makefile | 32 ++++-- sys/boot/pc32/boot2/boot1.S | 6 +- sys/boot/pc32/boot2/boot2.c | 248 ++++++++++++++++++++++++++----------------- sys/boot/pc32/bootasm.h | 5 +- sys/sys/types.h | 4 - 9 files changed, 375 insertions(+), 174 deletions(-) create mode 100644 sys/boot/common/boot2.h diff --git a/lib/libstand/hammerread.c b/lib/libstand/hammerread.c index b24a57b33b..083455f23c 100644 --- a/lib/libstand/hammerread.c +++ b/lib/libstand/hammerread.c @@ -45,10 +45,13 @@ #define LIBSTAND 1 #endif +#ifdef BOOT2 +#include "boot2.h" +#else #include - #include #include +#endif #ifdef TESTING #include @@ -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 index 0000000000..ddd9299b93 --- /dev/null +++ b/sys/boot/common/boot2.h @@ -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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +/* + * 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 diff --git a/sys/boot/common/dinode.h b/sys/boot/common/dinode.h index e16f215fd3..6b6a916465 100644 --- a/sys/boot/common/dinode.h +++ b/sys/boot/common/dinode.h @@ -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. */ diff --git a/sys/boot/common/ufsread.c b/sys/boot/common/ufsread.c index 93bd28731a..6b946000ac 100644 --- a/sys/boot/common/ufsread.c +++ b/sys/boot/common/ufsread.c @@ -25,9 +25,19 @@ * $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 +#endif +#include +#include +#include +#include #include #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 @@ -55,19 +65,27 @@ #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; } diff --git a/sys/boot/pc32/boot2/Makefile b/sys/boot/pc32/boot2/Makefile index 2a9043aca8..bd61016fbc 100644 --- a/sys/boot/pc32/boot2/Makefile +++ b/sys/boot/pc32/boot2/Makefile @@ -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 diff --git a/sys/boot/pc32/boot2/boot1.S b/sys/boot/pc32/boot2/boot1.S index 39cfcdfa0c..475ffe298b 100644 --- a/sys/boot/pc32/boot2/boot1.S +++ b/sys/boot/pc32/boot2/boot1.S @@ -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 diff --git a/sys/boot/pc32/boot2/boot2.c b/sys/boot/pc32/boot2/boot2.c index d37e751846..dd0aff91d9 100644 --- a/sys/boot/pc32/boot2/boot2.c +++ b/sys/boot/pc32/boot2/boot2.c @@ -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 #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 */ diff --git a/sys/boot/pc32/bootasm.h b/sys/boot/pc32/bootasm.h index f13516dfef..0db08f026a 100644 --- a/sys/boot/pc32/bootasm.h +++ b/sys/boot/pc32/bootasm.h @@ -72,8 +72,11 @@ /* * 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 diff --git a/sys/sys/types.h b/sys/sys/types.h index ebb106b634..12b43d1931 100644 --- a/sys/sys/types.h +++ b/sys/sys/types.h @@ -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 */ -- 2.11.4.GIT