OSDN Git Service

gpt: plug two gpt-header leaks 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   else
873     pth_free (pri);
874
875   PedSector backup_sector_num =
876     (valid_primary
877      ? PED_LE64_TO_CPU (pri->AlternateLBA)
878      : dev->length - 1);
879
880   void *s_bak;
881   if (!ptt_read_sector (dev, backup_sector_num, &s_bak))
882     return 1;
883   t = pth_new_from_raw (dev, s_bak);
884   free (s_bak);
885   if (t == NULL)
886     return 1;
887
888   GuidPartitionTableHeader_t *bak = t;
889   if (_header_is_valid (disk, bak, backup_sector_num))
890     {
891       *backup_gpt = bak;
892       *backup_sector_num_p = backup_sector_num;
893     }
894   else
895     pth_free (bak);
896
897   return 0;
898 }
899
900 /************************************************************
901  *  Intel is changing the EFI Spec. (after v1.02) to say that a
902  *  disk is considered to have a GPT label only if the GPT
903  *  structures are correct, and the MBR is actually a Protective
904  *  MBR (has one 0xEE type partition).
905  *  Problem occurs when a GPT-partitioned disk is then
906  *  edited with a legacy (non-GPT-aware) application, such as
907  *  fdisk (which doesn't generally erase the PGPT or AGPT).
908  *  How should such a disk get handled?  As a GPT disk (throwing
909  *  away the fdisk changes), or as an MSDOS disk (throwing away
910  *  the GPT information).  Previously, I've taken the GPT-is-right,
911  *  MBR is wrong, approach, to stay consistent with the EFI Spec.
912  *  Intel disagrees, saying the disk should then be treated
913  *  as having a msdos label, not a GPT label.  If this is true,
914  *  then what's the point of having an AGPT, since if the PGPT
915  *  is screwed up, likely the PMBR is too, and the PMBR becomes
916  *  a single point of failure.
917  *  So, in the Linux kernel, I'm going to test for PMBR, and
918  *  warn if it's not there, and treat the disk as MSDOS, with a note
919  *  for users to use Parted to "fix up" their disk if they
920  *  really want it to be considered GPT.
921  ************************************************************/
922 static int
923 gpt_read (PedDisk *disk)
924 {
925   GPTDiskData *gpt_disk_data = disk->disk_specific;
926   int i;
927 #ifndef DISCOVER_ONLY
928   int write_back = 1;
929 #endif
930
931   ped_disk_delete_all (disk);
932
933   /* motivation: let the user decide about the pmbr... during
934      ped_disk_probe(), they probably didn't get a choice... */
935   if (!gpt_probe (disk->dev))
936     goto error;
937
938   GuidPartitionTableHeader_t *gpt = NULL;
939   GuidPartitionTableHeader_t *primary_gpt;
940   GuidPartitionTableHeader_t *backup_gpt;
941   PedSector backup_sector_num;
942   int read_failure = gpt_read_headers (disk, &primary_gpt, &backup_gpt,
943                                        &backup_sector_num);
944   if (read_failure)
945     {
946       /* This includes the case in which there used to be a GPT partition
947          table here, with an alternate LBA that extended beyond the current
948          end-of-device.  It's treated as a non-match.  */
949
950       /* Another possibility:
951          The primary header is ok, but backup is corrupt.
952          In the UEFI spec, this means the primary GUID table
953          is officially invalid.  */
954       pth_free (backup_gpt);
955       pth_free (primary_gpt);
956       return 0;
957     }
958
959   if (primary_gpt && backup_gpt)
960     {
961       /* Both are valid.  */
962       if (PED_LE64_TO_CPU (primary_gpt->AlternateLBA) < disk->dev->length - 1)
963         {
964 #ifndef DISCOVER_ONLY
965           switch (ped_exception_throw
966                   (PED_EXCEPTION_ERROR,
967                    (PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL
968                     | PED_EXCEPTION_IGNORE),
969                    _("The backup GPT table is not at the end of the disk, as it "
970                      "should be.  This might mean that another operating system "
971                      "believes the disk is smaller.  Fix, by moving the backup "
972                      "to the end (and removing the old backup)?")))
973             {
974             case PED_EXCEPTION_CANCEL:
975               goto error_free_gpt;
976             case PED_EXCEPTION_FIX:
977               ptt_clear_sectors (disk->dev,
978                                  PED_LE64_TO_CPU (primary_gpt->AlternateLBA), 1);
979               break;
980             default:
981               write_back = 0;
982               break;
983             }
984 #endif /* !DISCOVER_ONLY */
985         }
986       gpt = primary_gpt;
987       pth_free (backup_gpt);
988     }
989   else if (!primary_gpt && !backup_gpt)
990     {
991       /* Both are corrupt.  */
992       ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
993                            _("Both the primary and backup GPT tables "
994                              "are corrupt.  Try making a fresh table, "
995                              "and using Parted's rescue feature to "
996                              "recover partitions."));
997       goto error;
998     }
999   else if (primary_gpt && !backup_gpt)
1000     {
1001       /* The primary header is ok, but backup is corrupt.  */
1002       if (ped_exception_throw
1003           (PED_EXCEPTION_ERROR, PED_EXCEPTION_OK_CANCEL,
1004            _("The backup GPT table is corrupt, but the "
1005              "primary appears OK, so that will be used."))
1006           == PED_EXCEPTION_CANCEL)
1007         goto error_free_gpt;
1008
1009       gpt = primary_gpt;
1010     }
1011   else /* !primary_gpt && backup_gpt */
1012     {
1013       /* primary GPT corrupt, backup is ok.  */
1014       if (ped_exception_throw
1015           (PED_EXCEPTION_ERROR, PED_EXCEPTION_OK_CANCEL,
1016            _("The primary GPT table is corrupt, but the "
1017              "backup appears OK, so that will be used."))
1018           == PED_EXCEPTION_CANCEL)
1019         goto error_free_gpt;
1020
1021       gpt = backup_gpt;
1022     }
1023   backup_gpt = NULL;
1024   primary_gpt = NULL;
1025
1026   if (!_parse_header (disk, gpt, &write_back))
1027     goto error_free_gpt;
1028
1029   size_t ptes_bytes;
1030   void *ptes = gpt_read_PE_array (disk, gpt, &ptes_bytes);
1031   if (ptes == NULL)
1032     goto error_free_gpt;
1033
1034   uint32_t ptes_crc = efi_crc32 (ptes, ptes_bytes);
1035   if (ptes_crc != gpt->PartitionEntryArrayCRC32)
1036     {
1037       ped_exception_throw
1038         (PED_EXCEPTION_ERROR,
1039          PED_EXCEPTION_CANCEL,
1040          _("primary partition table array CRC mismatch"));
1041       goto error_free_ptes;
1042     }
1043
1044   uint32_t p_ent_size = PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry);
1045   for (i = 0; i < gpt_disk_data->entry_count; i++)
1046     {
1047       GuidPartitionEntry_t *pte
1048         = (GuidPartitionEntry_t *) ((char *) ptes + i * p_ent_size);
1049       PedPartition *part;
1050       PedConstraint *constraint_exact;
1051
1052       if (!guid_cmp (pte->PartitionTypeGuid, UNUSED_ENTRY_GUID))
1053         continue;
1054
1055       part = _parse_part_entry (disk, pte);
1056       if (!part)
1057         goto error_delete_all;
1058
1059       part->fs_type = ped_file_system_probe (&part->geom);
1060       part->num = i + 1;
1061
1062       constraint_exact = ped_constraint_exact (&part->geom);
1063       if (!ped_disk_add_partition (disk, part, constraint_exact))
1064         {
1065           ped_partition_destroy (part);
1066           goto error_delete_all;
1067         }
1068       ped_constraint_destroy (constraint_exact);
1069     }
1070   free (ptes);
1071
1072 #ifndef DISCOVER_ONLY
1073   if (write_back)
1074     ped_disk_commit_to_dev (disk);
1075 #endif
1076
1077   pth_free (gpt);
1078   return 1;
1079
1080 error_delete_all:
1081   ped_disk_delete_all (disk);
1082 error_free_ptes:
1083   free (ptes);
1084 error_free_gpt:
1085   pth_free (primary_gpt);
1086   pth_free (backup_gpt);
1087   pth_free (gpt);
1088 error:
1089   return 0;
1090 }
1091
1092 #ifndef DISCOVER_ONLY
1093 /* Write the protective MBR (to keep DOS happy) */
1094 static int
1095 _write_pmbr (PedDevice *dev)
1096 {
1097   /* The UEFI spec is not clear about what to do with the following
1098      elements of the Protective MBR (pmbr): BootCode (0-440B),
1099      UniqueMBRSignature (440B-444B) and Unknown (444B-446B).
1100      With this in mind, we try not to modify these elements.  */
1101   void *s0;
1102   if (!ptt_read_sector (dev, 0, &s0))
1103     return 0;
1104   LegacyMBR_t *pmbr = s0;
1105
1106   /* Zero out the legacy partitions.  */
1107   memset (pmbr->PartitionRecord, 0, sizeof pmbr->PartitionRecord);
1108
1109   pmbr->Signature = PED_CPU_TO_LE16 (MSDOS_MBR_SIGNATURE);
1110   pmbr->PartitionRecord[0].OSType = EFI_PMBR_OSTYPE_EFI;
1111   pmbr->PartitionRecord[0].StartSector = 1;
1112   pmbr->PartitionRecord[0].EndHead = 0xFE;
1113   pmbr->PartitionRecord[0].EndSector = 0xFF;
1114   pmbr->PartitionRecord[0].EndTrack = 0xFF;
1115   pmbr->PartitionRecord[0].StartingLBA = PED_CPU_TO_LE32 (1);
1116   if ((dev->length - 1ULL) > 0xFFFFFFFFULL)
1117     pmbr->PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32 (0xFFFFFFFF);
1118   else
1119     pmbr->PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32 (dev->length - 1UL);
1120
1121   int write_ok = ped_device_write (dev, pmbr, GPT_PMBR_LBA,
1122                                    GPT_PMBR_SECTORS);
1123   free (s0);
1124   return write_ok;
1125 }
1126
1127 static int
1128 _generate_header (const PedDisk *disk, int alternate, uint32_t ptes_crc,
1129                   GuidPartitionTableHeader_t **gpt_p)
1130 {
1131   GPTDiskData *gpt_disk_data = disk->disk_specific;
1132   GuidPartitionTableHeader_t *gpt;
1133
1134   *gpt_p = pth_new_zeroed (disk->dev);
1135
1136   gpt = *gpt_p;
1137
1138   gpt->Signature = PED_CPU_TO_LE64 (GPT_HEADER_SIGNATURE);
1139   gpt->Revision = PED_CPU_TO_LE32 (GPT_HEADER_REVISION_V1_00);
1140
1141   /* per 1.00 spec */
1142   gpt->HeaderSize = PED_CPU_TO_LE32 (pth_get_size_static (disk->dev));
1143   gpt->HeaderCRC32 = 0;
1144   gpt->Reserved1 = 0;
1145
1146   if (alternate)
1147     {
1148       PedSector ptes_size = gpt_disk_data->entry_count
1149         * sizeof (GuidPartitionEntry_t) / disk->dev->sector_size;
1150
1151       gpt->MyLBA = PED_CPU_TO_LE64 (disk->dev->length - 1);
1152       gpt->AlternateLBA = PED_CPU_TO_LE64 (1);
1153       gpt->PartitionEntryLBA
1154         = PED_CPU_TO_LE64 (disk->dev->length - 1 - ptes_size);
1155     }
1156   else
1157     {
1158       gpt->MyLBA = PED_CPU_TO_LE64 (1);
1159       gpt->AlternateLBA = PED_CPU_TO_LE64 (disk->dev->length - 1);
1160       gpt->PartitionEntryLBA = PED_CPU_TO_LE64 (2);
1161     }
1162
1163   gpt->FirstUsableLBA = PED_CPU_TO_LE64 (gpt_disk_data->data_area.start);
1164   gpt->LastUsableLBA = PED_CPU_TO_LE64 (gpt_disk_data->data_area.end);
1165   gpt->DiskGUID = gpt_disk_data->uuid;
1166   gpt->NumberOfPartitionEntries
1167     = PED_CPU_TO_LE32 (gpt_disk_data->entry_count);
1168   gpt->SizeOfPartitionEntry = PED_CPU_TO_LE32 (sizeof (GuidPartitionEntry_t));
1169   gpt->PartitionEntryArrayCRC32 = PED_CPU_TO_LE32 (ptes_crc);
1170
1171   uint32_t crc;
1172   if (pth_crc32 (disk->dev, gpt, &crc) != 0)
1173     return 1;
1174
1175   gpt->HeaderCRC32 = PED_CPU_TO_LE32 (crc);
1176   return 0;
1177 }
1178
1179 static void
1180 _partition_generate_part_entry (PedPartition *part, GuidPartitionEntry_t *pte)
1181 {
1182   GPTPartitionData *gpt_part_data = part->disk_specific;
1183   unsigned int i;
1184
1185   PED_ASSERT (gpt_part_data != NULL, return);
1186
1187   pte->PartitionTypeGuid = gpt_part_data->type;
1188   pte->UniquePartitionGuid = gpt_part_data->uuid;
1189   pte->StartingLBA = PED_CPU_TO_LE64 (part->geom.start);
1190   pte->EndingLBA = PED_CPU_TO_LE64 (part->geom.end);
1191   memset (&pte->Attributes, 0, sizeof (GuidPartitionEntryAttributes_t));
1192
1193   if (gpt_part_data->hidden)
1194     pte->Attributes.RequiredToFunction = 1;
1195
1196   for (i = 0; i < 72 / sizeof (efi_char16_t); i++)
1197     pte->PartitionName[i]
1198       = (efi_char16_t) PED_CPU_TO_LE16 ((uint16_t) gpt_part_data->name[i]);
1199 }
1200
1201 static int
1202 gpt_write (const PedDisk *disk)
1203 {
1204   GPTDiskData *gpt_disk_data;
1205   GuidPartitionEntry_t *ptes;
1206   uint32_t ptes_crc;
1207   uint8_t *pth_raw;
1208   GuidPartitionTableHeader_t *gpt;
1209   PedPartition *part;
1210   int ptes_size;
1211
1212   PED_ASSERT (disk != NULL, goto error);
1213   PED_ASSERT (disk->dev != NULL, goto error);
1214   PED_ASSERT (disk->disk_specific != NULL, goto error);
1215
1216   gpt_disk_data = disk->disk_specific;
1217
1218   ptes_size = sizeof (GuidPartitionEntry_t) * gpt_disk_data->entry_count;
1219   ptes = (GuidPartitionEntry_t *) ped_malloc (ptes_size);
1220   if (!ptes)
1221     goto error;
1222   memset (ptes, 0, ptes_size);
1223   for (part = ped_disk_next_partition (disk, NULL); part;
1224        part = ped_disk_next_partition (disk, part))
1225     {
1226       if (part->type != 0)
1227         continue;
1228       _partition_generate_part_entry (part, &ptes[part->num - 1]);
1229     }
1230
1231   ptes_crc = efi_crc32 (ptes, ptes_size);
1232
1233   /* Write protective MBR */
1234   if (!_write_pmbr (disk->dev))
1235     goto error_free_ptes;
1236
1237   /* Write PTH and PTEs */
1238   if (_generate_header (disk, 0, ptes_crc, &gpt) != 0)
1239     goto error_free_ptes;
1240   if ((pth_raw = pth_get_raw (disk->dev, gpt)) == NULL)
1241     goto error_free_ptes;
1242   pth_free (gpt);
1243   bool write_ok = ped_device_write (disk->dev, pth_raw, 1, 1);
1244   free (pth_raw);
1245   if (!write_ok)
1246     goto error_free_ptes;
1247   if (!ped_device_write (disk->dev, ptes, 2,
1248                          ptes_size / disk->dev->sector_size))
1249     goto error_free_ptes;
1250
1251   /* Write Alternate PTH & PTEs */
1252   if (_generate_header (disk, 1, ptes_crc, &gpt) != 0)
1253     goto error_free_ptes;
1254   if ((pth_raw = pth_get_raw (disk->dev, gpt)) == NULL)
1255     goto error_free_ptes;
1256   pth_free (gpt);
1257   write_ok = ped_device_write (disk->dev, pth_raw, disk->dev->length - 1, 1);
1258   free (pth_raw);
1259   if (!write_ok)
1260     goto error_free_ptes;
1261   if (!ped_device_write (disk->dev, ptes,
1262                          disk->dev->length - 1 -
1263                          ptes_size / disk->dev->sector_size,
1264                          ptes_size / disk->dev->sector_size))
1265     goto error_free_ptes;
1266
1267   free (ptes);
1268   return ped_device_sync (disk->dev);
1269
1270   free (pth_raw);
1271 error_free_ptes:
1272   free (ptes);
1273 error:
1274   return 0;
1275 }
1276 #endif /* !DISCOVER_ONLY */
1277
1278 static int
1279 add_metadata_part (PedDisk *disk, PedSector start, PedSector length)
1280 {
1281   PedPartition *part;
1282   PedConstraint *constraint_exact;
1283   PED_ASSERT (disk != NULL, return 0);
1284
1285   part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
1286                             start, start + length - 1);
1287   if (!part)
1288     goto error;
1289
1290   constraint_exact = ped_constraint_exact (&part->geom);
1291   if (!ped_disk_add_partition (disk, part, constraint_exact))
1292     goto error_destroy_constraint;
1293   ped_constraint_destroy (constraint_exact);
1294   return 1;
1295
1296 error_destroy_constraint:
1297   ped_constraint_destroy (constraint_exact);
1298   ped_partition_destroy (part);
1299 error:
1300   return 0;
1301 }
1302
1303 static PedPartition *
1304 gpt_partition_new (const PedDisk *disk,
1305                    PedPartitionType part_type,
1306                    const PedFileSystemType *fs_type, PedSector start,
1307                    PedSector end)
1308 {
1309   PedPartition *part;
1310   GPTPartitionData *gpt_part_data;
1311
1312   part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
1313   if (!part)
1314     goto error;
1315
1316   if (part_type != 0)
1317     return part;
1318
1319   gpt_part_data = part->disk_specific =
1320     ped_malloc (sizeof (GPTPartitionData));
1321   if (!gpt_part_data)
1322     goto error_free_part;
1323
1324   gpt_part_data->type = PARTITION_BASIC_DATA_GUID;
1325   gpt_part_data->lvm = 0;
1326   gpt_part_data->raid = 0;
1327   gpt_part_data->boot = 0;
1328   gpt_part_data->bios_grub = 0;
1329   gpt_part_data->hp_service = 0;
1330   gpt_part_data->hidden = 0;
1331   gpt_part_data->msftres = 0;
1332   uuid_generate ((unsigned char *) &gpt_part_data->uuid);
1333   swap_uuid_and_efi_guid ((unsigned char *) (&gpt_part_data->uuid));
1334   memset (gpt_part_data->name, 0, sizeof gpt_part_data->name);
1335   return part;
1336
1337 error_free_part:
1338   _ped_partition_free (part);
1339 error:
1340   return NULL;
1341 }
1342
1343 static PedPartition *
1344 gpt_partition_duplicate (const PedPartition *part)
1345 {
1346   PedPartition *result;
1347   GPTPartitionData *part_data = part->disk_specific;
1348   GPTPartitionData *result_data;
1349
1350   result = _ped_partition_alloc (part->disk, part->type, part->fs_type,
1351                                  part->geom.start, part->geom.end);
1352   if (!result)
1353     goto error;
1354   result->num = part->num;
1355
1356   if (result->type != 0)
1357     return result;
1358
1359   result_data = result->disk_specific =
1360     ped_malloc (sizeof (GPTPartitionData));
1361   if (!result_data)
1362     goto error_free_part;
1363
1364   result_data->type = part_data->type;
1365   result_data->uuid = part_data->uuid;
1366   strcpy (result_data->name, part_data->name);
1367   return result;
1368
1369 error_free_part:
1370   _ped_partition_free (result);
1371 error:
1372   return NULL;
1373 }
1374
1375 static void
1376 gpt_partition_destroy (PedPartition *part)
1377 {
1378   if (part->type == 0)
1379     {
1380       PED_ASSERT (part->disk_specific != NULL, return);
1381       free (part->disk_specific);
1382     }
1383
1384   _ped_partition_free (part);
1385 }
1386
1387 static int
1388 gpt_partition_set_system (PedPartition *part,
1389                           const PedFileSystemType *fs_type)
1390 {
1391   GPTPartitionData *gpt_part_data = part->disk_specific;
1392
1393   PED_ASSERT (gpt_part_data != NULL, return 0);
1394
1395   part->fs_type = fs_type;
1396
1397   if (gpt_part_data->lvm)
1398     {
1399       gpt_part_data->type = PARTITION_LVM_GUID;
1400       return 1;
1401     }
1402   if (gpt_part_data->raid)
1403     {
1404       gpt_part_data->type = PARTITION_RAID_GUID;
1405       return 1;
1406     }
1407   if (gpt_part_data->boot)
1408     {
1409       gpt_part_data->type = PARTITION_SYSTEM_GUID;
1410       return 1;
1411     }
1412   if (gpt_part_data->bios_grub)
1413     {
1414       gpt_part_data->type = PARTITION_BIOS_GRUB_GUID;
1415       return 1;
1416     }
1417   if (gpt_part_data->hp_service)
1418     {
1419       gpt_part_data->type = PARTITION_HPSERVICE_GUID;
1420       return 1;
1421     }
1422   if (gpt_part_data->msftres)
1423     {
1424       gpt_part_data->type = PARTITION_MSFT_RESERVED_GUID;
1425       return 1;
1426     }
1427
1428   if (fs_type)
1429     {
1430       if (strncmp (fs_type->name, "fat", 3) == 0
1431           || strcmp (fs_type->name, "ntfs") == 0)
1432         {
1433           gpt_part_data->type = PARTITION_BASIC_DATA_GUID;
1434           return 1;
1435         }
1436       if (strncmp (fs_type->name, "hfs", 3) == 0)
1437         {
1438           gpt_part_data->type = PARTITION_APPLE_HFS_GUID;
1439           return 1;
1440         }
1441       if (strstr (fs_type->name, "swap"))
1442         {
1443           gpt_part_data->type = PARTITION_SWAP_GUID;
1444           return 1;
1445         }
1446     }
1447
1448   gpt_part_data->type = PARTITION_BASIC_DATA_GUID;
1449   return 1;
1450 }
1451
1452 /* Allocate metadata partitions for the GPTH and PTES */
1453 static int
1454 gpt_alloc_metadata (PedDisk *disk)
1455 {
1456   PedSector gptlength, pteslength = 0;
1457   GPTDiskData *gpt_disk_data;
1458
1459   PED_ASSERT (disk != NULL, return 0);
1460   PED_ASSERT (disk->dev != NULL, return 0);
1461   PED_ASSERT (disk->disk_specific != NULL, return 0);
1462   gpt_disk_data = disk->disk_specific;
1463
1464   gptlength = ped_div_round_up (sizeof (GuidPartitionTableHeader_t),
1465                                 disk->dev->sector_size);
1466   pteslength = ped_div_round_up (gpt_disk_data->entry_count
1467                                  * sizeof (GuidPartitionEntry_t),
1468                                  disk->dev->sector_size);
1469
1470   /* metadata at the start of the disk includes the MBR */
1471   if (!add_metadata_part (disk, GPT_PMBR_LBA,
1472                           GPT_PMBR_SECTORS + gptlength + pteslength))
1473     return 0;
1474
1475   /* metadata at the end of the disk */
1476   if (!add_metadata_part (disk, disk->dev->length - gptlength - pteslength,
1477                           gptlength + pteslength))
1478     return 0;
1479
1480   return 1;
1481 }
1482
1483 /* Does nothing, as the read/new/destroy functions maintain part->num */
1484 static int
1485 gpt_partition_enumerate (PedPartition *part)
1486 {
1487   GPTDiskData *gpt_disk_data = part->disk->disk_specific;
1488   int i;
1489
1490   /* never change the partition numbers */
1491   if (part->num != -1)
1492     return 1;
1493
1494   for (i = 1; i <= gpt_disk_data->entry_count; i++)
1495     {
1496       if (!ped_disk_get_partition (part->disk, i))
1497         {
1498           part->num = i;
1499           return 1;
1500         }
1501     }
1502
1503   PED_ASSERT (0, return 0);
1504
1505   return 0;                     /* used if debug is disabled */
1506 }
1507
1508 static int
1509 gpt_partition_set_flag (PedPartition *part, PedPartitionFlag flag, int state)
1510 {
1511   GPTPartitionData *gpt_part_data;
1512   PED_ASSERT (part != NULL, return 0);
1513   PED_ASSERT (part->disk_specific != NULL, return 0);
1514   gpt_part_data = part->disk_specific;
1515
1516   switch (flag)
1517     {
1518     case PED_PARTITION_BOOT:
1519       gpt_part_data->boot = state;
1520       if (state)
1521         gpt_part_data->raid
1522           = gpt_part_data->lvm
1523           = gpt_part_data->bios_grub
1524           = gpt_part_data->hp_service = gpt_part_data->msftres = 0;
1525       return gpt_partition_set_system (part, part->fs_type);
1526     case PED_PARTITION_BIOS_GRUB:
1527       gpt_part_data->bios_grub = state;
1528       if (state)
1529         gpt_part_data->raid
1530           = gpt_part_data->lvm
1531           = gpt_part_data->boot
1532           = gpt_part_data->hp_service = gpt_part_data->msftres = 0;
1533       return gpt_partition_set_system (part, part->fs_type);
1534     case PED_PARTITION_RAID:
1535       gpt_part_data->raid = state;
1536       if (state)
1537         gpt_part_data->boot
1538           = gpt_part_data->lvm
1539           = gpt_part_data->bios_grub
1540           = gpt_part_data->hp_service = gpt_part_data->msftres = 0;
1541       return gpt_partition_set_system (part, part->fs_type);
1542     case PED_PARTITION_LVM:
1543       gpt_part_data->lvm = state;
1544       if (state)
1545         gpt_part_data->boot
1546           = gpt_part_data->raid
1547           = gpt_part_data->bios_grub
1548           = gpt_part_data->hp_service = gpt_part_data->msftres = 0;
1549       return gpt_partition_set_system (part, part->fs_type);
1550     case PED_PARTITION_HPSERVICE:
1551       gpt_part_data->hp_service = state;
1552       if (state)
1553         gpt_part_data->boot
1554           = gpt_part_data->raid
1555           = gpt_part_data->lvm
1556           = gpt_part_data->bios_grub = gpt_part_data->msftres = 0;
1557       return gpt_partition_set_system (part, part->fs_type);
1558     case PED_PARTITION_MSFT_RESERVED:
1559       gpt_part_data->msftres = state;
1560       if (state)
1561         gpt_part_data->boot
1562           = gpt_part_data->raid
1563           = gpt_part_data->lvm
1564           = gpt_part_data->bios_grub = gpt_part_data->hp_service = 0;
1565       return gpt_partition_set_system (part, part->fs_type);
1566     case PED_PARTITION_HIDDEN:
1567       gpt_part_data->hidden = state;
1568       return 1;
1569     case PED_PARTITION_SWAP:
1570     case PED_PARTITION_ROOT:
1571     case PED_PARTITION_LBA:
1572     default:
1573       return 0;
1574     }
1575   return 1;
1576 }
1577
1578 static int
1579 gpt_partition_get_flag (const PedPartition *part, PedPartitionFlag flag)
1580 {
1581   GPTPartitionData *gpt_part_data;
1582   PED_ASSERT (part->disk_specific != NULL, return 0);
1583   gpt_part_data = part->disk_specific;
1584
1585   switch (flag)
1586     {
1587     case PED_PARTITION_RAID:
1588       return gpt_part_data->raid;
1589     case PED_PARTITION_LVM:
1590       return gpt_part_data->lvm;
1591     case PED_PARTITION_BOOT:
1592       return gpt_part_data->boot;
1593     case PED_PARTITION_BIOS_GRUB:
1594       return gpt_part_data->bios_grub;
1595     case PED_PARTITION_HPSERVICE:
1596       return gpt_part_data->hp_service;
1597     case PED_PARTITION_MSFT_RESERVED:
1598       return gpt_part_data->msftres;
1599     case PED_PARTITION_HIDDEN:
1600       return gpt_part_data->hidden;
1601     case PED_PARTITION_SWAP:
1602     case PED_PARTITION_LBA:
1603     case PED_PARTITION_ROOT:
1604     default:
1605       return 0;
1606     }
1607   return 0;
1608 }
1609
1610 static int
1611 gpt_partition_is_flag_available (const PedPartition *part,
1612                                  PedPartitionFlag flag)
1613 {
1614   switch (flag)
1615     {
1616     case PED_PARTITION_RAID:
1617     case PED_PARTITION_LVM:
1618     case PED_PARTITION_BOOT:
1619     case PED_PARTITION_BIOS_GRUB:
1620     case PED_PARTITION_HPSERVICE:
1621     case PED_PARTITION_MSFT_RESERVED:
1622     case PED_PARTITION_HIDDEN:
1623       return 1;
1624     case PED_PARTITION_SWAP:
1625     case PED_PARTITION_ROOT:
1626     case PED_PARTITION_LBA:
1627     default:
1628       return 0;
1629     }
1630   return 0;
1631 }
1632
1633 static void
1634 gpt_partition_set_name (PedPartition *part, const char *name)
1635 {
1636   GPTPartitionData *gpt_part_data = part->disk_specific;
1637
1638   strncpy (gpt_part_data->name, name, 36);
1639   gpt_part_data->name[36] = 0;
1640 }
1641
1642 static const char *
1643 gpt_partition_get_name (const PedPartition *part)
1644 {
1645   GPTPartitionData *gpt_part_data = part->disk_specific;
1646   return gpt_part_data->name;
1647 }
1648
1649 static int
1650 gpt_get_max_primary_partition_count (const PedDisk *disk)
1651 {
1652   const GPTDiskData *gpt_disk_data = disk->disk_specific;
1653   return gpt_disk_data->entry_count;
1654 }
1655
1656 /*
1657  * From (http://developer.apple.com/technotes/tn2006/tn2166.html Chapter 5).
1658  * According to the specs the first LBA (LBA0) is not relevant (it exists
1659  * to maintain compatibility).  on the second LBA(LBA1) gpt places the
1660  * header.  The header is as big as the block size.  After the header we
1661  * find the Entry array.  Each element of said array, describes each
1662  * partition.  One can have as much elements as can fit between the end of
1663  * the second LBA (where the header ends) and the FirstUsableLBA.
1664  * FirstUsableLBA is the first logical block that is used for contents
1665  * and is defined in header.
1666  *
1667  * /---------------------------------------------------\
1668  * | BLOCK0 | HEADER | Entry Array | First Usable LBA  |
1669  * |        | BLOCK1 |             |                   |
1670  * \---------------------------------------------------/
1671  *                  /              \
1672  *     /----------/                  \----------\
1673  *     /-----------------------------------------\
1674  *     |  E1  |  E2  |  E3  |...............| EN |
1675  *     \-----------------------------------------/
1676  *
1677  * The number of possible partitions or supported partitions is:
1678  * SP = FirstUsableLBA*Blocksize - 2*Blocksize / SizeOfPartitionEntry
1679  * SP = Blocksize(FirstusableLBA - 2) / SizeOfPartitoinEntry
1680  */
1681 static bool
1682 gpt_get_max_supported_partition_count (const PedDisk *disk, int *max_n)
1683 {
1684   GuidPartitionTableHeader_t *pth = NULL;
1685   uint8_t *pth_raw = ped_malloc (pth_get_size (disk->dev));
1686
1687   if (ped_device_read (disk->dev, pth_raw, 1, GPT_HEADER_SECTORS)
1688       || ped_device_read (disk->dev, pth_raw,
1689                           disk->dev->length, GPT_HEADER_SECTORS))
1690     pth = pth_new_from_raw (disk->dev, pth_raw);
1691   free (pth_raw);
1692
1693   if (pth == NULL)
1694     return false;
1695
1696   *max_n = (disk->dev->sector_size * (pth->FirstUsableLBA - 2)
1697             / PED_LE32_TO_CPU (pth->SizeOfPartitionEntry));
1698   pth_free (pth);
1699   return true;
1700 }
1701
1702 static PedConstraint *
1703 _non_metadata_constraint (const PedDisk *disk)
1704 {
1705   GPTDiskData *gpt_disk_data = disk->disk_specific;
1706
1707   return ped_constraint_new_from_max (&gpt_disk_data->data_area);
1708 }
1709
1710 static int
1711 gpt_partition_align (PedPartition *part, const PedConstraint *constraint)
1712 {
1713   PED_ASSERT (part != NULL, return 0);
1714
1715   if (_ped_partition_attempt_align (part, constraint,
1716                                     _non_metadata_constraint (part->disk)))
1717     return 1;
1718
1719 #ifndef DISCOVER_ONLY
1720   ped_exception_throw (PED_EXCEPTION_ERROR,
1721                        PED_EXCEPTION_CANCEL,
1722                        _("Unable to satisfy all constraints on the partition."));
1723 #endif
1724   return 0;
1725 }
1726
1727 static bool
1728 gpt_partition_check (const PedPartition *part)
1729 {
1730   return true;
1731 }
1732
1733 #ifdef DISCOVER_ONLY
1734 # define NULL_IF_DISCOVER_ONLY(val) NULL
1735 #else
1736 # define NULL_IF_DISCOVER_ONLY(val) val
1737 #endif
1738
1739 static PedDiskOps gpt_disk_ops =
1740 {
1741   probe:                        gpt_probe,
1742   clobber:                      NULL_IF_DISCOVER_ONLY (gpt_clobber),
1743   alloc:                        gpt_alloc,
1744   duplicate:                    gpt_duplicate,
1745   free:                         gpt_free,
1746   read:                         gpt_read,
1747   write:                        NULL_IF_DISCOVER_ONLY (gpt_write),
1748   partition_new:                gpt_partition_new,
1749   partition_duplicate:          gpt_partition_duplicate,
1750   partition_destroy:            gpt_partition_destroy,
1751   partition_set_system:         gpt_partition_set_system,
1752   partition_set_flag:           gpt_partition_set_flag,
1753   partition_get_flag:           gpt_partition_get_flag,
1754   partition_is_flag_available:  gpt_partition_is_flag_available,
1755   partition_set_name:           gpt_partition_set_name,
1756   partition_get_name:           gpt_partition_get_name,
1757   partition_align:              gpt_partition_align,
1758   partition_enumerate:          gpt_partition_enumerate,
1759   partition_check:              gpt_partition_check,
1760   alloc_metadata:               gpt_alloc_metadata,
1761   get_max_primary_partition_count: gpt_get_max_primary_partition_count,
1762   get_max_supported_partition_count: gpt_get_max_supported_partition_count
1763 };
1764
1765 static PedDiskType gpt_disk_type =
1766 {
1767   next:         NULL,
1768   name:         "gpt",
1769   ops:          &gpt_disk_ops,
1770   features:     PED_DISK_TYPE_PARTITION_NAME
1771 };
1772
1773 void
1774 ped_disk_gpt_init ()
1775 {
1776   PED_ASSERT (sizeof (GuidPartitionEntryAttributes_t) == 8, return);
1777   PED_ASSERT (sizeof (GuidPartitionEntry_t) == 128, return);
1778
1779   ped_disk_type_register (&gpt_disk_type);
1780 }
1781
1782 void
1783 ped_disk_gpt_done ()
1784 {
1785   ped_disk_type_unregister (&gpt_disk_type);
1786 }