[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