mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2025-01-01 00:18:15 +01:00
o Newer EFI implementations require that a GPT is preceeded by
a PMBR. Make sure the create command creates a PMBR as well (if not already present). o When parsing the MBR, explicitly check for a PMBR and create a PMBR map node if one is found. o When parsing the MBR, recurse to handle extended partitions. This allows us to flatten nested MBRs when migrating to a GPT. o Have the migrate command bail out if it encounters a partition it doesn't know how to migrate. This avoids data loss. o Change the output of the show command so that the UUIDs of the GPT partitions fit on the same line. o Show when partitions are extended partitions and add the PMBR type. Approved by: re (blanket)
This commit is contained in:
parent
8e7ea1fc7d
commit
2a944ecdef
@ -58,6 +58,7 @@ create(int fd)
|
||||
map_t *gpt, *tpg;
|
||||
map_t *tbl, *lbt;
|
||||
map_t *map;
|
||||
struct mbr *mbr;
|
||||
struct gpt_hdr *hdr;
|
||||
struct gpt_ent *ent;
|
||||
unsigned int i;
|
||||
@ -67,6 +68,40 @@ create(int fd)
|
||||
warnx("%s: error: device already contains a GPT", device_name);
|
||||
return;
|
||||
}
|
||||
if (map_find(MAP_TYPE_MBR) != NULL) {
|
||||
warnx("%s: error: device contains a MBR", device_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create PMBR.
|
||||
*/
|
||||
if (map_find(MAP_TYPE_PMBR) == NULL) {
|
||||
if (map_free(0LL, 1LL) == 0) {
|
||||
warnx("%s: error: no room for the PMBR", device_name);
|
||||
return;
|
||||
}
|
||||
mbr = gpt_read(fd, 0LL, 1);
|
||||
bzero(mbr, sizeof(*mbr));
|
||||
mbr->mbr_sig = MBR_SIG;
|
||||
mbr->mbr_part[0].part_shd = 0xff;
|
||||
mbr->mbr_part[0].part_ssect = 0xff;
|
||||
mbr->mbr_part[0].part_scyl = 0xff;
|
||||
mbr->mbr_part[0].part_typ = 0xee;
|
||||
mbr->mbr_part[0].part_ehd = 0xff;
|
||||
mbr->mbr_part[0].part_esect = 0xff;
|
||||
mbr->mbr_part[0].part_ecyl = 0xff;
|
||||
mbr->mbr_part[0].part_start_lo = 1;
|
||||
if (mediasz > 0xffffffff) {
|
||||
mbr->mbr_part[0].part_size_lo = 0xffff;
|
||||
mbr->mbr_part[0].part_size_hi = 0xffff;
|
||||
} else {
|
||||
mbr->mbr_part[0].part_size_lo = mediasz & 0xffff;
|
||||
mbr->mbr_part[0].part_size_hi = mediasz >> 16;
|
||||
}
|
||||
map = map_add(0LL, 1LL, MAP_TYPE_PMBR, mbr);
|
||||
gpt_write(fd, map);
|
||||
}
|
||||
|
||||
/* Get the amount of free space after the MBR */
|
||||
blocks = map_free(1LL, 0LL);
|
||||
|
128
sbin/gpt/gpt.c
128
sbin/gpt/gpt.c
@ -161,6 +161,90 @@ gpt_write(int fd, map_t *map)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
gpt_mbr(int fd, off_t lba)
|
||||
{
|
||||
struct mbr *mbr;
|
||||
map_t *m, *p;
|
||||
off_t size, start;
|
||||
unsigned int i, pmbr;
|
||||
|
||||
mbr = gpt_read(fd, lba, 1);
|
||||
if (mbr == NULL)
|
||||
return (-1);
|
||||
|
||||
if (mbr->mbr_sig != MBR_SIG) {
|
||||
if (verbose)
|
||||
warnx("%s: MBR not found at sector %llu", device_name,
|
||||
(long long)lba);
|
||||
free(mbr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Differentiate between a regular MBR and a PMBR. This is more
|
||||
* convenient in general. A PMBR is one with a single partition
|
||||
* of type 0xee.
|
||||
*/
|
||||
pmbr = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (mbr->mbr_part[i].part_typ == 0)
|
||||
continue;
|
||||
if (mbr->mbr_part[i].part_typ == 0xee)
|
||||
pmbr++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (pmbr && i == 4 && lba == 0) {
|
||||
if (pmbr != 1)
|
||||
warnx("%s: Suspicious PMBR at sector %llu",
|
||||
device_name, (long long)lba);
|
||||
else if (verbose > 1)
|
||||
warnx("%s: PMBR at sector %llu", device_name,
|
||||
(long long)lba);
|
||||
p = map_add(lba, 1LL, MAP_TYPE_PMBR, mbr);
|
||||
return ((p == NULL) ? -1 : 0);
|
||||
}
|
||||
if (pmbr)
|
||||
warnx("%s: Suspicious MBR at sector %llu", device_name,
|
||||
(long long)lba);
|
||||
else if (verbose > 1)
|
||||
warnx("%s: MBR at sector %llu", device_name, (long long)lba);
|
||||
|
||||
p = map_add(lba, 1LL, MAP_TYPE_MBR, mbr);
|
||||
if (p == NULL)
|
||||
return (-1);
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (mbr->mbr_part[i].part_typ == 0 ||
|
||||
mbr->mbr_part[i].part_typ == 0xee)
|
||||
continue;
|
||||
start = mbr->mbr_part[i].part_start_hi;
|
||||
start = (start << 16) + mbr->mbr_part[i].part_start_lo;
|
||||
size = mbr->mbr_part[i].part_size_hi;
|
||||
size = (size << 16) + mbr->mbr_part[i].part_size_lo;
|
||||
if (start == 0 && size == 0) {
|
||||
warnx("%s: Malformed MBR at sector %llu", device_name,
|
||||
(long long)lba);
|
||||
continue;
|
||||
}
|
||||
/* start is relative to the offset of the MBR itself. */
|
||||
start += lba;
|
||||
if (verbose > 2)
|
||||
warnx("%s: MBR part: type=%d, start=%llu, size=%llu",
|
||||
device_name, mbr->mbr_part[i].part_typ,
|
||||
(long long)start, (long long)size);
|
||||
if (mbr->mbr_part[i].part_typ != 15) {
|
||||
m = map_add(start, size, MAP_TYPE_MBR_PART, p);
|
||||
if (m == NULL)
|
||||
return (-1);
|
||||
} else {
|
||||
if (gpt_mbr(fd, start) == -1)
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
gpt_gpt(int fd, off_t lba)
|
||||
{
|
||||
@ -252,10 +336,6 @@ int
|
||||
gpt_open(const char *dev)
|
||||
{
|
||||
struct stat sb;
|
||||
struct mbr *mbr;
|
||||
map_t *m;
|
||||
uint32_t size, start;
|
||||
unsigned int i;
|
||||
int fd;
|
||||
|
||||
if (!stat(dev, &sb)) {
|
||||
@ -306,46 +386,8 @@ gpt_open(const char *dev)
|
||||
|
||||
map_init(mediasz / secsz);
|
||||
|
||||
/*
|
||||
* MBR
|
||||
*/
|
||||
mbr = gpt_read(fd, 0LL, 1);
|
||||
if (mbr == NULL)
|
||||
if (gpt_mbr(fd, 0LL) == -1)
|
||||
goto close;
|
||||
|
||||
if (mbr->mbr_sig == MBR_SIG) {
|
||||
if (verbose > 1)
|
||||
warnx("%s: MBR at sector 0", device_name);
|
||||
m = map_add(0LL, 1LL, MAP_TYPE_MBR, mbr);
|
||||
if (m == NULL)
|
||||
goto close;
|
||||
for (i = 0; i < 4; i++) {
|
||||
start = mbr->mbr_part[i].part_start_hi;
|
||||
start = (start << 16) + mbr->mbr_part[i].part_start_lo;
|
||||
size = mbr->mbr_part[i].part_size_hi;
|
||||
size = (size << 16) + mbr->mbr_part[i].part_size_lo;
|
||||
if (start == 0 && size == 0)
|
||||
continue;
|
||||
if (verbose > 2)
|
||||
warnx("%s: MBR partition: type=%d, start=%llu, size=%llu",
|
||||
device_name, mbr->mbr_part[i].part_typ,
|
||||
(long long)start, (long long)size);
|
||||
if (mbr->mbr_part[i].part_typ == 0xee)
|
||||
continue;
|
||||
m = map_add(start, size, MAP_TYPE_MBR_PART,
|
||||
mbr->mbr_part + i);
|
||||
if (m == NULL)
|
||||
goto close;
|
||||
}
|
||||
} else {
|
||||
if (verbose)
|
||||
warnx("%s: MBR not found", device_name);
|
||||
free(mbr);
|
||||
}
|
||||
|
||||
/*
|
||||
* GPT
|
||||
*/
|
||||
if (gpt_gpt(fd, 1LL) == -1)
|
||||
goto close;
|
||||
if (gpt_gpt(fd, mediasz / secsz - 1LL) == -1)
|
||||
|
@ -43,6 +43,7 @@ typedef struct map {
|
||||
#define MAP_TYPE_PRI_GPT_TBL 5
|
||||
#define MAP_TYPE_SEC_GPT_TBL 6
|
||||
#define MAP_TYPE_GPT_PART 7
|
||||
#define MAP_TYPE_PMBR 8
|
||||
void *map_data;
|
||||
} map_t;
|
||||
|
||||
|
@ -92,6 +92,8 @@ migrate_disklabel(int fd, off_t start, struct gpt_ent *ent)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
warnx("%s: warning: unknown FreeBSD partition (%d)",
|
||||
device_name, dl->d_partitions[i].p_fstype);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -120,9 +122,8 @@ migrate(int fd)
|
||||
last = mediasz / secsz - 1LL;
|
||||
|
||||
map = map_find(MAP_TYPE_MBR);
|
||||
if (map == NULL || map_find(MAP_TYPE_MBR_PART) == NULL) {
|
||||
warnx("%s: error: no partitions to convert",
|
||||
device_name);
|
||||
if (map == NULL || map->map_start != 0) {
|
||||
warnx("%s: error: no partitions to convert", device_name);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -212,6 +213,8 @@ migrate(int fd)
|
||||
size = (size << 16) + mbr->mbr_part[i].part_size_lo;
|
||||
|
||||
switch (mbr->mbr_part[i].part_typ) {
|
||||
case 0:
|
||||
continue;
|
||||
case 165: { /* FreeBSD */
|
||||
if (slice) {
|
||||
uuid_t freebsd = GPT_ENT_TYPE_FREEBSD;
|
||||
@ -235,7 +238,9 @@ migrate(int fd)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
continue;
|
||||
warnx("%s: error: unknown partition type (%d)",
|
||||
device_name, mbr->mbr_part[i].part_typ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ent = tbl->map_data;
|
||||
|
@ -52,11 +52,12 @@ usage_show(void)
|
||||
static void
|
||||
show(int fd __unused)
|
||||
{
|
||||
off_t end;
|
||||
map_t *m;
|
||||
struct mbr_part *part;
|
||||
off_t start, end;
|
||||
map_t *m, *p;
|
||||
struct mbr *mbr;
|
||||
struct gpt_ent *ent;
|
||||
char *s;
|
||||
unsigned int i;
|
||||
|
||||
printf(" %*s", lbawidth, "start");
|
||||
printf(" %*s", lbawidth, "end");
|
||||
@ -73,6 +74,8 @@ show(int fd __unused)
|
||||
putchar(' '); putchar(' ');
|
||||
switch (m->map_type) {
|
||||
case MAP_TYPE_MBR:
|
||||
if (m->map_start != 0)
|
||||
printf("Extended ");
|
||||
printf("MBR");
|
||||
break;
|
||||
case MAP_TYPE_PRI_GPT_HDR:
|
||||
@ -88,17 +91,29 @@ show(int fd __unused)
|
||||
printf("Sec GPT table");
|
||||
break;
|
||||
case MAP_TYPE_MBR_PART:
|
||||
printf("MBR partition: ");
|
||||
part = m->map_data;
|
||||
printf("type=%d", part->part_typ);
|
||||
p = m->map_data;
|
||||
if (p->map_start != 0)
|
||||
printf("Extended ");
|
||||
printf("MBR part ");
|
||||
mbr = p->map_data;
|
||||
for (i = 0; i < 4; i++) {
|
||||
start = mbr->mbr_part[i].part_start_hi << 16;
|
||||
start += mbr->mbr_part[i].part_start_lo;
|
||||
if (m->map_start == p->map_start + start)
|
||||
break;
|
||||
}
|
||||
printf("%d", mbr->mbr_part[i].part_typ);
|
||||
break;
|
||||
case MAP_TYPE_GPT_PART:
|
||||
printf("GPT partition: ");
|
||||
printf("GPT part ");
|
||||
ent = m->map_data;
|
||||
uuid_to_string(&ent->ent_type, &s, NULL);
|
||||
printf("type=%s", s);
|
||||
printf("%s", s);
|
||||
free(s);
|
||||
break;
|
||||
case MAP_TYPE_PMBR:
|
||||
printf("PMBR");
|
||||
break;
|
||||
}
|
||||
putchar('\n');
|
||||
m = m->map_next;
|
||||
|
Loading…
Reference in New Issue
Block a user