OSDN Git Service

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