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