OSDN Git Service

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