OSDN Git Service

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