diff --git a/parted-gpt-sync-mbr-label.patch b/parted-gpt-sync-mbr-label.patch new file mode 100644 index 0000000..1d0b472 --- /dev/null +++ b/parted-gpt-sync-mbr-label.patch @@ -0,0 +1,273 @@ +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); diff --git a/parted.changes b/parted.changes index 3bf2e90..6d280a5 100644 --- a/parted.changes +++ b/parted.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Thu Aug 25 10:22:09 UTC 2011 - puzel@novell.com + +- add parted-gpt-sync-mbr-label.patch (bnc#710402) + - this patch implements support for special label 'gpt-sync-mbr' + ------------------------------------------------------------------- Tue Aug 16 09:07:50 UTC 2011 - puzel@novell.com diff --git a/parted.spec b/parted.spec index 51c1455..2dad5ed 100644 --- a/parted.spec +++ b/parted.spec @@ -40,6 +40,7 @@ Patch11: do-not-create-dm-nodes.patch #PATCH-FEATURE-OPENSUSE more-reliable-informing-the-kernel.patch bnc#657360 petr.uzel@suse.cz Patch12: more-reliable-informing-the-kernel.patch Patch13: parted-2.4-ncursesw6.patch +Patch14: parted-gpt-sync-mbr-label.patch Requires: /sbin/udevadm BuildRequires: check-devel BuildRequires: device-mapper-devel >= 1.02.33 @@ -103,6 +104,7 @@ to develop applications that require these. %patch11 -p1 %patch12 -p1 %patch13 +%patch14 -p1 %build export CFLAGS="%{optflags} `ncursesw6-config --cflags`"