]> git.ipfire.org Git - thirdparty/util-linux.git/blob - libfdisk/src/gpt.c
libfdisk: provide more details about GPT
[thirdparty/util-linux.git] / libfdisk / src / gpt.c
1 /*
2 * Copyright (C) 2007 Karel Zak <kzak@redhat.com>
3 * Copyright (C) 2012 Davidlohr Bueso <dave@gnu.org>
4 *
5 * GUID Partition Table (GPT) support. Based on UEFI Specs 2.3.1
6 * Chapter 5: GUID Partition Table (GPT) Disk Layout (Jun 27th, 2012).
7 * Some ideas and inspiration from GNU parted and gptfdisk.
8 */
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <inttypes.h>
13 #include <sys/stat.h>
14 #include <sys/utsname.h>
15 #include <sys/types.h>
16 #include <fcntl.h>
17 #include <unistd.h>
18 #include <errno.h>
19 #include <ctype.h>
20 #include <uuid.h>
21
22 #include "fdiskP.h"
23
24 #include "nls.h"
25 #include "crc32.h"
26 #include "blkdev.h"
27 #include "bitops.h"
28 #include "strutils.h"
29 #include "all-io.h"
30
31 #define GPT_HEADER_SIGNATURE 0x5452415020494645LL /* EFI PART */
32 #define GPT_HEADER_REVISION_V1_02 0x00010200
33 #define GPT_HEADER_REVISION_V1_00 0x00010000
34 #define GPT_HEADER_REVISION_V0_99 0x00009900
35 #define GPT_HEADER_MINSZ 92 /* bytes */
36
37 #define GPT_PMBR_LBA 0
38 #define GPT_MBR_PROTECTIVE 1
39 #define GPT_MBR_HYBRID 2
40
41 #define GPT_PRIMARY_PARTITION_TABLE_LBA 0x00000001
42
43 #define EFI_PMBR_OSTYPE 0xEE
44 #define MSDOS_MBR_SIGNATURE 0xAA55
45 #define GPT_PART_NAME_LEN 72 / sizeof(uint16_t)
46 #define GPT_NPARTITIONS 128
47
48 /* Globally unique identifier */
49 struct gpt_guid {
50 uint32_t time_low;
51 uint16_t time_mid;
52 uint16_t time_hi_and_version;
53 uint8_t clock_seq_hi;
54 uint8_t clock_seq_low;
55 uint8_t node[6];
56 };
57
58
59 /* only checking that the GUID is 0 is enough to verify an empty partition. */
60 #define GPT_UNUSED_ENTRY_GUID \
61 ((struct gpt_guid) { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, \
62 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }})
63
64 /* Linux native partition type */
65 #define GPT_DEFAULT_ENTRY_TYPE "0FC63DAF-8483-4772-8E79-3D69D8477DE4"
66
67 /*
68 * Attribute bits
69 */
70 struct gpt_attr {
71 uint64_t required_to_function:1;
72 uint64_t no_blockio_protocol:1;
73 uint64_t legacy_bios_bootable:1;
74 uint64_t reserved:45;
75 uint64_t guid_secific:16;
76 } __attribute__ ((packed));
77
78 /* The GPT Partition entry array contains an array of GPT entries. */
79 struct gpt_entry {
80 struct gpt_guid type; /* purpose and type of the partition */
81 struct gpt_guid partition_guid;
82 uint64_t lba_start;
83 uint64_t lba_end;
84 struct gpt_attr attr;
85 uint16_t name[GPT_PART_NAME_LEN];
86 } __attribute__ ((packed));
87
88 /* GPT header */
89 struct gpt_header {
90 uint64_t signature; /* header identification */
91 uint32_t revision; /* header version */
92 uint32_t size; /* in bytes */
93 uint32_t crc32; /* header CRC checksum */
94 uint32_t reserved1; /* must be 0 */
95 uint64_t my_lba; /* LBA that contains this struct (LBA 1) */
96 uint64_t alternative_lba; /* backup GPT header */
97 uint64_t first_usable_lba; /* first usable logical block for partitions */
98 uint64_t last_usable_lba; /* last usable logical block for partitions */
99 struct gpt_guid disk_guid; /* unique disk identifier */
100 uint64_t partition_entry_lba; /* stat LBA of the partition entry array */
101 uint32_t npartition_entries; /* total partition entries - normally 128 */
102 uint32_t sizeof_partition_entry; /* bytes for each GUID pt */
103 uint32_t partition_entry_array_crc32; /* partition CRC checksum */
104 uint8_t reserved2[512 - 92]; /* must be 0 */
105 } __attribute__ ((packed));
106
107 struct gpt_record {
108 uint8_t boot_indicator; /* unused by EFI, set to 0x80 for bootable */
109 uint8_t start_head; /* unused by EFI, pt start in CHS */
110 uint8_t start_sector; /* unused by EFI, pt start in CHS */
111 uint8_t start_track;
112 uint8_t os_type; /* EFI and legacy non-EFI OS types */
113 uint8_t end_head; /* unused by EFI, pt end in CHS */
114 uint8_t end_sector; /* unused by EFI, pt end in CHS */
115 uint8_t end_track; /* unused by EFI, pt end in CHS */
116 uint32_t starting_lba; /* used by EFI - start addr of the on disk pt */
117 uint32_t size_in_lba; /* used by EFI - size of pt in LBA */
118 } __attribute__ ((packed));
119
120 /* Protected MBR and legacy MBR share same structure */
121 struct gpt_legacy_mbr {
122 uint8_t boot_code[440];
123 uint32_t unique_mbr_signature;
124 uint16_t unknown;
125 struct gpt_record partition_record[4];
126 uint16_t signature;
127 } __attribute__ ((packed));
128
129 /*
130 * Here be dragons!
131 * See: http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs
132 */
133 #define DEF_GUID(_u, _n) \
134 { \
135 .typestr = (_u), \
136 .name = (_n), \
137 }
138
139 static struct fdisk_parttype gpt_parttypes[] =
140 {
141 /* Generic OS */
142 DEF_GUID("C12A7328-F81F-11D2-BA4B-00A0C93EC93B", N_("EFI System")),
143
144 DEF_GUID("024DEE41-33E7-11D3-9D69-0008C781F39F", N_("MBR partition scheme")),
145 /* Hah!IdontneedEFI */
146 DEF_GUID("21686148-6449-6E6F-744E-656564454649", N_("BIOS boot partition")),
147
148 /* Windows */
149 DEF_GUID("E3C9E316-0B5C-4DB8-817D-F92DF00215AE", N_("Microsoft reserved")),
150 DEF_GUID("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", N_("Microsoft basic data")),
151 DEF_GUID("5808C8AA-7E8F-42E0-85D2-E1E90434CFB3", N_("Microsoft LDM metadata")),
152 DEF_GUID("AF9B60A0-1431-4F62-BC68-3311714A69AD", N_("Microsoft LDM data")),
153 DEF_GUID("DE94BBA4-06D1-4D40-A16A-BFD50179D6AC", N_("Windows recovery evironment")),
154 DEF_GUID("37AFFC90-EF7D-4E96-91C3-2D7AE055B174", N_("IBM General Parallel Fs")),
155
156 /* HP-UX */
157 DEF_GUID("75894C1E-3AEB-11D3-B7C1-7B03A0000000", N_("HP-UX data partition")),
158 DEF_GUID("E2A1E728-32E3-11D6-A682-7B03A0000000", N_("HP-UX service partition")),
159
160 /* Linux */
161 DEF_GUID("0FC63DAF-8483-4772-8E79-3D69D8477DE4", N_("Linux filesystem")),
162 DEF_GUID("A19D880F-05FC-4D3B-A006-743F0F84911E", N_("Linux RAID")),
163 DEF_GUID("0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", N_("Linux swap")),
164 DEF_GUID("E6D6D379-F507-44C2-A23C-238F2A3DF928", N_("Linux LVM")),
165 DEF_GUID("8DA63339-0007-60C0-C436-083AC8230908", N_("Linux reserved")),
166
167 /* FreeBSD */
168 DEF_GUID("516E7CB4-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD data")),
169 DEF_GUID("83BD6B9D-7F41-11DC-BE0B-001560B84F0F", N_("FreeBSD boot")),
170 DEF_GUID("516E7CB5-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD swap")),
171 DEF_GUID("516E7CB6-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD UFS")),
172 DEF_GUID("516E7CBA-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD ZFS")),
173 DEF_GUID("516E7CB8-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD Vinum")),
174
175 /* Apple OSX */
176 DEF_GUID("48465300-0000-11AA-AA11-00306543ECAC", N_("Apple HFS/HFS+")),
177 DEF_GUID("55465300-0000-11AA-AA11-00306543ECAC", N_("Apple UFS")),
178 DEF_GUID("52414944-0000-11AA-AA11-00306543ECAC", N_("Apple RAID")),
179 DEF_GUID("52414944-5F4F-11AA-AA11-00306543ECAC", N_("Apple RAID offline")),
180 DEF_GUID("426F6F74-0000-11AA-AA11-00306543ECAC", N_("Apple boot")),
181 DEF_GUID("4C616265-6C00-11AA-AA11-00306543ECAC", N_("Apple label")),
182 DEF_GUID("5265636F-7665-11AA-AA11-00306543ECAC", N_("Apple TV recovery")),
183 DEF_GUID("53746F72-6167-11AA-AA11-00306543ECAC", N_("Apple Core storage")),
184
185 /* Solaris */
186 DEF_GUID("6A82CB45-1DD2-11B2-99A6-080020736631", N_("Solaris boot")),
187 DEF_GUID("6A85CF4D-1DD2-11B2-99A6-080020736631", N_("Solaris root")),
188 /* same as Apple ZFS */
189 DEF_GUID("6A898CC3-1DD2-11B2-99A6-080020736631", N_("Solaris /usr & Apple ZFS")),
190 DEF_GUID("6A87C46F-1DD2-11B2-99A6-080020736631", N_("Solaris swap")),
191 DEF_GUID("6A8B642B-1DD2-11B2-99A6-080020736631", N_("Solaris backup")),
192 DEF_GUID("6A8EF2E9-1DD2-11B2-99A6-080020736631", N_("Solaris /var")),
193 DEF_GUID("6A90BA39-1DD2-11B2-99A6-080020736631", N_("Solaris /home")),
194 DEF_GUID("6A9283A5-1DD2-11B2-99A6-080020736631", N_("Solaris alternate sector")),
195 DEF_GUID("6A945A3B-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 1")),
196 DEF_GUID("6A9630D1-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 2")),
197 DEF_GUID("6A980767-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 3")),
198 DEF_GUID("6A96237F-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 4")),
199 DEF_GUID("6A8D2AC7-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 5")),
200
201 /* NetBSD */
202 DEF_GUID("49F48D32-B10E-11DC-B99B-0019D1879648", N_("NetBSD swap")),
203 DEF_GUID("49F48D5A-B10E-11DC-B99B-0019D1879648", N_("NetBSD FFS")),
204 DEF_GUID("49F48D82-B10E-11DC-B99B-0019D1879648", N_("NetBSD LFS")),
205 DEF_GUID("2DB519C4-B10E-11DC-B99B-0019D1879648", N_("NetBSD concatenated")),
206 DEF_GUID("2DB519EC-B10E-11DC-B99B-0019D1879648", N_("NetBSD encrypted")),
207 DEF_GUID("49F48DAA-B10E-11DC-B99B-0019D1879648", N_("NetBSD RAID")),
208
209 /* ChromeOS */
210 DEF_GUID("FE3A2A5D-4F32-41A7-B725-ACCC3285A309", N_("ChromeOS kernel")),
211 DEF_GUID("3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC", N_("ChromeOS root fs")),
212 DEF_GUID("2E0A753D-9E48-43B0-8337-B15192CB1B5E", N_("ChromeOS reserved")),
213
214 /* MidnightBSD */
215 DEF_GUID("85D5E45A-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD data")),
216 DEF_GUID("85D5E45E-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD boot")),
217 DEF_GUID("85D5E45B-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD swap")),
218 DEF_GUID("0394Ef8B-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD UFS")),
219 DEF_GUID("85D5E45D-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD ZFS")),
220 DEF_GUID("85D5E45C-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD Vinum")),
221 };
222
223 /* gpt_entry macros */
224 #define gpt_partition_start(_e) le64_to_cpu((_e)->lba_start)
225 #define gpt_partition_end(_e) le64_to_cpu((_e)->lba_end)
226
227 /*
228 * in-memory fdisk GPT stuff
229 */
230 struct fdisk_gpt_label {
231 struct fdisk_label head; /* generic part */
232
233 /* gpt specific part */
234 struct gpt_header *pheader; /* primary header */
235 struct gpt_header *bheader; /* backup header */
236 struct gpt_entry *ents; /* entries (partitions) */
237 };
238
239 static void gpt_deinit(struct fdisk_label *lb);
240
241 static inline struct fdisk_gpt_label *self_label(struct fdisk_context *cxt)
242 {
243 return (struct fdisk_gpt_label *) cxt->label;
244 }
245
246 /*
247 * Returns the partition length, or 0 if end is before beginning.
248 */
249 static uint64_t gpt_partition_size(const struct gpt_entry *e)
250 {
251 uint64_t start = gpt_partition_start(e);
252 uint64_t end = gpt_partition_end(e);
253
254 return start > end ? 0 : end - start + 1ULL;
255 }
256
257 #ifdef CONFIG_LIBFDISK_DEBUG
258 /* prints UUID in the real byte order! */
259 static void dbgprint_uuid(const char *mesg, struct gpt_guid *guid)
260 {
261 const unsigned char *uuid = (unsigned char *) guid;
262
263 fprintf(stderr, "%s: "
264 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
265 mesg,
266 uuid[0], uuid[1], uuid[2], uuid[3],
267 uuid[4], uuid[5],
268 uuid[6], uuid[7],
269 uuid[8], uuid[9],
270 uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]);
271 }
272 #endif
273
274 /*
275 * UUID is traditionally 16 byte big-endian array, except Intel EFI
276 * specification where the UUID is a structure of little-endian fields.
277 */
278 static void swap_efi_guid(struct gpt_guid *uid)
279 {
280 uid->time_low = swab32(uid->time_low);
281 uid->time_mid = swab16(uid->time_mid);
282 uid->time_hi_and_version = swab16(uid->time_hi_and_version);
283 }
284
285 static int string_to_guid(const char *in, struct gpt_guid *guid)
286 {
287 if (uuid_parse(in, (unsigned char *) guid)) /* BE */
288 return -1;
289 swap_efi_guid(guid); /* LE */
290 return 0;
291 }
292
293 static char *guid_to_string(struct gpt_guid *guid, char *out)
294 {
295 struct gpt_guid u = *guid; /* LE */
296
297 swap_efi_guid(&u); /* BE */
298 uuid_unparse_upper((unsigned char *) &u, out);
299
300 return out;
301 }
302
303 static const char *gpt_get_header_revstr(struct gpt_header *header)
304 {
305 if (!header)
306 goto unknown;
307
308 switch (header->revision) {
309 case GPT_HEADER_REVISION_V1_02:
310 return "1.2";
311 case GPT_HEADER_REVISION_V1_00:
312 return "1.0";
313 case GPT_HEADER_REVISION_V0_99:
314 return "0.99";
315 default:
316 goto unknown;
317 }
318
319 unknown:
320 return "unknown";
321 }
322
323 static inline int partition_unused(const struct gpt_entry *e)
324 {
325 return !memcmp(&e->type, &GPT_UNUSED_ENTRY_GUID,
326 sizeof(struct gpt_guid));
327 }
328
329 /*
330 * Builds a clean new valid protective MBR - will wipe out any existing data.
331 * Returns 0 on success, otherwise < 0 on error.
332 */
333 static int gpt_mknew_pmbr(struct fdisk_context *cxt)
334 {
335 struct gpt_legacy_mbr *pmbr = NULL;
336
337 if (!cxt || !cxt->firstsector)
338 return -ENOSYS;
339
340 fdisk_zeroize_firstsector(cxt);
341
342 pmbr = (struct gpt_legacy_mbr *) cxt->firstsector;
343
344 pmbr->signature = cpu_to_le16(MSDOS_MBR_SIGNATURE);
345 pmbr->partition_record[0].os_type = EFI_PMBR_OSTYPE;
346 pmbr->partition_record[0].start_sector = 1;
347 pmbr->partition_record[0].end_head = 0xFE;
348 pmbr->partition_record[0].end_sector = 0xFF;
349 pmbr->partition_record[0].end_track = 0xFF;
350 pmbr->partition_record[0].starting_lba = cpu_to_le32(1);
351 pmbr->partition_record[0].size_in_lba =
352 cpu_to_le32(min((uint32_t) cxt->total_sectors - 1, 0xFFFFFFFF));
353
354 return 0;
355 }
356
357 /* some universal differences between the headers */
358 static void gpt_mknew_header_common(struct fdisk_context *cxt,
359 struct gpt_header *header, uint64_t lba)
360 {
361 if (!cxt || !header)
362 return;
363
364 header->my_lba = cpu_to_le64(lba);
365
366 if (lba == GPT_PRIMARY_PARTITION_TABLE_LBA) { /* primary */
367 header->alternative_lba = cpu_to_le64(cxt->total_sectors - 1);
368 header->partition_entry_lba = cpu_to_le64(2);
369 } else { /* backup */
370 uint64_t esz = le32_to_cpu(header->npartition_entries) * sizeof(struct gpt_entry);
371 uint64_t esects = (esz + cxt->sector_size - 1) / cxt->sector_size;
372
373 header->alternative_lba = cpu_to_le64(GPT_PRIMARY_PARTITION_TABLE_LBA);
374 header->partition_entry_lba = cpu_to_le64(cxt->total_sectors - 1 - esects);
375 }
376 }
377
378 /*
379 * Builds a new GPT header (at sector lba) from a backup header2.
380 * If building a primary header, then backup is the secondary, and vice versa.
381 *
382 * Always pass a new (zeroized) header to build upon as we don't
383 * explicitly zero-set some values such as CRCs and reserved.
384 *
385 * Returns 0 on success, otherwise < 0 on error.
386 */
387 static int gpt_mknew_header_from_bkp(struct fdisk_context *cxt,
388 struct gpt_header *header,
389 uint64_t lba,
390 struct gpt_header *header2)
391 {
392 if (!cxt || !header || !header2)
393 return -ENOSYS;
394
395 header->signature = header2->signature;
396 header->revision = header2->revision;
397 header->size = header2->size;
398 header->npartition_entries = header2->npartition_entries;
399 header->sizeof_partition_entry = header2->sizeof_partition_entry;
400 header->first_usable_lba = header2->first_usable_lba;
401 header->last_usable_lba = header2->last_usable_lba;
402
403 memcpy(&header->disk_guid,
404 &header2->disk_guid, sizeof(header2->disk_guid));
405 gpt_mknew_header_common(cxt, header, lba);
406
407 return 0;
408 }
409
410 /*
411 * Builds a clean new GPT header (currently under revision 1.0).
412 *
413 * Always pass a new (zeroized) header to build upon as we don't
414 * explicitly zero-set some values such as CRCs and reserved.
415 *
416 * Returns 0 on success, otherwise < 0 on error.
417 */
418 static int gpt_mknew_header(struct fdisk_context *cxt,
419 struct gpt_header *header, uint64_t lba)
420 {
421 uint64_t esz = 0, first, last;
422
423 if (!cxt || !header)
424 return -ENOSYS;
425
426 esz = sizeof(struct gpt_entry) * GPT_NPARTITIONS / cxt->sector_size;
427
428 header->signature = cpu_to_le64(GPT_HEADER_SIGNATURE);
429 header->revision = cpu_to_le32(GPT_HEADER_REVISION_V1_00);
430 header->size = cpu_to_le32(sizeof(struct gpt_header));
431
432 /*
433 * 128 partitions is the default. It can go behond this, however,
434 * we're creating a de facto header here, so no funny business.
435 */
436 header->npartition_entries = cpu_to_le32(GPT_NPARTITIONS);
437 header->sizeof_partition_entry = cpu_to_le32(sizeof(struct gpt_entry));
438
439 last = cxt->total_sectors - 2 - esz;
440 first = esz + 2;
441
442 if (first < cxt->first_lba && cxt->first_lba < last)
443 /* Align according to topology */
444 first = cxt->first_lba;
445
446 header->first_usable_lba = cpu_to_le64(first);
447 header->last_usable_lba = cpu_to_le64(last);
448
449 gpt_mknew_header_common(cxt, header, lba);
450 uuid_generate_random((unsigned char *) &header->disk_guid);
451 swap_efi_guid(&header->disk_guid);
452
453 return 0;
454 }
455
456 /*
457 * Checks if there is a valid protective MBR partition table.
458 * Returns 0 if it is invalid or failure. Otherwise, return
459 * GPT_MBR_PROTECTIVE or GPT_MBR_HYBRID, depeding on the detection.
460 */
461 static int valid_pmbr(struct fdisk_context *cxt)
462 {
463 int i, ret = 0; /* invalid by default */
464 struct gpt_legacy_mbr *pmbr = NULL;
465
466 if (!cxt->firstsector)
467 goto done;
468
469 pmbr = (struct gpt_legacy_mbr *) cxt->firstsector;
470
471 if (le16_to_cpu(pmbr->signature) != MSDOS_MBR_SIGNATURE)
472 goto done;
473
474 /* LBA of the GPT partition header */
475 if (pmbr->partition_record[0].starting_lba !=
476 cpu_to_le32(GPT_PRIMARY_PARTITION_TABLE_LBA))
477 goto done;
478
479 /* seems like a valid MBR was found, check DOS primary partitions */
480 for (i = 0; i < 4; i++) {
481 if (pmbr->partition_record[i].os_type == EFI_PMBR_OSTYPE) {
482 /*
483 * Ok, we at least know that there's a protective MBR,
484 * now check if there are other partition types for
485 * hybrid MBR.
486 */
487 ret = GPT_MBR_PROTECTIVE;
488 goto check_hybrid;
489 }
490 }
491 check_hybrid:
492 if (ret != GPT_MBR_PROTECTIVE)
493 goto done;
494 for (i = 0 ; i < 4; i++) {
495 if ((pmbr->partition_record[i].os_type != EFI_PMBR_OSTYPE) &&
496 (pmbr->partition_record[i].os_type != 0x00))
497 ret = GPT_MBR_HYBRID;
498 }
499
500 /*
501 * Protective MBRs take up the lesser of the whole disk
502 * or 2 TiB (32bit LBA), ignoring the rest of the disk.
503 *
504 * Hybrid MBRs do not necessarily comply with this.
505 */
506 if (ret == GPT_MBR_PROTECTIVE) {
507 if (le32_to_cpu(pmbr->partition_record[0].size_in_lba) !=
508 min((uint32_t) cxt->total_sectors - 1, 0xFFFFFFFF))
509 ret = 0;
510 }
511 done:
512 return ret;
513 }
514
515 static uint64_t last_lba(struct fdisk_context *cxt)
516 {
517 struct stat s;
518
519 memset(&s, 0, sizeof(s));
520 if (fstat(cxt->dev_fd, &s) == -1) {
521 fdisk_warn(cxt, _("gpt: stat() failed"));
522 return 0;
523 }
524
525 if (S_ISBLK(s.st_mode))
526 return cxt->total_sectors - 1;
527 else if (S_ISREG(s.st_mode)) {
528 uint64_t sectors = s.st_size >> cxt->sector_size;
529 return (sectors / cxt->sector_size) - 1ULL;
530 } else
531 fdisk_warnx(cxt, _("gpt: cannot handle files with mode %o"), s.st_mode);
532 return 0;
533 }
534
535 static ssize_t read_lba(struct fdisk_context *cxt, uint64_t lba,
536 void *buffer, const size_t bytes)
537 {
538 off_t offset = lba * cxt->sector_size;
539
540 if (lseek(cxt->dev_fd, offset, SEEK_SET) == (off_t) -1)
541 return -1;
542 return read(cxt->dev_fd, buffer, bytes) != bytes;
543 }
544
545
546 /* Returns the GPT entry array */
547 static struct gpt_entry *gpt_read_entries(struct fdisk_context *cxt,
548 struct gpt_header *header)
549 {
550 ssize_t sz;
551 struct gpt_entry *ret = NULL;
552 off_t offset;
553
554 assert(cxt);
555 assert(header);
556
557 sz = le32_to_cpu(header->npartition_entries) *
558 le32_to_cpu(header->sizeof_partition_entry);
559
560 ret = calloc(1, sz);
561 if (!ret)
562 return NULL;
563 offset = le64_to_cpu(header->partition_entry_lba) *
564 cxt->sector_size;
565
566 if (offset != lseek(cxt->dev_fd, offset, SEEK_SET))
567 goto fail;
568 if (sz != read(cxt->dev_fd, ret, sz))
569 goto fail;
570
571 return ret;
572
573 fail:
574 free(ret);
575 return NULL;
576 }
577
578 static inline uint32_t count_crc32(const unsigned char *buf, size_t len)
579 {
580 return (crc32(~0L, buf, len) ^ ~0L);
581 }
582
583 /*
584 * Recompute header and partition array 32bit CRC checksums.
585 * This function does not fail - if there's corruption, then it
586 * will be reported when checksuming it again (ie: probing or verify).
587 */
588 static void gpt_recompute_crc(struct gpt_header *header, struct gpt_entry *ents)
589 {
590 uint32_t crc = 0;
591 size_t entry_sz = 0;
592
593 if (!header)
594 return;
595
596 /* header CRC */
597 header->crc32 = 0;
598 crc = count_crc32((unsigned char *) header, le32_to_cpu(header->size));
599 header->crc32 = cpu_to_le32(crc);
600
601 /* partition entry array CRC */
602 header->partition_entry_array_crc32 = 0;
603 entry_sz = le32_to_cpu(header->npartition_entries) *
604 le32_to_cpu(header->sizeof_partition_entry);
605
606 crc = count_crc32((unsigned char *) ents, entry_sz);
607 header->partition_entry_array_crc32 = cpu_to_le32(crc);
608 }
609
610 /*
611 * Compute the 32bit CRC checksum of the partition table header.
612 * Returns 1 if it is valid, otherwise 0.
613 */
614 static int gpt_check_header_crc(struct gpt_header *header, struct gpt_entry *ents)
615 {
616 uint32_t crc, orgcrc = le32_to_cpu(header->crc32);
617
618 header->crc32 = 0;
619 crc = count_crc32((unsigned char *) header, le32_to_cpu(header->size));
620 header->crc32 = cpu_to_le32(orgcrc);
621
622 if (crc == le32_to_cpu(header->crc32))
623 return 1;
624
625 /*
626 * If we have checksum mismatch it may be due to stale data,
627 * like a partition being added or deleted. Recompute the CRC again
628 * and make sure this is not the case.
629 */
630 if (ents) {
631 gpt_recompute_crc(header, ents);
632 orgcrc = le32_to_cpu(header->crc32);
633 header->crc32 = 0;
634 crc = count_crc32((unsigned char *) header, le32_to_cpu(header->size));
635 header->crc32 = cpu_to_le32(orgcrc);
636
637 return crc == le32_to_cpu(header->crc32);
638 }
639
640 return 0;
641 }
642
643 /*
644 * It initializes the partition entry array.
645 * Returns 1 if the checksum is valid, otherwise 0.
646 */
647 static int gpt_check_entryarr_crc(struct gpt_header *header,
648 struct gpt_entry *ents)
649 {
650 int ret = 0;
651 ssize_t entry_sz;
652 uint32_t crc;
653
654 if (!header || !ents)
655 goto done;
656
657 entry_sz = le32_to_cpu(header->npartition_entries) *
658 le32_to_cpu(header->sizeof_partition_entry);
659
660 if (!entry_sz)
661 goto done;
662
663 crc = count_crc32((unsigned char *) ents, entry_sz);
664 ret = (crc == le32_to_cpu(header->partition_entry_array_crc32));
665 done:
666 return ret;
667 }
668
669 static int gpt_check_lba_sanity(struct fdisk_context *cxt, struct gpt_header *header)
670 {
671 int ret = 0;
672 uint64_t lu, fu, lastlba = last_lba(cxt);
673
674 fu = le64_to_cpu(header->first_usable_lba);
675 lu = le64_to_cpu(header->last_usable_lba);
676
677 /* check if first and last usable LBA make sense */
678 if (lu < fu) {
679 DBG(LABEL, dbgprint("error: header last LBA is before first LBA"));
680 goto done;
681 }
682
683 /* check if first and last usable LBAs with the disk's last LBA */
684 if (fu > lastlba || lu > lastlba) {
685 DBG(LABEL, dbgprint("error: header LBAs are after the disk's last LBA"));
686 goto done;
687 }
688
689 /* the header has to be outside usable range */
690 if (fu < GPT_PRIMARY_PARTITION_TABLE_LBA &&
691 GPT_PRIMARY_PARTITION_TABLE_LBA < lu) {
692 DBG(LABEL, dbgprint("error: header outside of usable range"));
693 goto done;
694 }
695
696 ret = 1; /* sane */
697 done:
698 return ret;
699 }
700
701 /* Check if there is a valid header signature */
702 static int gpt_check_signature(struct gpt_header *header)
703 {
704 return header->signature == cpu_to_le64(GPT_HEADER_SIGNATURE);
705 }
706
707 /*
708 * Return the specified GPT Header, or NULL upon failure/invalid.
709 * Note that all tests must pass to ensure a valid header,
710 * we do not rely on only testing the signature for a valid probe.
711 */
712 static struct gpt_header *gpt_read_header(struct fdisk_context *cxt,
713 uint64_t lba,
714 struct gpt_entry **_ents)
715 {
716 struct gpt_header *header = NULL;
717 struct gpt_entry *ents = NULL;
718 uint32_t hsz;
719
720 if (!cxt)
721 return NULL;
722
723 header = calloc(1, sizeof(*header));
724 if (!header)
725 return NULL;
726
727 /* read and verify header */
728 if (read_lba(cxt, lba, header, sizeof(struct gpt_header)) != 0)
729 goto invalid;
730
731 if (!gpt_check_signature(header))
732 goto invalid;
733
734 if (!gpt_check_header_crc(header, NULL))
735 goto invalid;
736
737 /* read and verify entries */
738 ents = gpt_read_entries(cxt, header);
739 if (!ents)
740 goto invalid;
741
742 if (!gpt_check_entryarr_crc(header, ents))
743 goto invalid;
744
745 if (!gpt_check_lba_sanity(cxt, header))
746 goto invalid;
747
748 /* valid header must be at MyLBA */
749 if (le64_to_cpu(header->my_lba) != lba)
750 goto invalid;
751
752 /* make sure header size is between 92 and sector size bytes */
753 hsz = le32_to_cpu(header->size);
754 if (hsz < GPT_HEADER_MINSZ || hsz > cxt->sector_size)
755 goto invalid;
756
757 if (_ents)
758 *_ents = ents;
759 else
760 free(ents);
761
762 return header;
763 invalid:
764 free(header);
765 free(ents);
766 return NULL;
767 }
768
769 /*
770 * Returns the number of partitions that are in use.
771 */
772 static unsigned partitions_in_use(struct gpt_header *header, struct gpt_entry *e)
773 {
774 uint32_t i, used = 0;
775
776 if (!header || ! e)
777 return 0;
778
779 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++)
780 if (!partition_unused(&e[i]))
781 used++;
782 return used;
783 }
784
785
786 /*
787 * Check if a partition is too big for the disk (sectors).
788 * Returns the faulting partition number, otherwise 0.
789 */
790 static uint32_t partition_check_too_big(struct gpt_header *header,
791 struct gpt_entry *e, uint64_t sectors)
792 {
793 uint32_t i;
794
795 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
796 if (partition_unused(&e[i]))
797 continue;
798 if (gpt_partition_end(&e[i]) >= sectors)
799 return i + 1;
800 }
801
802 return 0;
803 }
804
805 /*
806 * Check if a partition ends before it begins
807 * Returns the faulting partition number, otherwise 0.
808 */
809 static uint32_t partition_start_after_end(struct gpt_header *header, struct gpt_entry *e)
810 {
811 uint32_t i;
812
813 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
814 if (partition_unused(&e[i]))
815 continue;
816 if (gpt_partition_start(&e[i]) > gpt_partition_end(&e[i]))
817 return i + 1;
818 }
819
820 return 0;
821 }
822
823 /*
824 * Check if partition e1 overlaps with partition e2
825 */
826 static inline int partition_overlap(struct gpt_entry *e1, struct gpt_entry *e2)
827 {
828 uint64_t start1 = gpt_partition_start(e1);
829 uint64_t end1 = gpt_partition_end(e1);
830 uint64_t start2 = gpt_partition_start(e2);
831 uint64_t end2 = gpt_partition_end(e2);
832
833 return (start1 && start2 && (start1 <= end2) != (end1 < start2));
834 }
835
836 /*
837 * Find any paritions that overlap.
838 */
839 static uint32_t partition_check_overlaps(struct gpt_header *header, struct gpt_entry *e)
840 {
841 uint32_t i, j;
842
843 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++)
844 for (j = 0; j < i; j++) {
845 if (partition_unused(&e[i]) ||
846 partition_unused(&e[j]))
847 continue;
848 if (partition_overlap(&e[i], &e[j])) {
849 DBG(LABEL, dbgprint("GPT partitions overlap detected [%u vs. %u]", i, j));
850 return i + 1;
851 }
852 }
853
854 return 0;
855 }
856
857 /*
858 * Find the first available block after the starting point; returns 0 if
859 * there are no available blocks left, or error. From gdisk.
860 */
861 static uint64_t find_first_available(struct gpt_header *header,
862 struct gpt_entry *e, uint64_t start)
863 {
864 uint64_t first;
865 uint32_t i, first_moved = 0;
866
867 uint64_t fu, lu;
868
869 if (!header || !e)
870 return 0;
871
872 fu = le64_to_cpu(header->first_usable_lba);
873 lu = le64_to_cpu(header->last_usable_lba);
874
875 /*
876 * Begin from the specified starting point or from the first usable
877 * LBA, whichever is greater...
878 */
879 first = start < fu ? fu : start;
880
881 /*
882 * Now search through all partitions; if first is within an
883 * existing partition, move it to the next sector after that
884 * partition and repeat. If first was moved, set firstMoved
885 * flag; repeat until firstMoved is not set, so as to catch
886 * cases where partitions are out of sequential order....
887 */
888 do {
889 first_moved = 0;
890 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
891 if (partition_unused(&e[i]))
892 continue;
893 if (first < gpt_partition_start(&e[i]))
894 continue;
895 if (first <= gpt_partition_end(&e[i])) {
896 first = gpt_partition_end(&e[i]) + 1;
897 first_moved = 1;
898 }
899 }
900 } while (first_moved == 1);
901
902 if (first > lu)
903 first = 0;
904
905 return first;
906 }
907
908
909 /* Returns last available sector in the free space pointed to by start. From gdisk. */
910 static uint64_t find_last_free(struct gpt_header *header,
911 struct gpt_entry *e, uint64_t start)
912 {
913 uint32_t i;
914 uint64_t nearest_start;
915
916 if (!header || !e)
917 return 0;
918
919 nearest_start = le64_to_cpu(header->last_usable_lba);
920
921 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
922 uint64_t ps = gpt_partition_start(&e[i]);
923
924 if (nearest_start > ps && ps > start)
925 nearest_start = ps - 1;
926 }
927
928 return nearest_start;
929 }
930
931 /* Returns the last free sector on the disk. From gdisk. */
932 static uint64_t find_last_free_sector(struct gpt_header *header,
933 struct gpt_entry *e)
934 {
935 uint32_t i, last_moved;
936 uint64_t last = 0;
937
938 if (!header || !e)
939 goto done;
940
941 /* start by assuming the last usable LBA is available */
942 last = le64_to_cpu(header->last_usable_lba);
943 do {
944 last_moved = 0;
945 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
946 if ((last >= gpt_partition_start(&e[i])) &&
947 (last <= gpt_partition_end(&e[i]))) {
948 last = gpt_partition_start(&e[i]) - 1;
949 last_moved = 1;
950 }
951 }
952 } while (last_moved == 1);
953 done:
954 return last;
955 }
956
957 /*
958 * Finds the first available sector in the largest block of unallocated
959 * space on the disk. Returns 0 if there are no available blocks left.
960 * From gdisk.
961 */
962 static uint64_t find_first_in_largest(struct gpt_header *header, struct gpt_entry *e)
963 {
964 uint64_t start = 0, first_sect, last_sect;
965 uint64_t segment_size, selected_size = 0, selected_segment = 0;
966
967 if (!header || !e)
968 goto done;
969
970 do {
971 first_sect = find_first_available(header, e, start);
972 if (first_sect != 0) {
973 last_sect = find_last_free(header, e, first_sect);
974 segment_size = last_sect - first_sect + 1;
975
976 if (segment_size > selected_size) {
977 selected_size = segment_size;
978 selected_segment = first_sect;
979 }
980 start = last_sect + 1;
981 }
982 } while (first_sect != 0);
983
984 done:
985 return selected_segment;
986 }
987
988 /*
989 * Find the total number of free sectors, the number of segments in which
990 * they reside, and the size of the largest of those segments. From gdisk.
991 */
992 static uint64_t get_free_sectors(struct fdisk_context *cxt, struct gpt_header *header,
993 struct gpt_entry *e, uint32_t *nsegments,
994 uint64_t *largest_segment)
995 {
996 uint32_t num = 0;
997 uint64_t first_sect, last_sect;
998 uint64_t largest_seg = 0, segment_sz;
999 uint64_t totfound = 0, start = 0; /* starting point for each search */
1000
1001 if (!cxt->total_sectors)
1002 goto done;
1003
1004 do {
1005 first_sect = find_first_available(header, e, start);
1006 if (first_sect) {
1007 last_sect = find_last_free(header, e, first_sect);
1008 segment_sz = last_sect - first_sect + 1;
1009
1010 if (segment_sz > largest_seg)
1011 largest_seg = segment_sz;
1012 totfound += segment_sz;
1013 num++;
1014 start = last_sect + 1;
1015 }
1016 } while (first_sect);
1017
1018 done:
1019 if (nsegments)
1020 *nsegments = num;
1021 if (largest_segment)
1022 *largest_segment = largest_seg;
1023
1024 return totfound;
1025 }
1026
1027 static int gpt_probe_label(struct fdisk_context *cxt)
1028 {
1029 int mbr_type;
1030 struct fdisk_gpt_label *gpt;
1031
1032 assert(cxt);
1033 assert(cxt->label);
1034 assert(fdisk_is_disklabel(cxt, GPT));
1035
1036 gpt = self_label(cxt);
1037
1038 mbr_type = valid_pmbr(cxt);
1039 if (!mbr_type)
1040 goto failed;
1041
1042 DBG(LABEL, dbgprint("found a %s MBR", mbr_type == GPT_MBR_PROTECTIVE ?
1043 "protective" : "hybrid"));
1044
1045 /* primary header */
1046 gpt->pheader = gpt_read_header(cxt, GPT_PRIMARY_PARTITION_TABLE_LBA,
1047 &gpt->ents);
1048
1049 /*
1050 * TODO: If the primary GPT is corrupt, we must check the last LBA of the
1051 * device to see if it has a valid GPT Header and point to a valid GPT
1052 * Partition Entry Array.
1053 * If it points to a valid GPT Partition Entry Array, then software should
1054 * restore the primary GPT if allowed by platform policy settings.
1055 *
1056 * For now we just abort GPT probing!
1057 */
1058 if (!gpt->pheader || !gpt->ents)
1059 goto failed;
1060
1061 /* OK, probing passed, now initialize backup header and fdisk variables. */
1062 gpt->bheader = gpt_read_header(cxt, last_lba(cxt), NULL);
1063
1064 cxt->label->nparts_max = le32_to_cpu(gpt->pheader->npartition_entries);
1065 cxt->label->nparts_cur = partitions_in_use(gpt->pheader, gpt->ents);
1066
1067 fdisk_warnx(cxt, _("WARNING: fdisk GPT support is currently new, and therefore "
1068 "in an experimental phase. Use at your own discretion."));
1069
1070 return 1;
1071 failed:
1072 DBG(LABEL, dbgprint("GPT probe failed"));
1073 gpt_deinit(cxt->label);
1074 return 0;
1075 }
1076
1077 /*
1078 * Stolen from libblkid - can be removed once partition semantics
1079 * are added to the fdisk API.
1080 */
1081 static char *encode_to_utf8(unsigned char *src, size_t count)
1082 {
1083 uint16_t c;
1084 char *dest;
1085 size_t i, j, len = count;
1086
1087 dest = calloc(1, count);
1088 if (!dest)
1089 return NULL;
1090
1091 for (j = i = 0; i + 2 <= count; i += 2) {
1092 /* always little endian */
1093 c = (src[i+1] << 8) | src[i];
1094 if (c == 0) {
1095 dest[j] = '\0';
1096 break;
1097 } else if (c < 0x80) {
1098 if (j+1 >= len)
1099 break;
1100 dest[j++] = (uint8_t) c;
1101 } else if (c < 0x800) {
1102 if (j+2 >= len)
1103 break;
1104 dest[j++] = (uint8_t) (0xc0 | (c >> 6));
1105 dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
1106 } else {
1107 if (j+3 >= len)
1108 break;
1109 dest[j++] = (uint8_t) (0xe0 | (c >> 12));
1110 dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
1111 dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
1112 }
1113 }
1114 dest[j] = '\0';
1115
1116 return dest;
1117 }
1118
1119 /*
1120 * List label partitions.
1121 * This function must currently exist to comply with standard fdisk
1122 * requirements, but once partition semantics are added to the fdisk
1123 * API it can be removed for custom implementation (see gpt_label struct).
1124 */
1125 static int gpt_list_disklabel(struct fdisk_context *cxt)
1126 {
1127 int rc, trunc = TT_FL_TRUNC;
1128 uint32_t i;
1129 struct fdisk_gpt_label *gpt;
1130 struct gpt_header *h;
1131 uint64_t fu;
1132 uint64_t lu;
1133 struct tt *tb = NULL;
1134
1135 assert(cxt);
1136 assert(cxt->label);
1137 assert(fdisk_is_disklabel(cxt, GPT));
1138
1139 gpt = self_label(cxt);
1140 h = gpt->pheader;
1141 fu = le64_to_cpu(gpt->pheader->first_usable_lba);
1142 lu = le64_to_cpu(gpt->pheader->last_usable_lba);
1143
1144 tb = tt_new_table(TT_FL_FREEDATA);
1145 if (!tb)
1146 return -ENOMEM;
1147
1148 /* don't trunc anything in expert mode */
1149 if (fdisk_context_display_details(cxt)) {
1150 trunc = 0;
1151 fdisk_info(cxt, _("First LBA: %ju"), h->first_usable_lba);
1152 fdisk_info(cxt, _("Last LBA: %ju"), h->last_usable_lba);
1153 fdisk_info(cxt, _("Alternative LBA: %ju"), h->alternative_lba);
1154 fdisk_info(cxt, _("Partitions entries LBA: %ju"), h->partition_entry_lba);
1155 fdisk_info(cxt, _("Allocated partition entries: %ju"), h->npartition_entries);
1156 }
1157 tt_define_column(tb, _("Device"), 0.1, 0);
1158 tt_define_column(tb, _("Start"), 12, TT_FL_RIGHT);
1159 tt_define_column(tb, _("End"), 12, TT_FL_RIGHT);
1160 tt_define_column(tb, _("Size"), 6, TT_FL_RIGHT);
1161 tt_define_column(tb, _("Type"), 0.1, trunc);
1162
1163 if (fdisk_context_display_details(cxt)) {
1164 tt_define_column(tb, _("UUID"), 36, 0);
1165 tt_define_column(tb, _("Name"), 0.2, trunc);
1166 }
1167
1168 for (i = 0; i < le32_to_cpu(h->npartition_entries); i++) {
1169 struct gpt_entry *e = &gpt->ents[i];
1170 char *sizestr = NULL, *p;
1171 uint64_t start = gpt_partition_start(e);
1172 uint64_t size = gpt_partition_size(e);
1173 struct fdisk_parttype *t;
1174 struct tt_line *ln;
1175 char u_str[37];
1176
1177 if (partition_unused(&gpt->ents[i]) || start == 0)
1178 continue;
1179 /* the partition has to inside usable range */
1180 if (start < fu || start + size - 1 > lu)
1181 continue;
1182 ln = tt_add_line(tb, NULL);
1183 if (!ln)
1184 continue;
1185
1186 if (fdisk_context_display_details(cxt) &&
1187 asprintf(&p, "%ju", size * cxt->sector_size) > 0)
1188 sizestr = p;
1189 else
1190 sizestr = size_to_human_string(SIZE_SUFFIX_1LETTER,
1191 size * cxt->sector_size);
1192 t = fdisk_get_partition_type(cxt, i);
1193
1194 /* basic columns */
1195 p = fdisk_partname(cxt->dev_path, i + 1);
1196 if (p)
1197 tt_line_set_data(ln, 0, p);
1198 if (asprintf(&p, "%ju", start) > 0)
1199 tt_line_set_data(ln, 1, p);
1200 if (asprintf(&p, "%ju", gpt_partition_end(e)) > 0)
1201 tt_line_set_data(ln, 2, p);
1202 if (sizestr)
1203 tt_line_set_data(ln, 3, sizestr);
1204 if (t && t->name)
1205 tt_line_set_data(ln, 4, strdup(t->name));
1206
1207 /* expert menu column(s) */
1208 if (fdisk_context_display_details(cxt)) {
1209 char *name = encode_to_utf8(
1210 (unsigned char *)e->name,
1211 sizeof(e->name));
1212
1213 if (guid_to_string(&e->partition_guid, u_str))
1214 tt_line_set_data(ln, 5, strdup(u_str));
1215 if (name)
1216 tt_line_set_data(ln, 6, name);
1217 }
1218
1219 fdisk_warn_alignment(cxt, start, i);
1220 fdisk_free_parttype(t);
1221 }
1222
1223 rc = fdisk_print_table(cxt, tb);
1224 tt_free_table(tb);
1225
1226 return rc;
1227 }
1228
1229 /*
1230 * Write partitions.
1231 * Returns 0 on success, or corresponding error otherwise.
1232 */
1233 static int gpt_write_partitions(struct fdisk_context *cxt,
1234 struct gpt_header *header, struct gpt_entry *ents)
1235 {
1236 off_t offset = le64_to_cpu(header->partition_entry_lba) * cxt->sector_size;
1237 uint32_t nparts = le32_to_cpu(header->npartition_entries);
1238 uint32_t totwrite = nparts * le32_to_cpu(header->sizeof_partition_entry);
1239 ssize_t rc;
1240
1241 if (offset != lseek(cxt->dev_fd, offset, SEEK_SET))
1242 goto fail;
1243
1244 rc = write(cxt->dev_fd, ents, totwrite);
1245 if (rc > 0 && totwrite == (uint32_t) rc)
1246 return 0;
1247 fail:
1248 return -errno;
1249 }
1250
1251 /*
1252 * Write a GPT header to a specified LBA
1253 * Returns 0 on success, or corresponding error otherwise.
1254 */
1255 static int gpt_write_header(struct fdisk_context *cxt,
1256 struct gpt_header *header, uint64_t lba)
1257 {
1258 off_t offset = lba * cxt->sector_size;
1259
1260 if (offset != lseek(cxt->dev_fd, offset, SEEK_SET))
1261 goto fail;
1262 if (cxt->sector_size ==
1263 (size_t) write(cxt->dev_fd, header, cxt->sector_size))
1264 return 0;
1265 fail:
1266 return -errno;
1267 }
1268
1269 /*
1270 * Write the protective MBR.
1271 * Returns 0 on success, or corresponding error otherwise.
1272 */
1273 static int gpt_write_pmbr(struct fdisk_context *cxt)
1274 {
1275 off_t offset;
1276 struct gpt_legacy_mbr *pmbr = NULL;
1277
1278 assert(cxt);
1279 assert(cxt->firstsector);
1280
1281 pmbr = (struct gpt_legacy_mbr *) cxt->firstsector;
1282
1283 /* zero out the legacy partitions */
1284 memset(pmbr->partition_record, 0, sizeof(pmbr->partition_record));
1285
1286 pmbr->signature = cpu_to_le16(MSDOS_MBR_SIGNATURE);
1287 pmbr->partition_record[0].os_type = EFI_PMBR_OSTYPE;
1288 pmbr->partition_record[0].start_sector = 1;
1289 pmbr->partition_record[0].end_head = 0xFE;
1290 pmbr->partition_record[0].end_sector = 0xFF;
1291 pmbr->partition_record[0].end_track = 0xFF;
1292 pmbr->partition_record[0].starting_lba = cpu_to_le32(1);
1293
1294 /*
1295 * Set size_in_lba to the size of the disk minus one. If the size of the disk
1296 * is too large to be represented by a 32bit LBA (2Tb), set it to 0xFFFFFFFF.
1297 */
1298 if (cxt->total_sectors - 1 > 0xFFFFFFFFULL)
1299 pmbr->partition_record[0].size_in_lba = cpu_to_le32(0xFFFFFFFF);
1300 else
1301 pmbr->partition_record[0].size_in_lba =
1302 cpu_to_le32(cxt->total_sectors - 1UL);
1303
1304 offset = GPT_PMBR_LBA * cxt->sector_size;
1305 if (offset != lseek(cxt->dev_fd, offset, SEEK_SET))
1306 goto fail;
1307
1308 /* pMBR covers the first sector (LBA) of the disk */
1309 if (write_all(cxt->dev_fd, pmbr, cxt->sector_size))
1310 goto fail;
1311 return 0;
1312 fail:
1313 return -errno;
1314 }
1315
1316 /*
1317 * Writes in-memory GPT and pMBR data to disk.
1318 * Returns 0 if successful write, otherwise, a corresponding error.
1319 * Any indication of error will abort the operation.
1320 */
1321 static int gpt_write_disklabel(struct fdisk_context *cxt)
1322 {
1323 struct fdisk_gpt_label *gpt;
1324
1325 assert(cxt);
1326 assert(cxt->label);
1327 assert(fdisk_is_disklabel(cxt, GPT));
1328
1329 gpt = self_label(cxt);
1330
1331 /* we do not want to mess up hybrid MBRs by creating a valid pmbr */
1332 if (valid_pmbr(cxt) == GPT_MBR_HYBRID)
1333 goto err0;
1334
1335 /* check that disk is big enough to handle the backup header */
1336 if (le64_to_cpu(gpt->pheader->alternative_lba) > cxt->total_sectors)
1337 goto err0;
1338
1339 /* check that the backup header is properly placed */
1340 if (le64_to_cpu(gpt->pheader->alternative_lba) < cxt->total_sectors - 1)
1341 /* TODO: correct this (with user authorization) and write */
1342 goto err0;
1343
1344 if (partition_check_overlaps(gpt->pheader, gpt->ents))
1345 goto err0;
1346
1347 /* recompute CRCs for both headers */
1348 gpt_recompute_crc(gpt->pheader, gpt->ents);
1349 gpt_recompute_crc(gpt->bheader, gpt->ents);
1350
1351 /*
1352 * UEFI requires writing in this specific order:
1353 * 1) backup partition tables
1354 * 2) backup GPT header
1355 * 3) primary partition tables
1356 * 4) primary GPT header
1357 * 5) protective MBR
1358 *
1359 * If any write fails, we abort the rest.
1360 */
1361 if (gpt_write_partitions(cxt, gpt->bheader, gpt->ents) != 0)
1362 goto err1;
1363 if (gpt_write_header(cxt, gpt->bheader,
1364 le64_to_cpu(gpt->pheader->alternative_lba)) != 0)
1365 goto err1;
1366 if (gpt_write_partitions(cxt, gpt->pheader, gpt->ents) != 0)
1367 goto err1;
1368 if (gpt_write_header(cxt, gpt->pheader, GPT_PRIMARY_PARTITION_TABLE_LBA) != 0)
1369 goto err1;
1370 if (gpt_write_pmbr(cxt) != 0)
1371 goto err1;
1372
1373 DBG(LABEL, dbgprint("GPT write success"));
1374 return 0;
1375 err0:
1376 DBG(LABEL, dbgprint("GPT write failed: incorrect input"));
1377 errno = EINVAL;
1378 return -EINVAL;
1379 err1:
1380 DBG(LABEL, dbgprint("GPT write failed: %m"));
1381 return -errno;
1382 }
1383
1384 /*
1385 * Verify data integrity and report any found problems for:
1386 * - primary and backup header validations
1387 * - paritition validations
1388 */
1389 static int gpt_verify_disklabel(struct fdisk_context *cxt)
1390 {
1391 int nerror = 0;
1392 unsigned int ptnum;
1393 struct fdisk_gpt_label *gpt;
1394
1395 assert(cxt);
1396 assert(cxt->label);
1397 assert(fdisk_is_disklabel(cxt, GPT));
1398
1399 gpt = self_label(cxt);
1400
1401 if (!gpt || !gpt->bheader) {
1402 nerror++;
1403 fdisk_warnx(cxt, _("Disk does not contain a valid backup header."));
1404 }
1405
1406 if (!gpt_check_header_crc(gpt->pheader, gpt->ents)) {
1407 nerror++;
1408 fdisk_warnx(cxt, _("Invalid primary header CRC checksum."));
1409 }
1410 if (gpt->bheader && !gpt_check_header_crc(gpt->bheader, gpt->ents)) {
1411 nerror++;
1412 fdisk_warnx(cxt, _("Invalid backup header CRC checksum."));
1413 }
1414
1415 if (!gpt_check_entryarr_crc(gpt->pheader, gpt->ents)) {
1416 nerror++;
1417 fdisk_warnx(cxt, _("Invalid partition entry checksum."));
1418 }
1419
1420 if (!gpt_check_lba_sanity(cxt, gpt->pheader)) {
1421 nerror++;
1422 fdisk_warnx(cxt, _("Invalid primary header LBA sanity checks."));
1423 }
1424 if (gpt->bheader && !gpt_check_lba_sanity(cxt, gpt->bheader)) {
1425 nerror++;
1426 fdisk_warnx(cxt, _("Invalid backup header LBA sanity checks."));
1427 }
1428
1429 if (le64_to_cpu(gpt->pheader->my_lba) != GPT_PRIMARY_PARTITION_TABLE_LBA) {
1430 nerror++;
1431 fdisk_warnx(cxt, _("MyLBA mismatch with real position at primary header."));
1432 }
1433 if (gpt->bheader && le64_to_cpu(gpt->bheader->my_lba) != last_lba(cxt)) {
1434 nerror++;
1435 fdisk_warnx(cxt, _("MyLBA mismatch with real position at backup header."));
1436
1437 }
1438 if (le64_to_cpu(gpt->pheader->alternative_lba) >= cxt->total_sectors) {
1439 nerror++;
1440 fdisk_warnx(cxt, _("Disk is to small to hold all data."));
1441 }
1442
1443 /*
1444 * if the GPT is the primary table, check the alternateLBA
1445 * to see if it is a valid GPT
1446 */
1447 if (gpt->bheader && (le64_to_cpu(gpt->pheader->my_lba) !=
1448 le64_to_cpu(gpt->bheader->alternative_lba))) {
1449 nerror++;
1450 fdisk_warnx(cxt, _("Primary and backup header mismatch."));
1451 }
1452
1453 ptnum = partition_check_overlaps(gpt->pheader, gpt->ents);
1454 if (ptnum) {
1455 nerror++;
1456 fdisk_warnx(cxt, _("Partition %u overlaps with partition %u."),
1457 ptnum, ptnum+1);
1458 }
1459
1460 ptnum = partition_check_too_big(gpt->pheader, gpt->ents, cxt->total_sectors);
1461 if (ptnum) {
1462 nerror++;
1463 fdisk_warnx(cxt, _("Partition %u is too big for the disk."),
1464 ptnum);
1465 }
1466
1467 ptnum = partition_start_after_end(gpt->pheader, gpt->ents);
1468 if (ptnum) {
1469 nerror++;
1470 fdisk_warnx(cxt, _("Partition %u ends before it starts."),
1471 ptnum);
1472 }
1473
1474 if (!nerror) { /* yay :-) */
1475 uint32_t nsegments = 0;
1476 uint64_t free_sectors = 0, largest_segment = 0;
1477
1478 fdisk_info(cxt, _("No errors detected"));
1479 fdisk_info(cxt, _("Header version: %s"), gpt_get_header_revstr(gpt->pheader));
1480 fdisk_info(cxt, _("Using %u out of %d partitions."),
1481 partitions_in_use(gpt->pheader, gpt->ents),
1482 le32_to_cpu(gpt->pheader->npartition_entries));
1483
1484 free_sectors = get_free_sectors(cxt, gpt->pheader, gpt->ents,
1485 &nsegments, &largest_segment);
1486 fdisk_info(cxt, _("A total of %ld free sectors available in %d segment(s) "
1487 "(largest %ld)."),
1488 free_sectors, nsegments, largest_segment);
1489 } else
1490 fdisk_warnx(cxt, _("Detected %d error(s)."), nerror);
1491
1492 return 0;
1493 }
1494
1495 /* Delete a single GPT partition, specified by partnum. */
1496 static int gpt_delete_partition(struct fdisk_context *cxt,
1497 size_t partnum)
1498 {
1499 struct fdisk_gpt_label *gpt;
1500
1501 assert(cxt);
1502 assert(cxt->label);
1503 assert(fdisk_is_disklabel(cxt, GPT));
1504
1505 gpt = self_label(cxt);
1506
1507 if (partnum >= cxt->label->nparts_max
1508 || partition_unused(&gpt->ents[partnum]))
1509 return -EINVAL;
1510
1511 /* hasta la vista, baby! */
1512 memset(&gpt->ents[partnum], 0, sizeof(struct gpt_entry));
1513 if (!partition_unused(&gpt->ents[partnum]))
1514 return -EINVAL;
1515 else {
1516 gpt_recompute_crc(gpt->pheader, gpt->ents);
1517 gpt_recompute_crc(gpt->bheader, gpt->ents);
1518 cxt->label->nparts_cur--;
1519 fdisk_label_set_changed(cxt->label, 1);
1520 }
1521
1522 return 0;
1523 }
1524
1525 static void gpt_entry_set_type(struct gpt_entry *e, struct gpt_guid *uuid)
1526 {
1527 e->type = *uuid;
1528 DBG(LABEL, dbgprint_uuid("new type", &(e->type)));
1529 }
1530
1531 /*
1532 * Create a new GPT partition entry, specified by partnum, and with a range
1533 * of fsect to lsenct sectors, of type t.
1534 * Returns 0 on success, or negative upon failure.
1535 */
1536 static int gpt_create_new_partition(struct fdisk_context *cxt,
1537 size_t partnum, uint64_t fsect, uint64_t lsect,
1538 struct gpt_guid *type,
1539 struct gpt_entry *entries)
1540 {
1541 struct gpt_entry *e = NULL;
1542 struct fdisk_gpt_label *gpt;
1543
1544 assert(cxt);
1545 assert(cxt->label);
1546 assert(fdisk_is_disklabel(cxt, GPT));
1547
1548 gpt = self_label(cxt);
1549
1550 if (fsect > lsect || partnum >= cxt->label->nparts_max)
1551 return -EINVAL;
1552
1553 e = calloc(1, sizeof(*e));
1554 if (!e)
1555 return -ENOMEM;
1556 e->lba_end = cpu_to_le64(lsect);
1557 e->lba_start = cpu_to_le64(fsect);
1558
1559 gpt_entry_set_type(e, type);
1560
1561 /*
1562 * Any time a new partition entry is created a new GUID must be
1563 * generated for that partition, and every partition is guaranteed
1564 * to have a unique GUID.
1565 */
1566 uuid_generate_random((unsigned char *) &e->partition_guid);
1567 swap_efi_guid(&e->partition_guid);
1568
1569 memcpy(&entries[partnum], e, sizeof(*e));
1570
1571 gpt_recompute_crc(gpt->pheader, entries);
1572 gpt_recompute_crc(gpt->bheader, entries);
1573
1574 free(e);
1575 return 0;
1576 }
1577
1578 /* Performs logical checks to add a new partition entry */
1579 static int gpt_add_partition(
1580 struct fdisk_context *cxt,
1581 size_t partnum,
1582 struct fdisk_parttype *t)
1583 {
1584 uint64_t user_f, user_l; /* user input ranges for first and last sectors */
1585 uint64_t disk_f, disk_l; /* first and last available sector ranges on device*/
1586 uint64_t dflt_f, dflt_l; /* largest segment (default) */
1587 struct gpt_guid typeid;
1588 struct fdisk_gpt_label *gpt;
1589 struct gpt_header *pheader;
1590 struct gpt_entry *ents;
1591 struct fdisk_ask *ask = NULL;
1592 int rc;
1593
1594 assert(cxt);
1595 assert(cxt->label);
1596 assert(fdisk_is_disklabel(cxt, GPT));
1597
1598 gpt = self_label(cxt);
1599
1600 if (partnum >= cxt->label->nparts_max)
1601 return -EINVAL;
1602
1603 pheader = gpt->pheader;
1604 ents = gpt->ents;
1605
1606 if (!partition_unused(&ents[partnum])) {
1607 fdisk_warnx(cxt, _("Partition %zd is already defined. "
1608 "Delete it before re-adding it."), partnum +1);
1609 return -EINVAL;
1610 }
1611 if (le32_to_cpu(pheader->npartition_entries) ==
1612 partitions_in_use(pheader, ents)) {
1613 fdisk_warnx(cxt, _("All partitions are already in use."));
1614 return -EINVAL;
1615 }
1616
1617 if (!get_free_sectors(cxt, pheader, ents, NULL, NULL)) {
1618 fdisk_warnx(cxt, _("No free sectors available."));
1619 return -ENOSPC;
1620 }
1621
1622 disk_f = find_first_available(pheader, ents, 0);
1623 disk_l = find_last_free_sector(pheader, ents);
1624
1625 /* the default is the largest free space */
1626 dflt_f = find_first_in_largest(pheader, ents);
1627 dflt_l = find_last_free(pheader, ents, dflt_f);
1628
1629 /* align the default in range <dflt_f,dflt_l>*/
1630 dflt_f = fdisk_align_lba_in_range(cxt, dflt_f, dflt_f, dflt_l);
1631
1632 string_to_guid(t && t->typestr ? t->typestr : GPT_DEFAULT_ENTRY_TYPE, &typeid);
1633
1634 /* get user input for first and last sectors of the new partition */
1635 for (;;) {
1636 if (!ask)
1637 ask = fdisk_new_ask();
1638 else
1639 fdisk_reset_ask(ask);
1640
1641 /* First sector */
1642 fdisk_ask_set_query(ask, _("First sector"));
1643 fdisk_ask_set_type(ask, FDISK_ASKTYPE_NUMBER);
1644 fdisk_ask_number_set_low(ask, disk_f); /* minimal */
1645 fdisk_ask_number_set_default(ask, dflt_f); /* default */
1646 fdisk_ask_number_set_high(ask, disk_l); /* maximal */
1647
1648 rc = fdisk_do_ask(cxt, ask);
1649 if (rc)
1650 goto done;
1651
1652 user_f = fdisk_ask_number_get_result(ask);
1653 if (user_f != find_first_available(pheader, ents, user_f)) {
1654 fdisk_warnx(cxt, _("Sector %ju already used."), user_f);
1655 continue;
1656 }
1657
1658 fdisk_reset_ask(ask);
1659
1660 /* Last sector */
1661 dflt_l = find_last_free(pheader, ents, user_f);
1662
1663 fdisk_ask_set_query(ask, _("Last sector, +sectors or +size{K,M,G,T,P}"));
1664 fdisk_ask_set_type(ask, FDISK_ASKTYPE_OFFSET);
1665 fdisk_ask_number_set_low(ask, user_f); /* minimal */
1666 fdisk_ask_number_set_default(ask, dflt_l); /* default */
1667 fdisk_ask_number_set_high(ask, dflt_l); /* maximal */
1668 fdisk_ask_number_set_base(ask, user_f); /* base for relative input */
1669 fdisk_ask_number_set_unit(ask, cxt->sector_size);
1670
1671 rc = fdisk_do_ask(cxt, ask);
1672 if (rc)
1673 goto done;
1674
1675 user_l = fdisk_ask_number_get_result(ask);
1676 if (fdisk_ask_number_is_relative(ask))
1677 user_l = fdisk_align_lba_in_range(cxt, user_l, user_f, dflt_l) - 1;
1678 if (user_l > user_f && user_l <= disk_l)
1679 break;
1680 }
1681
1682 if (gpt_create_new_partition(cxt, partnum,
1683 user_f, user_l, &typeid, ents) != 0)
1684 fdisk_warnx(cxt, _("Could not create partition %zd"), partnum + 1);
1685 else {
1686 fdisk_info(cxt, _("Created partition %zd\n"), partnum + 1);
1687 cxt->label->nparts_cur++;
1688 fdisk_label_set_changed(cxt->label, 1);
1689 }
1690
1691 rc = 0;
1692 done:
1693 fdisk_free_ask(ask);
1694 return rc;
1695 }
1696
1697 /*
1698 * Create a new GPT disklabel - destroys any previous data.
1699 */
1700 static int gpt_create_disklabel(struct fdisk_context *cxt)
1701 {
1702 int rc = 0;
1703 ssize_t esz = 0;
1704 char str[37];
1705 struct fdisk_gpt_label *gpt;
1706
1707 assert(cxt);
1708 assert(cxt->label);
1709 assert(fdisk_is_disklabel(cxt, GPT));
1710
1711 gpt = self_label(cxt);
1712
1713 /* label private stuff has to be empty, see gpt_deinit() */
1714 assert(gpt->pheader == NULL);
1715 assert(gpt->bheader == NULL);
1716
1717 /*
1718 * When no header, entries or pmbr is set, we're probably
1719 * dealing with a new, empty disk - so always allocate memory
1720 * to deal with the data structures whatever the case is.
1721 */
1722 rc = gpt_mknew_pmbr(cxt);
1723 if (rc < 0)
1724 goto done;
1725
1726 /* primary */
1727 gpt->pheader = calloc(1, sizeof(*gpt->pheader));
1728 if (!gpt->pheader) {
1729 rc = -ENOMEM;
1730 goto done;
1731 }
1732 rc = gpt_mknew_header(cxt, gpt->pheader, GPT_PRIMARY_PARTITION_TABLE_LBA);
1733 if (rc < 0)
1734 goto done;
1735
1736 /* backup ("copy" primary) */
1737 gpt->bheader = calloc(1, sizeof(*gpt->bheader));
1738 if (!gpt->bheader) {
1739 rc = -ENOMEM;
1740 goto done;
1741 }
1742 rc = gpt_mknew_header_from_bkp(cxt, gpt->bheader,
1743 last_lba(cxt), gpt->pheader);
1744 if (rc < 0)
1745 goto done;
1746
1747 esz = le32_to_cpu(gpt->pheader->npartition_entries) *
1748 le32_to_cpu(gpt->pheader->sizeof_partition_entry);
1749 gpt->ents = calloc(1, esz);
1750 if (!gpt->ents) {
1751 rc = -ENOMEM;
1752 goto done;
1753 }
1754 gpt_recompute_crc(gpt->pheader, gpt->ents);
1755 gpt_recompute_crc(gpt->bheader, gpt->ents);
1756
1757 cxt->label->nparts_max = le32_to_cpu(gpt->pheader->npartition_entries);
1758 cxt->label->nparts_cur = 0;
1759
1760 guid_to_string(&gpt->pheader->disk_guid, str);
1761 fdisk_info(cxt, _("Building a new GPT disklabel (GUID: %s)"), str);
1762 fdisk_label_set_changed(cxt->label, 1);
1763 done:
1764 return rc;
1765 }
1766
1767 static int gpt_get_disklabel_id(struct fdisk_context *cxt, char **id)
1768 {
1769 struct fdisk_gpt_label *gpt;
1770 char str[37];
1771
1772 assert(cxt);
1773 assert(id);
1774 assert(cxt->label);
1775 assert(fdisk_is_disklabel(cxt, GPT));
1776
1777 gpt = self_label(cxt);
1778 guid_to_string(&gpt->pheader->disk_guid, str);
1779
1780 *id = strdup(str);
1781 if (!*id)
1782 return -ENOMEM;
1783 return 0;
1784 }
1785
1786 static int gpt_set_disklabel_id(struct fdisk_context *cxt)
1787 {
1788 struct fdisk_gpt_label *gpt;
1789 struct gpt_guid uuid;
1790 char *str, *old, *new;
1791 int rc;
1792
1793 assert(cxt);
1794 assert(cxt->label);
1795 assert(fdisk_is_disklabel(cxt, GPT));
1796
1797 gpt = self_label(cxt);
1798 if (fdisk_ask_string(cxt,
1799 _("Enter new disk UUID (in 8-4-4-4-12 format)"), &str))
1800 return -EINVAL;
1801
1802 rc = string_to_guid(str, &uuid);
1803 free(str);
1804
1805 if (rc) {
1806 fdisk_warnx(cxt, _("Failed to parse your UUID."));
1807 return rc;
1808 }
1809
1810 gpt_get_disklabel_id(cxt, &old);
1811
1812 gpt->pheader->disk_guid = uuid;
1813 gpt->bheader->disk_guid = uuid;
1814
1815 gpt_recompute_crc(gpt->pheader, gpt->ents);
1816 gpt_recompute_crc(gpt->bheader, gpt->ents);
1817
1818 gpt_get_disklabel_id(cxt, &new);
1819
1820 fdisk_info(cxt, _("Changing disk identifier from %s to %s."), old, new);
1821
1822 free(old);
1823 free(new);
1824 fdisk_label_set_changed(cxt->label, 1);
1825 return 0;
1826 }
1827
1828
1829 static struct fdisk_parttype *gpt_get_partition_type(
1830 struct fdisk_context *cxt,
1831 size_t i)
1832 {
1833 struct fdisk_parttype *t;
1834 char str[37];
1835 struct fdisk_gpt_label *gpt;
1836
1837 assert(cxt);
1838 assert(cxt->label);
1839 assert(fdisk_is_disklabel(cxt, GPT));
1840
1841 gpt = self_label(cxt);
1842
1843 if ((uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries))
1844 return NULL;
1845
1846 guid_to_string(&gpt->ents[i].type, str);
1847 t = fdisk_get_parttype_from_string(cxt, str);
1848 if (!t)
1849 t = fdisk_new_unknown_parttype(0, str);
1850
1851 return t;
1852 }
1853
1854
1855 static int gpt_set_partition_type(
1856 struct fdisk_context *cxt,
1857 size_t i,
1858 struct fdisk_parttype *t)
1859 {
1860 struct gpt_guid uuid;
1861 struct fdisk_gpt_label *gpt;
1862
1863 assert(cxt);
1864 assert(cxt->label);
1865 assert(fdisk_is_disklabel(cxt, GPT));
1866
1867 gpt = self_label(cxt);
1868 if ((uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries)
1869 || !t || !t->typestr || string_to_guid(t->typestr, &uuid) != 0)
1870 return -EINVAL;
1871
1872 gpt_entry_set_type(&gpt->ents[i], &uuid);
1873 gpt_recompute_crc(gpt->pheader, gpt->ents);
1874 gpt_recompute_crc(gpt->bheader, gpt->ents);
1875
1876 fdisk_label_set_changed(cxt->label, 1);
1877 return 0;
1878 }
1879
1880 static int gpt_get_partition_status(
1881 struct fdisk_context *cxt,
1882 size_t i,
1883 int *status)
1884 {
1885 struct fdisk_gpt_label *gpt;
1886 struct gpt_entry *e;
1887
1888 assert(cxt);
1889 assert(cxt->label);
1890 assert(fdisk_is_disklabel(cxt, GPT));
1891
1892 gpt = self_label(cxt);
1893
1894 if (!status || (uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries))
1895 return -EINVAL;
1896
1897 e = &gpt->ents[i];
1898 *status = FDISK_PARTSTAT_NONE;
1899
1900 if (!partition_unused(e) || gpt_partition_start(e))
1901 *status = FDISK_PARTSTAT_USED;
1902
1903 return 0;
1904 }
1905
1906 int fdisk_gpt_partition_set_uuid(struct fdisk_context *cxt, size_t i)
1907 {
1908 struct fdisk_gpt_label *gpt;
1909 struct gpt_entry *e;
1910 struct gpt_guid uuid;
1911 char *str, new_u[37], old_u[37];
1912 int rc;
1913
1914 assert(cxt);
1915 assert(cxt->label);
1916 assert(fdisk_is_disklabel(cxt, GPT));
1917
1918 DBG(LABEL, dbgprint("UUID change requested partno=%zd", i));
1919
1920 gpt = self_label(cxt);
1921
1922 if ((uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries))
1923 return -EINVAL;
1924
1925 if (fdisk_ask_string(cxt,
1926 _("New UUID (in 8-4-4-4-12 format)"), &str))
1927 return -EINVAL;
1928
1929 rc = string_to_guid(str, &uuid);
1930 free(str);
1931
1932 if (rc) {
1933 fdisk_warnx(cxt, _("Failed to parse your UUID."));
1934 return rc;
1935 }
1936
1937 e = &gpt->ents[i];
1938
1939 guid_to_string(&e->partition_guid, old_u);
1940 guid_to_string(&uuid, new_u);
1941 fdisk_info(cxt, _("Changing partition UUID from %s to %s"),
1942 old_u, new_u);
1943
1944 e->partition_guid = uuid;
1945 gpt_recompute_crc(gpt->pheader, gpt->ents);
1946 gpt_recompute_crc(gpt->bheader, gpt->ents);
1947
1948 fdisk_label_set_changed(cxt->label, 1);
1949 return 0;
1950 }
1951
1952 int fdisk_gpt_partition_set_name(struct fdisk_context *cxt, size_t i)
1953 {
1954 struct fdisk_gpt_label *gpt;
1955 struct gpt_entry *e;
1956 char *str, *old, name[GPT_PART_NAME_LEN] = { 0 };
1957 size_t sz;
1958
1959 assert(cxt);
1960 assert(cxt->label);
1961 assert(fdisk_is_disklabel(cxt, GPT));
1962
1963 DBG(LABEL, dbgprint("NAME change requested partno=%zd", i));
1964
1965 gpt = self_label(cxt);
1966
1967 if ((uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries))
1968 return -EINVAL;
1969
1970 if (fdisk_ask_string(cxt, _("New name"), &str))
1971 return -EINVAL;
1972
1973 e = &gpt->ents[i];
1974 old = encode_to_utf8((unsigned char *)e->name, sizeof(e->name));
1975
1976 fdisk_info(cxt, _("Changing partition name from '%s' to '%.*s'"),
1977 old, GPT_PART_NAME_LEN, str);
1978 sz = strlen(str);
1979 if (sz) {
1980 if (sz > GPT_PART_NAME_LEN)
1981 sz = GPT_PART_NAME_LEN;
1982 memcpy(name, str, sz);
1983 }
1984 free(str);
1985 free(old);
1986
1987 for (i = 0; i < GPT_PART_NAME_LEN; i++)
1988 e->name[i] = cpu_to_le16((uint16_t) name[i]);
1989
1990 gpt_recompute_crc(gpt->pheader, gpt->ents);
1991 gpt_recompute_crc(gpt->bheader, gpt->ents);
1992
1993 fdisk_label_set_changed(cxt->label, 1);
1994 return 0;
1995 }
1996
1997
1998 /*
1999 * Deinitialize fdisk-specific variables
2000 */
2001 static void gpt_deinit(struct fdisk_label *lb)
2002 {
2003 struct fdisk_gpt_label *gpt = (struct fdisk_gpt_label *) lb;
2004
2005 if (!gpt)
2006 return;
2007
2008 free(gpt->ents);
2009 free(gpt->pheader);
2010 free(gpt->bheader);
2011
2012 gpt->ents = NULL;
2013 gpt->pheader = NULL;
2014 gpt->bheader = NULL;
2015 }
2016
2017 static const struct fdisk_label_operations gpt_operations =
2018 {
2019 .probe = gpt_probe_label,
2020 .write = gpt_write_disklabel,
2021 .verify = gpt_verify_disklabel,
2022 .create = gpt_create_disklabel,
2023 .list = gpt_list_disklabel,
2024 .get_id = gpt_get_disklabel_id,
2025 .set_id = gpt_set_disklabel_id,
2026
2027 .part_add = gpt_add_partition,
2028 .part_delete = gpt_delete_partition,
2029 .part_get_type = gpt_get_partition_type,
2030 .part_set_type = gpt_set_partition_type,
2031
2032 .part_get_status = gpt_get_partition_status,
2033
2034 .deinit = gpt_deinit
2035 };
2036
2037 /*
2038 * allocates GPT in-memory stuff
2039 */
2040 struct fdisk_label *fdisk_new_gpt_label(struct fdisk_context *cxt)
2041 {
2042 struct fdisk_label *lb;
2043 struct fdisk_gpt_label *gpt;
2044
2045 assert(cxt);
2046
2047 gpt = calloc(1, sizeof(*gpt));
2048 if (!gpt)
2049 return NULL;
2050
2051 /* initialize generic part of the driver */
2052 lb = (struct fdisk_label *) gpt;
2053 lb->name = "gpt";
2054 lb->id = FDISK_DISKLABEL_GPT;
2055 lb->op = &gpt_operations;
2056 lb->parttypes = gpt_parttypes;
2057 lb->nparttypes = ARRAY_SIZE(gpt_parttypes);
2058
2059 return lb;
2060 }