Add a GPT-aware variant of zfsboot which should be used in a similar manner
to gptboot, i.e. installed in a freebsd-boot partition using /sbin/gpart or /sbin/gpt. Tweak the /boot/loader ZFS support so that it can find ZFS pools that are contained in GPT partitions.
This commit is contained in:
parent
14dddafbb3
commit
51f0d2e192
@ -1,7 +1,7 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SUBDIR= mbr pmbr boot0 boot0sio btx boot2 cdboot gptboot zfsboot \
|
||||
kgzldr libi386 libfirewire loader
|
||||
gptzfsboot kgzldr libi386 libfirewire loader
|
||||
|
||||
# special boot programs, 'self-extracting boot2+loader'
|
||||
SUBDIR+= pxeldr
|
||||
|
74
sys/boot/i386/gptzfsboot/Makefile
Normal file
74
sys/boot/i386/gptzfsboot/Makefile
Normal file
@ -0,0 +1,74 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../boot2 ${.CURDIR}/../gptboot ${.CURDIR}/../zfsboot
|
||||
|
||||
FILES= gptzfsboot
|
||||
|
||||
NM?= nm
|
||||
|
||||
BOOT_COMCONSOLE_PORT?= 0x3f8
|
||||
BOOT_COMCONSOLE_SPEED?= 9600
|
||||
B2SIOFMT?= 0x3
|
||||
|
||||
REL1= 0x700
|
||||
ORG1= 0x7c00
|
||||
ORG2= 0x0
|
||||
|
||||
CFLAGS= -Os \
|
||||
-fno-guess-branch-probability \
|
||||
-fomit-frame-pointer \
|
||||
-fno-unit-at-a-time \
|
||||
-mno-align-long-strings \
|
||||
-mrtd \
|
||||
-mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 \
|
||||
-DGPT -DBOOT2 \
|
||||
-DSIOPRT=${BOOT_COMCONSOLE_PORT} \
|
||||
-DSIOFMT=${B2SIOFMT} \
|
||||
-DSIOSPD=${BOOT_COMCONSOLE_SPEED} \
|
||||
-I${.CURDIR}/../../common \
|
||||
-I${.CURDIR}/../../zfs \
|
||||
-I${.CURDIR}/../../../cddl/boot/zfs \
|
||||
-I${.CURDIR}/../btx/lib -I. \
|
||||
-I${.CURDIR}/../boot2 \
|
||||
-Wall -Waggregate-return -Wbad-function-cast -Wcast-align \
|
||||
-Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
|
||||
-Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \
|
||||
-Winline --param max-inline-insns-single=100
|
||||
|
||||
LDFLAGS=-static -N --gc-sections
|
||||
|
||||
# Pick up ../Makefile.inc early.
|
||||
.include <bsd.init.mk>
|
||||
|
||||
CLEANFILES= gptzfsboot
|
||||
|
||||
gptzfsboot: gptldr.bin gptzfsboot.bin ${BTXKERN}
|
||||
btxld -v -E ${ORG2} -f bin -b ${BTXKERN} -l gptldr.bin \
|
||||
-o ${.TARGET} gptzfsboot.bin
|
||||
|
||||
CLEANFILES+= gptldr.bin gptldr.out gptldr.o
|
||||
|
||||
gptldr.bin: gptldr.out
|
||||
objcopy -S -O binary gptldr.out ${.TARGET}
|
||||
|
||||
gptldr.out: gptldr.o
|
||||
${LD} ${LDFLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} gptldr.o
|
||||
|
||||
CLEANFILES+= gptzfsboot.bin gptzfsboot.out zfsboot.o sio.o
|
||||
|
||||
gptzfsboot.bin: gptzfsboot.out
|
||||
objcopy -S -O binary gptzfsboot.out ${.TARGET}
|
||||
|
||||
gptzfsboot.out: ${BTXCRT} zfsboot.o sio.o
|
||||
${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC}
|
||||
|
||||
zfsboot.o: ${.CURDIR}/../../zfs/zfsimpl.c
|
||||
|
||||
.if ${MACHINE_ARCH} == "amd64"
|
||||
beforedepend gptzfsboot.o: machine
|
||||
CLEANFILES+= machine
|
||||
machine:
|
||||
ln -sf ${.CURDIR}/../../../i386/include machine
|
||||
.endif
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -19,6 +19,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/diskmbr.h>
|
||||
#ifdef GPT
|
||||
#include <sys/gpt.h>
|
||||
#endif
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
@ -32,7 +35,9 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <btxv86.h>
|
||||
|
||||
#ifndef GPT
|
||||
#include "zfsboot.h"
|
||||
#endif
|
||||
#include "lib.h"
|
||||
|
||||
#define IO_KEYBOARD 1
|
||||
@ -103,6 +108,9 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
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,
|
||||
@ -408,6 +416,12 @@ int13probe(int drive)
|
||||
static void
|
||||
probe_drive(struct dsk *dsk, spa_t **spap)
|
||||
{
|
||||
#ifdef GPT
|
||||
struct gpt_hdr hdr;
|
||||
struct gpt_ent *ent;
|
||||
daddr_t slba, elba;
|
||||
unsigned part, entries_per_sec;
|
||||
#endif
|
||||
struct dos_partition *dp;
|
||||
char *sec;
|
||||
unsigned i;
|
||||
@ -424,6 +438,63 @@ probe_drive(struct dsk *dsk, spa_t **spap)
|
||||
|
||||
sec = dmadat->secbuf;
|
||||
dsk->start = 0;
|
||||
|
||||
#ifdef GPT
|
||||
/*
|
||||
* First check for GPT.
|
||||
*/
|
||||
if (drvread(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 presense 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.
|
||||
*/
|
||||
entries_per_sec = DEV_BSIZE / hdr.hdr_entsz;
|
||||
slba = hdr.hdr_lba_table;
|
||||
elba = slba + hdr.hdr_entries / entries_per_sec;
|
||||
while (slba < elba) {
|
||||
if (drvread(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) {
|
||||
dsk->start = ent->ent_lba_start;
|
||||
if (vdev_probe(vdev_read, dsk, spap) == 0) {
|
||||
/*
|
||||
* We record the first pool we find (we will try
|
||||
* to boot from that one.
|
||||
*/
|
||||
spap = 0;
|
||||
|
||||
/*
|
||||
* This slice had a vdev. We need a new dsk
|
||||
* structure now since the vdev now owns this one.
|
||||
*/
|
||||
struct dsk *newdsk;
|
||||
newdsk = malloc(sizeof(struct dsk));
|
||||
*newdsk = *dsk;
|
||||
dsk = newdsk;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
slba++;
|
||||
}
|
||||
return;
|
||||
trymbr:
|
||||
#endif
|
||||
|
||||
if (drvread(dsk, sec, DOSBBSECTOR, 1))
|
||||
return;
|
||||
dp = (void *)(sec + DOSPARTOFF);
|
||||
@ -441,7 +512,7 @@ probe_drive(struct dsk *dsk, spa_t **spap)
|
||||
|
||||
/*
|
||||
* This slice had a vdev. We need a new dsk structure now
|
||||
* sice the vdev now owns this one.
|
||||
* since the vdev now owns this one.
|
||||
*/
|
||||
struct dsk *newdsk;
|
||||
newdsk = malloc(sizeof(struct dsk));
|
||||
@ -859,9 +930,42 @@ putchar(int c)
|
||||
xputc(c);
|
||||
}
|
||||
|
||||
#ifdef GPT
|
||||
static struct {
|
||||
uint16_t len;
|
||||
uint16_t count;
|
||||
uint16_t seg;
|
||||
uint16_t off;
|
||||
uint64_t lba;
|
||||
} packet;
|
||||
#endif
|
||||
|
||||
static int
|
||||
drvread(struct dsk *dsk, void *buf, unsigned lba, unsigned nblk)
|
||||
{
|
||||
#ifdef GPT
|
||||
static unsigned c = 0x2d5c7c2f;
|
||||
|
||||
if (!OPT_CHECK(RBX_QUIET))
|
||||
printf("%c\b", c = c << 8 | c >> 24);
|
||||
packet.len = 0x10;
|
||||
packet.count = nblk;
|
||||
packet.seg = VTOPOFF(buf);
|
||||
packet.off = VTOPSEG(buf);
|
||||
packet.lba = lba + dsk->start;
|
||||
v86.ctl = V86_FLAGS;
|
||||
v86.addr = 0x13;
|
||||
v86.eax = 0x4200;
|
||||
v86.edx = dsk->drive;
|
||||
v86.ds = VTOPSEG(&packet);
|
||||
v86.esi = VTOPOFF(&packet);
|
||||
v86int();
|
||||
if (V86_CY(v86.efl)) {
|
||||
printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
static unsigned c = 0x2d5c7c2f;
|
||||
|
||||
lba += dsk->start;
|
||||
@ -881,6 +985,7 @@ drvread(struct dsk *dsk, void *buf, unsigned lba, unsigned nblk)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -414,10 +414,14 @@ zfs_dev_init(void)
|
||||
close(fd);
|
||||
|
||||
for (slice = 1; slice <= 4; slice++) {
|
||||
sprintf(devname, "disk%ds%d:", unit, slice);
|
||||
sprintf(devname, "disk%dp%d:", unit, slice);
|
||||
fd = open(devname, O_RDONLY);
|
||||
if (fd == -1)
|
||||
continue;
|
||||
if (fd == -1) {
|
||||
sprintf(devname, "disk%ds%d:", unit, slice);
|
||||
fd = open(devname, O_RDONLY);
|
||||
if (fd == -1)
|
||||
continue;
|
||||
}
|
||||
if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
|
||||
close(fd);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user