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$
|
# $FreeBSD$
|
||||||
|
|
||||||
SUBDIR= mbr pmbr boot0 boot0sio btx boot2 cdboot gptboot zfsboot \
|
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'
|
# special boot programs, 'self-extracting boot2+loader'
|
||||||
SUBDIR+= pxeldr
|
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/param.h>
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
#include <sys/diskmbr.h>
|
#include <sys/diskmbr.h>
|
||||||
|
#ifdef GPT
|
||||||
|
#include <sys/gpt.h>
|
||||||
|
#endif
|
||||||
#include <sys/reboot.h>
|
#include <sys/reboot.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
|
|
||||||
@ -32,7 +35,9 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include <btxv86.h>
|
#include <btxv86.h>
|
||||||
|
|
||||||
|
#ifndef GPT
|
||||||
#include "zfsboot.h"
|
#include "zfsboot.h"
|
||||||
|
#endif
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
#define IO_KEYBOARD 1
|
#define IO_KEYBOARD 1
|
||||||
@ -103,6 +108,9 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
extern uint32_t _end;
|
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 char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */
|
||||||
static const unsigned char flags[NOPT] = {
|
static const unsigned char flags[NOPT] = {
|
||||||
RBX_DUAL,
|
RBX_DUAL,
|
||||||
@ -408,6 +416,12 @@ int13probe(int drive)
|
|||||||
static void
|
static void
|
||||||
probe_drive(struct dsk *dsk, spa_t **spap)
|
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;
|
struct dos_partition *dp;
|
||||||
char *sec;
|
char *sec;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
@ -424,6 +438,63 @@ probe_drive(struct dsk *dsk, spa_t **spap)
|
|||||||
|
|
||||||
sec = dmadat->secbuf;
|
sec = dmadat->secbuf;
|
||||||
dsk->start = 0;
|
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))
|
if (drvread(dsk, sec, DOSBBSECTOR, 1))
|
||||||
return;
|
return;
|
||||||
dp = (void *)(sec + DOSPARTOFF);
|
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
|
* 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;
|
struct dsk *newdsk;
|
||||||
newdsk = malloc(sizeof(struct dsk));
|
newdsk = malloc(sizeof(struct dsk));
|
||||||
@ -859,9 +930,42 @@ putchar(int c)
|
|||||||
xputc(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
|
static int
|
||||||
drvread(struct dsk *dsk, void *buf, unsigned lba, unsigned nblk)
|
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;
|
static unsigned c = 0x2d5c7c2f;
|
||||||
|
|
||||||
lba += dsk->start;
|
lba += dsk->start;
|
||||||
@ -881,6 +985,7 @@ drvread(struct dsk *dsk, void *buf, unsigned lba, unsigned nblk)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -414,10 +414,14 @@ zfs_dev_init(void)
|
|||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
for (slice = 1; slice <= 4; slice++) {
|
for (slice = 1; slice <= 4; slice++) {
|
||||||
|
sprintf(devname, "disk%dp%d:", unit, slice);
|
||||||
|
fd = open(devname, O_RDONLY);
|
||||||
|
if (fd == -1) {
|
||||||
sprintf(devname, "disk%ds%d:", unit, slice);
|
sprintf(devname, "disk%ds%d:", unit, slice);
|
||||||
fd = open(devname, O_RDONLY);
|
fd = open(devname, O_RDONLY);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
|
if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user