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 */