OSDN Git Service

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