OSDN Git Service

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