svn commit: r362431 - in head: stand stand/efi/libefi stand/efi/loader stand/i386/gptzfsboot stand/i386/libi386 stand/i386/zfsboot stand/libsa/zfs stand/userboot/userboot sys/cddl/boot/zfs
Toomas Soome
tsoome at FreeBSD.org
Sat Jun 20 06:23:32 UTC 2020
Author: tsoome
Date: Sat Jun 20 06:23:31 2020
New Revision: 362431
URL: https://svnweb.freebsd.org/changeset/base/362431
Log:
loader: create single zfs nextboot implementation
We should have nextboot feature implemented in libsa zfs code.
To get there, I have created zfs_nextboot() implementation based on
two sources, our current simple textual string based approach with added
structured boot label PAD structure from OpenZFS.
Secondly, all nvlist details are moved to separate source file and
restructured a bit. This is done to provide base support to add nvlist
add/update feature in followup updates.
And finally, the zfsboot/gptzfsboot disk access functions are swapped to use
libi386 and libsa.
Sponsored by: Netflix, Klara Inc.
Differential Revision: https://reviews.freebsd.org/D25324
Added:
head/stand/libsa/zfs/nvlist.c (contents, props changed)
Modified:
head/stand/efi/libefi/Makefile
head/stand/efi/loader/main.c
head/stand/i386/gptzfsboot/Makefile
head/stand/i386/libi386/Makefile
head/stand/i386/zfsboot/Makefile
head/stand/i386/zfsboot/zfsboot.c
head/stand/libsa/zfs/Makefile.inc
head/stand/libsa/zfs/libzfs.h
head/stand/libsa/zfs/zfs.c
head/stand/libsa/zfs/zfsimpl.c
head/stand/loader.mk
head/stand/userboot/userboot/Makefile
head/sys/cddl/boot/zfs/zfsimpl.h
Modified: head/stand/efi/libefi/Makefile
==============================================================================
--- head/stand/efi/libefi/Makefile Sat Jun 20 06:20:00 2020 (r362430)
+++ head/stand/efi/libefi/Makefile Sat Jun 20 06:23:31 2020 (r362431)
@@ -52,6 +52,8 @@ CFLAGS.efi_console.c+= -I${SRCTOP}/sys/teken
CFLAGS.teken.c+= -I${SRCTOP}/sys/teken
.if ${MK_LOADER_ZFS} != "no"
CFLAGS+= -I${ZFSSRC}
+CFLAGS+= -I${SYSDIR}/cddl/boot/zfs
+CFLAGS+= -I${SYSDIR}/cddl/contrib/opensolaris/uts/common
CFLAGS+= -DEFI_ZFS_BOOT
.endif
Modified: head/stand/efi/loader/main.c
==============================================================================
--- head/stand/efi/loader/main.c Sat Jun 20 06:20:00 2020 (r362430)
+++ head/stand/efi/loader/main.c Sat Jun 20 06:23:31 2020 (r362431)
@@ -260,6 +260,8 @@ probe_zfs_currdev(uint64_t guid)
{
char *devname;
struct zfs_devdesc currdev;
+ char *buf = NULL;
+ bool rv;
currdev.dd.d_dev = &zfs_dev;
currdev.dd.d_unit = 0;
@@ -269,7 +271,18 @@ probe_zfs_currdev(uint64_t guid)
devname = efi_fmtdev(&currdev);
init_zfs_bootenv(devname);
- return (sanity_check_currdev());
+ rv = sanity_check_currdev();
+ if (rv) {
+ buf = malloc(VDEV_PAD_SIZE);
+ if (buf != NULL) {
+ if (zfs_nextboot(&currdev, buf, VDEV_PAD_SIZE) == 0) {
+ printf("zfs nextboot: %s\n", buf);
+ set_currdev(buf);
+ }
+ free(buf);
+ }
+ }
+ return (rv);
}
#endif
Modified: head/stand/i386/gptzfsboot/Makefile
==============================================================================
--- head/stand/i386/gptzfsboot/Makefile Sat Jun 20 06:20:00 2020 (r362430)
+++ head/stand/i386/gptzfsboot/Makefile Sat Jun 20 06:23:31 2020 (r362431)
@@ -4,7 +4,7 @@
.PATH: ${BOOTSRC}/i386/boot2 ${BOOTSRC}/i386/gptboot \
${BOOTSRC}/i386/zfsboot ${BOOTSRC}/i386/common \
- ${SASRC}
+ ${BOOTSRC}/common
FILES= gptzfsboot
MAN= gptzfsboot.8
@@ -19,12 +19,16 @@ ORG2= 0x0
CFLAGS+=-DBOOTPROG=\"gptzfsboot\" \
-O1 \
- -DGPT -DZFS -DBOOT2 \
+ -DBOOT2 \
+ -DLOADER_GPT_SUPPORT \
+ -DLOADER_MBR_SUPPORT \
+ -DLOADER_ZFS_SUPPORT \
-DSIOPRT=${BOOT_COMCONSOLE_PORT} \
-DSIOFMT=${B2SIOFMT} \
-DSIOSPD=${BOOT_COMCONSOLE_SPEED} \
-I${LDRSRC} \
-I${BOOTSRC}/i386/common \
+ -I${BOOTSRC}/i386/libi386 \
-I${ZFSSRC} \
-I${SYSDIR}/crypto/skein \
-I${SYSDIR}/cddl/boot/zfs \
@@ -60,15 +64,18 @@ gptldr.bin: gptldr.out
gptldr.out: gptldr.o
${LD} ${LD_FLAGS} -e start --defsym ORG=${ORG1} -T ${LDSCRIPT} -o ${.TARGET} gptldr.o
-CLEANFILES+= gptzfsboot.bin gptzfsboot.out zfsboot.o sio.o cons.o \
- drv.o gpt.o ${OPENCRYPTO_XTS}
+OBJS= zfsboot.o sio.o cons.o bcache.o devopen.o disk.o part.o zfs_cmd.o
+CLEANFILES+= gptzfsboot.bin gptzfsboot.out ${OBJS} ${OPENCRYPTO_XTS}
+# i386 standalone support library
+LIBI386= ${BOOTOBJ}/i386/libi386/libi386.a
+
gptzfsboot.bin: gptzfsboot.out
${OBJCOPY} -S -O binary gptzfsboot.out ${.TARGET}
-gptzfsboot.out: ${BTXCRT} zfsboot.o sio.o gpt.o drv.o cons.o \
+gptzfsboot.out: ${BTXCRT} ${OBJS} \
${OPENCRYPTO_XTS}
- ${LD} ${LD_FLAGS} --defsym ORG=${ORG2} -T ${LDSCRIPT} -o ${.TARGET} ${.ALLSRC} ${LIBSA32}
+ ${LD} ${LD_FLAGS} --defsym ORG=${ORG2} -T ${LDSCRIPT} -o ${.TARGET} ${.ALLSRC} ${LIBI386} ${LIBSA32}
zfsboot.o: ${ZFSSRC}/zfsimpl.c
Modified: head/stand/i386/libi386/Makefile
==============================================================================
--- head/stand/i386/libi386/Makefile Sat Jun 20 06:20:00 2020 (r362430)
+++ head/stand/i386/libi386/Makefile Sat Jun 20 06:23:31 2020 (r362431)
@@ -37,6 +37,8 @@ CFLAGS+= -Dalloca=__builtin_alloca
CFLAGS+= -I${BOOTSRC}/ficl -I${BOOTSRC}/ficl/i386 \
-I${LDRSRC} -I${BOOTSRC}/i386/common \
+ -I${SYSDIR}/cddl/boot/zfs \
+ -I${SYSDIR}/cddl/contrib/opensolaris/uts/common \
-I${SYSDIR}/contrib/dev/acpica/include
# Handle FreeBSD specific %b and %D printf format specifiers
Modified: head/stand/i386/zfsboot/Makefile
==============================================================================
--- head/stand/i386/zfsboot/Makefile Sat Jun 20 06:20:00 2020 (r362430)
+++ head/stand/i386/zfsboot/Makefile Sat Jun 20 06:23:31 2020 (r362431)
@@ -2,7 +2,7 @@
.include <bsd.init.mk>
-.PATH: ${BOOTSRC}/i386/boot2 ${BOOTSRC}/i386/common ${SASRC}
+.PATH: ${BOOTSRC}/i386/boot2 ${BOOTSRC}/i386/common ${BOOTSRC}/common
FILES= zfsboot
MAN= zfsboot.8
@@ -17,13 +17,17 @@ ORG2= 0x2000
CFLAGS+=-DBOOTPROG=\"zfsboot\" \
-O1 \
- -DZFS -DBOOT2 \
+ -DBOOT2 \
+ -DLOADER_GPT_SUPPORT \
+ -DLOADER_MBR_SUPPORT \
+ -DLOADER_ZFS_SUPPORT \
+ -DLOADER_UFS_SUPPORT \
-DSIOPRT=${BOOT_COMCONSOLE_PORT} \
-DSIOFMT=${B2SIOFMT} \
-DSIOSPD=${BOOT_COMCONSOLE_SPEED} \
-I${LDRSRC} \
-I${BOOTSRC}/i386/common \
- -I${BOOTSRC}/i386 \
+ -I${BOOTSRC}/i386/libi386 \
-I${ZFSSRC} \
-I${SYSDIR}/crypto/skein \
-I${SYSDIR}/cddl/boot/zfs \
@@ -34,6 +38,8 @@ CFLAGS+=-DBOOTPROG=\"zfsboot\" \
-Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
-Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings
+CFLAGS.part.c+= -DHAVE_MEMCPY -I${SRCTOP}/sys/contrib/zlib
+
CFLAGS.gcc+= --param max-inline-insns-single=100
LD_FLAGS+=${LD_FLAGS_BIN}
@@ -51,14 +57,18 @@ zfsboot1: zfsldr.out
zfsldr.out: zfsldr.o
${LD} ${LD_FLAGS} -e start --defsym ORG=${ORG1} -T ${LDSCRIPT} -o ${.TARGET} zfsldr.o
+OBJS= zfsboot.o sio.o cons.o bcache.o devopen.o disk.o part.o zfs_cmd.o
CLEANFILES+= zfsboot2 zfsboot.ld zfsboot.ldr zfsboot.bin zfsboot.out \
- zfsboot.o zfsboot.s zfsboot.s.tmp sio.o cons.o drv.o
+ ${OBJS}
# We currently allow 256k bytes for zfsboot - in practice it could be
# any size up to 3.5Mb but keeping it fixed size simplifies zfsldr.
#
BOOT2SIZE= 262144
+# i386 standalone support library
+LIBI386= ${BOOTOBJ}/i386/libi386/libi386.a
+
zfsboot2: zfsboot.ld
@set -- `ls -l ${.ALLSRC}`; x=$$((${BOOT2SIZE}-$$5)); \
echo "$$x bytes available"; test $$x -ge 0
@@ -74,8 +84,8 @@ zfsboot.ldr:
zfsboot.bin: zfsboot.out
${OBJCOPY} -S -O binary zfsboot.out ${.TARGET}
-zfsboot.out: ${BTXCRT} zfsboot.o sio.o drv.o cons.o
- ${LD} ${LD_FLAGS} --defsym ORG=${ORG2} -T ${LDSCRIPT} -o ${.TARGET} ${.ALLSRC} ${LIBSA32}
+zfsboot.out: ${BTXCRT} ${OBJS}
+ ${LD} ${LD_FLAGS} --defsym ORG=${ORG2} -T ${LDSCRIPT} -o ${.TARGET} ${.ALLSRC} ${LIBI386} ${LIBSA32}
SRCS= zfsboot.c
Modified: head/stand/i386/zfsboot/zfsboot.c
==============================================================================
--- head/stand/i386/zfsboot/zfsboot.c Sat Jun 20 06:20:00 2020 (r362430)
+++ head/stand/i386/zfsboot/zfsboot.c Sat Jun 20 06:23:31 2020 (r362431)
@@ -16,7 +16,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "stand.h"
+#include <stand.h>
#include <sys/param.h>
#include <sys/errno.h>
@@ -35,15 +35,16 @@ __FBSDID("$FreeBSD$");
#include <stddef.h>
#include <a.out.h>
-
+#include "bootstrap.h"
+#include "libi386.h"
#include <btxv86.h>
#include "lib.h"
#include "rbx.h"
-#include "drv.h"
-#include "edd.h"
#include "cons.h"
#include "bootargs.h"
+#include "disk.h"
+#include "part.h"
#include "paths.h"
#include "libzfs.h"
@@ -61,13 +62,8 @@ __FBSDID("$FreeBSD$");
#define TYPE_MAXHARD TYPE_DA
#define TYPE_FD 2
-#define DEV_GELIBOOT_BSIZE 4096
-
extern uint32_t _end;
-#ifdef GPT
-static const uuid_t freebsd_zfs_uuid = GPT_ENT_TYPE_FREEBSD_ZFS;
-#endif
static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */
static const unsigned char flags[NOPT] = {
RBX_DUAL,
@@ -107,785 +103,153 @@ static const struct string {
static const unsigned char dev_maj[NDEV] = {30, 4, 2};
+static struct i386_devdesc *bdev;
static char cmd[512];
static char cmddup[512];
static char kname[1024];
-static char rootname[256];
static int comspeed = SIOSPD;
static struct bootinfo bootinfo;
static uint32_t bootdev;
static struct zfs_boot_args zfsargs;
+#ifdef LOADER_GELI_SUPPORT
+static struct geli_boot_args geliargs;
+#endif
-vm_offset_t high_heap_base;
-uint32_t bios_basemem, bios_extmem, high_heap_size;
+extern vm_offset_t high_heap_base;
+extern uint32_t bios_basemem, bios_extmem, high_heap_size;
-static struct bios_smap smap;
+static char *heap_top;
+static char *heap_bottom;
-/*
- * The minimum amount of memory to reserve in bios_extmem for the heap.
- */
-#define HEAP_MIN (64 * 1024 * 1024)
-
-static char *heap_next;
-static char *heap_end;
-
-/* Buffers that must not span a 64k boundary. */
-#define READ_BUF_SIZE 8192
-struct dmadat {
- char rdbuf[READ_BUF_SIZE]; /* for reading large things */
- char secbuf[READ_BUF_SIZE]; /* for MBR/disklabel */
-};
-static struct dmadat *dmadat;
-
void exit(int);
-void reboot(void);
+static void i386_zfs_probe(void);
static void load(void);
static int parse_cmd(void);
-static void bios_getmem(void);
-int main(void);
#ifdef LOADER_GELI_SUPPORT
#include "geliboot.h"
static char gelipw[GELI_PW_MAXLEN];
#endif
-struct zfsdsk {
- struct dsk dsk;
-#ifdef LOADER_GELI_SUPPORT
- struct geli_dev *gdev;
+struct arch_switch archsw; /* MI/MD interface boundary */
+static char boot_devname[2 * ZFS_MAXNAMELEN + 8]; /* disk or pool:dataset */
+
+struct devsw *devsw[] = {
+ &bioshd,
+#if defined(LOADER_ZFS_SUPPORT)
+ &zfs_dev,
#endif
+ NULL
};
-#include "zfsimpl.c"
-
-/*
- * Read from a dnode (which must be from a ZPL filesystem).
- */
-static int
-zfs_read(spa_t *spa, const dnode_phys_t *dnode, off_t *offp, void *start,
- size_t size)
-{
- const znode_phys_t *zp = (const znode_phys_t *) dnode->dn_bonus;
- size_t n;
- int rc;
-
- n = size;
- if (*offp + n > zp->zp_size)
- n = zp->zp_size - *offp;
-
- rc = dnode_read(spa, dnode, *offp, start, n);
- if (rc)
- return (-1);
- *offp += n;
-
- return (n);
-}
-
-/*
- * Current ZFS pool
- */
-static spa_t *spa;
-static spa_t *primary_spa;
-static vdev_t *primary_vdev;
-
-/*
- * A wrapper for dskread that doesn't have to worry about whether the
- * buffer pointer crosses a 64k boundary.
- */
-static int
-vdev_read(void *xvdev, void *priv, off_t off, void *buf, size_t bytes)
-{
- char *p;
- daddr_t lba, alignlba;
- off_t diff;
- unsigned int nb, alignnb;
- struct zfsdsk *zdsk = priv;
-
- if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1)))
- return (-1);
-
- p = buf;
- lba = off / DEV_BSIZE;
- lba += zdsk->dsk.start;
- /*
- * Align reads to 4k else 4k sector GELIs will not decrypt.
- * Round LBA down to nearest multiple of DEV_GELIBOOT_BSIZE bytes.
- */
- alignlba = rounddown2(off, DEV_GELIBOOT_BSIZE) / DEV_BSIZE;
- /*
- * The read must be aligned to DEV_GELIBOOT_BSIZE bytes relative to the
- * start of the GELI partition, not the start of the actual disk.
- */
- alignlba += zdsk->dsk.start;
- diff = (lba - alignlba) * DEV_BSIZE;
-
- while (bytes > 0) {
- nb = bytes / DEV_BSIZE;
- /*
- * Ensure that the read size plus the leading offset does not
- * exceed the size of the read buffer.
- */
- if (nb > (READ_BUF_SIZE - diff) / DEV_BSIZE)
- nb = (READ_BUF_SIZE - diff) / DEV_BSIZE;
- /*
- * Round the number of blocks to read up to the nearest multiple
- * of DEV_GELIBOOT_BSIZE.
- */
- alignnb = roundup2(nb * DEV_BSIZE + diff, DEV_GELIBOOT_BSIZE)
- / DEV_BSIZE;
-
- if (zdsk->dsk.size > 0 && alignlba + alignnb >
- zdsk->dsk.size + zdsk->dsk.start) {
- printf("Shortening read at %lld from %d to %lld\n",
- alignlba, alignnb,
- (zdsk->dsk.size + zdsk->dsk.start) - alignlba);
- alignnb = (zdsk->dsk.size + zdsk->dsk.start) - alignlba;
- }
-
- if (drvread(&zdsk->dsk, dmadat->rdbuf, alignlba, alignnb))
- return (-1);
-#ifdef LOADER_GELI_SUPPORT
- /* decrypt */
- if (zdsk->gdev != NULL) {
- if (geli_read(zdsk->gdev,
- ((alignlba - zdsk->dsk.start) * DEV_BSIZE),
- dmadat->rdbuf, alignnb * DEV_BSIZE))
- return (-1);
- }
+struct fs_ops *file_system[] = {
+#if defined(LOADER_ZFS_SUPPORT)
+ &zfs_fsops,
#endif
- memcpy(p, dmadat->rdbuf + diff, nb * DEV_BSIZE);
- p += nb * DEV_BSIZE;
- lba += nb;
- alignlba += alignnb;
- bytes -= nb * DEV_BSIZE;
- /* Don't need the leading offset after the first block. */
- diff = 0;
- }
-
- return (0);
-}
-/* Match the signature exactly due to signature madness */
-static int
-vdev_read2(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
-{
- return (vdev_read(vdev, priv, off, buf, bytes));
-}
-
-
-static int
-vdev_write(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
-{
- char *p;
- daddr_t lba;
- unsigned int nb;
- struct zfsdsk *zdsk = priv;
-
- if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1)))
- return (-1);
-
- p = buf;
- lba = off / DEV_BSIZE;
- lba += zdsk->dsk.start;
- while (bytes > 0) {
- nb = bytes / DEV_BSIZE;
- if (nb > READ_BUF_SIZE / DEV_BSIZE)
- nb = READ_BUF_SIZE / DEV_BSIZE;
- memcpy(dmadat->rdbuf, p, nb * DEV_BSIZE);
- if (drvwrite(&zdsk->dsk, dmadat->rdbuf, lba, nb))
- return (-1);
- p += nb * DEV_BSIZE;
- lba += nb;
- bytes -= nb * DEV_BSIZE;
- }
-
- return (0);
-}
-
-static int
-xfsread(const dnode_phys_t *dnode, off_t *offp, void *buf, size_t nbyte)
-{
- if ((size_t)zfs_read(spa, dnode, offp, buf, nbyte) != nbyte) {
- printf("Invalid format\n");
- return (-1);
- }
- return (0);
-}
-
-/*
- * Read Pad2 (formerly "Boot Block Header") area of the first
- * vdev label of the given vdev.
- */
-static int
-vdev_read_pad2(vdev_t *vdev, char *buf, size_t size)
-{
- blkptr_t bp;
- char *tmp;
- off_t off = offsetof(vdev_label_t, vl_pad2);
- int rc;
-
- if (size > VDEV_PAD_SIZE)
- size = VDEV_PAD_SIZE;
-
- tmp = malloc(VDEV_PAD_SIZE);
- if (tmp == NULL)
- return (ENOMEM);
-
- BP_ZERO(&bp);
- BP_SET_LSIZE(&bp, VDEV_PAD_SIZE);
- BP_SET_PSIZE(&bp, VDEV_PAD_SIZE);
- BP_SET_CHECKSUM(&bp, ZIO_CHECKSUM_LABEL);
- BP_SET_COMPRESS(&bp, ZIO_COMPRESS_OFF);
- DVA_SET_OFFSET(BP_IDENTITY(&bp), off);
- rc = vdev_read_phys(vdev, &bp, tmp, off, 0);
- if (rc == 0)
- memcpy(buf, tmp, size);
- free(tmp);
- return (rc);
-}
-
-static int
-vdev_clear_pad2(vdev_t *vdev)
-{
- char *zeroes;
- uint64_t *end;
- off_t off = offsetof(vdev_label_t, vl_pad2);
- int rc;
-
- zeroes = malloc(VDEV_PAD_SIZE);
- if (zeroes == NULL)
- return (ENOMEM);
-
- memset(zeroes, 0, VDEV_PAD_SIZE);
- end = (uint64_t *)(zeroes + VDEV_PAD_SIZE);
- /* ZIO_CHECKSUM_LABEL magic and pre-calcualted checksum for all zeros */
- end[-5] = 0x0210da7ab10c7a11;
- end[-4] = 0x97f48f807f6e2a3f;
- end[-3] = 0xaf909f1658aacefc;
- end[-2] = 0xcbd1ea57ff6db48b;
- end[-1] = 0x6ec692db0d465fab;
- rc = vdev_write(vdev, vdev->v_read_priv, off, zeroes, VDEV_PAD_SIZE);
- free(zeroes);
- return (rc);
-}
-
-static void
-bios_getmem(void)
-{
- uint64_t size;
-
- /* Parse system memory map */
- v86.ebx = 0;
- do {
- v86.ctl = V86_FLAGS;
- v86.addr = 0x15; /* int 0x15 function 0xe820 */
- v86.eax = 0xe820;
- v86.ecx = sizeof(struct bios_smap);
- v86.edx = SMAP_SIG;
- v86.es = VTOPSEG(&smap);
- v86.edi = VTOPOFF(&smap);
- v86int();
- if (V86_CY(v86.efl) || (v86.eax != SMAP_SIG))
- break;
- /* look for a low-memory segment that's large enough */
- if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0) &&
- (smap.length >= (512 * 1024)))
- bios_basemem = smap.length;
- /* look for the first segment in 'extended' memory */
- if ((smap.type == SMAP_TYPE_MEMORY) &&
- (smap.base == 0x100000)) {
- bios_extmem = smap.length;
- }
-
- /*
- * Look for the largest segment in 'extended' memory beyond
- * 1MB but below 4GB.
- */
- if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base > 0x100000) &&
- (smap.base < 0x100000000ull)) {
- size = smap.length;
-
- /*
- * If this segment crosses the 4GB boundary,
- * truncate it.
- */
- if (smap.base + size > 0x100000000ull)
- size = 0x100000000ull - smap.base;
-
- if (size > high_heap_size) {
- high_heap_size = size;
- high_heap_base = smap.base;
- }
- }
- } while (v86.ebx != 0);
-
- /* Fall back to the old compatibility function for base memory */
- if (bios_basemem == 0) {
- v86.ctl = 0;
- v86.addr = 0x12; /* int 0x12 */
- v86int();
-
- bios_basemem = (v86.eax & 0xffff) * 1024;
- }
-
- /*
- * Fall back through several compatibility functions for extended
- * memory.
- */
- if (bios_extmem == 0) {
- v86.ctl = V86_FLAGS;
- v86.addr = 0x15; /* int 0x15 function 0xe801 */
- v86.eax = 0xe801;
- v86int();
- if (!V86_CY(v86.efl)) {
- bios_extmem = ((v86.ecx & 0xffff) +
- ((v86.edx & 0xffff) * 64)) * 1024;
- }
- }
- if (bios_extmem == 0) {
- v86.ctl = 0;
- v86.addr = 0x15; /* int 0x15 function 0x88 */
- v86.eax = 0x8800;
- v86int();
- bios_extmem = (v86.eax & 0xffff) * 1024;
- }
-
- /*
- * If we have extended memory and did not find a suitable heap
- * region in the SMAP, use the last 3MB of 'extended' memory as a
- * high heap candidate.
- */
- if (bios_extmem >= HEAP_MIN && high_heap_size < HEAP_MIN) {
- high_heap_size = HEAP_MIN;
- high_heap_base = bios_extmem + 0x100000 - HEAP_MIN;
- }
-}
-
-/*
- * Try to detect a device supported by the legacy int13 BIOS
- */
-static int
-int13probe(int drive)
-{
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- v86.eax = 0x800;
- v86.edx = drive;
- v86int();
-
- if (!V86_CY(v86.efl) && /* carry clear */
- ((v86.edx & 0xff) != (drive & DRV_MASK))) { /* unit # OK */
- if ((v86.ecx & 0x3f) == 0) { /* absurd sector size */
- return (0); /* skip device */
- }
- return (1);
- }
- return (0);
-}
-
-/*
- * We call this when we find a ZFS vdev - ZFS consumes the dsk
- * structure so we must make a new one.
- */
-static struct zfsdsk *
-copy_dsk(struct zfsdsk *zdsk)
-{
- struct zfsdsk *newdsk;
-
- newdsk = malloc(sizeof(struct zfsdsk));
- *newdsk = *zdsk;
- return (newdsk);
-}
-
-/*
- * Get disk size from GPT.
- */
-static uint64_t
-drvsize_gpt(struct dsk *dskp)
-{
-#ifdef GPT
- struct gpt_hdr hdr;
- char *sec;
-
- sec = dmadat->secbuf;
- if (drvread(dskp, sec, 1, 1))
- return (0);
-
- memcpy(&hdr, sec, sizeof(hdr));
- if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0 ||
- hdr.hdr_lba_self != 1 || hdr.hdr_revision < 0x00010000 ||
- hdr.hdr_entsz < sizeof(struct gpt_ent) ||
- DEV_BSIZE % hdr.hdr_entsz != 0) {
- return (0);
- }
- return (hdr.hdr_lba_alt + 1);
-#else
- return (0);
+#if defined(LOADER_UFS_SUPPORT)
+ &ufs_fsops,
#endif
-}
+ NULL
+};
-/*
- * Get disk size from eax=0x800 and 0x4800. We need to probe both
- * because 0x4800 may not be available and we would like to get more
- * or less correct disk size - if it is possible at all.
- * Note we do not really want to touch drv.c because that code is shared
- * with boot2 and we can not afford to grow that code.
- */
-static uint64_t
-drvsize_ext(struct zfsdsk *zdsk)
+caddr_t
+ptov(uintptr_t x)
{
- struct dsk *dskp;
- uint64_t size, tmp;
- int cyl, hds, sec;
-
- dskp = &zdsk->dsk;
-
- /* Try to read disk size from GPT */
- size = drvsize_gpt(dskp);
- if (size != 0)
- return (size);
-
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- v86.eax = 0x800;
- v86.edx = dskp->drive;
- v86int();
-
- /* Don't error out if we get bad sector number, try EDD as well */
- if (V86_CY(v86.efl) || /* carry set */
- (v86.edx & 0xff) <= (unsigned)(dskp->drive & 0x7f)) /* unit # bad */
- return (0);
- cyl = ((v86.ecx & 0xc0) << 2) + ((v86.ecx & 0xff00) >> 8) + 1;
- /* Convert max head # -> # of heads */
- hds = ((v86.edx & 0xff00) >> 8) + 1;
- sec = v86.ecx & 0x3f;
-
- size = (uint64_t)cyl * hds * sec;
-
- /* Determine if we can use EDD with this device. */
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- v86.eax = 0x4100;
- v86.edx = dskp->drive;
- v86.ebx = 0x55aa;
- v86int();
- if (V86_CY(v86.efl) || /* carry set */
- (v86.ebx & 0xffff) != 0xaa55 || /* signature */
- (v86.ecx & EDD_INTERFACE_FIXED_DISK) == 0)
- return (size);
-
- tmp = drvsize(dskp);
- if (tmp > size)
- size = tmp;
-
- return (size);
+ return (PTOV(x));
}
-/*
- * The "layered" ioctl to read disk/partition size. Unfortunately
- * the zfsboot case is hardest, because we do not have full software
- * stack available, so we need to do some manual work here.
- */
-uint64_t
-ldi_get_size(void *priv)
-{
- struct zfsdsk *zdsk = priv;
- uint64_t size = zdsk->dsk.size;
-
- if (zdsk->dsk.start == 0)
- size = drvsize_ext(zdsk);
-
- return (size * DEV_BSIZE);
-}
-
-static void
-probe_drive(struct zfsdsk *zdsk)
-{
-#ifdef GPT
- struct gpt_hdr hdr;
- struct gpt_ent *ent;
- unsigned part, entries_per_sec;
- daddr_t slba;
-#endif
-#if defined(GPT) || defined(LOADER_GELI_SUPPORT)
- daddr_t elba;
-#endif
-
- struct dos_partition *dp;
- char *sec;
- unsigned i;
-
-#ifdef LOADER_GELI_SUPPORT
- /*
- * Taste the disk, if it is GELI encrypted, decrypt it then dig out the
- * partition table and probe each slice/partition in turn for a vdev or
- * GELI encrypted vdev.
- */
- elba = drvsize_ext(zdsk);
- if (elba > 0) {
- elba--;
- }
- zdsk->gdev = geli_taste(vdev_read, zdsk, elba, "disk%u:0:");
- if ((zdsk->gdev != NULL) && (geli_havekey(zdsk->gdev) == 0))
- geli_passphrase(zdsk->gdev, gelipw);
-#endif /* LOADER_GELI_SUPPORT */
-
- sec = dmadat->secbuf;
- zdsk->dsk.start = 0;
-
-#ifdef GPT
- /*
- * First check for GPT.
- */
- if (drvread(&zdsk->dsk, sec, 1, 1)) {
- return;
- }
- memcpy(&hdr, sec, sizeof(hdr));
- if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0 ||
- hdr.hdr_lba_self != 1 || hdr.hdr_revision < 0x00010000 ||
- hdr.hdr_entsz < sizeof(*ent) || DEV_BSIZE % hdr.hdr_entsz != 0) {
- goto trymbr;
- }
-
- /*
- * Probe all GPT partitions for the presence of ZFS pools. We
- * return the spa_t for the first we find (if requested). This
- * will have the effect of booting from the first pool on the
- * disk.
- *
- * If no vdev is found, GELI decrypting the device and try again
- */
- entries_per_sec = DEV_BSIZE / hdr.hdr_entsz;
- slba = hdr.hdr_lba_table;
- elba = slba + hdr.hdr_entries / entries_per_sec;
- while (slba < elba) {
- zdsk->dsk.start = 0;
- if (drvread(&zdsk->dsk, sec, slba, 1))
- return;
- for (part = 0; part < entries_per_sec; part++) {
- ent = (struct gpt_ent *)(sec + part * hdr.hdr_entsz);
- if (memcmp(&ent->ent_type, &freebsd_zfs_uuid,
- sizeof(uuid_t)) == 0) {
- zdsk->dsk.start = ent->ent_lba_start;
- zdsk->dsk.size =
- ent->ent_lba_end - ent->ent_lba_start + 1;
- zdsk->dsk.slice = part + 1;
- zdsk->dsk.part = 255;
- if (vdev_probe(vdev_read2, zdsk, NULL) == 0) {
- /*
- * This slice had a vdev. We need a new
- * dsk structure now since the vdev now
- * owns this one.
- */
- zdsk = copy_dsk(zdsk);
- }
-#ifdef LOADER_GELI_SUPPORT
- else if ((zdsk->gdev = geli_taste(vdev_read,
- zdsk, ent->ent_lba_end - ent->ent_lba_start,
- "disk%up%u:", zdsk->dsk.unit,
- zdsk->dsk.slice)) != NULL) {
- if (geli_havekey(zdsk->gdev) == 0 ||
- geli_passphrase(zdsk->gdev, gelipw)
- == 0) {
- /*
- * This slice has GELI,
- * check it for ZFS.
- */
- if (vdev_probe(vdev_read2,
- zdsk, NULL) == 0) {
- /*
- * This slice had a
- * vdev. We need a new
- * dsk structure now
- * since the vdev now
- * owns this one.
- */
- zdsk = copy_dsk(zdsk);
- }
- break;
- }
- }
-#endif /* LOADER_GELI_SUPPORT */
- }
- }
- slba++;
- }
- return;
-trymbr:
-#endif /* GPT */
-
- if (drvread(&zdsk->dsk, sec, DOSBBSECTOR, 1))
- return;
- dp = (void *)(sec + DOSPARTOFF);
-
- for (i = 0; i < NDOSPART; i++) {
- if (!dp[i].dp_typ)
- continue;
- zdsk->dsk.start = dp[i].dp_start;
- zdsk->dsk.size = dp[i].dp_size;
- zdsk->dsk.slice = i + 1;
- if (vdev_probe(vdev_read2, zdsk, NULL) == 0) {
- zdsk = copy_dsk(zdsk);
- }
-#ifdef LOADER_GELI_SUPPORT
- else if ((zdsk->gdev = geli_taste(vdev_read, zdsk,
- dp[i].dp_size - dp[i].dp_start, "disk%us%u:")) != NULL) {
- if (geli_havekey(zdsk->gdev) == 0 ||
- geli_passphrase(zdsk->gdev, gelipw) == 0) {
- /*
- * This slice has GELI, check it for ZFS.
- */
- if (vdev_probe(vdev_read2, zdsk, NULL) == 0) {
- /*
- * This slice had a vdev. We need a new
- * dsk structure now since the vdev now
- * owns this one.
- */
- zdsk = copy_dsk(zdsk);
- }
- break;
- }
- }
-#endif /* LOADER_GELI_SUPPORT */
- }
-}
-
int
main(void)
{
- dnode_phys_t dn;
- off_t off;
- struct zfsdsk *zdsk;
- int autoboot, i;
- int nextboot;
- int rc;
+ unsigned i;
+ int auto_boot, fd, nextboot = 0;
+ struct disk_devdesc devdesc;
- dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
-
bios_getmem();
if (high_heap_size > 0) {
- heap_end = PTOV(high_heap_base + high_heap_size);
- heap_next = PTOV(high_heap_base);
+ heap_top = PTOV(high_heap_base + high_heap_size);
+ heap_bottom = PTOV(high_heap_base);
} else {
- heap_next = (char *)dmadat + sizeof(*dmadat);
- heap_end = (char *)PTOV(bios_basemem);
+ heap_bottom = (char *)
+ (roundup2(__base + (int32_t)&_end, 0x10000) - __base);
+ heap_top = (char *)PTOV(bios_basemem);
}
- setheap(heap_next, heap_end);
+ setheap(heap_bottom, heap_top);
- zdsk = calloc(1, sizeof(struct zfsdsk));
- zdsk->dsk.drive = *(uint8_t *)PTOV(ARGS);
- zdsk->dsk.type = zdsk->dsk.drive & DRV_HARD ? TYPE_AD : TYPE_FD;
- zdsk->dsk.unit = zdsk->dsk.drive & DRV_MASK;
- zdsk->dsk.slice = *(uint8_t *)PTOV(ARGS + 1) + 1;
- zdsk->dsk.part = 0;
- zdsk->dsk.start = 0;
- zdsk->dsk.size = drvsize_ext(zdsk);
+ /*
+ * Initialise the block cache. Set the upper limit.
+ */
+ bcache_init(32768, 512);
+ archsw.arch_autoload = NULL;
+ archsw.arch_getdev = i386_getdev;
+ archsw.arch_copyin = NULL;
+ archsw.arch_copyout = NULL;
+ archsw.arch_readin = NULL;
+ archsw.arch_isainb = NULL;
+ archsw.arch_isaoutb = NULL;
+ archsw.arch_zfs_probe = i386_zfs_probe;
+
bootinfo.bi_version = BOOTINFO_VERSION;
bootinfo.bi_size = sizeof(bootinfo);
bootinfo.bi_basemem = bios_basemem / 1024;
bootinfo.bi_extmem = bios_extmem / 1024;
bootinfo.bi_memsizes_valid++;
- bootinfo.bi_bios_dev = zdsk->dsk.drive;
+ bootinfo.bi_bios_dev = *(uint8_t *)PTOV(ARGS);
- bootdev = MAKEBOOTDEV(dev_maj[zdsk->dsk.type],
- zdsk->dsk.slice, zdsk->dsk.unit, zdsk->dsk.part);
+ /* Set up fall back device name. */
+ snprintf(boot_devname, sizeof (boot_devname), "disk%d:",
+ bd_bios2unit(bootinfo.bi_bios_dev));
- /* Process configuration file */
+ for (i = 0; devsw[i] != NULL; i++)
+ if (devsw[i]->dv_init != NULL)
+ (devsw[i]->dv_init)();
- autoboot = 1;
+ disk_parsedev(&devdesc, boot_devname + 4, NULL);
- zfs_init();
+ bootdev = MAKEBOOTDEV(dev_maj[DEVT_DISK], devdesc.d_slice + 1,
+ devdesc.dd.d_unit,
+ devdesc.d_partition >= 0 ? devdesc.d_partition : 0xff);
/*
- * Probe the boot drive first - we will try to boot from whatever
- * pool we find on that drive.
+ * zfs_fmtdev() can be called only after dv_init
*/
- probe_drive(zdsk);
-
- /*
- * Probe the rest of the drives that the bios knows about. This
- * will find any other available pools and it may fill in missing
- * vdevs for the boot pool.
- */
-#ifndef VIRTUALBOX
- for (i = 0; i < *(unsigned char *)PTOV(BIOS_NUMDRIVES); i++)
-#else
- for (i = 0; i < MAXBDDEV; i++)
-#endif
- {
- if ((i | DRV_HARD) == *(uint8_t *)PTOV(ARGS))
- continue;
-
- if (!int13probe(i | DRV_HARD))
- break;
-
- zdsk = calloc(1, sizeof(struct zfsdsk));
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-head
mailing list