Hi,

I made this patch to create hybrid GPT/DOS labels.  It still needs some
cleanup though, and I don't have time to finish it right now (but I intend
to do it).

I'm posting it here just in case it's useful to someone.

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What good is a phone call… if you are unable to speak?
(as seen on /.)
diff -ur -x Makefile.in ../parted-1.8.8.git.2008.03.24/libparted/labels/dos.c libparted/labels/dos.c
--- ../parted-1.8.8.git.2008.03.24/libparted/labels/dos.c	2008-06-19 17:41:05.000000000 +0200
+++ libparted/labels/dos.c	2008-06-20 00:18:58.000000000 +0200
@@ -322,7 +322,7 @@
 		* (dev->sector_size / 512);
 }
 
-static void
+void
 sector_to_chs (const PedDevice* dev, const PedCHSGeometry* bios_geom,
 	       PedSector sector, RawCHS* chs)
 {
diff -ur -x Makefile.in ../parted-1.8.8.git.2008.03.24/libparted/labels/gpt.c libparted/labels/gpt.c
--- ../parted-1.8.8.git.2008.03.24/libparted/labels/gpt.c	2008-06-19 17:41:05.000000000 +0200
+++ libparted/labels/gpt.c	2008-06-20 00:17:25.000000000 +0200
@@ -186,6 +186,11 @@
         (GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / \
          sizeof(GuidPartitionEntry_t))
 
+typedef struct {
+	uint8_t         head;
+	uint8_t         sector;
+	uint8_t         cylinder;
+} __attribute__((packed)) RawCHS;
 
 struct __attribute__ ((packed)) _PartitionRecord_t {
 	/* Not used by EFI firmware. Set to 0x80 to indicate that this
@@ -193,13 +198,7 @@
 	uint8_t BootIndicator;
 
 	/* Start of partition in CHS address, not used by EFI firmware. */
-	uint8_t StartHead;
-
-	/* Start of partition in CHS address, not used by EFI firmware. */
-	uint8_t StartSector;
-
-	/* Start of partition in CHS address, not used by EFI firmware. */
-	uint8_t StartTrack;
+	RawCHS StartCHS;
 
 	/* OS type. A value of 0xEF defines an EFI system partition.
 	   Other values are reserved for legacy operating systems, and
@@ -207,13 +206,7 @@
 	uint8_t OSType;
 
 	/* End of partition in CHS address, not used by EFI firmware. */
-	uint8_t EndHead;
-
-	/* End of partition in CHS address, not used by EFI firmware. */
-	uint8_t EndSector;
-
-	/* End of partition in CHS address, not used by EFI firmware. */
-	uint8_t EndTrack;
+	RawCHS EndCHS;
 
 	/* Starting LBA address of the partition on the disk. Used by
 	   EFI firmware to define the start of the partition. */
@@ -936,25 +929,25 @@
 	return 0;
 }
 
+extern void sector_to_chs (const PedDevice* dev, void* bios_geom, PedSector sector, RawCHS* chs);
+
 #ifndef DISCOVER_ONLY
 /* Writes the protective MBR (to keep DOS happy) */
 static int
 _write_pmbr (PedDevice * dev)
 {
 	LegacyMBR_t pmbr;
+	PedCHSGeometry bios_geom;
+	bios_geom.heads = 255;
+	bios_geom.sectors = 63;
 
 	memset(&pmbr, 0, sizeof(pmbr));
 	pmbr.Signature = PED_CPU_TO_LE16(MSDOS_MBR_SIGNATURE);
 	pmbr.PartitionRecord[0].OSType      = EFI_PMBR_OSTYPE_EFI;
-	pmbr.PartitionRecord[0].StartSector = 1;
-	pmbr.PartitionRecord[0].EndHead     = 0xFE;
-	pmbr.PartitionRecord[0].EndSector   = 0xFF;
-	pmbr.PartitionRecord[0].EndTrack    = 0xFF;
+	sector_to_chs (dev, &bios_geom, 1, &pmbr.PartitionRecord[0].StartCHS);
+	sector_to_chs (dev, &bios_geom, 34 - 1, &pmbr.PartitionRecord[0].EndCHS);
 	pmbr.PartitionRecord[0].StartingLBA = PED_CPU_TO_LE32(1);
-	if ((dev->length - 1ULL) > 0xFFFFFFFFULL) 
-		pmbr.PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32(0xFFFFFFFF);
-	else
-		pmbr.PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32(dev->length - 1UL);
+	pmbr.PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32(33);
 
 	return ped_device_write (dev, &pmbr, GPT_PMBR_LBA, GPT_PMBR_SECTORS);
 }
@@ -1004,9 +997,10 @@
 }
 
 static void
-_partition_generate_part_entry (PedPartition* part, GuidPartitionEntry_t* pte)
+_partition_generate_part_entry (PedPartition* part, GuidPartitionEntry_t* ptes, int num)
 {
 	GPTPartitionData* gpt_part_data = part->disk_specific;
+	GuidPartitionEntry_t* pte = &ptes[num];
 	unsigned int i;
 
 	PED_ASSERT (gpt_part_data != NULL, return);
@@ -1024,6 +1018,23 @@
 		pte->PartitionName[i]
 			= (efi_char16_t) PED_CPU_TO_LE16(
 				(uint16_t) gpt_part_data->name[i]);
+
+	/* Don't use partition 0, as it corresponds to GPT metadata.  */
+	num++;
+	if (num < 4 && (part->geom.end - 1ULL) <= 0xFFFFFFFFULL) {
+		LegacyMBR_t pmbr;
+		PedCHSGeometry bios_geom;
+		bios_geom.heads = 255;
+		bios_geom.sectors = 63;
+
+		ped_device_read (part->disk->dev, &pmbr, GPT_PMBR_LBA, GPT_PMBR_SECTORS);
+		pmbr.PartitionRecord[num].OSType = 0x0c;
+		sector_to_chs (part->disk->dev, &bios_geom, part->geom.start, &pmbr.PartitionRecord[num].StartCHS);
+		sector_to_chs (part->disk->dev, &bios_geom, part->geom.end - 1, &pmbr.PartitionRecord[num].EndCHS);
+		pmbr.PartitionRecord[num].StartingLBA = PED_CPU_TO_LE32(part->geom.start);
+		pmbr.PartitionRecord[num].SizeInLBA = PED_CPU_TO_LE32(part->geom.end - part->geom.start);
+		ped_device_write (part->disk->dev, &pmbr, GPT_PMBR_LBA, GPT_PMBR_SECTORS);
+	}
 }
 
 static int
@@ -1041,6 +1052,10 @@
 	PED_ASSERT (disk->dev != NULL, goto error);
 	PED_ASSERT (disk->disk_specific != NULL, goto error);
 
+	/* Write protective MBR */
+	if (!_write_pmbr (disk->dev))
+		goto error_free_ptes;
+
 	gpt_disk_data = disk->disk_specific;
 
 	ptes_size = sizeof (GuidPartitionEntry_t) * gpt_disk_data->entry_count;
@@ -1052,15 +1067,11 @@
 	     part = ped_disk_next_partition (disk, part)) {
 		if (part->type != 0)
 			continue;
-		_partition_generate_part_entry (part, &ptes[part->num - 1]);
+		_partition_generate_part_entry (part, ptes, part->num - 1);
 	}
 
 	ptes_crc = efi_crc32 (ptes, ptes_size);
 
-	/* Write protective MBR */
-	if (!_write_pmbr (disk->dev))
-		goto error_free_ptes;
-
 	/* Write PTH and PTEs */
 	_generate_header (disk, 0, ptes_crc, &gpt);
         pth_raw = pth_get_raw (disk->dev, gpt);
diff -ur -x Makefile.in ../parted-1.8.8.git.2008.03.24/libparted/labels/dos.c libparted/labels/dos.c
--- ../parted-1.8.8.git.2008.03.24/libparted/labels/dos.c	2008-06-19 17:41:05.000000000 +0200
+++ libparted/labels/dos.c	2008-06-20 00:18:58.000000000 +0200
@@ -322,7 +322,7 @@
 		* (dev->sector_size / 512);
 }
 
-static void
+void
 sector_to_chs (const PedDevice* dev, const PedCHSGeometry* bios_geom,
 	       PedSector sector, RawCHS* chs)
 {
diff -ur -x Makefile.in ../parted-1.8.8.git.2008.03.24/libparted/labels/gpt.c libparted/labels/gpt.c
--- ../parted-1.8.8.git.2008.03.24/libparted/labels/gpt.c	2008-06-19 17:41:05.000000000 +0200
+++ libparted/labels/gpt.c	2008-06-20 00:17:25.000000000 +0200
@@ -186,6 +186,11 @@
         (GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / \
          sizeof(GuidPartitionEntry_t))
 
+typedef struct {
+	uint8_t         head;
+	uint8_t         sector;
+	uint8_t         cylinder;
+} __attribute__((packed)) RawCHS;
 
 struct __attribute__ ((packed)) _PartitionRecord_t {
 	/* Not used by EFI firmware. Set to 0x80 to indicate that this
@@ -193,13 +198,7 @@
 	uint8_t BootIndicator;
 
 	/* Start of partition in CHS address, not used by EFI firmware. */
-	uint8_t StartHead;
-
-	/* Start of partition in CHS address, not used by EFI firmware. */
-	uint8_t StartSector;
-
-	/* Start of partition in CHS address, not used by EFI firmware. */
-	uint8_t StartTrack;
+	RawCHS StartCHS;
 
 	/* OS type. A value of 0xEF defines an EFI system partition.
 	   Other values are reserved for legacy operating systems, and
@@ -207,13 +206,7 @@
 	uint8_t OSType;
 
 	/* End of partition in CHS address, not used by EFI firmware. */
-	uint8_t EndHead;
-
-	/* End of partition in CHS address, not used by EFI firmware. */
-	uint8_t EndSector;
-
-	/* End of partition in CHS address, not used by EFI firmware. */
-	uint8_t EndTrack;
+	RawCHS EndCHS;
 
 	/* Starting LBA address of the partition on the disk. Used by
 	   EFI firmware to define the start of the partition. */
@@ -936,25 +929,25 @@
 	return 0;
 }
 
+extern void sector_to_chs (const PedDevice* dev, void* bios_geom, PedSector sector, RawCHS* chs);
+
 #ifndef DISCOVER_ONLY
 /* Writes the protective MBR (to keep DOS happy) */
 static int
 _write_pmbr (PedDevice * dev)
 {
 	LegacyMBR_t pmbr;
+	PedCHSGeometry bios_geom;
+	bios_geom.heads = 255;
+	bios_geom.sectors = 63;
 
 	memset(&pmbr, 0, sizeof(pmbr));
 	pmbr.Signature = PED_CPU_TO_LE16(MSDOS_MBR_SIGNATURE);
 	pmbr.PartitionRecord[0].OSType      = EFI_PMBR_OSTYPE_EFI;
-	pmbr.PartitionRecord[0].StartSector = 1;
-	pmbr.PartitionRecord[0].EndHead     = 0xFE;
-	pmbr.PartitionRecord[0].EndSector   = 0xFF;
-	pmbr.PartitionRecord[0].EndTrack    = 0xFF;
+	sector_to_chs (dev, &bios_geom, 1, &pmbr.PartitionRecord[0].StartCHS);
+	sector_to_chs (dev, &bios_geom, 34 - 1, &pmbr.PartitionRecord[0].EndCHS);
 	pmbr.PartitionRecord[0].StartingLBA = PED_CPU_TO_LE32(1);
-	if ((dev->length - 1ULL) > 0xFFFFFFFFULL) 
-		pmbr.PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32(0xFFFFFFFF);
-	else
-		pmbr.PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32(dev->length - 1UL);
+	pmbr.PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32(33);
 
 	return ped_device_write (dev, &pmbr, GPT_PMBR_LBA, GPT_PMBR_SECTORS);
 }
@@ -1004,9 +997,10 @@
 }
 
 static void
-_partition_generate_part_entry (PedPartition* part, GuidPartitionEntry_t* pte)
+_partition_generate_part_entry (PedPartition* part, GuidPartitionEntry_t* ptes, int num)
 {
 	GPTPartitionData* gpt_part_data = part->disk_specific;
+	GuidPartitionEntry_t* pte = &ptes[num];
 	unsigned int i;
 
 	PED_ASSERT (gpt_part_data != NULL, return);
@@ -1024,6 +1018,23 @@
 		pte->PartitionName[i]
 			= (efi_char16_t) PED_CPU_TO_LE16(
 				(uint16_t) gpt_part_data->name[i]);
+
+	/* Don't use partition 0, as it corresponds to GPT metadata.  */
+	num++;
+	if (num < 4 && (part->geom.end - 1ULL) <= 0xFFFFFFFFULL) {
+		LegacyMBR_t pmbr;
+		PedCHSGeometry bios_geom;
+		bios_geom.heads = 255;
+		bios_geom.sectors = 63;
+
+		ped_device_read (part->disk->dev, &pmbr, GPT_PMBR_LBA, GPT_PMBR_SECTORS);
+		pmbr.PartitionRecord[num].OSType = 0x0c;
+		sector_to_chs (part->disk->dev, &bios_geom, part->geom.start, &pmbr.PartitionRecord[num].StartCHS);
+		sector_to_chs (part->disk->dev, &bios_geom, part->geom.end - 1, &pmbr.PartitionRecord[num].EndCHS);
+		pmbr.PartitionRecord[num].StartingLBA = PED_CPU_TO_LE32(part->geom.start);
+		pmbr.PartitionRecord[num].SizeInLBA = PED_CPU_TO_LE32(part->geom.end - part->geom.start);
+		ped_device_write (part->disk->dev, &pmbr, GPT_PMBR_LBA, GPT_PMBR_SECTORS);
+	}
 }
 
 static int
@@ -1041,6 +1052,10 @@
 	PED_ASSERT (disk->dev != NULL, goto error);
 	PED_ASSERT (disk->disk_specific != NULL, goto error);
 
+	/* Write protective MBR */
+	if (!_write_pmbr (disk->dev))
+		goto error_free_ptes;
+
 	gpt_disk_data = disk->disk_specific;
 
 	ptes_size = sizeof (GuidPartitionEntry_t) * gpt_disk_data->entry_count;
@@ -1052,15 +1067,11 @@
 	     part = ped_disk_next_partition (disk, part)) {
 		if (part->type != 0)
 			continue;
-		_partition_generate_part_entry (part, &ptes[part->num - 1]);
+		_partition_generate_part_entry (part, ptes, part->num - 1);
 	}
 
 	ptes_crc = efi_crc32 (ptes, ptes_size);
 
-	/* Write protective MBR */
-	if (!_write_pmbr (disk->dev))
-		goto error_free_ptes;
-
 	/* Write PTH and PTEs */
 	_generate_header (disk, 0, ptes_crc, &gpt);
         pth_raw = pth_get_raw (disk->dev, gpt);
_______________________________________________
parted-devel mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/parted-devel

Reply via email to