SHA256
1
0
forked from pool/parted
parted/parted-gpt-mbr-sync.patch

140 lines
4.0 KiB
Diff

Index: libparted/labels/gpt.c
===================================================================
--- libparted/labels/gpt.c.orig
+++ libparted/labels/gpt.c
@@ -46,6 +46,8 @@
# define _(String) (String)
#endif /* ENABLE_NLS */
+#define GPT_SYNC_MBR
+
#define EFI_PMBR_OSTYPE_EFI 0xEE
#define MSDOS_MBR_SIGNATURE 0xaa55
@@ -402,6 +404,7 @@ guid_cmp (efi_guid_t left, efi_guid_t ri
return memcmp(&left, &right, sizeof(efi_guid_t));
}
+#ifndef GPT_SYNC_MBR
/* checks if 'mbr' is a protective MBR partition table */
static inline int
_pmbr_is_valid (const LegacyMBR_t* mbr)
@@ -418,6 +421,7 @@ _pmbr_is_valid (const LegacyMBR_t* mbr)
}
return 0;
}
+#endif
static int
gpt_probe (const PedDevice * dev)
@@ -445,6 +449,7 @@ gpt_probe (const PedDevice * dev)
if (!gpt_sig_found)
return 0;
+#ifndef GPT_SYNC_MBR
if (ped_device_read(dev, &legacy_mbr, 0, GPT_HEADER_SECTORS)) {
if (!_pmbr_is_valid (&legacy_mbr)) {
int ex_status = ped_exception_throw (
@@ -463,6 +468,7 @@ gpt_probe (const PedDevice * dev)
return 0;
}
}
+#endif
return 1;
}
@@ -928,15 +934,51 @@ error:
return 0;
}
+#ifdef GPT_SYNC_MBR
+static inline unsigned char
+_part_to_ostype (PedPartition* part)
+{
+ GPTPartitionData* gpt_part_data = part->disk_specific;
+ if (part->fs_type) {
+ if (strncmp (part->fs_type->name, "fat", 3) == 0) return 0xc;
+ if (strncmp (part->fs_type->name, "ntfs", 4) == 0) return 0x7;
+ if (strncmp (part->fs_type->name, "hfs", 3) == 0) return 0xaf;
+ if (strstr (part->fs_type->name, "swap")) return 0x82;
+ }
+ return 0x83; // Everything else is Linux
+}
+
+static inline uint32_t
+_part_32bitmax (uint64_t in)
+{
+ if (in > 0xFFFFFFFFULL)
+ return 0xFFFFFFFF;
+ else
+ return (uint32_t)in;
+}
+#endif
+
#ifndef DISCOVER_ONLY
/* Writes the protective MBR (to keep DOS happy) */
static int
-_write_pmbr (PedDevice * dev)
+_write_pmbr (PedDisk * disk)
{
+ PedDevice * dev = disk->dev;
LegacyMBR_t pmbr;
+#ifdef GPT_SYNC_MBR
+ int i;
+ PedPartition* part = NULL;
+#endif
+#ifdef GPT_SYNC_MBR
+ /* Keep the old MBR as much as possible */
+ ped_device_read(dev, &pmbr, 0, GPT_HEADER_SECTORS);
+ memset(&pmbr.PartitionRecord, 0, sizeof(pmbr.PartitionRecord));
+#else
memset(&pmbr, 0, sizeof(pmbr));
+#endif
pmbr.Signature = PED_CPU_TO_LE16(MSDOS_MBR_SIGNATURE);
+#ifndef GPT_SYNC_MBR
pmbr.PartitionRecord[0].OSType = EFI_PMBR_OSTYPE_EFI;
pmbr.PartitionRecord[0].StartSector = 1;
pmbr.PartitionRecord[0].EndHead = 0xFE;
@@ -947,6 +989,31 @@ _write_pmbr (PedDevice * dev)
pmbr.PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32(0xFFFFFFFF);
else
pmbr.PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32(dev->length - 1UL);
+#else
+ /* sync the first 4 GPT entries to MBR primary partitions */
+ for (i=0; i < 4; i++) {
+ part = ped_disk_next_partition (disk, part);
+ if (part == NULL)
+ break;
+ /* we might get a starting garbage partition */
+ if (part->geom.start == 0 || part->type == PED_PARTITION_METADATA || part->type == PED_PARTITION_FREESPACE) {
+ i--;
+ continue;
+ }
+ pmbr.PartitionRecord[i].OSType = _part_to_ostype(part);
+ pmbr.PartitionRecord[i].StartSector = 1;
+ pmbr.PartitionRecord[i].StartHead = 0xFE;
+ pmbr.PartitionRecord[i].StartSector = 0xFF;
+ pmbr.PartitionRecord[i].StartTrack = 0xFF;
+ pmbr.PartitionRecord[i].EndHead = 0xFE;
+ pmbr.PartitionRecord[i].EndSector = 0xFF;
+ pmbr.PartitionRecord[i].EndTrack = 0xFF;
+ pmbr.PartitionRecord[i].StartingLBA = _part_32bitmax(part->geom.start);
+ if(((GPTPartitionData*)part->disk_specific)->boot)
+ pmbr.PartitionRecord[i].BootIndicator = 0x80;
+ pmbr.PartitionRecord[i].SizeInLBA = _part_32bitmax(part->geom.end - part->geom.start);
+ }
+#endif
return ped_device_write (dev, &pmbr, GPT_PMBR_LBA, GPT_PMBR_SECTORS);
}
@@ -1050,7 +1117,7 @@ gpt_write(const PedDisk * disk)
ptes_crc = efi_crc32 (ptes, ptes_size);
/* Write protective MBR */
- if (!_write_pmbr (disk->dev))
+ if (!_write_pmbr (disk))
goto error_free_ptes;
/* Write PTH and PTEs */