274 lines
8.0 KiB
Diff
274 lines
8.0 KiB
Diff
|
Index: parted-2.4/libparted/labels/gpt.c
|
||
|
===================================================================
|
||
|
--- parted-2.4.orig/libparted/labels/gpt.c
|
||
|
+++ parted-2.4/libparted/labels/gpt.c
|
||
|
@@ -51,11 +51,6 @@
|
||
|
# define _(String) (String)
|
||
|
#endif /* ENABLE_NLS */
|
||
|
|
||
|
-/* IA64 always has a properly working EFI implementation */
|
||
|
-#ifndef __ia64__
|
||
|
-#define GPT_SYNC_MBR
|
||
|
-#endif
|
||
|
-
|
||
|
#define EFI_PMBR_OSTYPE_EFI 0xEE
|
||
|
#define MSDOS_MBR_SIGNATURE 0xaa55
|
||
|
|
||
|
@@ -290,6 +285,7 @@ typedef struct _GPTPartitionData
|
||
|
} GPTPartitionData;
|
||
|
|
||
|
static PedDiskType gpt_disk_type;
|
||
|
+static PedDiskType gpt_sync_mbr_disk_type;
|
||
|
|
||
|
static inline uint32_t
|
||
|
pth_get_size (const PedDevice *dev)
|
||
|
@@ -458,8 +454,50 @@ _pmbr_is_valid (const LegacyMBR_t *mbr)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+/* checks if device has a hybrid protective MBR partition table
|
||
|
+ *
|
||
|
+ * If the 1st partition has type 0xEE that spans the entire
|
||
|
+ * size of the disk from sector 1 to the last sector
|
||
|
+ * (or 2 TiB, whichever is smaller), we consider it 'normal' GPT.
|
||
|
+ * Otherwise it is synced GPT with hybridized pMBR.
|
||
|
+ */
|
||
|
+static inline int
|
||
|
+_has_hybrid_pmbr (const PedDevice *dev)
|
||
|
+{
|
||
|
+ int has_hybrid_pmbr = 1;
|
||
|
+
|
||
|
+ PED_ASSERT (dev != NULL);
|
||
|
+
|
||
|
+ void *label;
|
||
|
+ if (!ptt_read_sector (dev, 0, &label))
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ LegacyMBR_t mbr;
|
||
|
+ memcpy(&mbr, label, sizeof(mbr));
|
||
|
+
|
||
|
+ if (mbr.Signature != PED_CPU_TO_LE16 (MSDOS_MBR_SIGNATURE)) {
|
||
|
+ free(label);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ uint32_t efi_gpt_expected_size;
|
||
|
+ if ((dev->length - 1ULL) > 0xFFFFFFFFULL)
|
||
|
+ efi_gpt_expected_size = 0xFFFFFFFF;
|
||
|
+ else
|
||
|
+ efi_gpt_expected_size = dev->length - 1UL;
|
||
|
+
|
||
|
+ if ((mbr.PartitionRecord[0].OSType == EFI_PMBR_OSTYPE_EFI) &&
|
||
|
+ (mbr.PartitionRecord[0].StartingLBA == PED_CPU_TO_LE32(1)) &&
|
||
|
+ (mbr.PartitionRecord[0].SizeInLBA == PED_CPU_TO_LE32(efi_gpt_expected_size)))
|
||
|
+ /* pMBR is not hybrid */
|
||
|
+ has_hybrid_pmbr = 0;
|
||
|
+
|
||
|
+ free(label);
|
||
|
+ return has_hybrid_pmbr;
|
||
|
+}
|
||
|
+
|
||
|
static int
|
||
|
-gpt_probe (const PedDevice *dev)
|
||
|
+_gpt_probe_generic(const PedDevice *dev)
|
||
|
{
|
||
|
GuidPartitionTableHeader_t *gpt = NULL;
|
||
|
int gpt_sig_found = 0;
|
||
|
@@ -512,6 +550,19 @@ gpt_probe (const PedDevice *dev)
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
+static int
|
||
|
+gpt_probe (const PedDevice *dev)
|
||
|
+{
|
||
|
+ return _gpt_probe_generic(dev) && !_has_hybrid_pmbr(dev);
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static int
|
||
|
+gpt_sync_mbr_probe (const PedDevice *dev)
|
||
|
+{
|
||
|
+ return _gpt_probe_generic(dev) && _has_hybrid_pmbr(dev);
|
||
|
+}
|
||
|
+
|
||
|
static PedDisk *
|
||
|
gpt_alloc (const PedDevice *dev)
|
||
|
{
|
||
|
@@ -543,6 +594,36 @@ error:
|
||
|
}
|
||
|
|
||
|
static PedDisk *
|
||
|
+gpt_sync_mbr_alloc (const PedDevice *dev)
|
||
|
+{
|
||
|
+ PedDisk *disk;
|
||
|
+ GPTDiskData *gpt_disk_data;
|
||
|
+ PedSector data_start, data_end;
|
||
|
+
|
||
|
+ disk = _ped_disk_alloc ((PedDevice *) dev, &gpt_sync_mbr_disk_type);
|
||
|
+ if (!disk)
|
||
|
+ goto error;
|
||
|
+ disk->disk_specific = gpt_disk_data = ped_malloc (sizeof (GPTDiskData));
|
||
|
+ if (!disk->disk_specific)
|
||
|
+ goto error_free_disk;
|
||
|
+
|
||
|
+ data_start = 2 + GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / dev->sector_size;
|
||
|
+ data_end = dev->length - 2
|
||
|
+ - GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / dev->sector_size;
|
||
|
+ ped_geometry_init (&gpt_disk_data->data_area, dev, data_start,
|
||
|
+ data_end - data_start + 1);
|
||
|
+ gpt_disk_data->entry_count = GPT_DEFAULT_PARTITION_ENTRIES;
|
||
|
+ uuid_generate ((unsigned char *) &gpt_disk_data->uuid);
|
||
|
+ swap_uuid_and_efi_guid ((unsigned char *) (&gpt_disk_data->uuid));
|
||
|
+ return disk;
|
||
|
+
|
||
|
+error_free_disk:
|
||
|
+ free (disk);
|
||
|
+error:
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+static PedDisk *
|
||
|
gpt_duplicate (const PedDisk *disk)
|
||
|
{
|
||
|
PedDisk *new_disk;
|
||
|
@@ -920,7 +1001,7 @@ gpt_read (PedDisk *disk)
|
||
|
|
||
|
/* motivation: let the user decide about the pmbr... during
|
||
|
ped_disk_probe(), they probably didn't get a choice... */
|
||
|
- if (!gpt_probe (disk->dev))
|
||
|
+ if (!gpt_probe (disk->dev) && !gpt_sync_mbr_probe(disk->dev))
|
||
|
goto error;
|
||
|
|
||
|
GuidPartitionTableHeader_t *gpt = NULL;
|
||
|
@@ -1078,7 +1159,6 @@ error:
|
||
|
}
|
||
|
|
||
|
|
||
|
-#ifdef GPT_SYNC_MBR
|
||
|
static inline unsigned char
|
||
|
_part_to_ostype (PedPartition* part)
|
||
|
{
|
||
|
@@ -1116,7 +1196,6 @@ _part_32bitmax (uint64_t in)
|
||
|
else
|
||
|
return (uint32_t)in;
|
||
|
}
|
||
|
-#endif
|
||
|
|
||
|
|
||
|
#ifndef DISCOVER_ONLY
|
||
|
@@ -1126,10 +1205,11 @@ _write_pmbr (const PedDisk *disk)
|
||
|
{
|
||
|
PedDevice * dev = disk->dev;
|
||
|
|
||
|
-#ifdef GPT_SYNC_MBR
|
||
|
+ /* need sync GPT -> hybrid pMBR ? */
|
||
|
+ int sync_pmbr = !strcmp(disk->type->name, "gpt_sync_mbr") ? 1 : 0;
|
||
|
+
|
||
|
int i, pmbr_id, first_entry = 0, last_entry = 3;
|
||
|
PedPartition *part = NULL, *esp;
|
||
|
-#endif
|
||
|
|
||
|
/* The UEFI spec is not clear about what to do with the following
|
||
|
elements of the Protective MBR (pmbr): BootCode (0-440B),
|
||
|
@@ -1140,13 +1220,12 @@ _write_pmbr (const PedDisk *disk)
|
||
|
return 0;
|
||
|
LegacyMBR_t *pmbr = s0;
|
||
|
|
||
|
-#ifndef GPT_SYNC_MBR
|
||
|
/* Zero out the legacy partitions. */
|
||
|
memset (pmbr->PartitionRecord, 0, sizeof pmbr->PartitionRecord);
|
||
|
-#endif
|
||
|
|
||
|
pmbr->Signature = PED_CPU_TO_LE16 (MSDOS_MBR_SIGNATURE);
|
||
|
-#ifndef GPT_SYNC_MBR
|
||
|
+
|
||
|
+ if (!sync_pmbr) {
|
||
|
pmbr->PartitionRecord[0].OSType = EFI_PMBR_OSTYPE_EFI;
|
||
|
pmbr->PartitionRecord[0].StartSector = 1;
|
||
|
pmbr->PartitionRecord[0].EndHead = 0xFE;
|
||
|
@@ -1157,7 +1236,7 @@ _write_pmbr (const PedDisk *disk)
|
||
|
pmbr->PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32 (0xFFFFFFFF);
|
||
|
else
|
||
|
pmbr->PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32 (dev->length - 1UL);
|
||
|
-#else
|
||
|
+ } else {
|
||
|
/* Search for an EFI System Partition */
|
||
|
esp = _find_first_part(disk);
|
||
|
if (!esp || !esp->fs_type || strncmp (esp->fs_type->name, "fat", 3) != 0)
|
||
|
@@ -1203,8 +1282,7 @@ _write_pmbr (const PedDisk *disk)
|
||
|
pmbr->PartitionRecord[i].BootIndicator = 0x80;
|
||
|
pmbr->PartitionRecord[i].SizeInLBA = _part_32bitmax(part->geom.end - part->geom.start + 1);
|
||
|
}
|
||
|
-#endif
|
||
|
-
|
||
|
+ }
|
||
|
int write_ok = ped_device_write (dev, pmbr, GPT_PMBR_LBA,
|
||
|
GPT_PMBR_SECTORS);
|
||
|
free (s0);
|
||
|
@@ -1902,6 +1980,38 @@ static PedDiskOps gpt_disk_ops =
|
||
|
PT_op_function_initializers (gpt)
|
||
|
};
|
||
|
|
||
|
+static PedDiskOps gpt_sync_mbr_disk_ops =
|
||
|
+{
|
||
|
+ clobber: NULL,
|
||
|
+ write: NULL_IF_DISCOVER_ONLY (gpt_write),
|
||
|
+
|
||
|
+ partition_set_name: gpt_partition_set_name,
|
||
|
+ partition_get_name: gpt_partition_get_name,
|
||
|
+
|
||
|
+ /* probe function redefined */
|
||
|
+ probe: gpt_sync_mbr_probe,
|
||
|
+ /* alloc function redefined */
|
||
|
+ alloc: gpt_sync_mbr_alloc,
|
||
|
+ duplicate: gpt_duplicate,
|
||
|
+ free: gpt_free,
|
||
|
+ read: gpt_read,
|
||
|
+ partition_new: gpt_partition_new,
|
||
|
+ partition_duplicate: gpt_partition_duplicate,
|
||
|
+ partition_set_flag: gpt_partition_set_flag,
|
||
|
+ partition_get_flag: gpt_partition_get_flag,
|
||
|
+ partition_set_system: gpt_partition_set_system,
|
||
|
+ partition_is_flag_available: gpt_partition_is_flag_available,
|
||
|
+ partition_align: gpt_partition_align,
|
||
|
+ partition_destroy: gpt_partition_destroy,
|
||
|
+ partition_enumerate: gpt_partition_enumerate,
|
||
|
+ alloc_metadata: gpt_alloc_metadata,
|
||
|
+ get_max_primary_partition_count: gpt_get_max_primary_partition_count,
|
||
|
+ get_max_supported_partition_count: gpt_get_max_supported_partition_count,
|
||
|
+ partition_check: gpt_partition_check,
|
||
|
+ max_length: gpt_partition_max_length,
|
||
|
+ max_start_sector: gpt_partition_max_start_sector
|
||
|
+};
|
||
|
+
|
||
|
static PedDiskType gpt_disk_type =
|
||
|
{
|
||
|
next: NULL,
|
||
|
@@ -1910,16 +2020,26 @@ static PedDiskType gpt_disk_type =
|
||
|
features: PED_DISK_TYPE_PARTITION_NAME
|
||
|
};
|
||
|
|
||
|
+static PedDiskType gpt_sync_mbr_disk_type =
|
||
|
+{
|
||
|
+ next: NULL,
|
||
|
+ name: "gpt_sync_mbr",
|
||
|
+ ops: &gpt_sync_mbr_disk_ops,
|
||
|
+ features: PED_DISK_TYPE_PARTITION_NAME
|
||
|
+};
|
||
|
+
|
||
|
void
|
||
|
ped_disk_gpt_init ()
|
||
|
{
|
||
|
ped_disk_type_register (&gpt_disk_type);
|
||
|
+ ped_disk_type_register (&gpt_sync_mbr_disk_type);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ped_disk_gpt_done ()
|
||
|
{
|
||
|
ped_disk_type_unregister (&gpt_disk_type);
|
||
|
+ ped_disk_type_unregister (&gpt_sync_mbr_disk_type);
|
||
|
}
|
||
|
|
||
|
verify (sizeof (GuidPartitionEntryAttributes_t) == 8);
|