OSDN Git Service

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