2010-04-02 13:35:12 +02:00
|
|
|
---
|
|
|
|
libparted/labels/gpt.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
|
|
1 file changed, 107 insertions(+), 2 deletions(-)
|
|
|
|
|
2008-07-19 00:25:20 +02:00
|
|
|
Index: libparted/labels/gpt.c
|
|
|
|
===================================================================
|
2011-08-16 11:13:00 +02:00
|
|
|
--- libparted/labels/gpt.c.orig
|
|
|
|
+++ libparted/labels/gpt.c
|
|
|
|
@@ -51,6 +51,11 @@
|
2008-07-19 00:25:20 +02:00
|
|
|
# define _(String) (String)
|
2010-04-02 13:35:12 +02:00
|
|
|
#endif /* ENABLE_NLS */
|
2008-07-19 00:25:20 +02:00
|
|
|
|
2008-08-11 23:37:59 +02:00
|
|
|
+/* IA64 always has a properly working EFI implementation */
|
|
|
|
+#ifndef __ia64__
|
2008-07-19 00:25:20 +02:00
|
|
|
+#define GPT_SYNC_MBR
|
2008-08-11 23:37:59 +02:00
|
|
|
+#endif
|
2008-07-19 00:25:20 +02:00
|
|
|
+
|
|
|
|
#define EFI_PMBR_OSTYPE_EFI 0xEE
|
|
|
|
#define MSDOS_MBR_SIGNATURE 0xaa55
|
|
|
|
|
2011-08-16 11:13:00 +02:00
|
|
|
@@ -1072,11 +1077,60 @@ error:
|
2010-04-02 13:35:12 +02:00
|
|
|
return 0;
|
2008-07-19 00:25:20 +02:00
|
|
|
}
|
|
|
|
|
2010-04-02 13:35:12 +02:00
|
|
|
+
|
2008-07-19 00:25:20 +02:00
|
|
|
+#ifdef GPT_SYNC_MBR
|
|
|
|
+static inline unsigned char
|
|
|
|
+_part_to_ostype (PedPartition* part)
|
|
|
|
+{
|
2010-04-02 13:35:12 +02:00
|
|
|
+ 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
|
2008-07-19 00:25:20 +02:00
|
|
|
+}
|
|
|
|
+
|
2008-08-11 23:37:59 +02:00
|
|
|
+static inline PedPartition*
|
2009-08-06 22:06:27 +02:00
|
|
|
+_find_first_part (const PedDisk* disk)
|
2008-08-11 23:37:59 +02:00
|
|
|
+{
|
2010-04-02 13:35:12 +02:00
|
|
|
+ PedPartition *retval = NULL, *part = NULL;
|
|
|
|
+ uint64_t lowest_end = 0xffffffffffffffff;
|
|
|
|
+ while (part = ped_disk_next_partition (disk, part)) {
|
|
|
|
+ if (part->geom.start == 0 || part->type == PED_PARTITION_METADATA
|
|
|
|
+ || part->type == PED_PARTITION_FREESPACE)
|
|
|
|
+ continue;
|
|
|
|
+ if (part->geom.end < lowest_end) {
|
|
|
|
+ retval = part;
|
|
|
|
+ lowest_end = part->geom.end;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return retval;
|
2008-08-11 23:37:59 +02:00
|
|
|
+}
|
|
|
|
+
|
2008-07-19 00:25:20 +02:00
|
|
|
+static inline uint32_t
|
|
|
|
+_part_32bitmax (uint64_t in)
|
|
|
|
+{
|
2010-04-02 13:35:12 +02:00
|
|
|
+ if (in > 0xFFFFFFFFULL)
|
|
|
|
+ return 0xFFFFFFFF;
|
|
|
|
+ else
|
|
|
|
+ return (uint32_t)in;
|
2008-07-19 00:25:20 +02:00
|
|
|
+}
|
|
|
|
+#endif
|
2009-08-06 22:06:27 +02:00
|
|
|
+
|
2008-07-19 00:25:20 +02:00
|
|
|
+
|
|
|
|
#ifndef DISCOVER_ONLY
|
2009-08-06 22:06:27 +02:00
|
|
|
/* Write the protective MBR (to keep DOS happy) */
|
2008-07-19 00:25:20 +02:00
|
|
|
static int
|
2010-04-02 13:35:12 +02:00
|
|
|
-_write_pmbr (PedDevice *dev)
|
|
|
|
+_write_pmbr (const PedDisk *disk)
|
2008-07-19 00:25:20 +02:00
|
|
|
{
|
2010-04-02 13:35:12 +02:00
|
|
|
+ PedDevice * dev = disk->dev;
|
|
|
|
+
|
2008-07-19 00:25:20 +02:00
|
|
|
+#ifdef GPT_SYNC_MBR
|
2010-04-02 13:35:12 +02:00
|
|
|
+ int i, pmbr_id, first_entry = 0, last_entry = 3;
|
|
|
|
+ PedPartition *part = NULL, *esp;
|
2008-07-19 00:25:20 +02:00
|
|
|
+#endif
|
2009-08-06 22:06:27 +02:00
|
|
|
+
|
2010-04-02 13:35:12 +02:00
|
|
|
/* The UEFI spec is not clear about what to do with the following
|
|
|
|
elements of the Protective MBR (pmbr): BootCode (0-440B),
|
|
|
|
UniqueMBRSignature (440B-444B) and Unknown (444B-446B).
|
2011-08-16 11:13:00 +02:00
|
|
|
@@ -1086,10 +1140,13 @@ _write_pmbr (PedDevice *dev)
|
2010-04-02 13:35:12 +02:00
|
|
|
return 0;
|
|
|
|
LegacyMBR_t *pmbr = s0;
|
2008-07-19 00:25:20 +02:00
|
|
|
|
2009-08-06 22:06:27 +02:00
|
|
|
+#ifndef GPT_SYNC_MBR
|
2010-04-02 13:35:12 +02:00
|
|
|
/* Zero out the legacy partitions. */
|
|
|
|
memset (pmbr->PartitionRecord, 0, sizeof pmbr->PartitionRecord);
|
2008-07-19 00:25:20 +02:00
|
|
|
+#endif
|
2009-08-06 22:06:27 +02:00
|
|
|
|
2010-04-02 13:35:12 +02:00
|
|
|
pmbr->Signature = PED_CPU_TO_LE16 (MSDOS_MBR_SIGNATURE);
|
2008-07-19 00:25:20 +02:00
|
|
|
+#ifndef GPT_SYNC_MBR
|
2010-04-02 13:35:12 +02:00
|
|
|
pmbr->PartitionRecord[0].OSType = EFI_PMBR_OSTYPE_EFI;
|
|
|
|
pmbr->PartitionRecord[0].StartSector = 1;
|
|
|
|
pmbr->PartitionRecord[0].EndHead = 0xFE;
|
2011-08-16 11:13:00 +02:00
|
|
|
@@ -1100,6 +1157,53 @@ _write_pmbr (PedDevice *dev)
|
2010-04-02 13:35:12 +02:00
|
|
|
pmbr->PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32 (0xFFFFFFFF);
|
|
|
|
else
|
|
|
|
pmbr->PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32 (dev->length - 1UL);
|
2008-07-19 00:25:20 +02:00
|
|
|
+#else
|
2010-04-02 13:35:12 +02:00
|
|
|
+ /* Search for an EFI System Partition */
|
|
|
|
+ esp = _find_first_part(disk);
|
|
|
|
+ if (!esp || !esp->fs_type || strncmp (esp->fs_type->name, "fat", 3) != 0)
|
|
|
|
+ esp = NULL;
|
2008-08-11 23:37:59 +02:00
|
|
|
+
|
2010-04-02 13:35:12 +02:00
|
|
|
+ pmbr_id = 3;
|
|
|
|
+ if (esp) {
|
|
|
|
+ pmbr_id = 0;
|
|
|
|
+ first_entry = 1;
|
|
|
|
+ last_entry = 4;
|
|
|
|
+ }
|
2008-08-11 23:37:59 +02:00
|
|
|
+
|
2010-04-02 13:35:12 +02:00
|
|
|
+ /* Write a pseudo-PMBR so Linux is happy */
|
|
|
|
+ pmbr->PartitionRecord[pmbr_id].OSType = EFI_PMBR_OSTYPE_EFI;
|
|
|
|
+ pmbr->PartitionRecord[pmbr_id].StartSector = 1;
|
|
|
|
+ pmbr->PartitionRecord[pmbr_id].EndHead = 0xFE;
|
|
|
|
+ pmbr->PartitionRecord[pmbr_id].EndSector = 0xFF;
|
|
|
|
+ pmbr->PartitionRecord[pmbr_id].EndTrack = 0xFF;
|
|
|
|
+ pmbr->PartitionRecord[pmbr_id].StartingLBA = PED_CPU_TO_LE32(1);
|
|
|
|
+ pmbr->PartitionRecord[pmbr_id].SizeInLBA = 1;
|
|
|
|
+ if (esp)
|
|
|
|
+ pmbr->PartitionRecord[pmbr_id].SizeInLBA = esp->geom.end - 1;
|
2008-08-11 23:37:59 +02:00
|
|
|
+
|
2010-04-02 13:35:12 +02:00
|
|
|
+ /* sync the first 3 GPT entries to MBR primary partitions */
|
|
|
|
+ for (i=first_entry; i < last_entry; 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 || part == esp) {
|
|
|
|
+ i--;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ pmbr->PartitionRecord[i].OSType = _part_to_ostype(part);
|
|
|
|
+ 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;
|
2011-08-16 11:13:00 +02:00
|
|
|
+ pmbr->PartitionRecord[i].SizeInLBA = _part_32bitmax(part->geom.end - part->geom.start + 1);
|
2010-04-02 13:35:12 +02:00
|
|
|
+ }
|
2008-07-19 00:25:20 +02:00
|
|
|
+#endif
|
|
|
|
|
2010-04-02 13:35:12 +02:00
|
|
|
int write_ok = ped_device_write (dev, pmbr, GPT_PMBR_LBA,
|
|
|
|
GPT_PMBR_SECTORS);
|
2011-08-16 11:13:00 +02:00
|
|
|
@@ -1216,7 +1320,7 @@ gpt_write (const PedDisk *disk)
|
2010-04-02 13:35:12 +02:00
|
|
|
ptes_crc = efi_crc32 (ptes, ptes_size);
|
2008-07-19 00:25:20 +02:00
|
|
|
|
2010-04-02 13:35:12 +02:00
|
|
|
/* Write protective MBR */
|
|
|
|
- if (!_write_pmbr (disk->dev))
|
|
|
|
+ if (!_write_pmbr (disk))
|
|
|
|
goto error_free_ptes;
|
2008-07-19 00:25:20 +02:00
|
|
|
|
2010-04-02 13:35:12 +02:00
|
|
|
/* Write PTH and PTEs */
|