[Midnightbsd-cvs] src [10015] trunk/sys/geom/part/g_part_gpt.c: sync gpt code
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sun May 27 17:50:39 EDT 2018
Revision: 10015
http://svnweb.midnightbsd.org/src/?rev=10015
Author: laffer1
Date: 2018-05-27 17:50:38 -0400 (Sun, 27 May 2018)
Log Message:
-----------
sync gpt code
Modified Paths:
--------------
trunk/sys/geom/part/g_part_gpt.c
Modified: trunk/sys/geom/part/g_part_gpt.c
===================================================================
--- trunk/sys/geom/part/g_part_gpt.c 2018-05-27 21:45:04 UTC (rev 10014)
+++ trunk/sys/geom/part/g_part_gpt.c 2018-05-27 21:50:38 UTC (rev 10015)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2002, 2005-2007, 2011 Marcel Moolenaar
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/geom/part/g_part_gpt.c 293634 2016-01-10 13:53:57Z ae $");
#include <sys/param.h>
#include <sys/bio.h>
@@ -44,6 +45,7 @@
#include <sys/sysctl.h>
#include <sys/uuid.h>
#include <geom/geom.h>
+#include <geom/geom_int.h>
#include <geom/part/g_part.h>
#include "g_part_if.h"
@@ -145,6 +147,8 @@
G_PART_SCHEME_DECLARE(g_part_gpt);
static struct uuid gpt_uuid_apple_boot = GPT_ENT_TYPE_APPLE_BOOT;
+static struct uuid gpt_uuid_apple_core_storage =
+ GPT_ENT_TYPE_APPLE_CORE_STORAGE;
static struct uuid gpt_uuid_apple_hfs = GPT_ENT_TYPE_APPLE_HFS;
static struct uuid gpt_uuid_apple_label = GPT_ENT_TYPE_APPLE_LABEL;
static struct uuid gpt_uuid_apple_raid = GPT_ENT_TYPE_APPLE_RAID;
@@ -174,6 +178,7 @@
static struct uuid gpt_uuid_vmfs = GPT_ENT_TYPE_VMFS;
static struct uuid gpt_uuid_vmkdiag = GPT_ENT_TYPE_VMKDIAG;
static struct uuid gpt_uuid_vmreserved = GPT_ENT_TYPE_VMRESERVED;
+static struct uuid gpt_uuid_vmvsanhdr = GPT_ENT_TYPE_VMVSANHDR;
static struct uuid gpt_uuid_ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA;
static struct uuid gpt_uuid_ms_reserved = GPT_ENT_TYPE_MS_RESERVED;
static struct uuid gpt_uuid_ms_ldm_data = GPT_ENT_TYPE_MS_LDM_DATA;
@@ -186,6 +191,16 @@
static struct uuid gpt_uuid_netbsd_swap = GPT_ENT_TYPE_NETBSD_SWAP;
static struct uuid gpt_uuid_mbr = GPT_ENT_TYPE_MBR;
static struct uuid gpt_uuid_unused = GPT_ENT_TYPE_UNUSED;
+static struct uuid gpt_uuid_dfbsd_swap = GPT_ENT_TYPE_DRAGONFLY_SWAP;
+static struct uuid gpt_uuid_dfbsd_ufs1 = GPT_ENT_TYPE_DRAGONFLY_UFS1;
+static struct uuid gpt_uuid_dfbsd_vinum = GPT_ENT_TYPE_DRAGONFLY_VINUM;
+static struct uuid gpt_uuid_dfbsd_ccd = GPT_ENT_TYPE_DRAGONFLY_CCD;
+static struct uuid gpt_uuid_dfbsd_legacy = GPT_ENT_TYPE_DRAGONFLY_LEGACY;
+static struct uuid gpt_uuid_dfbsd_hammer = GPT_ENT_TYPE_DRAGONFLY_HAMMER;
+static struct uuid gpt_uuid_dfbsd_hammer2 = GPT_ENT_TYPE_DRAGONFLY_HAMMER2;
+static struct uuid gpt_uuid_dfbsd_label32 = GPT_ENT_TYPE_DRAGONFLY_LABEL32;
+static struct uuid gpt_uuid_dfbsd_label64 = GPT_ENT_TYPE_DRAGONFLY_LABEL64;
+static struct uuid gpt_uuid_prep_boot = GPT_ENT_TYPE_PREP_BOOT;
static struct g_part_uuid_alias {
struct uuid *uuid;
@@ -193,6 +208,7 @@
int mbrtype;
} gpt_uuid_alias_match[] = {
{ &gpt_uuid_apple_boot, G_PART_ALIAS_APPLE_BOOT, 0xab },
+ { &gpt_uuid_apple_core_storage, G_PART_ALIAS_APPLE_CORE_STORAGE, 0 },
{ &gpt_uuid_apple_hfs, G_PART_ALIAS_APPLE_HFS, 0xaf },
{ &gpt_uuid_apple_label, G_PART_ALIAS_APPLE_LABEL, 0 },
{ &gpt_uuid_apple_raid, G_PART_ALIAS_APPLE_RAID, 0 },
@@ -215,6 +231,7 @@
{ &gpt_uuid_vmfs, G_PART_ALIAS_VMFS, 0 },
{ &gpt_uuid_vmkdiag, G_PART_ALIAS_VMKDIAG, 0 },
{ &gpt_uuid_vmreserved, G_PART_ALIAS_VMRESERVED, 0 },
+ { &gpt_uuid_vmvsanhdr, G_PART_ALIAS_VMVSANHDR, 0 },
{ &gpt_uuid_mbr, G_PART_ALIAS_MBR, 0 },
{ &gpt_uuid_midnightbsd, G_PART_ALIAS_MIDNIGHTBSD, 0xa5},
{ &gpt_uuid_midnightbsd_boot, G_PART_ALIAS_MIDNIGHTBSD_BOOT, 0 },
@@ -233,6 +250,16 @@
{ &gpt_uuid_netbsd_lfs, G_PART_ALIAS_NETBSD_LFS, 0 },
{ &gpt_uuid_netbsd_raid, G_PART_ALIAS_NETBSD_RAID, 0 },
{ &gpt_uuid_netbsd_swap, G_PART_ALIAS_NETBSD_SWAP, 0 },
+ { &gpt_uuid_dfbsd_swap, G_PART_ALIAS_DFBSD_SWAP, 0 },
+ { &gpt_uuid_dfbsd_ufs1, G_PART_ALIAS_DFBSD_UFS, 0 },
+ { &gpt_uuid_dfbsd_vinum, G_PART_ALIAS_DFBSD_VINUM, 0 },
+ { &gpt_uuid_dfbsd_ccd, G_PART_ALIAS_DFBSD_CCD, 0 },
+ { &gpt_uuid_dfbsd_legacy, G_PART_ALIAS_DFBSD_LEGACY, 0 },
+ { &gpt_uuid_dfbsd_hammer, G_PART_ALIAS_DFBSD_HAMMER, 0 },
+ { &gpt_uuid_dfbsd_hammer2, G_PART_ALIAS_DFBSD_HAMMER2, 0 },
+ { &gpt_uuid_dfbsd_label32, G_PART_ALIAS_DFBSD, 0xa5 },
+ { &gpt_uuid_dfbsd_label64, G_PART_ALIAS_DFBSD64, 0xa5 },
+ { &gpt_uuid_prep_boot, G_PART_ALIAS_PREP_BOOT, 0x41 },
{ NULL, 0, 0 }
};
@@ -274,6 +301,16 @@
return (0);
}
+static void
+gpt_create_pmbr(struct g_part_gpt_table *table, struct g_provider *pp)
+{
+
+ bzero(table->mbr + DOSPARTOFF, DOSPARTSIZE * NDOSPART);
+ gpt_write_mbr_entry(table->mbr, 0, 0xee, 1,
+ MIN(pp->mediasize / pp->sectorsize - 1, UINT32_MAX));
+ le16enc(table->mbr + DOSMAGICOFFSET, DOSMAGIC);
+}
+
/*
* Under Boot Camp the PMBR partition (type 0xEE) doesn't cover the
* whole disk anymore. Rather, it covers the GPT table and the EFI
@@ -298,7 +335,7 @@
}
static void
-gpt_update_bootcamp(struct g_part_table *basetable)
+gpt_update_bootcamp(struct g_part_table *basetable, struct g_provider *pp)
{
struct g_part_entry *baseentry;
struct g_part_gpt_entry *entry;
@@ -355,6 +392,7 @@
disable:
table->bootcamp = 0;
+ gpt_create_pmbr(table, pp);
}
static struct gpt_hdr *
@@ -623,6 +661,8 @@
pp->sectorsize)
return (ENOSPC);
+ gpt_create_pmbr(table, pp);
+
/* Allocate space for the header */
table->hdr = g_malloc(sizeof(struct gpt_hdr), M_WAITOK | M_ZERO);
@@ -704,8 +744,9 @@
entry = (struct g_part_gpt_entry *)baseentry;
return ((EQUUID(&entry->ent.ent_type, &gpt_uuid_midnightbsd_swap) ||
- EQUUID(&entry->ent.ent_type, &gpt_uuid_freebsd_swap) ||
- EQUUID(&entry->ent.ent_type, &gpt_uuid_linux_swap)) ? 1 : 0);
+ EQUUID(&entry->ent.ent_type, &gpt_uuid_freebsd_swap) ||
+ EQUUID(&entry->ent.ent_type, &gpt_uuid_linux_swap) ||
+ EQUUID(&entry->ent.ent_type, &gpt_uuid_dfbsd_swap)) ? 1 : 0);
}
static int
@@ -733,8 +774,11 @@
struct g_part_entry *baseentry, struct g_part_parms *gpp)
{
struct g_part_gpt_entry *entry;
+
+ if (baseentry == NULL)
+ return (g_part_gpt_recover(basetable));
+
entry = (struct g_part_gpt_entry *)baseentry;
-
baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1;
entry->ent.ent_lba_end = baseentry->gpe_end;
@@ -758,8 +802,8 @@
g_part_gpt_probe(struct g_part_table *table, struct g_consumer *cp)
{
struct g_provider *pp;
- char *buf;
- int error, res;
+ u_char *buf;
+ int error, index, pri, res;
/* We don't nest, which means that our depth should be 0. */
if (table->gpt_depth != 0)
@@ -784,23 +828,34 @@
if (pp->sectorsize < MBRSIZE || pp->mediasize < 6 * pp->sectorsize)
return (ENOSPC);
- /* Check that there's a MBR. */
+ /*
+ * Check that there's a MBR or a PMBR. If it's a PMBR, we return
+ * as the highest priority on a match, otherwise we assume some
+ * GPT-unaware tool has destroyed the GPT by recreating a MBR and
+ * we really want the MBR scheme to take precedence.
+ */
buf = g_read_data(cp, 0L, pp->sectorsize, &error);
if (buf == NULL)
return (error);
res = le16dec(buf + DOSMAGICOFFSET);
- g_free(buf);
- if (res != DOSMAGIC)
- return (ENXIO);
+ pri = G_PART_PROBE_PRI_LOW;
+ if (res == DOSMAGIC) {
+ for (index = 0; index < NDOSPART; index++) {
+ if (buf[DOSPARTOFF + DOSPARTSIZE * index + 4] == 0xee)
+ pri = G_PART_PROBE_PRI_HIGH;
+ }
+ g_free(buf);
- /* Check that there's a primary header. */
- buf = g_read_data(cp, pp->sectorsize, pp->sectorsize, &error);
- if (buf == NULL)
- return (error);
- res = memcmp(buf, GPT_HDR_SIG, 8);
- g_free(buf);
- if (res == 0)
- return (G_PART_PROBE_PRI_HIGH);
+ /* Check that there's a primary header. */
+ buf = g_read_data(cp, pp->sectorsize, pp->sectorsize, &error);
+ if (buf == NULL)
+ return (error);
+ res = memcmp(buf, GPT_HDR_SIG, 8);
+ g_free(buf);
+ if (res == 0)
+ return (pri);
+ } else
+ g_free(buf);
/* No primary? Check that there's a secondary. */
buf = g_read_data(cp, pp->mediasize - pp->sectorsize, pp->sectorsize,
@@ -809,7 +864,7 @@
return (error);
res = memcmp(buf, GPT_HDR_SIG, 8);
g_free(buf);
- return ((res == 0) ? G_PART_PROBE_PRI_HIGH : ENXIO);
+ return ((res == 0) ? pri : ENXIO);
}
static int
@@ -918,9 +973,10 @@
basetable->gpt_first = table->hdr->hdr_lba_start;
basetable->gpt_last = table->hdr->hdr_lba_end;
- basetable->gpt_entries = table->hdr->hdr_entries;
+ basetable->gpt_entries = (table->hdr->hdr_lba_start - 2) *
+ pp->sectorsize / table->hdr->hdr_entsz;
- for (index = basetable->gpt_entries - 1; index >= 0; index--) {
+ for (index = table->hdr->hdr_entries - 1; index >= 0; index--) {
if (EQUUID(&tbl[index].ent_type, &gpt_uuid_unused))
continue;
entry = (struct g_part_gpt_entry *)g_part_new_entry(
@@ -951,9 +1007,13 @@
static int
g_part_gpt_recover(struct g_part_table *basetable)
{
+ struct g_part_gpt_table *table;
+ struct g_provider *pp;
- g_gpt_set_defaults(basetable,
- LIST_FIRST(&basetable->gpt_gp->consumer)->provider);
+ table = (struct g_part_gpt_table *)basetable;
+ pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
+ gpt_create_pmbr(table, pp);
+ g_gpt_set_defaults(basetable, pp);
basetable->gpt_corrupt = 0;
return (0);
}
@@ -964,6 +1024,8 @@
{
struct g_part_gpt_entry *entry;
struct g_part_gpt_table *table;
+ struct g_provider *pp;
+ uint8_t *p;
uint64_t attr;
int i;
@@ -971,15 +1033,47 @@
entry = (struct g_part_gpt_entry *)baseentry;
if (strcasecmp(attrib, "active") == 0) {
- if (!table->bootcamp || baseentry->gpe_index > NDOSPART)
- return (EINVAL);
- for (i = 0; i < NDOSPART; i++) {
- table->mbr[DOSPARTOFF + i * DOSPARTSIZE] =
- (i == baseentry->gpe_index - 1) ? 0x80 : 0;
+ if (table->bootcamp) {
+ /* The active flag must be set on a valid entry. */
+ if (entry == NULL)
+ return (ENXIO);
+ if (baseentry->gpe_index > NDOSPART)
+ return (EINVAL);
+ for (i = 0; i < NDOSPART; i++) {
+ p = &table->mbr[DOSPARTOFF + i * DOSPARTSIZE];
+ p[0] = (i == baseentry->gpe_index - 1)
+ ? ((set) ? 0x80 : 0) : 0;
+ }
+ } else {
+ /* The PMBR is marked as active without an entry. */
+ if (entry != NULL)
+ return (ENXIO);
+ for (i = 0; i < NDOSPART; i++) {
+ p = &table->mbr[DOSPARTOFF + i * DOSPARTSIZE];
+ p[0] = (p[4] == 0xee) ? ((set) ? 0x80 : 0) : 0;
+ }
}
return (0);
+ } else if (strcasecmp(attrib, "lenovofix") == 0) {
+ /*
+ * Write the 0xee GPT entry to slot #1 (2nd slot) in the pMBR.
+ * This workaround allows Lenovo X220, T420, T520, etc to boot
+ * from GPT Partitions in BIOS mode.
+ */
+
+ if (entry != NULL)
+ return (ENXIO);
+
+ pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
+ bzero(table->mbr + DOSPARTOFF, DOSPARTSIZE * NDOSPART);
+ gpt_write_mbr_entry(table->mbr, ((set) ? 1 : 0), 0xee, 1,
+ MIN(pp->mediasize / pp->sectorsize - 1, UINT32_MAX));
+ return (0);
}
+ if (entry == NULL)
+ return (ENODEV);
+
attr = 0;
if (strcasecmp(attrib, "bootme") == 0) {
attr |= GPT_ENT_ATTR_BOOTME;
@@ -1047,18 +1141,8 @@
/* Reconstruct the MBR from the GPT if under Boot Camp. */
if (table->bootcamp)
- gpt_update_bootcamp(basetable);
+ gpt_update_bootcamp(basetable, pp);
- /* Update partition entries in the PMBR if Boot Camp disabled. */
- if (!table->bootcamp) {
- bzero(table->mbr + DOSPARTOFF, DOSPARTSIZE * NDOSPART);
- gpt_write_mbr_entry(table->mbr, 0, 0xee, 1,
- MIN(pp->mediasize / pp->sectorsize - 1, UINT32_MAX));
- /* Mark the PMBR active since some BIOS require it. */
- table->mbr[DOSPARTOFF] = 0x80;
- }
- le16enc(table->mbr + DOSMAGICOFFSET, DOSMAGIC);
-
/* Write the PMBR */
buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO);
bcopy(table->mbr, buf, MBRSIZE);
@@ -1204,16 +1288,16 @@
/* Write the Unicode character in UTF-8 */
if (ch < 0x80)
- sbuf_printf(sb, "%c", ch);
+ g_conf_printf_escaped(sb, "%c", ch);
else if (ch < 0x800)
- sbuf_printf(sb, "%c%c", 0xc0 | (ch >> 6),
+ g_conf_printf_escaped(sb, "%c%c", 0xc0 | (ch >> 6),
0x80 | (ch & 0x3f));
else if (ch < 0x10000)
- sbuf_printf(sb, "%c%c%c", 0xe0 | (ch >> 12),
+ g_conf_printf_escaped(sb, "%c%c%c", 0xe0 | (ch >> 12),
0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f));
else if (ch < 0x200000)
- sbuf_printf(sb, "%c%c%c%c", 0xf0 | (ch >> 18),
- 0x80 | ((ch >> 12) & 0x3f),
+ g_conf_printf_escaped(sb, "%c%c%c%c", 0xf0 |
+ (ch >> 18), 0x80 | ((ch >> 12) & 0x3f),
0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f));
}
}
More information about the Midnightbsd-cvs
mailing list