Commit 315910bd authored by Mike Hibler's avatar Mike Hibler
Browse files

Teach imageunzip and frisbee about GPT.

Now the -s option works as well as the -D option to set the partition
type. We can now properly save and restore both partition and whole
disk images. Well, once I change the scripts...
parent d8b6eb6a
#
# Copyright (c) 2000-2014 University of Utah and the Flux Group.
# Copyright (c) 2000-2015 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -32,6 +32,12 @@ DISTFILES = TODO client.c decls.h event.c event.h log.c log.h \
network.c queue.h server.c trace.c trace.h utils.c utils.h
EXPANDCOPYRIGHT = /usr/site/lib/copyright/expand-copyr
#
# XXX should be in sync with imagezip/GNUmakefile
#
WITH_MBR = 1
WITH_GPT = 1
#
# Support encrypted and signed-checksumed images.
# Requires openssl libraries.
......@@ -102,12 +108,13 @@ endif
endif
CLIENTFLAGS = $(CFLAGS)
CLIENTLIBS =
ifeq ($(SYSTEM),Linux)
CLIENTLIBS = -lrt -lz $(PTHREADLIBS)
CLIENTLIBS += -lrt -lz $(PTHREADLIBS)
else
CLIENTLIBS = -lz $(PTHREADLIBS)
CLIENTLIBS += -lz $(PTHREADLIBS)
endif
CLIENTOBJS = client.o frisbee.o mbr.o checksum.o disksize.o $(SHAREDOBJS)
CLIENTOBJS = client.o frisbee.o checksum.o disksize.o $(SHAREDOBJS)
SERVERFLAGS = $(CFLAGS)
SERVERLIBS = $(PTHREADLIBS)
......@@ -154,6 +161,9 @@ LDFLAGS = $(LDSTATIC)
IUZFLAGS = -DFRISBEE -I$(IZSRCDIR)
IUZLIBS =
IUZDEPS =
# be consistent with how imagezip builds
IUZDEPFLAGS = $(PTHREADCFLAGS)
ifeq ($(WITH_CRYPTO),1)
IUZFLAGS += -DWITH_CRYPTO
......@@ -162,6 +172,16 @@ IUZFLAGS += -DSIGN_CHECKSUM
endif
IUZLIBS += -lcrypto
endif
ifeq ($(WITH_MBR),1)
IUZFLAGS += -DWITH_MBR
IUZLIBS += ../imagezip/mbr/libmbr.a
IUZDEPS += ../imagezip/mbr/libmbr.a
endif
ifeq ($(WITH_GPT),1)
IUZFLAGS += -DWITH_GPT
IUZLIBS += ../imagezip/gpt/libgpt.a
IUZDEPS += ../imagezip/gpt/libgpt.a
endif
#
# Define this to use select to implement packet-receive-with-timeout
......@@ -213,7 +233,7 @@ endif
#CLIENTLIBS += -lpubsub
#EVENTFLAGS = $(CFLAGS) -I/usr/local/include/pubsub -I$(TESTBED_SRCDIR)
frisbee-debug: $(CLIENTOBJS)
frisbee-debug: $(CLIENTOBJS) $(IUZDEPS)
$(CC) $(LDFLAGS) $(CLIENTFLAGS) $(CLIENTOBJS) $(CLIENTLIBS) $(IUZLIBS) -o $@
# cp frisbee frisbee.debug
# strip frisbee
......@@ -259,7 +279,12 @@ event.o: $(SRCDIR)/event.c decls.h log.h event.h
$(IZSRCDIR)/imageunzip.c: $(IZSRCDIR)/imagehdr.h $(IZSRCDIR)/queue.h $(IZSRCDIR)/checksum.h
$(IZSRCDIR)/checksum.c: $(IZSRCDIR)/imagehdr.h $(IZSRCDIR)/checksum.h
$(IZSRCDIR)/mbr/mbr.c: $(IZSRCDIR)/imagehdr.h $(IZSRCDIR)/sliceinfo.h $(IZSRCDIR)/mbr/mbr.h
# XXX
../imagezip/mbr/libmbr.a:
$(MAKE) SUBDIRCFLAGS="$(IUZDEPFLAGS)" -C ../imagezip/mbr all
../imagezip/gpt/libgpt.a:
$(MAKE) SUBDIRCFLAGS="$(IUZDEPFLAGS)" -C ../imagezip/gpt all
disksize.o: $(IZSRCDIR)/disksize.c
$(CC) -c $(CFLAGS) $(IUZFLAGS) -o disksize.o $<
......@@ -267,9 +292,6 @@ disksize.o: $(IZSRCDIR)/disksize.c
checksum.o: $(IZSRCDIR)/checksum.c
$(CC) -c $(CFLAGS) $(IUZFLAGS) -o checksum.o $<
mbr.o: $(IZSRCDIR)/mbr/mbr.c
$(CC) -c $(CFLAGS) $(IUZFLAGS) -I$(IZSRCDIR)/mbr -o mbr.o $<
frisbee.o: $(IZSRCDIR)/imageunzip.c
$(CC) -c $(CFLAGS) $(IUZFLAGS) -I$(IZSRCDIR) -o frisbee.o $<
......
/*
* Copyright (c) 2000-2014 University of Utah and the Flux Group.
* Copyright (c) 2000-2015 University of Utah and the Flux Group.
*
* {{{EMULAB-LICENSE
*
......@@ -364,7 +364,7 @@ main(int argc, char **argv)
break;
case 'D':
dostype = atoi(optarg);
dostype = (int)strtoul(optarg, NULL, 0);
break;
case 'k':
......
#
# Copyright (c) 2000-2014 University of Utah and the Flux Group.
# Copyright (c) 2000-2015 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -132,6 +132,7 @@ ZIPCFLAGS = $(CFLAGS) -Wall
ZIPLIBS =
UNZIPCFLAGS = $(CFLAGS) $(PTHREADCFLAGS) -Wall
UNZIPLIBS = $(LIBS) $(PTHREADLIBS)
UNZIPDIRS =
HASHCFLAGS = $(CFLAGS) $(PTHREADCFLAGS) -Wall
HASHLIBS = $(LIBS) -lcrypto $(PTHREADLIBS)
......@@ -154,6 +155,7 @@ endif
ifeq ($(WITH_MBR),1)
CFLAGS += -DWITH_MBR
SUBDIRS += mbr
UNZIPDIRS += mbr
ZIPLIBS += mbr/libmbr.a
UNZIPLIBS += mbr/libmbr.a
endif
......@@ -162,7 +164,9 @@ endif
ifeq ($(WITH_GPT),1)
CFLAGS += -DWITH_GPT
SUBDIRS += gpt
UNZIPDIRS += gpt
ZIPLIBS += gpt/libgpt.a
UNZIPLIBS += gpt/libgpt.a
endif
# UFS/UFS2
......@@ -236,7 +240,7 @@ imagezip: $(SUBDIRS) imagezip.o sliceinfo.o disksize.o checksum.o version.o $(ZI
imagezip.o: imagezip.c
$(CC) -c $(ZIPCFLAGS) -o imagezip.o $<
imageunzip: mbr imageunzip.o disksize.o checksum.o crc.o version.o
imageunzip: $(UNZIPDIRS) imageunzip.o disksize.o checksum.o crc.o version.o
$(CC) $(CFLAGS) imageunzip.o disksize.o checksum.o crc.o version.o $(UNZIPLIBS) -o imageunzip
imageunzip.o: imageunzip.c
......
/*
* Copyright (c) 2000-2014 University of Utah and the Flux Group.
* Copyright (c) 2000-2015 University of Utah and the Flux Group.
*
* {{{EMULAB-LICENSE
*
......@@ -104,7 +104,7 @@ getdisksize(int fd)
if (lastoff > 0)
disksize = (unsigned long)(lastoff / ssize);
#ifdef TEST
fprintf(stderr, "lseek SEEK_END returned %lu\n", disksize);
fprintf(stderr, "lseek SEEK_END returned %ld, disksize=%lu\n", (long)lastoff, disksize);
#endif
}
......@@ -112,15 +112,17 @@ getdisksize(int fd)
/*
* Make sure we can seek to that sector
*/
if (lseek(fd, (off_t)(disksize-1) * ssize, SEEK_SET) < 0)
fprintf(stderr, "WARNING: "
"could not seek to final sector (%lu) of disk\n",
disksize - 1);
if (whuzat >= 0) {
if (lseek(fd, whuzat, SEEK_SET) < 0)
fprintf(stderr, "WARNING: "
"could not seek to previous offset on disk\n");
if (disksize > 0) {
if (lseek(fd, (off_t)(disksize-1) * ssize, SEEK_SET) < 0)
fprintf(stderr, "WARNING: could not seek to "
"final sector (%lu) of disk\n",
disksize - 1);
if (whuzat >= 0) {
if (lseek(fd, whuzat, SEEK_SET) < 0)
fprintf(stderr, "WARNING: could not seek to "
"previous offset on disk\n");
}
}
return disksize;
......
......@@ -47,13 +47,6 @@ extern void restorefixups(int isempty);
extern void dumpfixups(int verbose, int count);
extern uint64_t getdisksize(int fd);
#ifdef WITH_MBR
extern int parse_mbr(int fd, struct iz_disk *disk, int dowarn);
#endif
#ifdef WITH_GPT
extern int parse_gpt(int fd, struct iz_disk *disk, int dowarn);
#endif
extern SLICEMAP_PROCESS_PROTO(read_rawslice);
extern SLICEMAP_PROCESS_PROTO(read_bsdslice);
extern SLICEMAP_PROCESS_PROTO(read_bsdslicenl);
......
......@@ -30,6 +30,9 @@ include $(OBJDIR)/Makeconf
CFLAGS += -DIMAGEZIP $(SUBDIRCFLAGS) -I$(MAINDIR) -I$(SRCDIR)
# XXX avoid a symbol conflict
CFLAGS += -Dcrc32=gpt_crc32
all: libgpt.a
include $(TESTBED_SRCDIR)/GNUmakerules
......
......@@ -60,7 +60,9 @@ static int curent, bootonce;
static char *secbuf;
#ifndef IMAGEZIP
static void
static
#endif
void
gptupdate(const char *which, struct dsk *dskp, struct gpt_hdr *hdr,
struct gpt_ent *table)
{
......@@ -96,6 +98,7 @@ gptupdate(const char *which, struct dsk *dskp, struct gpt_hdr *hdr,
}
}
#ifndef IMAGEZIP
int
gptfind(const uuid_t *uuid, struct dsk *dskp, int part)
{
......@@ -237,7 +240,6 @@ gptbootfailed(struct dsk *dskp)
gptupdate("backup", dskp, &hdr_backup, table_backup);
}
}
#endif
static void
gptbootconv(const char *which, struct dsk *dskp, struct gpt_hdr *hdr,
......@@ -285,6 +287,7 @@ gptbootconv(const char *which, struct dsk *dskp, struct gpt_hdr *hdr,
if (drvwrite(dskp, secbuf, hdr->hdr_lba_self, 1))
printf("%s: unable to update %s GPT header\n", BOOTPROG, which);
}
#endif
static int
gptread_table(const char *which, const uuid_t *uuid, struct dsk *dskp,
......@@ -371,6 +374,7 @@ gptread(const uuid_t *uuid, struct dsk *dskp, char *buf)
}
}
#ifndef IMAGEZIP
/*
* Convert all BOOTONCE without BOOTME flags into BOOTFAILED.
* BOOTONCE without BOOTME means that we tried to boot from it,
......@@ -384,6 +388,7 @@ gptread(const uuid_t *uuid, struct dsk *dskp, char *buf)
gptbootconv("primary", dskp, &hdr_primary, table_primary);
if (hdr_backup_lba != 0)
gptbootconv("backup", dskp, &hdr_backup, table_backup);
#endif
if (hdr_primary_lba == 0 && hdr_backup_lba == 0)
return (-1);
......@@ -392,12 +397,25 @@ gptread(const uuid_t *uuid, struct dsk *dskp, char *buf)
#ifdef IMAGEZIP
void
gptgettables(struct gpt_hdr **hdr, struct gpt_ent **ent)
gptgettables(struct gpt_hdr **hdr, struct gpt_ent **ent,
struct gpt_hdr **ohdr, struct gpt_ent **oent)
{
if (hdr)
*hdr = gpthdr;
if (ent)
*ent = gpttable;
if (ohdr)
*ohdr = (gpthdr == &hdr_primary) ?
&hdr_backup : &hdr_primary;
if (oent)
*oent = (gpttable == table_primary) ?
table_backup : table_primary;
}
#endif
/* XXX hack so we can use gptupdate */
void
gptsetcurent(int idx)
{
curent = idx;
}
#endif
......@@ -49,6 +49,7 @@
static char lastmsg[512];
static int silent = 0;
static void gpt_utf8_to_utf16(const uint8_t *s8, uint16_t *s16, size_t s16len);
int
gpt_printf(const char * __restrict fmt, ...)
......@@ -128,60 +129,80 @@ struct gptmap {
struct uuid gpttype;
char *desc;
iz_type iztype;
uint16_t shortid;
};
struct gptmap gptmap[] = {
{GPT_ENT_TYPE_UNUSED, "UNUSED", IZTYPE_UNUSED},
{GPT_ENT_TYPE_FREEBSD, "FREEBSD", IZTYPE_386BSD},
{GPT_ENT_TYPE_FREEBSD_UFS, "FREEBSD_UFS", IZTYPE_FBSDNOLABEL},
{GPT_ENT_TYPE_LINUX_DATA, "LINUX_DATA", IZTYPE_LINUX},
{GPT_ENT_TYPE_LINUX_SWAP, "LINUX_SWAP", IZTYPE_LINSWP},
{GPT_ENT_TYPE_BIOS_BOOT, "BIOS_BOOT", IZTYPE_BIOSBOOT},
{GPT_ENT_TYPE_FREEBSD_BOOT, "FREEBSD_BOOT", IZTYPE_FBSDBOOT},
{GPT_ENT_TYPE_FREEBSD_SWAP, "FREEBSD_SWAP", IZTYPE_FBSDSWAP},
{GPT_ENT_TYPE_EFI, "EFI", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_MBR, "MBR", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_FREEBSD_NANDFS, "FREEBSD_NANDFS", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_FREEBSD_VINUM, "FREEBSD_VINUM", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_FREEBSD_ZFS, "FREEBSD_ZFS", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_PREP_BOOT, "PREP_BOOT", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_MS_RESERVED, "MS_RESERVED", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_MS_BASIC_DATA, "MS_BASIC_DATA", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_MS_LDM_METADATA, "MS_LDM_METADATA", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_MS_LDM_DATA, "MS_LDM_DATA", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_LINUX_RAID, "LINUX_RAID", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_LINUX_LVM, "LINUX_LVM", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_VMFS, "VMFS", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_VMKDIAG, "VMKDIAG", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_VMRESERVED, "VMRESERVED", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_VMVSANHDR, "VMVSANHDR", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_APPLE_BOOT, "APPLE_BOOT", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_APPLE_HFS, "APPLE_HFS", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_APPLE_UFS, "APPLE_UFS", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_APPLE_ZFS, "APPLE_ZFS", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_APPLE_RAID, "APPLE_RAID", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_APPLE_RAID_OFFLINE, "APPLE_RAID_OFFLINE", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_APPLE_LABEL, "APPLE_LABEL", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_APPLE_TV_RECOVERY, "APPLE_TV_RECOVERY", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_NETBSD_FFS, "NETBSD_FFS", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_NETBSD_LFS, "NETBSD_LFS", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_NETBSD_SWAP, "NETBSD_SWAP", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_NETBSD_RAID, "NETBSD_RAID", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_NETBSD_CCD, "NETBSD_CCD", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_NETBSD_CGD, "NETBSD_CGD", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_DRAGONFLY_LABEL32, "DRAGONFLY_LABEL32", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_DRAGONFLY_SWAP, "DRAGONFLY_SWAP", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_DRAGONFLY_UFS1, "DRAGONFLY_UFS1", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_DRAGONFLY_VINUM, "DRAGONFLY_VINUM", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_DRAGONFLY_CCD, "DRAGONFLY_CCD", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_DRAGONFLY_LABEL64, "DRAGONFLY_LABEL64", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_DRAGONFLY_LEGACY, "DRAGONFLY_LEGACY", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_DRAGONFLY_HAMMER, "DRAGONFLY_HAMMER", IZTYPE_UNKNOWN},
{GPT_ENT_TYPE_DRAGONFLY_HAMMER2, "DRAGONFLY_HAMMER2", IZTYPE_UNKNOWN}
{GPT_ENT_TYPE_UNUSED, "Unused entry", IZTYPE_UNUSED, 0x0000},
{GPT_ENT_TYPE_FREEBSD, "FreeBSD disklabel", IZTYPE_386BSD, 0xA500},
{GPT_ENT_TYPE_FREEBSD_UFS, "FreeBSD UFS", IZTYPE_FBSDNOLABEL, 0xA503},
{GPT_ENT_TYPE_LINUX_DATA, "Linux filesystem", IZTYPE_LINUX, 0x8300},
{GPT_ENT_TYPE_LINUX_SWAP, "Linux swap", IZTYPE_LINSWP, 0x8200},
{GPT_ENT_TYPE_BIOS_BOOT, "BIOS boot partition", IZTYPE_BIOSBOOT, 0xEF02},
{GPT_ENT_TYPE_FREEBSD_BOOT, "FreeBSD boot", IZTYPE_FBSDBOOT, 0xA501},
{GPT_ENT_TYPE_FREEBSD_SWAP, "FreeBSD swap", IZTYPE_FBSDSWAP, 0xA502},
{GPT_ENT_TYPE_EFI, "EFI System", IZTYPE_UNKNOWN, 0xEF00},
{GPT_ENT_TYPE_MBR, "MBR partition scheme", IZTYPE_UNKNOWN, 0xEF01},
{GPT_ENT_TYPE_FREEBSD_NANDFS, "FREEBSD_NANDFS", IZTYPE_UNKNOWN, 0xFFFF},
{GPT_ENT_TYPE_FREEBSD_VINUM, "FreeBSD Vinum/RAID", IZTYPE_UNKNOWN, 0xA505},
{GPT_ENT_TYPE_FREEBSD_ZFS, "FreeBSD ZFS", IZTYPE_UNKNOWN, 0xA504},
{GPT_ENT_TYPE_PREP_BOOT, "PowerPC PReP boot", IZTYPE_UNKNOWN, 0x4100},
{GPT_ENT_TYPE_MS_RESERVED, "Microsoft reserved", IZTYPE_UNKNOWN, 0x0C01},
{GPT_ENT_TYPE_MS_BASIC_DATA, "Microsoft basic data", IZTYPE_UNKNOWN, 0x0700},
{GPT_ENT_TYPE_MS_LDM_METADATA, "Windows LDM metadata", IZTYPE_UNKNOWN, 0x4201},
{GPT_ENT_TYPE_MS_LDM_DATA, "Windows LDM data", IZTYPE_UNKNOWN, 0x4200},
{GPT_ENT_TYPE_LINUX_RAID, "Linux RAID", IZTYPE_UNKNOWN, 0xFD00},
{GPT_ENT_TYPE_LINUX_LVM, "Linux LVM", IZTYPE_UNKNOWN, 0x8E00},
{GPT_ENT_TYPE_VMFS, "VMWare VMFS", IZTYPE_UNKNOWN, 0xFB00},
{GPT_ENT_TYPE_VMKDIAG, "VMWare kcore crash protection", IZTYPE_UNKNOWN, 0xFC00},
{GPT_ENT_TYPE_VMRESERVED, "VMWare reserved", IZTYPE_UNKNOWN, 0xFB01},
{GPT_ENT_TYPE_VMVSANHDR, "VMVSANHDR", IZTYPE_UNKNOWN, 0xFB02},
{GPT_ENT_TYPE_APPLE_BOOT, "Apple boot", IZTYPE_UNKNOWN, 0xAB00},
{GPT_ENT_TYPE_APPLE_HFS, "Apple HFS/HFS+", IZTYPE_UNKNOWN, 0xAF00},
{GPT_ENT_TYPE_APPLE_UFS, "Apple UFS", IZTYPE_UNKNOWN, 0xA800},
{GPT_ENT_TYPE_APPLE_ZFS, "Solaris/Apple ZFS", IZTYPE_UNKNOWN, 0xBF01},
{GPT_ENT_TYPE_APPLE_RAID, "Apple RAID", IZTYPE_UNKNOWN, 0xAF01},
{GPT_ENT_TYPE_APPLE_RAID_OFFLINE, "Apple RAID offline", IZTYPE_UNKNOWN, 0xAF02},
{GPT_ENT_TYPE_APPLE_LABEL, "Apple label", IZTYPE_UNKNOWN, 0xAF03},
{GPT_ENT_TYPE_APPLE_TV_RECOVERY, "AppleTV recovery", IZTYPE_UNKNOWN, 0xAF04},
{GPT_ENT_TYPE_NETBSD_FFS, "NetBSD FFS", IZTYPE_UNKNOWN, 0xA902},
{GPT_ENT_TYPE_NETBSD_LFS, "NetBSD LFS", IZTYPE_UNKNOWN, 0xA903},
{GPT_ENT_TYPE_NETBSD_SWAP, "NetBSD swap", IZTYPE_UNKNOWN, 0xA901},
{GPT_ENT_TYPE_NETBSD_RAID, "NetBSD RAID", IZTYPE_UNKNOWN, 0xA906},
{GPT_ENT_TYPE_NETBSD_CCD, "NetBSD concatenated", IZTYPE_UNKNOWN, 0xA904},
{GPT_ENT_TYPE_NETBSD_CGD, "NetBSD encrypted", IZTYPE_UNKNOWN, 0xA905},
{GPT_ENT_TYPE_DRAGONFLY_LABEL32, "Dragonfly label32", IZTYPE_UNKNOWN, 0xFFFF},
{GPT_ENT_TYPE_DRAGONFLY_SWAP, "Dragonfly swap", IZTYPE_UNKNOWN, 0xFFFF},
{GPT_ENT_TYPE_DRAGONFLY_UFS1, "Dragonfly UFS1", IZTYPE_UNKNOWN, 0xFFFF},
{GPT_ENT_TYPE_DRAGONFLY_VINUM, "Dragonfly Vinum", IZTYPE_UNKNOWN, 0xFFFF},
{GPT_ENT_TYPE_DRAGONFLY_CCD, "Dragonfly concatenated", IZTYPE_UNKNOWN, 0xFFFF},
{GPT_ENT_TYPE_DRAGONFLY_LABEL64, "Dragonfly label64", IZTYPE_UNKNOWN, 0xFFFF},
{GPT_ENT_TYPE_DRAGONFLY_LEGACY, "Dragonfly legacy", IZTYPE_UNKNOWN, 0xFFFF},
{GPT_ENT_TYPE_DRAGONFLY_HAMMER, "Dragonfly Hammer", IZTYPE_UNKNOWN, 0xFFFF},
{GPT_ENT_TYPE_DRAGONFLY_HAMMER2, "Dragonfly Hammer2", IZTYPE_UNKNOWN, 0xFFFF}
};
int ngptmap = sizeof(gptmap) / sizeof(gptmap[0]);
struct gptmap *
getgpttype(struct uuid *gtype)
static struct gptmap *
getgpttypebyiztype(iz_type iztype)
{
int i;
/* check both DOS ids and GPT ids */
if (iztype <= 0xFF) {
for (i = 0; i < ngptmap; i++)
if (gptmap[i].iztype == iztype)
return &gptmap[i];
return NULL;
}
for (i = 0; i < ngptmap; i++)
if (gptmap[i].shortid == iztype)
return &gptmap[i];
return NULL;
}
static struct gptmap *
getgpttypebyuuid(struct uuid *gtype)
{
int i;
for (i = 0; i < ngptmap; i++)
......@@ -219,7 +240,7 @@ parse_gpt(int fd, struct iz_disk *disk, int dowarn)
return 1;
/* XXX get pointers to the static structs in gpt.c */
gptgettables(&hdr, &ent);
gptgettables(&hdr, &ent, NULL, NULL);
if (!hdr || !ent) {
warnx("GPT: no header or table!?");
return 1;
......@@ -233,7 +254,7 @@ parse_gpt(int fd, struct iz_disk *disk, int dowarn)
losect = ~0;
hisect = 0;
for (i = 0; i < hdr->hdr_entries; i++) {
struct gptmap *gmap = getgpttype(&ent[i].ent_type);
struct gptmap *gmap = getgpttypebyuuid(&ent[i].ent_type);
uint64_t start = ent[i].ent_lba_start;
uint64_t size = ent[i].ent_lba_end - ent[i].ent_lba_start + 1;
iz_type type = IZTYPE_UNKNOWN;
......@@ -329,3 +350,124 @@ parse_gpt(int fd, struct iz_disk *disk, int dowarn)
return 0;
}
int
set_gpt_type(int fd, int slice, iz_type iztype)
{
struct gptmap *gmap;
struct gpt_hdr *hdr, *ohdr;
struct gpt_ent *ent, *oent;
char secbuf[SECSIZE+SECSIZE-1], *buf = SECALIGN(secbuf);
struct dsk dsk;
uuid_t uuid;
gmap = getgpttypebyiztype(iztype);
if (gmap == NULL) {
fprintf(stderr, "Cannot map type 0x%x to a GPT type\n",
iztype);
return 1;
}
/* read existing GPT */
dsk.fd = fd;
if (gptread(&uuid, &dsk, buf))
return 1;
gptgettables(&hdr, &ent, &ohdr, &oent);
if (!hdr || !ent || !oent) {
fprintf(stderr, "GPT: no header or table!?\n");
return 1;
}
if (slice > hdr->hdr_entries) {
fprintf(stderr, "Invalid slice number %d\n", slice);
return 1;
}
/* change partition type in both copies */
memcpy(&ent[slice-1].ent_type, &gmap->gpttype, sizeof(struct uuid));
memcpy(&oent[slice-1].ent_type, &gmap->gpttype, sizeof(struct uuid));
/* set the name from the description (this is what sgpart does) */
int len = sizeof(ent[slice-1].ent_name) / 2;
gpt_utf8_to_utf16((uint8_t *)gmap->desc, ent[slice-1].ent_name, len);
gpt_utf8_to_utf16((uint8_t *)gmap->desc, oent[slice-1].ent_name, len);
/* write out new GPT */
gptsetcurent(slice - 1);
gptupdate("primary", &dsk, hdr, ent);
gptupdate("backup", &dsk, ohdr, oent);
return 0;
}
#ifdef __FreeBSD__
#include <sys/endian.h>
#endif
/* Ripped from /usr/src/sys/geom/part/g_part_gpt.c */
static void
gpt_utf8_to_utf16(const uint8_t *s8, uint16_t *s16, size_t s16len)
{
size_t s16idx, s8idx;
uint32_t utfchar;
unsigned int c, utfbytes;
s8idx = s16idx = 0;
utfchar = 0;
utfbytes = 0;
bzero(s16, s16len << 1);
while (s8[s8idx] != 0 && s16idx < s16len) {
c = s8[s8idx++];
if ((c & 0xc0) != 0x80) {
/* Initial characters. */
if (utfbytes != 0) {
/* Incomplete encoding of previous char. */
s16[s16idx++] = htole16(0xfffd);
}
if ((c & 0xf8) == 0xf0) {
utfchar = c & 0x07;
utfbytes = 3;
} else if ((c & 0xf0) == 0xe0) {
utfchar = c & 0x0f;
utfbytes = 2;
} else if ((c & 0xe0) == 0xc0) {
utfchar = c & 0x1f;
utfbytes = 1;
} else {
utfchar = c & 0x7f;
utfbytes = 0;
}
} else {
/* Followup characters. */
if (utfbytes > 0) {
utfchar = (utfchar << 6) + (c & 0x3f);
utfbytes--;
} else if (utfbytes == 0)
utfbytes = ~0;
}
/*
* Write the complete Unicode character as UTF-16 when we
* have all the UTF-8 charactars collected.
*/
if (utfbytes == 0) {
/*
* If we need to write 2 UTF-16 characters, but
* we only have room for 1, then we truncate the
* string by writing a 0 instead.
*/
if (utfchar >= 0x10000 && s16idx < s16len - 1) {
s16[s16idx++] =
htole16(0xd800 | ((utfchar >> 10) - 0x40));
s16[s16idx++] =
htole16(0xdc00 | (utfchar & 0x3ff));
} else
s16[s16idx++] = (utfchar >= 0x10000) ? 0 :
htole16(utfchar);
}
}
/*
* If our input string was truncated, append an invalid encoding
* character to the output string.
*/
if (utfbytes != 0 && s16idx < s16len)
s16[s16idx++] = htole16(0xfffd);
}
......@@ -55,6 +55,10 @@ int drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk);
uint64_t drvsize(struct dsk *dskp);
int gptread(const uuid_t *uuid, struct dsk *dskp, char *buf);
void gptgettables(struct gpt_hdr **hdr, struct gpt_ent **ent);
void gptgettables(struct gpt_hdr **hdr, struct gpt_ent **ent,
struct gpt_hdr **ohdr, struct gpt_ent **oent);
void gptupdate(const char *which, struct dsk *dskp, struct gpt_hdr *hdr,
struct gpt_ent *table);
void gptsetcurent(int idx);
#endif /* _GPT_GLUE_H */
......@@ -630,7 +630,7 @@ main(int argc, char *argv[])
break;
case 'D':
dostype = atoi(optarg);
dostype = (int)strtoul(optarg, NULL, 0);
break;
case 'p':
......@@ -1922,27 +1922,51 @@ zero_remainder()
}
#include "sliceinfo.h"
#ifdef WITH_MBR
#include "mbr/mbr.h"
#endif
#ifdef WITH_GPT
#include "gpt/gpt_glue.h"
#endif