OSDN Git Service

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