[Midnightbsd-cvs] src [10190] trunk/sys/boot/i386/zfsboot: zfs boot

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Fri Jun 1 19:33:09 EDT 2018


Revision: 10190
          http://svnweb.midnightbsd.org/src/?rev=10190
Author:   laffer1
Date:     2018-06-01 19:33:08 -0400 (Fri, 01 Jun 2018)
Log Message:
-----------
zfs boot

Modified Paths:
--------------
    trunk/sys/boot/i386/zfsboot/Makefile
    trunk/sys/boot/i386/zfsboot/zfsboot.8
    trunk/sys/boot/i386/zfsboot/zfsboot.c

Modified: trunk/sys/boot/i386/zfsboot/Makefile
===================================================================
--- trunk/sys/boot/i386/zfsboot/Makefile	2018-06-01 23:30:37 UTC (rev 10189)
+++ trunk/sys/boot/i386/zfsboot/Makefile	2018-06-01 23:33:08 UTC (rev 10190)
@@ -1,5 +1,5 @@
 # $MidnightBSD$
-# $FreeBSD: stable/9/sys/boot/i386/zfsboot/Makefile 272697 2014-10-07 13:37:10Z avg $
+# $FreeBSD: stable/10/sys/boot/i386/zfsboot/Makefile 319025 2017-05-28 01:14:59Z ngie $
 
 .PATH:		${.CURDIR}/../boot2 ${.CURDIR}/../common ${.CURDIR}/../../common
 
@@ -18,7 +18,7 @@
 
 CFLAGS=	-DBOOTPROG=\"zfsboot\" \
 	-O1 \
-	-DBOOT2 \
+	-DZFS -DBOOT2 \
 	-DSIOPRT=${BOOT_COMCONSOLE_PORT} \
 	-DSIOFMT=${B2SIOFMT} \
 	-DSIOSPD=${BOOT_COMCONSOLE_SPEED} \
@@ -37,6 +37,8 @@
 
 LD_FLAGS=-static -N --gc-sections
 
+LIBSTAND=	${.OBJDIR}/../../libstand32/libstand.a
+
 # Pick up ../Makefile.inc early.
 .include <bsd.init.mk>
 
@@ -48,7 +50,7 @@
 CLEANFILES+=	zfsboot1 zfsldr.out zfsldr.o
 
 zfsboot1: zfsldr.out
-	objcopy -S -O binary zfsldr.out ${.TARGET}
+	${OBJCOPY} -S -O binary zfsldr.out ${.TARGET}
 
 zfsldr.out: zfsldr.o
 	${LD} ${LD_FLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} zfsldr.o
@@ -62,9 +64,9 @@
 BOOT2SIZE=	65536
 
 zfsboot2: zfsboot.ld
-	@set -- `ls -l zfsboot.ld`; x=$$((${BOOT2SIZE}-$$5)); \
+	@set -- `ls -l ${.ALLSRC}`; x=$$((${BOOT2SIZE}-$$5)); \
 	    echo "$$x bytes available"; test $$x -ge 0
-	dd if=zfsboot.ld of=${.TARGET} obs=${BOOT2SIZE} conv=osync
+	${DD} if=${.ALLSRC} of=${.TARGET} obs=${BOOT2SIZE} conv=osync
 
 zfsboot.ld: zfsboot.ldr zfsboot.bin ${BTXKERN}
 	btxld -v -E ${ORG2} -f bin -b ${BTXKERN} -l zfsboot.ldr \
@@ -74,7 +76,7 @@
 	cp /dev/null ${.TARGET}
 
 zfsboot.bin: zfsboot.out
-	objcopy -S -O binary zfsboot.out ${.TARGET}
+	${OBJCOPY} -S -O binary zfsboot.out ${.TARGET}
 
 zfsboot.out: ${BTXCRT} zfsboot.o sio.o drv.o cons.o util.o
 	${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND}

Modified: trunk/sys/boot/i386/zfsboot/zfsboot.8
===================================================================
--- trunk/sys/boot/i386/zfsboot/zfsboot.8	2018-06-01 23:30:37 UTC (rev 10189)
+++ trunk/sys/boot/i386/zfsboot/zfsboot.8	2018-06-01 23:33:08 UTC (rev 10190)
@@ -23,10 +23,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: stable/9/sys/boot/i386/zfsboot/zfsboot.8 272697 2014-10-07 13:37:10Z avg $
-.\" $MidnightBSD$
+.\" $FreeBSD: stable/10/sys/boot/i386/zfsboot/zfsboot.8 331928 2018-04-03 14:09:34Z eugen $
 .\"
-.Dd September 15, 2014
+.Dd March 27, 2018
 .Dt ZFSBOOT 8
 .Os
 .Sh NAME
@@ -101,9 +100,9 @@
 .Bd -literal -offset indent
 gpart create -s mbr ada0
 gpart add -t freebsd ada0
-gpart create -s BSD ada0s1
 gpart bootcode -b /boot/boot0 ada0
 gpart set -a active -i 1 ada0
+dd if=/dev/zero of=/dev/ada0s1 count=2
 dd if=/boot/zfsboot of=/dev/ada0s1 count=1
 dd if=/boot/zfsboot of=/dev/ada0s1 iseek=1 oseek=1024
 .Ed

Modified: trunk/sys/boot/i386/zfsboot/zfsboot.c
===================================================================
--- trunk/sys/boot/i386/zfsboot/zfsboot.c	2018-06-01 23:30:37 UTC (rev 10189)
+++ trunk/sys/boot/i386/zfsboot/zfsboot.c	2018-06-01 23:33:08 UTC (rev 10190)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 1998 Robert Nordier
  * All rights reserved.
@@ -14,8 +15,6 @@
  */
 
 #include <sys/cdefs.h>
-/* $FreeBSD: stable/9/sys/boot/i386/zfsboot/zfsboot.c 300466 2016-05-23 05:30:24Z ngie $ */
-__MBSDID("$MidnightBSD$");
 
 #include <sys/param.h>
 #include <sys/errno.h>
@@ -43,14 +42,10 @@
 #include "util.h"
 #include "cons.h"
 #include "bootargs.h"
+#include "paths.h"
 
 #include "libzfs.h"
 
-#define PATH_DOTCONFIG	"/boot.config"
-#define PATH_CONFIG	"/boot/config"
-#define PATH_BOOT3	"/boot/zfsloader"
-#define PATH_KERNEL	"/boot/kernel/kernel"
-
 #define ARGS		0x900
 #define NOPT		14
 #define NDEV		3
@@ -67,7 +62,7 @@
 extern uint32_t _end;
 
 #ifdef GPT
-static const uuid_t freebsd_zfs_uuid = GPT_ENT_TYPE_FREEBSD_ZFS;
+static const uuid_t midnightbsd_zfs_uuid = GPT_ENT_TYPE_MIDNIGHTBSD_ZFS;
 #endif
 static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */
 static const unsigned char flags[NOPT] = {
@@ -122,6 +117,7 @@
 static struct dmadat *dmadat;
 
 void exit(int);
+void reboot(void);
 static void load(void);
 static int parse(void);
 static void bios_getmem(void);
@@ -163,7 +159,7 @@
 	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);
@@ -213,6 +209,35 @@
 }
 
 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 dsk *dsk = (struct dsk *) priv;
+
+	if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1)))
+		return -1;
+
+	p = buf;
+	lba = off / DEV_BSIZE;
+	lba += 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(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) {
@@ -222,6 +247,52 @@
     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 = zap_scratch;
+	off_t off = offsetof(vdev_label_t, vl_pad2);
+
+	if (size > VDEV_PAD_SIZE)
+		size = VDEV_PAD_SIZE;
+
+	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);
+	if (vdev_read_phys(vdev, &bp, tmp, off, 0))
+		return (EIO);
+	memcpy(buf, tmp, size);
+	return (0);
+}
+
+static int
+vdev_clear_pad2(vdev_t *vdev)
+{
+	char *zeroes = zap_scratch;
+	uint64_t *end;
+	off_t off = offsetof(vdev_label_t, vl_pad2);
+
+	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;
+	if (vdev_write(vdev, vdev->v_read_priv, off, zeroes, VDEV_PAD_SIZE))
+		return (EIO);
+	return (0);
+}
+
 static void
 bios_getmem(void)
 {
@@ -238,7 +309,7 @@
 	v86.es = VTOPSEG(&smap);
 	v86.edi = VTOPOFF(&smap);
 	v86int();
-	if ((v86.efl & 1) || (v86.eax != SMAP_SIG))
+	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) &&
@@ -285,7 +356,7 @@
 	v86.addr = 0x15;		/* int 0x15 function 0xe801*/
 	v86.eax = 0xe801;
 	v86int();
-	if (!(v86.efl & 1)) {
+	if (!V86_CY(v86.efl)) {
 	    bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024;
 	}
     }
@@ -320,7 +391,7 @@
     v86.edx = drive;
     v86int();
     
-    if (!(v86.efl & 0x1) &&				/* carry clear */
+    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 */
@@ -397,7 +468,7 @@
 	    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,
+	    if (memcmp(&ent->ent_type, &midnightbsd_zfs_uuid,
 		     sizeof(uuid_t)) == 0) {
 		dsk->start = ent->ent_lba_start;
 		if (vdev_probe(vdev_read, dsk, NULL) == 0) {
@@ -436,10 +507,12 @@
 int
 main(void)
 {
-    int autoboot, i;
     dnode_phys_t dn;
     off_t off;
     struct dsk *dsk;
+    int autoboot, i;
+    int nextboot;
+    int rc;
 
     dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
 
@@ -470,7 +543,7 @@
     bootinfo.bi_bios_dev = dsk->drive;
 
     bootdev = MAKEBOOTDEV(dev_maj[dsk->type],
-			  dsk->slice, dsk->unit, dsk->part),
+			  dsk->slice, dsk->unit, dsk->part);
 
     /* Process configuration file */
 
@@ -525,7 +598,39 @@
     primary_spa = spa;
     primary_vdev = spa_get_primary_vdev(spa);
 
-    if (zfs_spa_init(spa) != 0 || zfs_mount(spa, 0, &zfsmount) != 0) {
+    nextboot = 0;
+    rc  = vdev_read_pad2(primary_vdev, cmd, sizeof(cmd));
+    if (vdev_clear_pad2(primary_vdev))
+	printf("failed to clear pad2 area of primary vdev\n");
+    if (rc == 0) {
+	if (*cmd) {
+	    /*
+	     * We could find an old-style ZFS Boot Block header here.
+	     * Simply ignore it.
+	     */
+	    if (*(uint64_t *)cmd != 0x2f5b007b10c) {
+		/*
+		 * Note that parse() is destructive to cmd[] and we also want
+		 * to honor RBX_QUIET option that could be present in cmd[].
+		 */
+		nextboot = 1;
+		memcpy(cmddup, cmd, sizeof(cmd));
+		if (parse()) {
+		    printf("failed to parse pad2 area of primary vdev\n");
+		    reboot();
+		}
+		if (!OPT_CHECK(RBX_QUIET))
+		    printf("zfs nextboot: %s\n", cmddup);
+	    }
+	    /* Do not process this command twice */
+	    *cmd = 0;
+	}
+    } else
+	printf("failed to read pad2 area of primary vdev\n");
+
+    /* Mount ZFS only if it's not already mounted via nextboot parsing. */
+    if (zfsmount.spa == NULL &&
+	(zfs_spa_init(spa) != 0 || zfs_mount(spa, 0, &zfsmount) != 0)) {
 	printf("%s: failed to mount default pool %s\n",
 	    BOOTPROG, spa->spa_name);
 	autoboot = 0;
@@ -549,13 +654,17 @@
 	*cmd = 0;
     }
 
+    /* Do not risk waiting at the prompt forever. */
+    if (nextboot && !autoboot)
+	reboot();
+
     /*
-     * Try to exec stage 3 boot loader. If interrupted by a keypress,
+     * Try to exec /boot/loader. If interrupted by a keypress,
      * or in case of failure, try to load a kernel directly instead.
      */
 
     if (autoboot && !*kname) {
-	memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3));
+	memcpy(kname, PATH_LOADER_ZFS, sizeof(PATH_LOADER_ZFS));
 	if (!keyhit(3)) {
 	    load();
 	    memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL));
@@ -598,8 +707,15 @@
 void
 exit(int x)
 {
+    __exit(x);
 }
 
+void
+reboot(void)
+{
+    __exit(0);
+}
+
 static void
 load(void)
 {



More information about the Midnightbsd-cvs mailing list