2 libparted - a library for manipulating disk partitions
4 original version by Matt Domsch <Matt_Domsch@dell.com>
5 Disclaimed into the Public Domain
7 Portions Copyright (C) 2001-2003, 2005-2011 Free Software Foundation, Inc.
9 EFI GUID Partition Table handling
10 Per Intel EFI Specification v1.02
11 http://developer.intel.com/technology/efi/efi.htm
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 3 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 #include <parted/parted.h>
30 #include <parted/debug.h>
31 #include <parted/endian.h>
32 #include <parted/crc32.h>
35 #include <sys/types.h>
36 #include <sys/ioctl.h>
39 #include <uuid/uuid.h>
49 # define _(String) gettext (String)
51 # define _(String) (String)
52 #endif /* ENABLE_NLS */
54 #define EFI_PMBR_OSTYPE_EFI 0xEE
55 #define MSDOS_MBR_SIGNATURE 0xaa55
57 #define GPT_HEADER_SIGNATURE 0x5452415020494645LL
59 /* NOTE: the document that describes revision 1.00 is labelled "version 1.02",
60 * so some implementors got confused...
62 #define GPT_HEADER_REVISION_V1_02 0x00010200
63 #define GPT_HEADER_REVISION_V1_00 0x00010000
64 #define GPT_HEADER_REVISION_V0_99 0x00009900
66 typedef uint16_t efi_char16_t; /* UNICODE character */
67 typedef struct _GuidPartitionTableHeader_t GuidPartitionTableHeader_t;
68 typedef struct _GuidPartitionEntryAttributes_t GuidPartitionEntryAttributes_t;
69 typedef struct _GuidPartitionEntry_t GuidPartitionEntry_t;
70 typedef struct _PartitionRecord_t PartitionRecord_t;
71 typedef struct _LegacyMBR_t LegacyMBR_t;
72 typedef struct _GPTDiskData GPTDiskData;
79 uint16_t time_hi_and_version;
80 uint8_t clock_seq_hi_and_reserved;
81 uint8_t clock_seq_low;
83 } /* __attribute__ ((packed)) */ efi_guid_t;
84 /* commented out "__attribute__ ((packed))" to work around gcc bug (fixed
85 * in gcc3.1): __attribute__ ((packed)) breaks addressing on initialized
86 * data. It turns out we don't need it in this case, so it doesn't break
90 #define UNUSED_ENTRY_GUID \
91 ((efi_guid_t) { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, \
92 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }})
93 #define PARTITION_SYSTEM_GUID \
94 ((efi_guid_t) { PED_CPU_TO_LE32 (0xC12A7328), PED_CPU_TO_LE16 (0xF81F), \
95 PED_CPU_TO_LE16 (0x11d2), 0xBA, 0x4B, \
96 { 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B }})
97 #define PARTITION_BIOS_GRUB_GUID \
98 ((efi_guid_t) { PED_CPU_TO_LE32 (0x21686148), PED_CPU_TO_LE16 (0x6449), \
99 PED_CPU_TO_LE16 (0x6E6f), 0x74, 0x4E, \
100 { 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 }})
101 #define LEGACY_MBR_PARTITION_GUID \
102 ((efi_guid_t) { PED_CPU_TO_LE32 (0x024DEE41), PED_CPU_TO_LE16 (0x33E7), \
103 PED_CPU_TO_LE16 (0x11d3, 0x9D, 0x69, \
104 { 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F }})
105 #define PARTITION_MSFT_RESERVED_GUID \
106 ((efi_guid_t) { PED_CPU_TO_LE32 (0xE3C9E316), PED_CPU_TO_LE16 (0x0B5C), \
107 PED_CPU_TO_LE16 (0x4DB8), 0x81, 0x7D, \
108 { 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE }})
109 #define PARTITION_MSFT_RECOVERY \
110 ((efi_guid_t) { PED_CPU_TO_LE32 (0xDE94BBA4), PED_CPU_TO_LE16 (0x06D1), \
111 PED_CPU_TO_LE16 (0x4D40), 0xA1, 0x6A, \
112 { 0xBF, 0xD5, 0x01, 0x79, 0xD6, 0xAC }})
113 #define PARTITION_BASIC_DATA_GUID \
114 ((efi_guid_t) { PED_CPU_TO_LE32 (0xEBD0A0A2), PED_CPU_TO_LE16 (0xB9E5), \
115 PED_CPU_TO_LE16 (0x4433), 0x87, 0xC0, \
116 { 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }})
117 #define PARTITION_RAID_GUID \
118 ((efi_guid_t) { PED_CPU_TO_LE32 (0xa19d880f), PED_CPU_TO_LE16 (0x05fc), \
119 PED_CPU_TO_LE16 (0x4d3b), 0xa0, 0x06, \
120 { 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e }})
121 #define PARTITION_SWAP_GUID \
122 ((efi_guid_t) { PED_CPU_TO_LE32 (0x0657fd6d), PED_CPU_TO_LE16 (0xa4ab), \
123 PED_CPU_TO_LE16 (0x43c4), 0x84, 0xe5, \
124 { 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f }})
125 #define PARTITION_LVM_GUID \
126 ((efi_guid_t) { PED_CPU_TO_LE32 (0xe6d6d379), PED_CPU_TO_LE16 (0xf507), \
127 PED_CPU_TO_LE16 (0x44c2), 0xa2, 0x3c, \
128 { 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28 }})
129 #define PARTITION_RESERVED_GUID \
130 ((efi_guid_t) { PED_CPU_TO_LE32 (0x8da63339), PED_CPU_TO_LE16 (0x0007), \
131 PED_CPU_TO_LE16 (0x60c0), 0xc4, 0x36, \
132 { 0x08, 0x3a, 0xc8, 0x23, 0x09, 0x08 }})
133 #define PARTITION_HPSERVICE_GUID \
134 ((efi_guid_t) { PED_CPU_TO_LE32 (0xe2a1e728), PED_CPU_TO_LE16 (0x32e3), \
135 PED_CPU_TO_LE16 (0x11d6), 0xa6, 0x82, \
136 { 0x7b, 0x03, 0xa0, 0x00, 0x00, 0x00 }})
137 #define PARTITION_APPLE_HFS_GUID \
138 ((efi_guid_t) { PED_CPU_TO_LE32 (0x48465300), PED_CPU_TO_LE16 (0x0000), \
139 PED_CPU_TO_LE16 (0x11AA), 0xaa, 0x11, \
140 { 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC }})
141 #define PARTITION_APPLE_TV_RECOVERY_GUID \
142 ((efi_guid_t) { PED_CPU_TO_LE32 (0x5265636F), PED_CPU_TO_LE16 (0x7665), \
143 PED_CPU_TO_LE16 (0x11AA), 0xaa, 0x11, \
144 { 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC }})
146 struct __attribute__ ((packed)) _GuidPartitionTableHeader_t
151 uint32_t HeaderCRC32;
154 uint64_t AlternateLBA;
155 uint64_t FirstUsableLBA;
156 uint64_t LastUsableLBA;
158 uint64_t PartitionEntryLBA;
159 uint32_t NumberOfPartitionEntries;
160 uint32_t SizeOfPartitionEntry;
161 uint32_t PartitionEntryArrayCRC32;
165 struct __attribute__ ((packed)) _GuidPartitionEntryAttributes_t
167 #ifdef __GNUC__ /* XXX narrow this down to !TinyCC */
168 uint64_t RequiredToFunction:1;
169 uint64_t NoBlockIOProtocol:1;
170 uint64_t LegacyBIOSBootable:1;
171 uint64_t Reserved:45;
172 uint64_t GuidSpecific:16;
174 # warning "Using crippled partition entry type"
175 uint32_t RequiredToFunction:1;
176 uint32_t NoBlockIOProtocol:1;
177 uint32_t LegacyBIOSBootable:1;
178 uint32_t Reserved:30;
180 uint32_t GuidSpecific:16;
184 struct __attribute__ ((packed)) _GuidPartitionEntry_t
186 efi_guid_t PartitionTypeGuid;
187 efi_guid_t UniquePartitionGuid;
188 uint64_t StartingLBA;
190 GuidPartitionEntryAttributes_t Attributes;
191 efi_char16_t PartitionName[72 / sizeof (efi_char16_t)];
194 #define GPT_PMBR_LBA 0
195 #define GPT_PMBR_SECTORS 1
196 #define GPT_PRIMARY_HEADER_LBA 1
197 #define GPT_HEADER_SECTORS 1
198 #define GPT_PRIMARY_PART_TABLE_LBA 2
201 These values are only defaults. The actual on-disk structures
202 may define different sizes, so use those unless creating a new GPT disk!
205 #define GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE 16384
207 /* Number of actual partition entries should be calculated as: */
208 #define GPT_DEFAULT_PARTITION_ENTRIES \
209 (GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / \
210 sizeof(GuidPartitionEntry_t))
212 struct __attribute__ ((packed)) _PartitionRecord_t
214 /* Not used by EFI firmware. Set to 0x80 to indicate that this
215 is the bootable legacy partition. */
216 uint8_t BootIndicator;
218 /* Start of partition in CHS address, not used by EFI firmware. */
221 /* Start of partition in CHS address, not used by EFI firmware. */
224 /* Start of partition in CHS address, not used by EFI firmware. */
227 /* OS type. A value of 0xEF defines an EFI system partition.
228 Other values are reserved for legacy operating systems, and
229 allocated independently of the EFI specification. */
232 /* End of partition in CHS address, not used by EFI firmware. */
235 /* End of partition in CHS address, not used by EFI firmware. */
238 /* End of partition in CHS address, not used by EFI firmware. */
241 /* Starting LBA address of the partition on the disk. Used by
242 EFI firmware to define the start of the partition. */
243 uint32_t StartingLBA;
245 /* Size of partition in LBA. Used by EFI firmware to determine
246 the size of the partition. */
250 /* Protected Master Boot Record & Legacy MBR share same structure */
251 /* Needs to be packed because the u16s force misalignment. */
252 struct __attribute__ ((packed)) _LegacyMBR_t
254 uint8_t BootCode[440];
255 uint32_t UniqueMBRSignature;
257 PartitionRecord_t PartitionRecord[4];
261 /* uses libparted's disk_specific field in PedDisk, to store our info */
262 struct __attribute__ ((packed)) _GPTDiskData
264 PedGeometry data_area;
269 /* uses libparted's disk_specific field in PedPartition, to store our info */
270 typedef struct _GPTPartitionData
287 static PedDiskType gpt_disk_type;
289 static inline uint32_t
290 pth_get_size (const PedDevice *dev)
292 return GPT_HEADER_SECTORS * dev->sector_size;
295 static inline uint32_t
296 pth_get_size_static (const PedDevice *dev)
298 return sizeof (GuidPartitionTableHeader_t) - sizeof (uint8_t *);
301 static inline uint32_t
302 pth_get_size_rsv2 (const PedDevice *dev)
304 return pth_get_size (dev) - pth_get_size_static (dev);
307 static GuidPartitionTableHeader_t *
308 pth_new (const PedDevice *dev)
310 GuidPartitionTableHeader_t *pth =
311 ped_malloc (sizeof (GuidPartitionTableHeader_t) + sizeof (uint8_t));
313 pth->Reserved2 = ped_malloc (pth_get_size_rsv2 (dev));
318 static GuidPartitionTableHeader_t *
319 pth_new_zeroed (const PedDevice *dev)
321 GuidPartitionTableHeader_t *pth = pth_new (dev);
323 memset (pth, 0, pth_get_size_static (dev));
324 memset (pth->Reserved2, 0, pth_get_size_rsv2 (dev));
329 static GuidPartitionTableHeader_t *
330 pth_new_from_raw (const PedDevice *dev, const uint8_t *pth_raw)
332 GuidPartitionTableHeader_t *pth = pth_new (dev);
334 PED_ASSERT (pth_raw != NULL);
336 memcpy (pth, pth_raw, pth_get_size_static (dev));
337 memcpy (pth->Reserved2, pth_raw + pth_get_size_static (dev),
338 pth_get_size_rsv2 (dev));
344 pth_free (GuidPartitionTableHeader_t *pth)
348 PED_ASSERT (pth->Reserved2 != NULL);
350 free (pth->Reserved2);
355 pth_get_raw (const PedDevice *dev, const GuidPartitionTableHeader_t *pth)
357 PED_ASSERT (pth != NULL);
358 PED_ASSERT (pth->Reserved2 != NULL);
360 int size_static = pth_get_size_static (dev);
361 uint8_t *pth_raw = ped_malloc (pth_get_size (dev));
365 memcpy (pth_raw, pth, size_static);
366 memcpy (pth_raw + size_static, pth->Reserved2, pth_get_size_rsv2 (dev));
372 * swap_uuid_and_efi_guid() - converts between uuid formats
373 * @uuid - uuid_t in either format (converts it to the other)
375 * There are two different representations for Globally Unique Identifiers
378 * The RFC specifies a UUID as a string of 16 bytes, essentially
379 * a big-endian array of char.
380 * Intel, in their EFI Specification, references the same RFC, but
381 * then defines a GUID as a structure of little-endian fields.
382 * Coincidentally, both structures have the same format when unparsed.
384 * When read from disk, EFI GUIDs are in struct of little endian format,
385 * and need to be converted to be treated as uuid_t in memory.
387 * When writing to disk, uuid_ts need to be converted into EFI GUIDs.
392 swap_uuid_and_efi_guid (uuid_t uuid)
394 efi_guid_t *guid = (efi_guid_t *) uuid;
396 PED_ASSERT (uuid != NULL);
397 guid->time_low = PED_SWAP32 (guid->time_low);
398 guid->time_mid = PED_SWAP16 (guid->time_mid);
399 guid->time_hi_and_version = PED_SWAP16 (guid->time_hi_and_version);
402 /* returns the EFI-style CRC32 value for buf
403 * This function uses the crc32 function by Gary S. Brown,
404 * but seeds the function with ~0, and xor's with ~0 at the end.
406 static inline uint32_t
407 efi_crc32 (const void *buf, unsigned long len)
409 return (__efi_crc32 (buf, len, ~0L) ^ ~0L);
412 /* Compute the crc32 checksum of the partition table header
413 and store it in *CRC32. Return 0 upon success. Return 1
414 upon failure to allocate space. */
416 pth_crc32 (const PedDevice *dev, const GuidPartitionTableHeader_t *pth,
419 PED_ASSERT (dev != NULL);
420 PED_ASSERT (pth != NULL);
422 uint8_t *pth_raw = pth_get_raw (dev, pth);
426 *crc32 = efi_crc32 (pth_raw, PED_LE32_TO_CPU (pth->HeaderSize));
433 guid_cmp (efi_guid_t left, efi_guid_t right)
435 return memcmp (&left, &right, sizeof (efi_guid_t));
438 /* checks if 'mbr' is a protective MBR partition table */
440 _pmbr_is_valid (const LegacyMBR_t *mbr)
444 PED_ASSERT (mbr != NULL);
446 if (mbr->Signature != PED_CPU_TO_LE16 (MSDOS_MBR_SIGNATURE))
448 for (i = 0; i < 4; i++)
450 if (mbr->PartitionRecord[i].OSType == EFI_PMBR_OSTYPE_EFI)
457 gpt_probe (const PedDevice *dev)
459 GuidPartitionTableHeader_t *gpt = NULL;
460 int gpt_sig_found = 0;
462 PED_ASSERT (dev != NULL);
464 if (dev->length <= 1)
467 void *pth_raw = ped_malloc (pth_get_size (dev));
468 if (ped_device_read (dev, pth_raw, 1, GPT_HEADER_SECTORS)
469 || ped_device_read (dev, pth_raw, dev->length - 1, GPT_HEADER_SECTORS))
471 gpt = pth_new_from_raw (dev, pth_raw);
472 if (gpt->Signature == PED_CPU_TO_LE64 (GPT_HEADER_SIGNATURE))
484 if (!ptt_read_sector (dev, 0, &label))
488 if (!_pmbr_is_valid ((const LegacyMBR_t *) label))
490 int ex_status = ped_exception_throw
491 (PED_EXCEPTION_WARNING,
492 PED_EXCEPTION_YES_NO,
493 _("%s contains GPT signatures, indicating that it has "
494 "a GPT table. However, it does not have a valid "
495 "fake msdos partition table, as it should. Perhaps "
496 "it was corrupted -- possibly by a program that "
497 "doesn't understand GPT partition tables. Or "
498 "perhaps you deleted the GPT table, and are now "
499 "using an msdos partition table. Is this a GPT "
502 if (ex_status == PED_EXCEPTION_NO)
511 gpt_alloc (const PedDevice *dev)
514 GPTDiskData *gpt_disk_data;
515 PedSector data_start, data_end;
517 disk = _ped_disk_alloc ((PedDevice *) dev, &gpt_disk_type);
521 data_start = 2 + GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / dev->sector_size;
522 data_end = dev->length - 2
523 - GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / dev->sector_size;
525 /* If the device is too small to have room for data, reject it. */
526 if (data_end <= data_start)
527 goto error_free_disk;
529 disk->disk_specific = gpt_disk_data = ped_malloc (sizeof (GPTDiskData));
530 if (!disk->disk_specific)
531 goto error_free_disk;
533 ped_geometry_init (&gpt_disk_data->data_area, dev, data_start,
534 data_end - data_start + 1);
535 gpt_disk_data->entry_count = GPT_DEFAULT_PARTITION_ENTRIES;
536 uuid_generate ((unsigned char *) &gpt_disk_data->uuid);
537 swap_uuid_and_efi_guid ((unsigned char *) (&gpt_disk_data->uuid));
547 gpt_duplicate (const PedDisk *disk)
550 GPTDiskData *new_disk_data;
551 GPTDiskData *old_disk_data;
553 new_disk = ped_disk_new_fresh (disk->dev, &gpt_disk_type);
557 old_disk_data = disk->disk_specific;
558 new_disk_data = new_disk->disk_specific;
560 ped_geometry_init (&new_disk_data->data_area, disk->dev,
561 old_disk_data->data_area.start,
562 old_disk_data->data_area.length);
563 new_disk_data->entry_count = old_disk_data->entry_count;
564 new_disk_data->uuid = old_disk_data->uuid;
569 gpt_free (PedDisk *disk)
571 ped_disk_delete_all (disk);
572 free (disk->disk_specific);
573 _ped_disk_free (disk);
576 /* Given GUID Partition table header, GPT, read its partition array
577 entries from DISK into malloc'd storage. Set *PTES_BYTES to the
578 number of bytes required. Upon success, return a pointer to the
579 resulting buffer. Otherwise, set errno and return NULL. */
581 gpt_read_PE_array (PedDisk const *disk, GuidPartitionTableHeader_t const *gpt,
584 uint32_t p_ent_size = PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry);
585 *ptes_bytes = p_ent_size * PED_LE32_TO_CPU(gpt->NumberOfPartitionEntries);
586 size_t ptes_sectors = ped_div_round_up (*ptes_bytes,
587 disk->dev->sector_size);
589 if (xalloc_oversized (ptes_sectors, disk->dev->sector_size))
594 void *ptes = ped_malloc (ptes_sectors * disk->dev->sector_size);
598 if (!ped_device_read (disk->dev, ptes,
599 PED_LE64_TO_CPU (gpt->PartitionEntryLBA), ptes_sectors))
601 int saved_errno = errno;
611 check_PE_array_CRC (PedDisk const *disk,
612 GuidPartitionTableHeader_t const *gpt, bool *valid)
615 void *ptes = gpt_read_PE_array (disk, gpt, &ptes_bytes);
619 uint32_t ptes_crc = efi_crc32 (ptes, ptes_bytes);
620 *valid = (ptes_crc == PED_LE32_TO_CPU (gpt->PartitionEntryArrayCRC32));
626 _header_is_valid (PedDisk const *disk, GuidPartitionTableHeader_t *gpt,
629 uint32_t crc, origcrc;
630 PedDevice const *dev = disk->dev;
632 if (PED_LE64_TO_CPU (gpt->Signature) != GPT_HEADER_SIGNATURE)
635 * "While the GUID Partition Table Header's size may increase
636 * in the future it cannot span more than one block on the
637 * device." EFI Specification, version 1.10, 11.2.2.1
639 if (PED_LE32_TO_CPU (gpt->HeaderSize) < pth_get_size_static (dev)
640 || PED_LE32_TO_CPU (gpt->HeaderSize) > dev->sector_size)
643 /* The SizeOfPartitionEntry must be a multiple of 8 and
644 no smaller than the size of the PartitionEntry structure.
645 We also require that it be no larger than 1/16th of UINT32_MAX,
646 as an additional sanity check. */
647 uint32_t pe_size = PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry);
649 || ! (sizeof (GuidPartitionEntry_t) <= pe_size
650 && pe_size <= (UINT32_MAX >> 4)))
653 if (PED_LE64_TO_CPU (gpt->MyLBA) != my_lba)
656 PedSector alt_lba = PED_LE64_TO_CPU (gpt->AlternateLBA);
657 /* The backup table's AlternateLBA must be 1. */
658 if (my_lba != 1 && alt_lba != 1)
661 /* The alt_lba must never be the same as my_lba. */
662 if (alt_lba == my_lba)
666 if (check_PE_array_CRC (disk, gpt, &crc_match) != 0 || !crc_match)
669 PedSector first_usable = PED_LE64_TO_CPU (gpt->FirstUsableLBA);
670 if (first_usable < 3)
673 PedSector last_usable = PED_LE64_TO_CPU (gpt->LastUsableLBA);
674 if (disk->dev->length < last_usable)
677 origcrc = gpt->HeaderCRC32;
678 gpt->HeaderCRC32 = 0;
679 if (pth_crc32 (dev, gpt, &crc) != 0)
681 gpt->HeaderCRC32 = origcrc;
683 return crc == PED_LE32_TO_CPU (origcrc);
687 _parse_header (PedDisk *disk, const GuidPartitionTableHeader_t *gpt,
690 GPTDiskData *gpt_disk_data = disk->disk_specific;
691 PedSector first_usable;
692 PedSector last_usable;
693 PedSector last_usable_if_grown, last_usable_min_default;
694 static int asked_already;
696 #ifndef DISCOVER_ONLY
697 if (PED_LE32_TO_CPU (gpt->Revision) > GPT_HEADER_REVISION_V1_02)
699 if (ped_exception_throw
700 (PED_EXCEPTION_WARNING,
701 PED_EXCEPTION_IGNORE_CANCEL,
702 _("The format of the GPT partition table is version "
703 "%x, which is newer than what Parted can "
704 "recognise. Please report this!"),
705 PED_LE32_TO_CPU (gpt->Revision)) != PED_EXCEPTION_IGNORE)
710 first_usable = PED_LE64_TO_CPU (gpt->FirstUsableLBA);
711 last_usable = PED_LE64_TO_CPU (gpt->LastUsableLBA);
713 /* Need to check whether the volume has grown, the LastUsableLBA is
714 normally set to disk->dev->length - 2 - ptes_size (at least for parted
715 created volumes), where ptes_size is the number of entries *
716 size of each entry / sector size or 16k / sector size, whatever the greater.
717 If the volume has grown, offer the user the chance to use the new
718 space or continue with the current usable area. Only ask once per
719 parted invocation. */
722 = (disk->dev->length - 2 -
723 ((PedSector) (PED_LE32_TO_CPU (gpt->NumberOfPartitionEntries)) *
724 (PedSector) (PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry)) /
725 disk->dev->sector_size));
727 last_usable_min_default = disk->dev->length - 2 -
728 GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / disk->dev->sector_size;
730 if (last_usable_if_grown > last_usable_min_default)
732 last_usable_if_grown = last_usable_min_default;
735 PED_ASSERT (last_usable > first_usable);
736 PED_ASSERT (last_usable <= disk->dev->length);
738 PED_ASSERT (last_usable_if_grown > first_usable);
739 PED_ASSERT (last_usable_if_grown <= disk->dev->length);
741 if (!asked_already && last_usable < last_usable_if_grown)
744 PedExceptionOption q;
746 q = ped_exception_throw
747 (PED_EXCEPTION_WARNING,
748 PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE,
749 _("Not all of the space available to %s appears "
750 "to be used, you can fix the GPT to use all of the "
751 "space (an extra %llu blocks) or continue with the "
752 "current setting? "), disk->dev->path,
753 (uint64_t) (last_usable_if_grown - last_usable));
755 if (q == PED_EXCEPTION_FIX)
757 last_usable = last_usable_if_grown;
760 else if (q != PED_EXCEPTION_UNHANDLED)
766 ped_geometry_init (&gpt_disk_data->data_area, disk->dev,
767 first_usable, last_usable - first_usable + 1);
769 gpt_disk_data->entry_count
770 = PED_LE32_TO_CPU (gpt->NumberOfPartitionEntries);
771 PED_ASSERT (gpt_disk_data->entry_count > 0);
772 PED_ASSERT (gpt_disk_data->entry_count <= 8192);
774 gpt_disk_data->uuid = gpt->DiskGUID;
779 static PedPartition *
780 _parse_part_entry (PedDisk *disk, GuidPartitionEntry_t *pte)
783 GPTPartitionData *gpt_part_data;
786 part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
787 PED_LE64_TO_CPU (pte->StartingLBA),
788 PED_LE64_TO_CPU (pte->EndingLBA));
792 gpt_part_data = part->disk_specific;
793 gpt_part_data->type = pte->PartitionTypeGuid;
794 gpt_part_data->uuid = pte->UniquePartitionGuid;
795 for (i = 0; i < 72 / sizeof (efi_char16_t); i++)
796 gpt_part_data->name[i] =
797 (efi_char16_t) PED_LE16_TO_CPU ((uint16_t) pte->PartitionName[i]);
798 gpt_part_data->name[i] = 0;
800 gpt_part_data->lvm = gpt_part_data->raid
801 = gpt_part_data->boot = gpt_part_data->hp_service
802 = gpt_part_data->hidden = gpt_part_data->msftres
803 = gpt_part_data->msftrecv
804 = gpt_part_data->legacy_boot
805 = gpt_part_data->bios_grub = gpt_part_data->atvrecv = 0;
807 if (pte->Attributes.RequiredToFunction & 0x1)
808 gpt_part_data->hidden = 1;
809 if (pte->Attributes.LegacyBIOSBootable & 0x1)
810 gpt_part_data->legacy_boot = 1;
812 if (!guid_cmp (gpt_part_data->type, PARTITION_SYSTEM_GUID))
813 gpt_part_data->boot = 1;
814 else if (!guid_cmp (gpt_part_data->type, PARTITION_BIOS_GRUB_GUID))
815 gpt_part_data->bios_grub = 1;
816 else if (!guid_cmp (gpt_part_data->type, PARTITION_RAID_GUID))
817 gpt_part_data->raid = 1;
818 else if (!guid_cmp (gpt_part_data->type, PARTITION_LVM_GUID))
819 gpt_part_data->lvm = 1;
820 else if (!guid_cmp (gpt_part_data->type, PARTITION_HPSERVICE_GUID))
821 gpt_part_data->hp_service = 1;
822 else if (!guid_cmp (gpt_part_data->type, PARTITION_MSFT_RESERVED_GUID))
823 gpt_part_data->msftres = 1;
824 else if (!guid_cmp (gpt_part_data->type, PARTITION_MSFT_RECOVERY))
825 gpt_part_data->msftrecv = 1;
826 else if (!guid_cmp (gpt_part_data->type, PARTITION_APPLE_TV_RECOVERY_GUID))
827 gpt_part_data->atvrecv = 1;
832 /* Read the primary GPT at sector 1 of DEV.
833 Verify its CRC and that of its partition entry array.
834 If they are valid, read the backup GPT specified by AlternateLBA.
835 If not, read the backup GPT in the last sector of the disk.
836 Return 1 if any read fails.
837 Upon successful verification of the primary GPT, set *PRIMARY_GPT, else NULL.
838 Upon successful verification of the backup GPT, set *BACKUP_GPT, else NULL.
839 If we've set *BACKUP_GPT to non-NULL, set *BACKUP_SECTOR_NUM_P to the sector
840 number in which it was found. */
842 gpt_read_headers (PedDisk const *disk,
843 GuidPartitionTableHeader_t **primary_gpt,
844 GuidPartitionTableHeader_t **backup_gpt,
845 PedSector *backup_sector_num_p)
849 PedDevice const *dev = disk->dev;
852 if (!ptt_read_sector (dev, 1, &s1))
855 GuidPartitionTableHeader_t *t = pth_new_from_raw (dev, s1);
859 GuidPartitionTableHeader_t *pri = t;
861 bool valid_primary = _header_is_valid (disk, pri, 1);
867 PedSector backup_sector_num =
869 ? PED_LE64_TO_CPU (pri->AlternateLBA)
873 if (!ptt_read_sector (dev, backup_sector_num, &s_bak))
875 t = pth_new_from_raw (dev, s_bak);
880 GuidPartitionTableHeader_t *bak = t;
881 if (_header_is_valid (disk, bak, backup_sector_num))
884 *backup_sector_num_p = backup_sector_num;
892 /************************************************************
893 * Intel is changing the EFI Spec. (after v1.02) to say that a
894 * disk is considered to have a GPT label only if the GPT
895 * structures are correct, and the MBR is actually a Protective
896 * MBR (has one 0xEE type partition).
897 * Problem occurs when a GPT-partitioned disk is then
898 * edited with a legacy (non-GPT-aware) application, such as
899 * fdisk (which doesn't generally erase the PGPT or AGPT).
900 * How should such a disk get handled? As a GPT disk (throwing
901 * away the fdisk changes), or as an MSDOS disk (throwing away
902 * the GPT information). Previously, I've taken the GPT-is-right,
903 * MBR is wrong, approach, to stay consistent with the EFI Spec.
904 * Intel disagrees, saying the disk should then be treated
905 * as having a msdos label, not a GPT label. If this is true,
906 * then what's the point of having an AGPT, since if the PGPT
907 * is screwed up, likely the PMBR is too, and the PMBR becomes
908 * a single point of failure.
909 * So, in the Linux kernel, I'm going to test for PMBR, and
910 * warn if it's not there, and treat the disk as MSDOS, with a note
911 * for users to use Parted to "fix up" their disk if they
912 * really want it to be considered GPT.
913 ************************************************************/
915 gpt_read (PedDisk *disk)
917 GPTDiskData *gpt_disk_data = disk->disk_specific;
919 #ifndef DISCOVER_ONLY
923 ped_disk_delete_all (disk);
925 /* motivation: let the user decide about the pmbr... during
926 ped_disk_probe(), they probably didn't get a choice... */
927 if (!gpt_probe (disk->dev))
930 GuidPartitionTableHeader_t *gpt = NULL;
931 GuidPartitionTableHeader_t *primary_gpt;
932 GuidPartitionTableHeader_t *backup_gpt;
933 PedSector backup_sector_num;
934 int read_failure = gpt_read_headers (disk, &primary_gpt, &backup_gpt,
938 /* This includes the case in which there used to be a GPT partition
939 table here, with an alternate LBA that extended beyond the current
940 end-of-device. It's treated as a non-match. */
942 /* Another possibility:
943 The primary header is ok, but backup is corrupt.
944 In the UEFI spec, this means the primary GUID table
945 is officially invalid. */
946 pth_free (backup_gpt);
947 pth_free (primary_gpt);
951 if (primary_gpt && backup_gpt)
953 /* Both are valid. */
954 #ifndef DISCOVER_ONLY
955 if (PED_LE64_TO_CPU (primary_gpt->AlternateLBA) < disk->dev->length - 1)
957 switch (ped_exception_throw
958 (PED_EXCEPTION_ERROR,
959 (PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL
960 | PED_EXCEPTION_IGNORE),
961 _("The backup GPT table is not at the end of the disk, as it "
962 "should be. This might mean that another operating system "
963 "believes the disk is smaller. Fix, by moving the backup "
964 "to the end (and removing the old backup)?")))
966 case PED_EXCEPTION_CANCEL:
968 case PED_EXCEPTION_FIX:
969 ptt_clear_sectors (disk->dev,
970 PED_LE64_TO_CPU (primary_gpt->AlternateLBA), 1);
977 #endif /* !DISCOVER_ONLY */
979 pth_free (backup_gpt);
981 else if (!primary_gpt && !backup_gpt)
983 /* Both are corrupt. */
984 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
985 _("Both the primary and backup GPT tables "
986 "are corrupt. Try making a fresh table, "
987 "and using Parted's rescue feature to "
988 "recover partitions."));
991 else if (primary_gpt && !backup_gpt)
993 /* The primary header is ok, but backup is corrupt. */
994 if (ped_exception_throw
995 (PED_EXCEPTION_ERROR, PED_EXCEPTION_OK_CANCEL,
996 _("The backup GPT table is corrupt, but the "
997 "primary appears OK, so that will be used."))
998 == PED_EXCEPTION_CANCEL)
1003 else /* !primary_gpt && backup_gpt */
1005 /* primary GPT corrupt, backup is ok. */
1006 if (ped_exception_throw
1007 (PED_EXCEPTION_ERROR, PED_EXCEPTION_OK_CANCEL,
1008 _("The primary GPT table is corrupt, but the "
1009 "backup appears OK, so that will be used."))
1010 == PED_EXCEPTION_CANCEL)
1011 goto error_free_gpt;
1018 if (!_parse_header (disk, gpt, &write_back))
1019 goto error_free_gpt;
1022 void *ptes = gpt_read_PE_array (disk, gpt, &ptes_bytes);
1024 goto error_free_gpt;
1026 uint32_t ptes_crc = efi_crc32 (ptes, ptes_bytes);
1027 if (ptes_crc != PED_LE32_TO_CPU (gpt->PartitionEntryArrayCRC32))
1030 (PED_EXCEPTION_ERROR,
1031 PED_EXCEPTION_CANCEL,
1032 _("primary partition table array CRC mismatch"));
1033 goto error_free_ptes;
1036 uint32_t p_ent_size = PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry);
1037 for (i = 0; i < gpt_disk_data->entry_count; i++)
1039 GuidPartitionEntry_t *pte
1040 = (GuidPartitionEntry_t *) ((char *) ptes + i * p_ent_size);
1043 if (!guid_cmp (pte->PartitionTypeGuid, UNUSED_ENTRY_GUID))
1046 part = _parse_part_entry (disk, pte);
1048 goto error_delete_all;
1050 part->fs_type = ped_file_system_probe (&part->geom);
1053 PedConstraint *constraint_exact = ped_constraint_exact (&part->geom);
1054 if (!ped_disk_add_partition (disk, part, constraint_exact))
1056 ped_constraint_destroy (constraint_exact);
1057 ped_partition_destroy (part);
1058 goto error_delete_all;
1060 ped_constraint_destroy (constraint_exact);
1064 #ifndef DISCOVER_ONLY
1066 ped_disk_commit_to_dev (disk);
1073 ped_disk_delete_all (disk);
1077 pth_free (primary_gpt);
1078 pth_free (backup_gpt);
1084 #ifndef DISCOVER_ONLY
1085 /* Write the protective MBR (to keep DOS happy) */
1087 _write_pmbr (PedDevice *dev)
1089 /* The UEFI spec is not clear about what to do with the following
1090 elements of the Protective MBR (pmbr): BootCode (0-440B),
1091 UniqueMBRSignature (440B-444B) and Unknown (444B-446B).
1092 With this in mind, we try not to modify these elements. */
1094 if (!ptt_read_sector (dev, 0, &s0))
1096 LegacyMBR_t *pmbr = s0;
1098 /* Zero out the legacy partitions. */
1099 memset (pmbr->PartitionRecord, 0, sizeof pmbr->PartitionRecord);
1101 pmbr->Signature = PED_CPU_TO_LE16 (MSDOS_MBR_SIGNATURE);
1102 pmbr->PartitionRecord[0].OSType = EFI_PMBR_OSTYPE_EFI;
1103 pmbr->PartitionRecord[0].StartSector = 1;
1104 pmbr->PartitionRecord[0].EndHead = 0xFE;
1105 pmbr->PartitionRecord[0].EndSector = 0xFF;
1106 pmbr->PartitionRecord[0].EndTrack = 0xFF;
1107 pmbr->PartitionRecord[0].StartingLBA = PED_CPU_TO_LE32 (1);
1108 if ((dev->length - 1ULL) > 0xFFFFFFFFULL)
1109 pmbr->PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32 (0xFFFFFFFF);
1111 pmbr->PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32 (dev->length - 1UL);
1113 int write_ok = ped_device_write (dev, pmbr, GPT_PMBR_LBA,
1120 _generate_header (const PedDisk *disk, int alternate, uint32_t ptes_crc,
1121 GuidPartitionTableHeader_t **gpt_p)
1123 GPTDiskData *gpt_disk_data = disk->disk_specific;
1124 GuidPartitionTableHeader_t *gpt;
1126 *gpt_p = pth_new_zeroed (disk->dev);
1130 gpt->Signature = PED_CPU_TO_LE64 (GPT_HEADER_SIGNATURE);
1131 gpt->Revision = PED_CPU_TO_LE32 (GPT_HEADER_REVISION_V1_00);
1134 gpt->HeaderSize = PED_CPU_TO_LE32 (pth_get_size_static (disk->dev));
1135 gpt->HeaderCRC32 = 0;
1140 size_t ss = disk->dev->sector_size;
1141 PedSector ptes_bytes = (gpt_disk_data->entry_count
1142 * sizeof (GuidPartitionEntry_t));
1143 PedSector ptes_sectors = (ptes_bytes + ss - 1) / ss;
1145 gpt->MyLBA = PED_CPU_TO_LE64 (disk->dev->length - 1);
1146 gpt->AlternateLBA = PED_CPU_TO_LE64 (1);
1147 gpt->PartitionEntryLBA
1148 = PED_CPU_TO_LE64 (disk->dev->length - 1 - ptes_sectors);
1152 gpt->MyLBA = PED_CPU_TO_LE64 (1);
1153 gpt->AlternateLBA = PED_CPU_TO_LE64 (disk->dev->length - 1);
1154 gpt->PartitionEntryLBA = PED_CPU_TO_LE64 (2);
1157 gpt->FirstUsableLBA = PED_CPU_TO_LE64 (gpt_disk_data->data_area.start);
1158 gpt->LastUsableLBA = PED_CPU_TO_LE64 (gpt_disk_data->data_area.end);
1159 gpt->DiskGUID = gpt_disk_data->uuid;
1160 gpt->NumberOfPartitionEntries
1161 = PED_CPU_TO_LE32 (gpt_disk_data->entry_count);
1162 gpt->SizeOfPartitionEntry = PED_CPU_TO_LE32 (sizeof (GuidPartitionEntry_t));
1163 gpt->PartitionEntryArrayCRC32 = PED_CPU_TO_LE32 (ptes_crc);
1166 if (pth_crc32 (disk->dev, gpt, &crc) != 0)
1169 gpt->HeaderCRC32 = PED_CPU_TO_LE32 (crc);
1174 _partition_generate_part_entry (PedPartition *part, GuidPartitionEntry_t *pte)
1176 GPTPartitionData *gpt_part_data = part->disk_specific;
1179 PED_ASSERT (gpt_part_data != NULL);
1181 pte->PartitionTypeGuid = gpt_part_data->type;
1182 pte->UniquePartitionGuid = gpt_part_data->uuid;
1183 pte->StartingLBA = PED_CPU_TO_LE64 (part->geom.start);
1184 pte->EndingLBA = PED_CPU_TO_LE64 (part->geom.end);
1185 memset (&pte->Attributes, 0, sizeof (GuidPartitionEntryAttributes_t));
1187 if (gpt_part_data->hidden)
1188 pte->Attributes.RequiredToFunction = 1;
1189 if (gpt_part_data->legacy_boot)
1190 pte->Attributes.LegacyBIOSBootable = 1;
1192 for (i = 0; i < 72 / sizeof (efi_char16_t); i++)
1193 pte->PartitionName[i]
1194 = (efi_char16_t) PED_CPU_TO_LE16 ((uint16_t) gpt_part_data->name[i]);
1198 gpt_write (const PedDisk *disk)
1200 GPTDiskData *gpt_disk_data;
1201 GuidPartitionEntry_t *ptes;
1204 GuidPartitionTableHeader_t *gpt;
1208 PED_ASSERT (disk != NULL);
1209 PED_ASSERT (disk->dev != NULL);
1210 PED_ASSERT (disk->disk_specific != NULL);
1212 gpt_disk_data = disk->disk_specific;
1214 ptes_size = sizeof (GuidPartitionEntry_t) * gpt_disk_data->entry_count;
1215 ptes = (GuidPartitionEntry_t *) ped_malloc (ptes_size);
1218 memset (ptes, 0, ptes_size);
1219 for (part = ped_disk_next_partition (disk, NULL); part;
1220 part = ped_disk_next_partition (disk, part))
1222 if (part->type != 0)
1224 _partition_generate_part_entry (part, &ptes[part->num - 1]);
1227 ptes_crc = efi_crc32 (ptes, ptes_size);
1229 /* Write protective MBR */
1230 if (!_write_pmbr (disk->dev))
1231 goto error_free_ptes;
1233 /* Write PTH and PTEs */
1234 /* FIXME: Caution: this code is nearly identical to what's just below. */
1235 if (_generate_header (disk, 0, ptes_crc, &gpt) != 0)
1236 goto error_free_ptes;
1237 pth_raw = pth_get_raw (disk->dev, gpt);
1239 if (pth_raw == NULL)
1240 goto error_free_ptes;
1241 int write_ok = ped_device_write (disk->dev, pth_raw, 1, 1);
1244 goto error_free_ptes;
1245 if (!ped_device_write (disk->dev, ptes, 2,
1246 ptes_size / disk->dev->sector_size))
1247 goto error_free_ptes;
1249 /* Write Alternate PTH & PTEs */
1250 /* FIXME: Caution: this code is nearly identical to what's just above. */
1251 if (_generate_header (disk, 1, ptes_crc, &gpt) != 0)
1252 goto error_free_ptes;
1253 pth_raw = pth_get_raw (disk->dev, gpt);
1255 if (pth_raw == NULL)
1256 goto error_free_ptes;
1257 write_ok = ped_device_write (disk->dev, pth_raw, disk->dev->length - 1, 1);
1260 goto error_free_ptes;
1261 if (!ped_device_write (disk->dev, ptes,
1262 disk->dev->length - 1 -
1263 ptes_size / disk->dev->sector_size,
1264 ptes_size / disk->dev->sector_size))
1265 goto error_free_ptes;
1268 return ped_device_sync (disk->dev);
1275 #endif /* !DISCOVER_ONLY */
1278 add_metadata_part (PedDisk *disk, PedSector start, PedSector length)
1281 PedConstraint *constraint_exact;
1282 PED_ASSERT (disk != NULL);
1284 part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
1285 start, start + length - 1);
1289 constraint_exact = ped_constraint_exact (&part->geom);
1290 if (!ped_disk_add_partition (disk, part, constraint_exact))
1291 goto error_destroy_constraint;
1292 ped_constraint_destroy (constraint_exact);
1295 error_destroy_constraint:
1296 ped_constraint_destroy (constraint_exact);
1297 ped_partition_destroy (part);
1302 static PedPartition *
1303 gpt_partition_new (const PedDisk *disk,
1304 PedPartitionType part_type,
1305 const PedFileSystemType *fs_type, PedSector start,
1309 GPTPartitionData *gpt_part_data;
1311 part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
1318 gpt_part_data = part->disk_specific =
1319 ped_malloc (sizeof (GPTPartitionData));
1321 goto error_free_part;
1323 gpt_part_data->type = PARTITION_BASIC_DATA_GUID;
1324 gpt_part_data->lvm = 0;
1325 gpt_part_data->raid = 0;
1326 gpt_part_data->boot = 0;
1327 gpt_part_data->bios_grub = 0;
1328 gpt_part_data->hp_service = 0;
1329 gpt_part_data->hidden = 0;
1330 gpt_part_data->msftres = 0;
1331 gpt_part_data->msftrecv = 0;
1332 gpt_part_data->atvrecv = 0;
1333 gpt_part_data->legacy_boot = 0;
1334 uuid_generate ((unsigned char *) &gpt_part_data->uuid);
1335 swap_uuid_and_efi_guid ((unsigned char *) (&gpt_part_data->uuid));
1336 memset (gpt_part_data->name, 0, sizeof gpt_part_data->name);
1340 _ped_partition_free (part);
1345 static PedPartition *
1346 gpt_partition_duplicate (const PedPartition *part)
1348 PedPartition *result;
1349 GPTPartitionData *part_data = part->disk_specific;
1350 GPTPartitionData *result_data;
1352 result = _ped_partition_alloc (part->disk, part->type, part->fs_type,
1353 part->geom.start, part->geom.end);
1356 result->num = part->num;
1358 if (result->type != 0)
1361 result_data = result->disk_specific =
1362 ped_malloc (sizeof (GPTPartitionData));
1364 goto error_free_part;
1366 *result_data = *part_data;
1370 _ped_partition_free (result);
1376 gpt_partition_destroy (PedPartition *part)
1378 if (part->type == 0)
1380 PED_ASSERT (part->disk_specific != NULL);
1381 free (part->disk_specific);
1384 _ped_partition_free (part);
1388 gpt_partition_set_system (PedPartition *part,
1389 const PedFileSystemType *fs_type)
1391 GPTPartitionData *gpt_part_data = part->disk_specific;
1393 PED_ASSERT (gpt_part_data != NULL);
1395 part->fs_type = fs_type;
1397 if (gpt_part_data->lvm)
1399 gpt_part_data->type = PARTITION_LVM_GUID;
1402 if (gpt_part_data->raid)
1404 gpt_part_data->type = PARTITION_RAID_GUID;
1407 if (gpt_part_data->boot)
1409 gpt_part_data->type = PARTITION_SYSTEM_GUID;
1412 if (gpt_part_data->bios_grub)
1414 gpt_part_data->type = PARTITION_BIOS_GRUB_GUID;
1417 if (gpt_part_data->hp_service)
1419 gpt_part_data->type = PARTITION_HPSERVICE_GUID;
1422 if (gpt_part_data->msftres)
1424 gpt_part_data->type = PARTITION_MSFT_RESERVED_GUID;
1427 if (gpt_part_data->msftrecv)
1429 gpt_part_data->type = PARTITION_MSFT_RECOVERY;
1432 if (gpt_part_data->atvrecv)
1434 gpt_part_data->type = PARTITION_APPLE_TV_RECOVERY_GUID;
1440 if (strncmp (fs_type->name, "fat", 3) == 0
1441 || strcmp (fs_type->name, "ntfs") == 0)
1443 gpt_part_data->type = PARTITION_BASIC_DATA_GUID;
1446 if (strncmp (fs_type->name, "hfs", 3) == 0)
1448 gpt_part_data->type = PARTITION_APPLE_HFS_GUID;
1451 if (strstr (fs_type->name, "swap"))
1453 gpt_part_data->type = PARTITION_SWAP_GUID;
1458 gpt_part_data->type = PARTITION_BASIC_DATA_GUID;
1462 /* Allocate metadata partitions for the GPTH and PTES */
1464 gpt_alloc_metadata (PedDisk *disk)
1466 PedSector gptlength, pteslength = 0;
1467 GPTDiskData *gpt_disk_data;
1469 PED_ASSERT (disk != NULL);
1470 PED_ASSERT (disk->dev != NULL);
1471 PED_ASSERT (disk->disk_specific != NULL);
1472 gpt_disk_data = disk->disk_specific;
1474 gptlength = ped_div_round_up (sizeof (GuidPartitionTableHeader_t),
1475 disk->dev->sector_size);
1476 pteslength = ped_div_round_up (gpt_disk_data->entry_count
1477 * sizeof (GuidPartitionEntry_t),
1478 disk->dev->sector_size);
1480 /* metadata at the start of the disk includes the MBR */
1481 if (!add_metadata_part (disk, GPT_PMBR_LBA,
1482 GPT_PMBR_SECTORS + gptlength + pteslength))
1485 /* metadata at the end of the disk */
1486 if (!add_metadata_part (disk, disk->dev->length - gptlength - pteslength,
1487 gptlength + pteslength))
1493 /* Does nothing, as the read/new/destroy functions maintain part->num */
1495 gpt_partition_enumerate (PedPartition *part)
1497 GPTDiskData *gpt_disk_data = part->disk->disk_specific;
1500 /* never change the partition numbers */
1501 if (part->num != -1)
1504 for (i = 1; i <= gpt_disk_data->entry_count; i++)
1506 if (!ped_disk_get_partition (part->disk, i))
1515 return 0; /* used if debug is disabled */
1519 gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
1521 GPTPartitionData *gpt_part_data;
1522 PED_ASSERT (part != NULL);
1523 PED_ASSERT (part->disk_specific != NULL);
1524 gpt_part_data = part->disk_specific;
1528 case PED_PARTITION_BOOT:
1529 gpt_part_data->boot = state;
1532 = gpt_part_data->lvm
1533 = gpt_part_data->bios_grub
1534 = gpt_part_data->hp_service
1535 = gpt_part_data->msftres
1536 = gpt_part_data->msftrecv
1537 = gpt_part_data->atvrecv = 0;
1538 return gpt_partition_set_system (part, part->fs_type);
1539 case PED_PARTITION_BIOS_GRUB:
1540 gpt_part_data->bios_grub = state;
1543 = gpt_part_data->lvm
1544 = gpt_part_data->boot
1545 = gpt_part_data->hp_service
1546 = gpt_part_data->msftres
1547 = gpt_part_data->msftrecv
1548 = gpt_part_data->atvrecv = 0;
1549 return gpt_partition_set_system (part, part->fs_type);
1550 case PED_PARTITION_RAID:
1551 gpt_part_data->raid = state;
1554 = gpt_part_data->lvm
1555 = gpt_part_data->bios_grub
1556 = gpt_part_data->hp_service
1557 = gpt_part_data->msftres
1558 = gpt_part_data->msftrecv
1559 = gpt_part_data->atvrecv = 0;
1560 return gpt_partition_set_system (part, part->fs_type);
1561 case PED_PARTITION_LVM:
1562 gpt_part_data->lvm = state;
1565 = gpt_part_data->raid
1566 = gpt_part_data->bios_grub
1567 = gpt_part_data->hp_service
1568 = gpt_part_data->msftres
1569 = gpt_part_data->msftrecv
1570 = gpt_part_data->atvrecv = 0;
1571 return gpt_partition_set_system (part, part->fs_type);
1572 case PED_PARTITION_HPSERVICE:
1573 gpt_part_data->hp_service = state;
1576 = gpt_part_data->raid
1577 = gpt_part_data->lvm
1578 = gpt_part_data->bios_grub
1579 = gpt_part_data->msftres
1580 = gpt_part_data->msftrecv
1581 = gpt_part_data->atvrecv = 0;
1582 return gpt_partition_set_system (part, part->fs_type);
1583 case PED_PARTITION_MSFT_RESERVED:
1584 gpt_part_data->msftres = state;
1587 = gpt_part_data->raid
1588 = gpt_part_data->lvm
1589 = gpt_part_data->bios_grub
1590 = gpt_part_data->hp_service
1591 = gpt_part_data->msftrecv
1592 = gpt_part_data->atvrecv = 0;
1593 return gpt_partition_set_system (part, part->fs_type);
1594 case PED_PARTITION_DIAG:
1595 gpt_part_data->msftrecv = state;
1598 = gpt_part_data->raid
1599 = gpt_part_data->lvm
1600 = gpt_part_data->bios_grub
1601 = gpt_part_data->hp_service
1602 = gpt_part_data->msftres
1603 = gpt_part_data->atvrecv = 0;
1604 return gpt_partition_set_system (part, part->fs_type);
1605 case PED_PARTITION_APPLE_TV_RECOVERY:
1606 gpt_part_data->atvrecv = state;
1609 = gpt_part_data->raid
1610 = gpt_part_data->lvm
1611 = gpt_part_data->bios_grub
1612 = gpt_part_data->hp_service
1613 = gpt_part_data->msftres
1614 = gpt_part_data->msftrecv = 0;
1615 return gpt_partition_set_system (part, part->fs_type);
1616 case PED_PARTITION_HIDDEN:
1617 gpt_part_data->hidden = state;
1619 case PED_PARTITION_LEGACY_BOOT:
1620 gpt_part_data->legacy_boot = state;
1622 case PED_PARTITION_SWAP:
1623 case PED_PARTITION_ROOT:
1624 case PED_PARTITION_LBA:
1632 gpt_partition_get_flag (const PedPartition *part, PedPartitionFlag flag)
1634 GPTPartitionData *gpt_part_data;
1635 PED_ASSERT (part->disk_specific != NULL);
1636 gpt_part_data = part->disk_specific;
1640 case PED_PARTITION_RAID:
1641 return gpt_part_data->raid;
1642 case PED_PARTITION_LVM:
1643 return gpt_part_data->lvm;
1644 case PED_PARTITION_BOOT:
1645 return gpt_part_data->boot;
1646 case PED_PARTITION_BIOS_GRUB:
1647 return gpt_part_data->bios_grub;
1648 case PED_PARTITION_HPSERVICE:
1649 return gpt_part_data->hp_service;
1650 case PED_PARTITION_MSFT_RESERVED:
1651 return gpt_part_data->msftres;
1652 case PED_PARTITION_DIAG:
1653 return gpt_part_data->msftrecv;
1654 case PED_PARTITION_APPLE_TV_RECOVERY:
1655 return gpt_part_data->atvrecv;
1656 case PED_PARTITION_HIDDEN:
1657 return gpt_part_data->hidden;
1658 case PED_PARTITION_LEGACY_BOOT:
1659 return gpt_part_data->legacy_boot;
1660 case PED_PARTITION_SWAP:
1661 case PED_PARTITION_LBA:
1662 case PED_PARTITION_ROOT:
1670 gpt_partition_is_flag_available (const PedPartition *part,
1671 PedPartitionFlag flag)
1675 case PED_PARTITION_RAID:
1676 case PED_PARTITION_LVM:
1677 case PED_PARTITION_BOOT:
1678 case PED_PARTITION_BIOS_GRUB:
1679 case PED_PARTITION_HPSERVICE:
1680 case PED_PARTITION_MSFT_RESERVED:
1681 case PED_PARTITION_DIAG:
1682 case PED_PARTITION_APPLE_TV_RECOVERY:
1683 case PED_PARTITION_HIDDEN:
1684 case PED_PARTITION_LEGACY_BOOT:
1686 case PED_PARTITION_SWAP:
1687 case PED_PARTITION_ROOT:
1688 case PED_PARTITION_LBA:
1696 gpt_partition_set_name (PedPartition *part, const char *name)
1698 GPTPartitionData *gpt_part_data = part->disk_specific;
1700 strncpy (gpt_part_data->name, name, 36);
1701 gpt_part_data->name[36] = 0;
1705 gpt_partition_get_name (const PedPartition *part)
1707 GPTPartitionData *gpt_part_data = part->disk_specific;
1708 return gpt_part_data->name;
1712 gpt_get_max_primary_partition_count (const PedDisk *disk)
1714 const GPTDiskData *gpt_disk_data = disk->disk_specific;
1715 return gpt_disk_data->entry_count;
1719 * From (http://developer.apple.com/technotes/tn2006/tn2166.html Chapter 5).
1720 * According to the specs the first LBA (LBA0) is not relevant (it exists
1721 * to maintain compatibility). on the second LBA(LBA1) gpt places the
1722 * header. The header is as big as the block size. After the header we
1723 * find the Entry array. Each element of said array, describes each
1724 * partition. One can have as much elements as can fit between the end of
1725 * the second LBA (where the header ends) and the FirstUsableLBA.
1726 * FirstUsableLBA is the first logical block that is used for contents
1727 * and is defined in header.
1729 * /---------------------------------------------------\
1730 * | BLOCK0 | HEADER | Entry Array | First Usable LBA |
1732 * \---------------------------------------------------/
1734 * /----------/ \----------\
1735 * /-----------------------------------------\
1736 * | E1 | E2 | E3 |...............| EN |
1737 * \-----------------------------------------/
1739 * The number of possible partitions or supported partitions is:
1740 * SP = FirstUsableLBA*Blocksize - 2*Blocksize / SizeOfPartitionEntry
1741 * SP = Blocksize(FirstusableLBA - 2) / SizeOfPartitoinEntry
1744 gpt_get_max_supported_partition_count (const PedDisk *disk, int *max_n)
1746 GuidPartitionTableHeader_t *pth = NULL;
1747 uint8_t *pth_raw = ped_malloc (pth_get_size (disk->dev));
1749 if (ped_device_read (disk->dev, pth_raw, 1, GPT_HEADER_SECTORS)
1750 || ped_device_read (disk->dev, pth_raw,
1751 disk->dev->length, GPT_HEADER_SECTORS))
1752 pth = pth_new_from_raw (disk->dev, pth_raw);
1758 if (!_header_is_valid (disk, pth, 1))
1760 pth->FirstUsableLBA = 34;
1761 pth->SizeOfPartitionEntry
1762 = PED_CPU_TO_LE32 (sizeof (GuidPartitionEntry_t));
1765 *max_n = (disk->dev->sector_size * (pth->FirstUsableLBA - 2)
1766 / PED_LE32_TO_CPU (pth->SizeOfPartitionEntry));
1771 static PedConstraint *
1772 _non_metadata_constraint (const PedDisk *disk)
1774 GPTDiskData *gpt_disk_data = disk->disk_specific;
1776 return ped_constraint_new_from_max (&gpt_disk_data->data_area);
1780 gpt_partition_align (PedPartition *part, const PedConstraint *constraint)
1782 PED_ASSERT (part != NULL);
1784 if (_ped_partition_attempt_align (part, constraint,
1785 _non_metadata_constraint (part->disk)))
1788 #ifndef DISCOVER_ONLY
1789 ped_exception_throw (PED_EXCEPTION_ERROR,
1790 PED_EXCEPTION_CANCEL,
1791 _("Unable to satisfy all constraints on the partition."));
1796 #include "pt-common.h"
1797 PT_define_limit_functions (gpt)
1799 static PedDiskOps gpt_disk_ops =
1802 write: NULL_IF_DISCOVER_ONLY (gpt_write),
1804 partition_set_name: gpt_partition_set_name,
1805 partition_get_name: gpt_partition_get_name,
1807 PT_op_function_initializers (gpt)
1810 static PedDiskType gpt_disk_type =
1815 features: PED_DISK_TYPE_PARTITION_NAME
1819 ped_disk_gpt_init ()
1821 ped_disk_type_register (&gpt_disk_type);
1825 ped_disk_gpt_done ()
1827 ped_disk_type_unregister (&gpt_disk_type);
1830 verify (sizeof (GuidPartitionEntryAttributes_t) == 8);
1831 verify (sizeof (GuidPartitionEntry_t) == 128);