OSDN Git Service

gpt: tweak interfaces to pass disk, not disk->dev
[android-x86/external-parted.git] / libparted / labels / gpt.c
1 /*
2     libparted - a library for manipulating disk partitions
3
4     original version by Matt Domsch <Matt_Domsch@dell.com>
5     Disclaimed into the Public Domain
6
7     Portions Copyright (C) 2001-2003, 2005-2009 Free Software Foundation, Inc.
8
9     EFI GUID Partition Table handling
10     Per Intel EFI Specification v1.02
11     http://developer.intel.com/technology/efi/efi.htm
12
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.
17
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.
22
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/>.
25 */
26
27 #include <config.h>
28
29 #include <parted/parted.h>
30 #include <parted/debug.h>
31 #include <parted/endian.h>
32 #include <parted/crc32.h>
33 #include <inttypes.h>
34 #include <stdio.h>
35 #include <sys/types.h>
36 #include <sys/ioctl.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39 #include <uuid/uuid.h>
40 #include <stdbool.h>
41 #include <errno.h>
42 #include "xalloc.h"
43
44 #include "pt-tools.h"
45
46 #if ENABLE_NLS
47 #  include <libintl.h>
48 #  define _(String) gettext (String)
49 #else
50 #  define _(String) (String)
51 #endif /* ENABLE_NLS */
52
53 #define EFI_PMBR_OSTYPE_EFI 0xEE
54 #define MSDOS_MBR_SIGNATURE 0xaa55
55
56 #define GPT_HEADER_SIGNATURE 0x5452415020494645LL
57
58 /* NOTE: the document that describes revision 1.00 is labelled "version 1.02",
59  * so some implementors got confused...
60  */
61 #define GPT_HEADER_REVISION_V1_02 0x00010200
62 #define GPT_HEADER_REVISION_V1_00 0x00010000
63 #define GPT_HEADER_REVISION_V0_99 0x00009900
64
65 typedef uint16_t efi_char16_t;  /* UNICODE character */
66 typedef struct _GuidPartitionTableHeader_t GuidPartitionTableHeader_t;
67 typedef struct _GuidPartitionEntryAttributes_t GuidPartitionEntryAttributes_t;
68 typedef struct _GuidPartitionEntry_t GuidPartitionEntry_t;
69 typedef struct _PartitionRecord_t PartitionRecord_t;
70 typedef struct _LegacyMBR_t LegacyMBR_t;
71 typedef struct _GPTDiskData GPTDiskData;
72 typedef struct
73 {
74   uint32_t time_low;
75   uint16_t time_mid;
76   uint16_t time_hi_and_version;
77   uint8_t clock_seq_hi_and_reserved;
78   uint8_t clock_seq_low;
79   uint8_t node[6];
80 } /* __attribute__ ((packed)) */ efi_guid_t;
81 /* commented out "__attribute__ ((packed))" to work around gcc bug (fixed
82  * in gcc3.1): __attribute__ ((packed)) breaks addressing on initialized
83  * data.  It turns out we don't need it in this case, so it doesn't break
84  * anything :)
85  */
86
87 #define UNUSED_ENTRY_GUID    \
88     ((efi_guid_t) { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, \
89                     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }})
90 #define PARTITION_SYSTEM_GUID \
91     ((efi_guid_t) { PED_CPU_TO_LE32 (0xC12A7328), PED_CPU_TO_LE16 (0xF81F), \
92                     PED_CPU_TO_LE16 (0x11d2), 0xBA, 0x4B, \
93                     { 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B }})
94 #define PARTITION_BIOS_GRUB_GUID \
95     ((efi_guid_t) { PED_CPU_TO_LE32 (0x21686148), PED_CPU_TO_LE16 (0x6449), \
96                     PED_CPU_TO_LE16 (0x6E6f), 0x74, 0x4E, \
97                     { 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 }})
98 #define LEGACY_MBR_PARTITION_GUID \
99     ((efi_guid_t) { PED_CPU_TO_LE32 (0x024DEE41), PED_CPU_TO_LE16 (0x33E7), \
100                     PED_CPU_TO_LE16 (0x11d3, 0x9D, 0x69, \
101                     { 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F }})
102 #define PARTITION_MSFT_RESERVED_GUID \
103     ((efi_guid_t) { PED_CPU_TO_LE32 (0xE3C9E316), PED_CPU_TO_LE16 (0x0B5C), \
104                     PED_CPU_TO_LE16 (0x4DB8), 0x81, 0x7D, \
105                     { 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE }})
106 #define PARTITION_BASIC_DATA_GUID \
107     ((efi_guid_t) { PED_CPU_TO_LE32 (0xEBD0A0A2), PED_CPU_TO_LE16 (0xB9E5), \
108                     PED_CPU_TO_LE16 (0x4433), 0x87, 0xC0, \
109                     { 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }})
110 #define PARTITION_RAID_GUID \
111     ((efi_guid_t) { PED_CPU_TO_LE32 (0xa19d880f), PED_CPU_TO_LE16 (0x05fc), \
112                     PED_CPU_TO_LE16 (0x4d3b), 0xa0, 0x06, \
113                     { 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e }})
114 #define PARTITION_SWAP_GUID \
115     ((efi_guid_t) { PED_CPU_TO_LE32 (0x0657fd6d), PED_CPU_TO_LE16 (0xa4ab), \
116                     PED_CPU_TO_LE16 (0x43c4), 0x84, 0xe5, \
117                     { 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f }})
118 #define PARTITION_LVM_GUID \
119     ((efi_guid_t) { PED_CPU_TO_LE32 (0xe6d6d379), PED_CPU_TO_LE16 (0xf507), \
120                     PED_CPU_TO_LE16 (0x44c2), 0xa2, 0x3c, \
121                     { 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28 }})
122 #define PARTITION_RESERVED_GUID \
123     ((efi_guid_t) { PED_CPU_TO_LE32 (0x8da63339), PED_CPU_TO_LE16 (0x0007), \
124                     PED_CPU_TO_LE16 (0x60c0), 0xc4, 0x36, \
125                     { 0x08, 0x3a, 0xc8, 0x23, 0x09, 0x08 }})
126 #define PARTITION_HPSERVICE_GUID \
127     ((efi_guid_t) { PED_CPU_TO_LE32 (0xe2a1e728), PED_CPU_TO_LE16 (0x32e3), \
128                     PED_CPU_TO_LE16 (0x11d6), 0xa6, 0x82, \
129                     { 0x7b, 0x03, 0xa0, 0x00, 0x00, 0x00 }})
130 #define PARTITION_APPLE_HFS_GUID \
131     ((efi_guid_t) { PED_CPU_TO_LE32 (0x48465300), PED_CPU_TO_LE16 (0x0000), \
132                     PED_CPU_TO_LE16 (0x11AA), 0xaa, 0x11, \
133                     { 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC }})
134
135 struct __attribute__ ((packed)) _GuidPartitionTableHeader_t
136 {
137   uint64_t Signature;
138   uint32_t Revision;
139   uint32_t HeaderSize;
140   uint32_t HeaderCRC32;
141   uint32_t Reserved1;
142   uint64_t MyLBA;
143   uint64_t AlternateLBA;
144   uint64_t FirstUsableLBA;
145   uint64_t LastUsableLBA;
146   efi_guid_t DiskGUID;
147   uint64_t PartitionEntryLBA;
148   uint32_t NumberOfPartitionEntries;
149   uint32_t SizeOfPartitionEntry;
150   uint32_t PartitionEntryArrayCRC32;
151   uint8_t *Reserved2;
152 };
153
154 struct __attribute__ ((packed)) _GuidPartitionEntryAttributes_t
155 {
156 #ifdef __GNUC__                 /* XXX narrow this down to !TinyCC */
157   uint64_t RequiredToFunction:1;
158   uint64_t Reserved:47;
159   uint64_t GuidSpecific:16;
160 #else
161 #       warning "Using crippled partition entry type"
162   uint32_t RequiredToFunction:1;
163   uint32_t Reserved:32;
164   uint32_t LOST:5;
165   uint32_t GuidSpecific:16;
166 #endif
167 };
168
169 struct __attribute__ ((packed)) _GuidPartitionEntry_t
170 {
171   efi_guid_t PartitionTypeGuid;
172   efi_guid_t UniquePartitionGuid;
173   uint64_t StartingLBA;
174   uint64_t EndingLBA;
175   GuidPartitionEntryAttributes_t Attributes;
176   efi_char16_t PartitionName[72 / sizeof (efi_char16_t)];
177 };
178
179 #define GPT_PMBR_LBA 0
180 #define GPT_PMBR_SECTORS 1
181 #define GPT_PRIMARY_HEADER_LBA 1
182 #define GPT_HEADER_SECTORS 1
183 #define GPT_PRIMARY_PART_TABLE_LBA 2
184
185 /*
186    These values are only defaults.  The actual on-disk structures
187    may define different sizes, so use those unless creating a new GPT disk!
188 */
189
190 #define GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE 16384
191
192 /* Number of actual partition entries should be calculated as: */
193 #define GPT_DEFAULT_PARTITION_ENTRIES \
194         (GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / \
195          sizeof(GuidPartitionEntry_t))
196
197 struct __attribute__ ((packed)) _PartitionRecord_t
198 {
199   /* Not used by EFI firmware. Set to 0x80 to indicate that this
200      is the bootable legacy partition. */
201   uint8_t BootIndicator;
202
203   /* Start of partition in CHS address, not used by EFI firmware. */
204   uint8_t StartHead;
205
206   /* Start of partition in CHS address, not used by EFI firmware. */
207   uint8_t StartSector;
208
209   /* Start of partition in CHS address, not used by EFI firmware. */
210   uint8_t StartTrack;
211
212   /* OS type. A value of 0xEF defines an EFI system partition.
213      Other values are reserved for legacy operating systems, and
214      allocated independently of the EFI specification. */
215   uint8_t OSType;
216
217   /* End of partition in CHS address, not used by EFI firmware. */
218   uint8_t EndHead;
219
220   /* End of partition in CHS address, not used by EFI firmware. */
221   uint8_t EndSector;
222
223   /* End of partition in CHS address, not used by EFI firmware. */
224   uint8_t EndTrack;
225
226   /* Starting LBA address of the partition on the disk. Used by
227      EFI firmware to define the start of the partition. */
228   uint32_t StartingLBA;
229
230   /* Size of partition in LBA. Used by EFI firmware to determine
231      the size of the partition. */
232   uint32_t SizeInLBA;
233 };
234
235 /* Protected Master Boot Record  & Legacy MBR share same structure */
236 /* Needs to be packed because the u16s force misalignment. */
237 struct __attribute__ ((packed)) _LegacyMBR_t
238 {
239   uint8_t BootCode[440];
240   uint32_t UniqueMBRSignature;
241   uint16_t Unknown;
242   PartitionRecord_t PartitionRecord[4];
243   uint16_t Signature;
244 };
245
246 /* uses libparted's disk_specific field in PedDisk, to store our info */
247 struct __attribute__ ((packed)) _GPTDiskData
248 {
249   PedGeometry data_area;
250   int entry_count;
251   efi_guid_t uuid;
252 };
253
254 /* uses libparted's disk_specific field in PedPartition, to store our info */
255 typedef struct _GPTPartitionData
256 {
257   efi_guid_t type;
258   efi_guid_t uuid;
259   char name[37];
260   int lvm;
261   int raid;
262   int boot;
263   int bios_grub;
264   int hp_service;
265   int hidden;
266   int msftres;
267 } GPTPartitionData;
268
269 static PedDiskType gpt_disk_type;
270
271 static inline uint32_t
272 pth_get_size (const PedDevice *dev)
273 {
274   return GPT_HEADER_SECTORS * dev->sector_size;
275 }
276
277 static inline uint32_t
278 pth_get_size_static (const PedDevice *dev)
279 {
280   return sizeof (GuidPartitionTableHeader_t) - sizeof (uint8_t *);
281 }
282
283 static inline uint32_t
284 pth_get_size_rsv2 (const PedDevice *dev)
285 {
286   return pth_get_size (dev) - pth_get_size_static (dev);
287 }
288
289 static GuidPartitionTableHeader_t *
290 pth_new (const PedDevice *dev)
291 {
292   GuidPartitionTableHeader_t *pth =
293     ped_malloc (sizeof (GuidPartitionTableHeader_t) + sizeof (uint8_t));
294
295   pth->Reserved2 = ped_malloc (pth_get_size_rsv2 (dev));
296
297   return pth;
298 }
299
300 static GuidPartitionTableHeader_t *
301 pth_new_zeroed (const PedDevice *dev)
302 {
303   GuidPartitionTableHeader_t *pth = pth_new (dev);
304
305   memset (pth, 0, pth_get_size_static (dev));
306   memset (pth->Reserved2, 0, pth_get_size_rsv2 (dev));
307
308   return (pth);
309 }
310
311 static GuidPartitionTableHeader_t *
312 pth_new_from_raw (const PedDevice *dev, const uint8_t *pth_raw)
313 {
314   GuidPartitionTableHeader_t *pth = pth_new (dev);
315
316   PED_ASSERT (pth_raw != NULL, return 0);
317
318   memcpy (pth, pth_raw, pth_get_size_static (dev));
319   memcpy (pth->Reserved2, pth_raw + pth_get_size_static (dev),
320           pth_get_size_rsv2 (dev));
321
322   return pth;
323 }
324
325 static void
326 pth_free (GuidPartitionTableHeader_t *pth)
327 {
328   if (pth == NULL)
329     return;
330   PED_ASSERT (pth->Reserved2 != NULL, return);
331
332   free (pth->Reserved2);
333   free (pth);
334 }
335
336 static uint8_t *
337 pth_get_raw (const PedDevice *dev, const GuidPartitionTableHeader_t *pth)
338 {
339   PED_ASSERT (pth != NULL, return 0);
340   PED_ASSERT (pth->Reserved2 != NULL, return 0);
341
342   int size_static = pth_get_size_static (dev);
343   uint8_t *pth_raw = ped_malloc (pth_get_size (dev));
344   if (pth_raw == NULL)
345     return NULL;
346
347   memcpy (pth_raw, pth, size_static);
348   memcpy (pth_raw + size_static, pth->Reserved2, pth_get_size_rsv2 (dev));
349
350   return pth_raw;
351 }
352
353 /**
354  * swap_uuid_and_efi_guid() - converts between uuid formats
355  * @uuid - uuid_t in either format (converts it to the other)
356  *
357  * There are two different representations for Globally Unique Identifiers
358  * (GUIDs or UUIDs).
359  *
360  * The RFC specifies a UUID as a string of 16 bytes, essentially
361  * a big-endian array of char.
362  * Intel, in their EFI Specification, references the same RFC, but
363  * then defines a GUID as a structure of little-endian fields.
364  * Coincidentally, both structures have the same format when unparsed.
365  *
366  * When read from disk, EFI GUIDs are in struct of little endian format,
367  * and need to be converted to be treated as uuid_t in memory.
368  *
369  * When writing to disk, uuid_ts need to be converted into EFI GUIDs.
370  *
371  * Blame Intel.
372  */
373 static void
374 swap_uuid_and_efi_guid (uuid_t uuid)
375 {
376   efi_guid_t *guid = (efi_guid_t *) uuid;
377
378   PED_ASSERT (uuid != NULL, return);
379   guid->time_low = PED_SWAP32 (guid->time_low);
380   guid->time_mid = PED_SWAP16 (guid->time_mid);
381   guid->time_hi_and_version = PED_SWAP16 (guid->time_hi_and_version);
382 }
383
384 /* returns the EFI-style CRC32 value for buf
385  *      This function uses the crc32 function by Gary S. Brown,
386  * but seeds the function with ~0, and xor's with ~0 at the end.
387  */
388 static inline uint32_t
389 efi_crc32 (const void *buf, unsigned long len)
390 {
391   return (__efi_crc32 (buf, len, ~0L) ^ ~0L);
392 }
393
394 /* Compute the crc32 checksum of the partition table header
395    and store it in *CRC32.  Return 0 upon success.  Return 1
396    upon failure to allocate space.  */
397 static int
398 pth_crc32 (const PedDevice *dev, const GuidPartitionTableHeader_t *pth,
399            uint32_t *crc32)
400 {
401   PED_ASSERT (dev != NULL, return 0);
402   PED_ASSERT (pth != NULL, return 0);
403
404   uint8_t *pth_raw = pth_get_raw (dev, pth);
405   if (pth_raw == NULL)
406     return 1;
407
408   *crc32 = efi_crc32 (pth_raw, PED_LE32_TO_CPU (pth->HeaderSize));
409   free (pth_raw);
410
411   return 0;
412 }
413
414 static inline int
415 guid_cmp (efi_guid_t left, efi_guid_t right)
416 {
417   return memcmp (&left, &right, sizeof (efi_guid_t));
418 }
419
420 /* checks if 'mbr' is a protective MBR partition table */
421 static inline int
422 _pmbr_is_valid (const LegacyMBR_t *mbr)
423 {
424   int i;
425
426   PED_ASSERT (mbr != NULL, return 0);
427
428   if (mbr->Signature != PED_CPU_TO_LE16 (MSDOS_MBR_SIGNATURE))
429     return 0;
430   for (i = 0; i < 4; i++)
431     {
432       if (mbr->PartitionRecord[i].OSType == EFI_PMBR_OSTYPE_EFI)
433         return 1;
434     }
435   return 0;
436 }
437
438 static int
439 gpt_probe (const PedDevice *dev)
440 {
441   GuidPartitionTableHeader_t *gpt = NULL;
442   uint8_t *pth_raw = ped_malloc (pth_get_size (dev));
443   int gpt_sig_found = 0;
444
445   PED_ASSERT (dev != NULL, return 0);
446
447   if (ped_device_read (dev, pth_raw, 1, GPT_HEADER_SECTORS)
448       || ped_device_read (dev, pth_raw, dev->length - 1, GPT_HEADER_SECTORS))
449     {
450       gpt = pth_new_from_raw (dev, pth_raw);
451       if (gpt->Signature == PED_CPU_TO_LE64 (GPT_HEADER_SIGNATURE))
452         gpt_sig_found = 1;
453     }
454
455   free (pth_raw);
456
457   pth_free (gpt);
458
459   if (!gpt_sig_found)
460     return 0;
461
462   void *label;
463   if (!ptt_read_sector (dev, 0, &label))
464     return 0;
465
466   int ok = 1;
467   if (!_pmbr_is_valid ((const LegacyMBR_t *) label))
468     {
469       int ex_status = ped_exception_throw
470         (PED_EXCEPTION_WARNING,
471          PED_EXCEPTION_YES_NO,
472          _("%s contains GPT signatures, indicating that it has "
473            "a GPT table.  However, it does not have a valid "
474            "fake msdos partition table, as it should.  Perhaps "
475            "it was corrupted -- possibly by a program that "
476            "doesn't understand GPT partition tables.  Or "
477            "perhaps you deleted the GPT table, and are now "
478            "using an msdos partition table.  Is this a GPT "
479            "partition table?"),
480          dev->path);
481       if (ex_status == PED_EXCEPTION_NO)
482         ok = 0;
483     }
484
485   free (label);
486   return ok;
487 }
488
489 #ifndef DISCOVER_ONLY
490 /* writes zeros to the PMBR and the primary and alternate GPTHs and PTEs */
491 static int
492 gpt_clobber (PedDevice *dev)
493 {
494   uint8_t *pth_raw = ped_malloc (pth_get_size (dev));
495   GuidPartitionTableHeader_t *gpt;
496
497   PED_ASSERT (dev != NULL, return 0);
498
499   /*
500    * TO DISCUSS: check whether checksum is correct?
501    * If not, we might get a wrong AlternateLBA field and destroy
502    * one sector of random data.
503    */
504   if (!ped_device_read (dev, pth_raw,
505                         GPT_PRIMARY_HEADER_LBA, GPT_HEADER_SECTORS))
506     {
507       free (pth_raw);
508       return 0;
509     }
510
511   gpt = pth_new_from_raw (dev, pth_raw);
512   free (pth_raw);
513
514   if (!ptt_clear_sectors (dev, GPT_PMBR_LBA, GPT_PMBR_SECTORS))
515     goto error_free_with_gpt;
516   if (!ptt_clear_sectors (dev, GPT_PRIMARY_HEADER_LBA, GPT_HEADER_SECTORS))
517     goto error_free_with_gpt;
518   if (!ptt_clear_sectors (dev, dev->length - GPT_HEADER_SECTORS,
519                           GPT_HEADER_SECTORS))
520     goto error_free_with_gpt;
521
522   if ((PedSector) PED_LE64_TO_CPU (gpt->AlternateLBA) < dev->length - 1)
523     {
524       if (!ped_device_write (dev, gpt,
525                              PED_LE64_TO_CPU (gpt->AlternateLBA),
526                              GPT_HEADER_SECTORS))
527         return 0;
528     }
529
530   pth_free (gpt);
531
532   return 1;
533
534 error_free_with_gpt:
535   pth_free (gpt);
536   return 0;
537 }
538 #endif /* !DISCOVER_ONLY */
539
540 static PedDisk *
541 gpt_alloc (const PedDevice *dev)
542 {
543   PedDisk *disk;
544   GPTDiskData *gpt_disk_data;
545   PedSector data_start, data_end;
546
547   disk = _ped_disk_alloc ((PedDevice *) dev, &gpt_disk_type);
548   if (!disk)
549     goto error;
550   disk->disk_specific = gpt_disk_data = ped_malloc (sizeof (GPTDiskData));
551   if (!disk->disk_specific)
552     goto error_free_disk;
553
554   data_start = 2 + GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / dev->sector_size;
555   data_end = dev->length - 2
556     - GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / dev->sector_size;
557   ped_geometry_init (&gpt_disk_data->data_area, dev, data_start,
558                      data_end - data_start + 1);
559   gpt_disk_data->entry_count = GPT_DEFAULT_PARTITION_ENTRIES;
560   uuid_generate ((unsigned char *) &gpt_disk_data->uuid);
561   swap_uuid_and_efi_guid ((unsigned char *) (&gpt_disk_data->uuid));
562   return disk;
563
564 error_free_disk:
565   free (disk);
566 error:
567   return NULL;
568 }
569
570 static PedDisk *
571 gpt_duplicate (const PedDisk *disk)
572 {
573   PedDisk *new_disk;
574   GPTDiskData *new_disk_data;
575   GPTDiskData *old_disk_data;
576
577   new_disk = ped_disk_new_fresh (disk->dev, &gpt_disk_type);
578   if (!new_disk)
579     return NULL;
580
581   old_disk_data = disk->disk_specific;
582   new_disk_data = new_disk->disk_specific;
583
584   ped_geometry_init (&new_disk_data->data_area, disk->dev,
585                      old_disk_data->data_area.start,
586                      old_disk_data->data_area.length);
587   new_disk_data->entry_count = old_disk_data->entry_count;
588   new_disk_data->uuid = old_disk_data->uuid;
589   return new_disk;
590 }
591
592 static void
593 gpt_free (PedDisk *disk)
594 {
595   ped_disk_delete_all (disk);
596   free (disk->disk_specific);
597   _ped_disk_free (disk);
598 }
599
600 /* Given GUID Partition table header, GPT, read its partition array
601    entries from DISK into malloc'd storage.  Set *PTES_BYTES to the
602    number of bytes required.  Upon success, return a pointer to the
603    resulting buffer.  Otherwise, set errno and return NULL.  */
604 static void *
605 gpt_read_PE_array (PedDisk const *disk, GuidPartitionTableHeader_t const *gpt,
606                    size_t *ptes_bytes)
607 {
608   GPTDiskData *gpt_disk_data = disk->disk_specific;
609   uint32_t p_ent_size = PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry);
610   *ptes_bytes = p_ent_size * gpt_disk_data->entry_count;
611   size_t ptes_sectors = ped_div_round_up (*ptes_bytes,
612                                           disk->dev->sector_size);
613
614   if (xalloc_oversized (ptes_sectors, disk->dev->sector_size))
615     {
616       errno = ENOMEM;
617       return NULL;
618     }
619   void *ptes = ped_malloc (ptes_sectors * disk->dev->sector_size);
620   if (ptes == NULL)
621     return NULL;
622
623   if (!ped_device_read (disk->dev, ptes,
624                         PED_LE64_TO_CPU (gpt->PartitionEntryLBA), ptes_sectors))
625     {
626       int saved_errno = errno;
627       free (ptes);
628       errno = saved_errno;
629       return NULL;
630     }
631
632   return ptes;
633 }
634
635 static int
636 _header_is_valid (PedDisk const *disk, GuidPartitionTableHeader_t *gpt,
637                   PedSector my_lba)
638 {
639   uint32_t crc, origcrc;
640   PedDevice const *dev = disk->dev;
641
642   if (PED_LE64_TO_CPU (gpt->Signature) != GPT_HEADER_SIGNATURE)
643     return 0;
644   /*
645    * "While the GUID Partition Table Header's size may increase
646    * in the future it cannot span more than one block on the
647    * device."  EFI Specification, version 1.10, 11.2.2.1
648    */
649   if (PED_LE32_TO_CPU (gpt->HeaderSize) < pth_get_size_static (dev)
650       || PED_LE32_TO_CPU (gpt->HeaderSize) > dev->sector_size)
651     return 0;
652
653   /* The SizeOfPartitionEntry must be a multiple of 8 and
654      no smaller than the size of the PartitionEntry structure.
655      We also require that be no larger than 1/16th of UINT32_MAX,
656      as an additional sanity check.  */
657   uint32_t sope = PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry);
658   if (sope % 8 != 0
659       || sope < sizeof (GuidPartitionEntry_t) || (UINT32_MAX >> 4) < sope)
660     return 0;
661
662   if (PED_LE64_TO_CPU (gpt->MyLBA) != my_lba)
663     return 0;
664
665   PedSector alt_lba = PED_LE64_TO_CPU (gpt->AlternateLBA);
666   /* The backup table's AlternateLBA must be 1.  */
667   if (my_lba != 1 && alt_lba != 1)
668     return 0;
669
670   /* The alt_lba must never be the same as my_lba.  */
671   if (alt_lba == my_lba)
672     return 0;
673
674   origcrc = gpt->HeaderCRC32;
675   gpt->HeaderCRC32 = 0;
676   if (pth_crc32 (dev, gpt, &crc) != 0)
677     return 0;
678   gpt->HeaderCRC32 = origcrc;
679
680   return crc == PED_LE32_TO_CPU (origcrc);
681 }
682
683 static int
684 _parse_header (PedDisk *disk, const GuidPartitionTableHeader_t *gpt,
685                int *update_needed)
686 {
687   GPTDiskData *gpt_disk_data = disk->disk_specific;
688   PedSector first_usable;
689   PedSector last_usable;
690   PedSector last_usable_if_grown, last_usable_min_default;
691   static int asked_already;
692
693 #ifndef DISCOVER_ONLY
694   if (PED_LE32_TO_CPU (gpt->Revision) > GPT_HEADER_REVISION_V1_02)
695     {
696       if (ped_exception_throw
697           (PED_EXCEPTION_WARNING,
698            PED_EXCEPTION_IGNORE_CANCEL,
699            _("The format of the GPT partition table is version "
700              "%x, which is newer than what Parted can "
701              "recognise.  Please tell us!  bug-parted@gnu.org"),
702            PED_LE32_TO_CPU (gpt->Revision)) != PED_EXCEPTION_IGNORE)
703         return 0;
704     }
705 #endif
706
707   first_usable = PED_LE64_TO_CPU (gpt->FirstUsableLBA);
708   last_usable = PED_LE64_TO_CPU (gpt->LastUsableLBA);
709
710   /* Need to check whether the volume has grown, the LastUsableLBA is
711      normally set to disk->dev->length - 2 - ptes_size (at least for parted
712      created volumes), where ptes_size is the number of entries *
713      size of each entry / sector size or 16k / sector size, whatever the greater.
714      If the volume has grown, offer the user the chance to use the new
715      space or continue with the current usable area.  Only ask once per
716      parted invocation. */
717
718   last_usable_if_grown
719     = (disk->dev->length - 2 -
720        ((PedSector) (PED_LE32_TO_CPU (gpt->NumberOfPartitionEntries)) *
721         (PedSector) (PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry)) /
722         disk->dev->sector_size));
723
724   last_usable_min_default = disk->dev->length - 2 -
725     GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / disk->dev->sector_size;
726
727   if (last_usable_if_grown > last_usable_min_default)
728     {
729       last_usable_if_grown = last_usable_min_default;
730     }
731
732   PED_ASSERT (last_usable > first_usable, return 0);
733   PED_ASSERT (last_usable <= disk->dev->length, return 0);
734
735   PED_ASSERT (last_usable_if_grown > first_usable, return 0);
736   PED_ASSERT (last_usable_if_grown <= disk->dev->length, return 0);
737
738   if (!asked_already && last_usable < last_usable_if_grown)
739     {
740
741       PedExceptionOption q;
742
743       q = ped_exception_throw
744         (PED_EXCEPTION_WARNING,
745          PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE,
746          _("Not all of the space available to %s appears "
747            "to be used, you can fix the GPT to use all of the "
748            "space (an extra %llu blocks) or continue with the "
749            "current setting? "), disk->dev->path,
750          (uint64_t) (last_usable_if_grown - last_usable));
751
752       if (q == PED_EXCEPTION_FIX)
753         {
754           last_usable = last_usable_if_grown;
755           *update_needed = 1;
756         }
757       else if (q != PED_EXCEPTION_UNHANDLED)
758         {
759           asked_already = 1;
760         }
761     }
762
763   ped_geometry_init (&gpt_disk_data->data_area, disk->dev,
764                      first_usable, last_usable - first_usable + 1);
765
766   gpt_disk_data->entry_count
767     = PED_LE32_TO_CPU (gpt->NumberOfPartitionEntries);
768   PED_ASSERT (gpt_disk_data->entry_count > 0, return 0);
769   PED_ASSERT (gpt_disk_data->entry_count <= 8192, return 0);
770
771   gpt_disk_data->uuid = gpt->DiskGUID;
772
773   return 1;
774 }
775
776 static PedPartition *
777 _parse_part_entry (PedDisk *disk, GuidPartitionEntry_t *pte)
778 {
779   PedPartition *part;
780   GPTPartitionData *gpt_part_data;
781   unsigned int i;
782
783   part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
784                             PED_LE64_TO_CPU (pte->StartingLBA),
785                             PED_LE64_TO_CPU (pte->EndingLBA));
786   if (!part)
787     return NULL;
788
789   gpt_part_data = part->disk_specific;
790   gpt_part_data->type = pte->PartitionTypeGuid;
791   gpt_part_data->uuid = pte->UniquePartitionGuid;
792   for (i = 0; i < 72 / sizeof (efi_char16_t); i++)
793     gpt_part_data->name[i] =
794       (efi_char16_t) PED_LE16_TO_CPU ((uint16_t) pte->PartitionName[i]);
795   gpt_part_data->name[i] = 0;
796
797   gpt_part_data->lvm = gpt_part_data->raid
798     = gpt_part_data->boot = gpt_part_data->hp_service
799     = gpt_part_data->hidden = gpt_part_data->msftres
800     = gpt_part_data->bios_grub = 0;
801
802   if (pte->Attributes.RequiredToFunction & 0x1)
803     gpt_part_data->hidden = 1;
804
805   if (!guid_cmp (gpt_part_data->type, PARTITION_SYSTEM_GUID))
806     gpt_part_data->boot = 1;
807   else if (!guid_cmp (gpt_part_data->type, PARTITION_BIOS_GRUB_GUID))
808     gpt_part_data->bios_grub = 1;
809   else if (!guid_cmp (gpt_part_data->type, PARTITION_RAID_GUID))
810     gpt_part_data->raid = 1;
811   else if (!guid_cmp (gpt_part_data->type, PARTITION_LVM_GUID))
812     gpt_part_data->lvm = 1;
813   else if (!guid_cmp (gpt_part_data->type, PARTITION_HPSERVICE_GUID))
814     gpt_part_data->hp_service = 1;
815   else if (!guid_cmp (gpt_part_data->type, PARTITION_MSFT_RESERVED_GUID))
816     gpt_part_data->msftres = 1;
817
818   return part;
819 }
820
821 /* Read the primary GPT at sector 1 of DEV.
822    Verify its CRC and that of its partition entry array.
823    If they are valid, read the backup GPT specified by AlternateLBA.
824    If not, read the backup GPT in the last sector of the disk.
825    Return 1 if any read fails.
826    Upon successful verification of the primary GPT, set *PRIMARY_GPT, else NULL.
827    Upon successful verification of the backup GPT, set *BACKUP_GPT, else NULL.
828    If we've set *BACKUP_GPT to non-NULL, set *BACKUP_LBA to the sector
829    number in which it was found.  */
830 static int
831 gpt_read_headers (PedDisk const *disk,
832                   GuidPartitionTableHeader_t **primary_gpt,
833                   GuidPartitionTableHeader_t **backup_gpt,
834                   PedSector *backup_sector_num_p)
835 {
836   *primary_gpt = NULL;
837   *backup_gpt = NULL;
838   PedDevice const *dev = disk->dev;
839
840   void *s1;
841   if (!ptt_read_sector (dev, 1, &s1))
842     return 1;
843
844   GuidPartitionTableHeader_t *t = pth_new_from_raw (dev, s1);
845   free (s1);
846   if (t == NULL)
847     return 1;
848   GuidPartitionTableHeader_t *pri = t;
849
850   bool valid_primary = _header_is_valid (disk, pri, 1);
851   if (valid_primary)
852     *primary_gpt = pri;
853
854   PedSector backup_sector_num =
855     (valid_primary
856      ? PED_LE64_TO_CPU (pri->AlternateLBA)
857      : dev->length - 1);
858
859   void *s_bak;
860   if (!ptt_read_sector (dev, backup_sector_num, &s_bak))
861     return 1;
862   t = pth_new_from_raw (dev, s_bak);
863   if (t == NULL)
864     return 1;
865
866   GuidPartitionTableHeader_t *bak = t;
867   if (_header_is_valid (disk, bak, backup_sector_num))
868     {
869       *backup_gpt = bak;
870       *backup_sector_num_p = backup_sector_num;
871     }
872
873   return 0;
874 }
875
876 /************************************************************
877  *  Intel is changing the EFI Spec. (after v1.02) to say that a
878  *  disk is considered to have a GPT label only if the GPT
879  *  structures are correct, and the MBR is actually a Protective
880  *  MBR (has one 0xEE type partition).
881  *  Problem occurs when a GPT-partitioned disk is then
882  *  edited with a legacy (non-GPT-aware) application, such as
883  *  fdisk (which doesn't generally erase the PGPT or AGPT).
884  *  How should such a disk get handled?  As a GPT disk (throwing
885  *  away the fdisk changes), or as an MSDOS disk (throwing away
886  *  the GPT information).  Previously, I've taken the GPT-is-right,
887  *  MBR is wrong, approach, to stay consistent with the EFI Spec.
888  *  Intel disagrees, saying the disk should then be treated
889  *  as having a msdos label, not a GPT label.  If this is true,
890  *  then what's the point of having an AGPT, since if the PGPT
891  *  is screwed up, likely the PMBR is too, and the PMBR becomes
892  *  a single point of failure.
893  *  So, in the Linux kernel, I'm going to test for PMBR, and
894  *  warn if it's not there, and treat the disk as MSDOS, with a note
895  *  for users to use Parted to "fix up" their disk if they
896  *  really want it to be considered GPT.
897  ************************************************************/
898 static int
899 gpt_read (PedDisk *disk)
900 {
901   GPTDiskData *gpt_disk_data = disk->disk_specific;
902   int i;
903 #ifndef DISCOVER_ONLY
904   int write_back = 1;
905 #endif
906
907   ped_disk_delete_all (disk);
908
909   /* motivation: let the user decide about the pmbr... during
910      ped_disk_probe(), they probably didn't get a choice... */
911   if (!gpt_probe (disk->dev))
912     goto error;
913
914   GuidPartitionTableHeader_t *gpt = NULL;
915   GuidPartitionTableHeader_t *primary_gpt;
916   GuidPartitionTableHeader_t *backup_gpt;
917   PedSector backup_sector_num;
918   int read_failure = gpt_read_headers (disk, &primary_gpt, &backup_gpt,
919                                        &backup_sector_num);
920   if (read_failure)
921     {
922       /* This includes the case in which there used to be a GPT partition
923          table here, with an alternate LBA that extended beyond the current
924          end-of-device.  It's treated as a non-match.  */
925
926       /* Another possibility:
927          The primary header is ok, but backup is corrupt.
928          In the UEFI spec, this means the primary GUID table
929          is officially invalid.  */
930       pth_free (backup_gpt);
931       pth_free (primary_gpt);
932       return 0;
933     }
934
935   if (primary_gpt && backup_gpt)
936     {
937       /* Both are valid.  */
938       if (PED_LE64_TO_CPU (primary_gpt->AlternateLBA) < disk->dev->length - 1)
939         {
940 #ifndef DISCOVER_ONLY
941           switch (ped_exception_throw
942                   (PED_EXCEPTION_ERROR,
943                    (PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL
944                     | PED_EXCEPTION_IGNORE),
945                    _("The backup GPT table is not at the end of the disk, as it "
946                      "should be.  This might mean that another operating system "
947                      "believes the disk is smaller.  Fix, by moving the backup "
948                      "to the end (and removing the old backup)?")))
949             {
950             case PED_EXCEPTION_CANCEL:
951               goto error_free_gpt;
952             case PED_EXCEPTION_FIX:
953               ptt_clear_sectors (disk->dev,
954                                  PED_LE64_TO_CPU (primary_gpt->AlternateLBA), 1);
955               break;
956             default:
957               write_back = 0;
958               break;
959             }
960 #endif /* !DISCOVER_ONLY */
961         }
962       gpt = primary_gpt;
963       pth_free (backup_gpt);
964     }
965   else if (!primary_gpt && !backup_gpt)
966     {
967       /* Both are corrupt.  */
968       ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
969                            _("Both the primary and backup GPT tables "
970                              "are corrupt.  Try making a fresh table, "
971                              "and using Parted's rescue feature to "
972                              "recover partitions."));
973       goto error;
974     }
975   else if (primary_gpt && !backup_gpt)
976     {
977       /* The primary header is ok, but backup is corrupt.  */
978       if (ped_exception_throw
979           (PED_EXCEPTION_ERROR, PED_EXCEPTION_OK_CANCEL,
980            _("The backup GPT table is corrupt, but the "
981              "primary appears OK, so that will be used."))
982           == PED_EXCEPTION_CANCEL)
983         goto error_free_gpt;
984
985       gpt = primary_gpt;
986     }
987   else /* !primary_gpt && backup_gpt */
988     {
989       /* primary GPT corrupt, backup is ok.  */
990       if (ped_exception_throw
991           (PED_EXCEPTION_ERROR, PED_EXCEPTION_OK_CANCEL,
992            _("The primary GPT table is corrupt, but the "
993              "backup appears OK, so that will be used."))
994           == PED_EXCEPTION_CANCEL)
995         goto error_free_gpt;
996
997       gpt = backup_gpt;
998     }
999   backup_gpt = NULL;
1000   primary_gpt = NULL;
1001
1002   if (!_parse_header (disk, gpt, &write_back))
1003     goto error_free_gpt;
1004
1005   size_t ptes_bytes;
1006   void *ptes = gpt_read_PE_array (disk, gpt, &ptes_bytes);
1007   if (ptes == NULL)
1008     goto error_free_gpt;
1009
1010   uint32_t ptes_crc = efi_crc32 (ptes, ptes_bytes);
1011   if (ptes_crc != gpt->PartitionEntryArrayCRC32)
1012     {
1013       ped_exception_throw
1014         (PED_EXCEPTION_ERROR,
1015          PED_EXCEPTION_CANCEL,
1016          _("primary partition table array CRC mismatch"));
1017       goto error_free_ptes;
1018     }
1019
1020   uint32_t p_ent_size = PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry);
1021   for (i = 0; i < gpt_disk_data->entry_count; i++)
1022     {
1023       GuidPartitionEntry_t *pte
1024         = (GuidPartitionEntry_t *) ((char *) ptes + i * p_ent_size);
1025       PedPartition *part;
1026       PedConstraint *constraint_exact;
1027
1028       if (!guid_cmp (pte->PartitionTypeGuid, UNUSED_ENTRY_GUID))
1029         continue;
1030
1031       part = _parse_part_entry (disk, pte);
1032       if (!part)
1033         goto error_delete_all;
1034
1035       part->fs_type = ped_file_system_probe (&part->geom);
1036       part->num = i + 1;
1037
1038       constraint_exact = ped_constraint_exact (&part->geom);
1039       if (!ped_disk_add_partition (disk, part, constraint_exact))
1040         {
1041           ped_partition_destroy (part);
1042           goto error_delete_all;
1043         }
1044       ped_constraint_destroy (constraint_exact);
1045     }
1046   free (ptes);
1047
1048 #ifndef DISCOVER_ONLY
1049   if (write_back)
1050     ped_disk_commit_to_dev (disk);
1051 #endif
1052
1053   pth_free (gpt);
1054   return 1;
1055
1056 error_delete_all:
1057   ped_disk_delete_all (disk);
1058 error_free_ptes:
1059   free (ptes);
1060 error_free_gpt:
1061   pth_free (primary_gpt);
1062   pth_free (backup_gpt);
1063   pth_free (gpt);
1064 error:
1065   return 0;
1066 }
1067
1068 #ifndef DISCOVER_ONLY
1069 /* Write the protective MBR (to keep DOS happy) */
1070 static int
1071 _write_pmbr (PedDevice *dev)
1072 {
1073   /* The UEFI spec is not clear about what to do with the following
1074      elements of the Protective MBR (pmbr): BootCode (0-440B),
1075      UniqueMBRSignature (440B-444B) and Unknown (444B-446B).
1076      With this in mind, we try not to modify these elements.  */
1077   void *s0;
1078   if (!ptt_read_sector (dev, 0, &s0))
1079     return 0;
1080   LegacyMBR_t *pmbr = s0;
1081
1082   /* Zero out the legacy partitions.  */
1083   memset (pmbr->PartitionRecord, 0, sizeof pmbr->PartitionRecord);
1084
1085   pmbr->Signature = PED_CPU_TO_LE16 (MSDOS_MBR_SIGNATURE);
1086   pmbr->PartitionRecord[0].OSType = EFI_PMBR_OSTYPE_EFI;
1087   pmbr->PartitionRecord[0].StartSector = 1;
1088   pmbr->PartitionRecord[0].EndHead = 0xFE;
1089   pmbr->PartitionRecord[0].EndSector = 0xFF;
1090   pmbr->PartitionRecord[0].EndTrack = 0xFF;
1091   pmbr->PartitionRecord[0].StartingLBA = PED_CPU_TO_LE32 (1);
1092   if ((dev->length - 1ULL) > 0xFFFFFFFFULL)
1093     pmbr->PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32 (0xFFFFFFFF);
1094   else
1095     pmbr->PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32 (dev->length - 1UL);
1096
1097   int write_ok = ped_device_write (dev, pmbr, GPT_PMBR_LBA,
1098                                    GPT_PMBR_SECTORS);
1099   free (s0);
1100   return write_ok;
1101 }
1102
1103 static int
1104 _generate_header (const PedDisk *disk, int alternate, uint32_t ptes_crc,
1105                   GuidPartitionTableHeader_t **gpt_p)
1106 {
1107   GPTDiskData *gpt_disk_data = disk->disk_specific;
1108   GuidPartitionTableHeader_t *gpt;
1109
1110   *gpt_p = pth_new_zeroed (disk->dev);
1111
1112   gpt = *gpt_p;
1113
1114   gpt->Signature = PED_CPU_TO_LE64 (GPT_HEADER_SIGNATURE);
1115   gpt->Revision = PED_CPU_TO_LE32 (GPT_HEADER_REVISION_V1_00);
1116
1117   /* per 1.00 spec */
1118   gpt->HeaderSize = PED_CPU_TO_LE32 (pth_get_size_static (disk->dev));
1119   gpt->HeaderCRC32 = 0;
1120   gpt->Reserved1 = 0;
1121
1122   if (alternate)
1123     {
1124       PedSector ptes_size = gpt_disk_data->entry_count
1125         * sizeof (GuidPartitionEntry_t) / disk->dev->sector_size;
1126
1127       gpt->MyLBA = PED_CPU_TO_LE64 (disk->dev->length - 1);
1128       gpt->AlternateLBA = PED_CPU_TO_LE64 (1);
1129       gpt->PartitionEntryLBA
1130         = PED_CPU_TO_LE64 (disk->dev->length - 1 - ptes_size);
1131     }
1132   else
1133     {
1134       gpt->MyLBA = PED_CPU_TO_LE64 (1);
1135       gpt->AlternateLBA = PED_CPU_TO_LE64 (disk->dev->length - 1);
1136       gpt->PartitionEntryLBA = PED_CPU_TO_LE64 (2);
1137     }
1138
1139   gpt->FirstUsableLBA = PED_CPU_TO_LE64 (gpt_disk_data->data_area.start);
1140   gpt->LastUsableLBA = PED_CPU_TO_LE64 (gpt_disk_data->data_area.end);
1141   gpt->DiskGUID = gpt_disk_data->uuid;
1142   gpt->NumberOfPartitionEntries
1143     = PED_CPU_TO_LE32 (gpt_disk_data->entry_count);
1144   gpt->SizeOfPartitionEntry = PED_CPU_TO_LE32 (sizeof (GuidPartitionEntry_t));
1145   gpt->PartitionEntryArrayCRC32 = PED_CPU_TO_LE32 (ptes_crc);
1146
1147   uint32_t crc;
1148   if (pth_crc32 (disk->dev, gpt, &crc) != 0)
1149     return 1;
1150
1151   gpt->HeaderCRC32 = PED_CPU_TO_LE32 (crc);
1152   return 0;
1153 }
1154
1155 static void
1156 _partition_generate_part_entry (PedPartition *part, GuidPartitionEntry_t *pte)
1157 {
1158   GPTPartitionData *gpt_part_data = part->disk_specific;
1159   unsigned int i;
1160
1161   PED_ASSERT (gpt_part_data != NULL, return);
1162
1163   pte->PartitionTypeGuid = gpt_part_data->type;
1164   pte->UniquePartitionGuid = gpt_part_data->uuid;
1165   pte->StartingLBA = PED_CPU_TO_LE64 (part->geom.start);
1166   pte->EndingLBA = PED_CPU_TO_LE64 (part->geom.end);
1167   memset (&pte->Attributes, 0, sizeof (GuidPartitionEntryAttributes_t));
1168
1169   if (gpt_part_data->hidden)
1170     pte->Attributes.RequiredToFunction = 1;
1171
1172   for (i = 0; i < 72 / sizeof (efi_char16_t); i++)
1173     pte->PartitionName[i]
1174       = (efi_char16_t) PED_CPU_TO_LE16 ((uint16_t) gpt_part_data->name[i]);
1175 }
1176
1177 static int
1178 gpt_write (const PedDisk *disk)
1179 {
1180   GPTDiskData *gpt_disk_data;
1181   GuidPartitionEntry_t *ptes;
1182   uint32_t ptes_crc;
1183   uint8_t *pth_raw;
1184   GuidPartitionTableHeader_t *gpt;
1185   PedPartition *part;
1186   int ptes_size;
1187
1188   PED_ASSERT (disk != NULL, goto error);
1189   PED_ASSERT (disk->dev != NULL, goto error);
1190   PED_ASSERT (disk->disk_specific != NULL, goto error);
1191
1192   gpt_disk_data = disk->disk_specific;
1193
1194   ptes_size = sizeof (GuidPartitionEntry_t) * gpt_disk_data->entry_count;
1195   ptes = (GuidPartitionEntry_t *) ped_malloc (ptes_size);
1196   if (!ptes)
1197     goto error;
1198   memset (ptes, 0, ptes_size);
1199   for (part = ped_disk_next_partition (disk, NULL); part;
1200        part = ped_disk_next_partition (disk, part))
1201     {
1202       if (part->type != 0)
1203         continue;
1204       _partition_generate_part_entry (part, &ptes[part->num - 1]);
1205     }
1206
1207   ptes_crc = efi_crc32 (ptes, ptes_size);
1208
1209   /* Write protective MBR */
1210   if (!_write_pmbr (disk->dev))
1211     goto error_free_ptes;
1212
1213   /* Write PTH and PTEs */
1214   if (_generate_header (disk, 0, ptes_crc, &gpt) != 0)
1215     goto error_free_ptes;
1216   if ((pth_raw = pth_get_raw (disk->dev, gpt)) == NULL)
1217     goto error_free_ptes;
1218   pth_free (gpt);
1219   bool write_ok = ped_device_write (disk->dev, pth_raw, 1, 1);
1220   free (pth_raw);
1221   if (!write_ok)
1222     goto error_free_ptes;
1223   if (!ped_device_write (disk->dev, ptes, 2,
1224                          ptes_size / disk->dev->sector_size))
1225     goto error_free_ptes;
1226
1227   /* Write Alternate PTH & PTEs */
1228   if (_generate_header (disk, 1, ptes_crc, &gpt) != 0)
1229     goto error_free_ptes;
1230   if ((pth_raw = pth_get_raw (disk->dev, gpt)) == NULL)
1231     goto error_free_ptes;
1232   pth_free (gpt);
1233   write_ok = ped_device_write (disk->dev, pth_raw, disk->dev->length - 1, 1);
1234   free (pth_raw);
1235   if (!write_ok)
1236     goto error_free_ptes;
1237   if (!ped_device_write (disk->dev, ptes,
1238                          disk->dev->length - 1 -
1239                          ptes_size / disk->dev->sector_size,
1240                          ptes_size / disk->dev->sector_size))
1241     goto error_free_ptes;
1242
1243   free (ptes);
1244   return ped_device_sync (disk->dev);
1245
1246   free (pth_raw);
1247 error_free_ptes:
1248   free (ptes);
1249 error:
1250   return 0;
1251 }
1252 #endif /* !DISCOVER_ONLY */
1253
1254 static int
1255 add_metadata_part (PedDisk *disk, PedSector start, PedSector length)
1256 {
1257   PedPartition *part;
1258   PedConstraint *constraint_exact;
1259   PED_ASSERT (disk != NULL, return 0);
1260
1261   part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
1262                             start, start + length - 1);
1263   if (!part)
1264     goto error;
1265
1266   constraint_exact = ped_constraint_exact (&part->geom);
1267   if (!ped_disk_add_partition (disk, part, constraint_exact))
1268     goto error_destroy_constraint;
1269   ped_constraint_destroy (constraint_exact);
1270   return 1;
1271
1272 error_destroy_constraint:
1273   ped_constraint_destroy (constraint_exact);
1274   ped_partition_destroy (part);
1275 error:
1276   return 0;
1277 }
1278
1279 static PedPartition *
1280 gpt_partition_new (const PedDisk *disk,
1281                    PedPartitionType part_type,
1282                    const PedFileSystemType *fs_type, PedSector start,
1283                    PedSector end)
1284 {
1285   PedPartition *part;
1286   GPTPartitionData *gpt_part_data;
1287
1288   part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
1289   if (!part)
1290     goto error;
1291
1292   if (part_type != 0)
1293     return part;
1294
1295   gpt_part_data = part->disk_specific =
1296     ped_malloc (sizeof (GPTPartitionData));
1297   if (!gpt_part_data)
1298     goto error_free_part;
1299
1300   gpt_part_data->type = PARTITION_BASIC_DATA_GUID;
1301   gpt_part_data->lvm = 0;
1302   gpt_part_data->raid = 0;
1303   gpt_part_data->boot = 0;
1304   gpt_part_data->bios_grub = 0;
1305   gpt_part_data->hp_service = 0;
1306   gpt_part_data->hidden = 0;
1307   gpt_part_data->msftres = 0;
1308   uuid_generate ((unsigned char *) &gpt_part_data->uuid);
1309   swap_uuid_and_efi_guid ((unsigned char *) (&gpt_part_data->uuid));
1310   memset (gpt_part_data->name, 0, sizeof gpt_part_data->name);
1311   return part;
1312
1313 error_free_part:
1314   _ped_partition_free (part);
1315 error:
1316   return NULL;
1317 }
1318
1319 static PedPartition *
1320 gpt_partition_duplicate (const PedPartition *part)
1321 {
1322   PedPartition *result;
1323   GPTPartitionData *part_data = part->disk_specific;
1324   GPTPartitionData *result_data;
1325
1326   result = _ped_partition_alloc (part->disk, part->type, part->fs_type,
1327                                  part->geom.start, part->geom.end);
1328   if (!result)
1329     goto error;
1330   result->num = part->num;
1331
1332   if (result->type != 0)
1333     return result;
1334
1335   result_data = result->disk_specific =
1336     ped_malloc (sizeof (GPTPartitionData));
1337   if (!result_data)
1338     goto error_free_part;
1339
1340   result_data->type = part_data->type;
1341   result_data->uuid = part_data->uuid;
1342   strcpy (result_data->name, part_data->name);
1343   return result;
1344
1345 error_free_part:
1346   _ped_partition_free (result);
1347 error:
1348   return NULL;
1349 }
1350
1351 static void
1352 gpt_partition_destroy (PedPartition *part)
1353 {
1354   if (part->type == 0)
1355     {
1356       PED_ASSERT (part->disk_specific != NULL, return);
1357       free (part->disk_specific);
1358     }
1359
1360   _ped_partition_free (part);
1361 }
1362
1363 static int
1364 gpt_partition_set_system (PedPartition *part,
1365                           const PedFileSystemType *fs_type)
1366 {
1367   GPTPartitionData *gpt_part_data = part->disk_specific;
1368
1369   PED_ASSERT (gpt_part_data != NULL, return 0);
1370
1371   part->fs_type = fs_type;
1372
1373   if (gpt_part_data->lvm)
1374     {
1375       gpt_part_data->type = PARTITION_LVM_GUID;
1376       return 1;
1377     }
1378   if (gpt_part_data->raid)
1379     {
1380       gpt_part_data->type = PARTITION_RAID_GUID;
1381       return 1;
1382     }
1383   if (gpt_part_data->boot)
1384     {
1385       gpt_part_data->type = PARTITION_SYSTEM_GUID;
1386       return 1;
1387     }
1388   if (gpt_part_data->bios_grub)
1389     {
1390       gpt_part_data->type = PARTITION_BIOS_GRUB_GUID;
1391       return 1;
1392     }
1393   if (gpt_part_data->hp_service)
1394     {
1395       gpt_part_data->type = PARTITION_HPSERVICE_GUID;
1396       return 1;
1397     }
1398   if (gpt_part_data->msftres)
1399     {
1400       gpt_part_data->type = PARTITION_MSFT_RESERVED_GUID;
1401       return 1;
1402     }
1403
1404   if (fs_type)
1405     {
1406       if (strncmp (fs_type->name, "fat", 3) == 0
1407           || strcmp (fs_type->name, "ntfs") == 0)
1408         {
1409           gpt_part_data->type = PARTITION_BASIC_DATA_GUID;
1410           return 1;
1411         }
1412       if (strncmp (fs_type->name, "hfs", 3) == 0)
1413         {
1414           gpt_part_data->type = PARTITION_APPLE_HFS_GUID;
1415           return 1;
1416         }
1417       if (strstr (fs_type->name, "swap"))
1418         {
1419           gpt_part_data->type = PARTITION_SWAP_GUID;
1420           return 1;
1421         }
1422     }
1423
1424   gpt_part_data->type = PARTITION_BASIC_DATA_GUID;
1425   return 1;
1426 }
1427
1428 /* Allocate metadata partitions for the GPTH and PTES */
1429 static int
1430 gpt_alloc_metadata (PedDisk *disk)
1431 {
1432   PedSector gptlength, pteslength = 0;
1433   GPTDiskData *gpt_disk_data;
1434
1435   PED_ASSERT (disk != NULL, return 0);
1436   PED_ASSERT (disk->dev != NULL, return 0);
1437   PED_ASSERT (disk->disk_specific != NULL, return 0);
1438   gpt_disk_data = disk->disk_specific;
1439
1440   gptlength = ped_div_round_up (sizeof (GuidPartitionTableHeader_t),
1441                                 disk->dev->sector_size);
1442   pteslength = ped_div_round_up (gpt_disk_data->entry_count
1443                                  * sizeof (GuidPartitionEntry_t),
1444                                  disk->dev->sector_size);
1445
1446   /* metadata at the start of the disk includes the MBR */
1447   if (!add_metadata_part (disk, GPT_PMBR_LBA,
1448                           GPT_PMBR_SECTORS + gptlength + pteslength))
1449     return 0;
1450
1451   /* metadata at the end of the disk */
1452   if (!add_metadata_part (disk, disk->dev->length - gptlength - pteslength,
1453                           gptlength + pteslength))
1454     return 0;
1455
1456   return 1;
1457 }
1458
1459 /* Does nothing, as the read/new/destroy functions maintain part->num */
1460 static int
1461 gpt_partition_enumerate (PedPartition *part)
1462 {
1463   GPTDiskData *gpt_disk_data = part->disk->disk_specific;
1464   int i;
1465
1466   /* never change the partition numbers */
1467   if (part->num != -1)
1468     return 1;
1469
1470   for (i = 1; i <= gpt_disk_data->entry_count; i++)
1471     {
1472       if (!ped_disk_get_partition (part->disk, i))
1473         {
1474           part->num = i;
1475           return 1;
1476         }
1477     }
1478
1479   PED_ASSERT (0, return 0);
1480
1481   return 0;                     /* used if debug is disabled */
1482 }
1483
1484 static int
1485 gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
1486 {
1487   GPTPartitionData *gpt_part_data;
1488   PED_ASSERT (part != NULL, return 0);
1489   PED_ASSERT (part->disk_specific != NULL, return 0);
1490   gpt_part_data = part->disk_specific;
1491
1492   switch (flag)
1493     {
1494     case PED_PARTITION_BOOT:
1495       gpt_part_data->boot = state;
1496       if (state)
1497         gpt_part_data->raid
1498           = gpt_part_data->lvm
1499           = gpt_part_data->bios_grub
1500           = gpt_part_data->hp_service = gpt_part_data->msftres = 0;
1501       return gpt_partition_set_system (part, part->fs_type);
1502     case PED_PARTITION_BIOS_GRUB:
1503       gpt_part_data->bios_grub = state;
1504       if (state)
1505         gpt_part_data->raid
1506           = gpt_part_data->lvm
1507           = gpt_part_data->boot
1508           = gpt_part_data->hp_service = gpt_part_data->msftres = 0;
1509       return gpt_partition_set_system (part, part->fs_type);
1510     case PED_PARTITION_RAID:
1511       gpt_part_data->raid = state;
1512       if (state)
1513         gpt_part_data->boot
1514           = gpt_part_data->lvm
1515           = gpt_part_data->bios_grub
1516           = gpt_part_data->hp_service = gpt_part_data->msftres = 0;
1517       return gpt_partition_set_system (part, part->fs_type);
1518     case PED_PARTITION_LVM:
1519       gpt_part_data->lvm = state;
1520       if (state)
1521         gpt_part_data->boot
1522           = gpt_part_data->raid
1523           = gpt_part_data->bios_grub
1524           = gpt_part_data->hp_service = gpt_part_data->msftres = 0;
1525       return gpt_partition_set_system (part, part->fs_type);
1526     case PED_PARTITION_HPSERVICE:
1527       gpt_part_data->hp_service = state;
1528       if (state)
1529         gpt_part_data->boot
1530           = gpt_part_data->raid
1531           = gpt_part_data->lvm
1532           = gpt_part_data->bios_grub = gpt_part_data->msftres = 0;
1533       return gpt_partition_set_system (part, part->fs_type);
1534     case PED_PARTITION_MSFT_RESERVED:
1535       gpt_part_data->msftres = state;
1536       if (state)
1537         gpt_part_data->boot
1538           = gpt_part_data->raid
1539           = gpt_part_data->lvm
1540           = gpt_part_data->bios_grub = gpt_part_data->hp_service = 0;
1541       return gpt_partition_set_system (part, part->fs_type);
1542     case PED_PARTITION_HIDDEN:
1543       gpt_part_data->hidden = state;
1544       return 1;
1545     case PED_PARTITION_SWAP:
1546     case PED_PARTITION_ROOT:
1547     case PED_PARTITION_LBA:
1548     default:
1549       return 0;
1550     }
1551   return 1;
1552 }
1553
1554 static int
1555 gpt_partition_get_flag (const PedPartition *part, PedPartitionFlag flag)
1556 {
1557   GPTPartitionData *gpt_part_data;
1558   PED_ASSERT (part->disk_specific != NULL, return 0);
1559   gpt_part_data = part->disk_specific;
1560
1561   switch (flag)
1562     {
1563     case PED_PARTITION_RAID:
1564       return gpt_part_data->raid;
1565     case PED_PARTITION_LVM:
1566       return gpt_part_data->lvm;
1567     case PED_PARTITION_BOOT:
1568       return gpt_part_data->boot;
1569     case PED_PARTITION_BIOS_GRUB:
1570       return gpt_part_data->bios_grub;
1571     case PED_PARTITION_HPSERVICE:
1572       return gpt_part_data->hp_service;
1573     case PED_PARTITION_MSFT_RESERVED:
1574       return gpt_part_data->msftres;
1575     case PED_PARTITION_HIDDEN:
1576       return gpt_part_data->hidden;
1577     case PED_PARTITION_SWAP:
1578     case PED_PARTITION_LBA:
1579     case PED_PARTITION_ROOT:
1580     default:
1581       return 0;
1582     }
1583   return 0;
1584 }
1585
1586 static int
1587 gpt_partition_is_flag_available (const PedPartition *part,
1588                                  PedPartitionFlag flag)
1589 {
1590   switch (flag)
1591     {
1592     case PED_PARTITION_RAID:
1593     case PED_PARTITION_LVM:
1594     case PED_PARTITION_BOOT:
1595     case PED_PARTITION_BIOS_GRUB:
1596     case PED_PARTITION_HPSERVICE:
1597     case PED_PARTITION_MSFT_RESERVED:
1598     case PED_PARTITION_HIDDEN:
1599       return 1;
1600     case PED_PARTITION_SWAP:
1601     case PED_PARTITION_ROOT:
1602     case PED_PARTITION_LBA:
1603     default:
1604       return 0;
1605     }
1606   return 0;
1607 }
1608
1609 static void
1610 gpt_partition_set_name (PedPartition *part, const char *name)
1611 {
1612   GPTPartitionData *gpt_part_data = part->disk_specific;
1613
1614   strncpy (gpt_part_data->name, name, 36);
1615   gpt_part_data->name[36] = 0;
1616 }
1617
1618 static const char *
1619 gpt_partition_get_name (const PedPartition *part)
1620 {
1621   GPTPartitionData *gpt_part_data = part->disk_specific;
1622   return gpt_part_data->name;
1623 }
1624
1625 static int
1626 gpt_get_max_primary_partition_count (const PedDisk *disk)
1627 {
1628   const GPTDiskData *gpt_disk_data = disk->disk_specific;
1629   return gpt_disk_data->entry_count;
1630 }
1631
1632 /*
1633  * From (http://developer.apple.com/technotes/tn2006/tn2166.html Chapter 5).
1634  * According to the specs the first LBA (LBA0) is not relevant (it exists
1635  * to maintain compatibility).  on the second LBA(LBA1) gpt places the
1636  * header.  The header is as big as the block size.  After the header we
1637  * find the Entry array.  Each element of said array, describes each
1638  * partition.  One can have as much elements as can fit between the end of
1639  * the second LBA (where the header ends) and the FirstUsableLBA.
1640  * FirstUsableLBA is the first logical block that is used for contents
1641  * and is defined in header.
1642  *
1643  * /---------------------------------------------------\
1644  * | BLOCK0 | HEADER | Entry Array | First Usable LBA  |
1645  * |        | BLOCK1 |             |                   |
1646  * \---------------------------------------------------/
1647  *                  /              \
1648  *     /----------/                  \----------\
1649  *     /-----------------------------------------\
1650  *     |  E1  |  E2  |  E3  |...............| EN |
1651  *     \-----------------------------------------/
1652  *
1653  * The number of possible partitions or supported partitions is:
1654  * SP = FirstUsableLBA*Blocksize - 2*Blocksize / SizeOfPartitionEntry
1655  * SP = Blocksize(FirstusableLBA - 2) / SizeOfPartitoinEntry
1656  */
1657 static bool
1658 gpt_get_max_supported_partition_count (const PedDisk *disk, int *max_n)
1659 {
1660   GuidPartitionTableHeader_t *pth = NULL;
1661   uint8_t *pth_raw = ped_malloc (pth_get_size (disk->dev));
1662
1663   if (ped_device_read (disk->dev, pth_raw, 1, GPT_HEADER_SECTORS)
1664       || ped_device_read (disk->dev, pth_raw,
1665                           disk->dev->length, GPT_HEADER_SECTORS))
1666     pth = pth_new_from_raw (disk->dev, pth_raw);
1667   free (pth_raw);
1668
1669   if (pth == NULL)
1670     return false;
1671
1672   *max_n = (disk->dev->sector_size * (pth->FirstUsableLBA - 2)
1673             / PED_LE32_TO_CPU (pth->SizeOfPartitionEntry));
1674   pth_free (pth);
1675   return true;
1676 }
1677
1678 static PedConstraint *
1679 _non_metadata_constraint (const PedDisk *disk)
1680 {
1681   GPTDiskData *gpt_disk_data = disk->disk_specific;
1682
1683   return ped_constraint_new_from_max (&gpt_disk_data->data_area);
1684 }
1685
1686 static int
1687 gpt_partition_align (PedPartition *part, const PedConstraint *constraint)
1688 {
1689   PED_ASSERT (part != NULL, return 0);
1690
1691   if (_ped_partition_attempt_align (part, constraint,
1692                                     _non_metadata_constraint (part->disk)))
1693     return 1;
1694
1695 #ifndef DISCOVER_ONLY
1696   ped_exception_throw (PED_EXCEPTION_ERROR,
1697                        PED_EXCEPTION_CANCEL,
1698                        _("Unable to satisfy all constraints on the partition."));
1699 #endif
1700   return 0;
1701 }
1702
1703 static bool
1704 gpt_partition_check (const PedPartition *part)
1705 {
1706   return true;
1707 }
1708
1709 #ifdef DISCOVER_ONLY
1710 # define NULL_IF_DISCOVER_ONLY(val) NULL
1711 #else
1712 # define NULL_IF_DISCOVER_ONLY(val) val
1713 #endif
1714
1715 static PedDiskOps gpt_disk_ops =
1716 {
1717   probe:                        gpt_probe,
1718   clobber:                      NULL_IF_DISCOVER_ONLY (gpt_clobber),
1719   alloc:                        gpt_alloc,
1720   duplicate:                    gpt_duplicate,
1721   free:                         gpt_free,
1722   read:                         gpt_read,
1723   write:                        NULL_IF_DISCOVER_ONLY (gpt_write),
1724   partition_new:                gpt_partition_new,
1725   partition_duplicate:          gpt_partition_duplicate,
1726   partition_destroy:            gpt_partition_destroy,
1727   partition_set_system:         gpt_partition_set_system,
1728   partition_set_flag:           gpt_partition_set_flag,
1729   partition_get_flag:           gpt_partition_get_flag,
1730   partition_is_flag_available:  gpt_partition_is_flag_available,
1731   partition_set_name:           gpt_partition_set_name,
1732   partition_get_name:           gpt_partition_get_name,
1733   partition_align:              gpt_partition_align,
1734   partition_enumerate:          gpt_partition_enumerate,
1735   partition_check:              gpt_partition_check,
1736   alloc_metadata:               gpt_alloc_metadata,
1737   get_max_primary_partition_count: gpt_get_max_primary_partition_count,
1738   get_max_supported_partition_count: gpt_get_max_supported_partition_count
1739 };
1740
1741 static PedDiskType gpt_disk_type =
1742 {
1743   next:         NULL,
1744   name:         "gpt",
1745   ops:          &gpt_disk_ops,
1746   features:     PED_DISK_TYPE_PARTITION_NAME
1747 };
1748
1749 void
1750 ped_disk_gpt_init ()
1751 {
1752   PED_ASSERT (sizeof (GuidPartitionEntryAttributes_t) == 8, return);
1753   PED_ASSERT (sizeof (GuidPartitionEntry_t) == 128, return);
1754
1755   ped_disk_type_register (&gpt_disk_type);
1756 }
1757
1758 void
1759 ped_disk_gpt_done ()
1760 {
1761   ped_disk_type_unregister (&gpt_disk_type);
1762 }