OSDN Git Service

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