blob: 8c1c96c37240a363c73a6fa196425336254ec1b3 [file] [log] [blame]
bigbiff7b4c7a62015-01-01 19:44:14 -05001/*
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/**
32 * SECTION: gpt
33 * @title: UEFI GPT
34 * @short_description: specific functionality
35 */
36
37#define GPT_HEADER_SIGNATURE 0x5452415020494645LL /* EFI PART */
38#define GPT_HEADER_REVISION_V1_02 0x00010200
39#define GPT_HEADER_REVISION_V1_00 0x00010000
40#define GPT_HEADER_REVISION_V0_99 0x00009900
41#define GPT_HEADER_MINSZ 92 /* bytes */
42
43#define GPT_PMBR_LBA 0
44#define GPT_MBR_PROTECTIVE 1
45#define GPT_MBR_HYBRID 2
46
47#define GPT_PRIMARY_PARTITION_TABLE_LBA 0x00000001
48
49#define EFI_PMBR_OSTYPE 0xEE
50#define MSDOS_MBR_SIGNATURE 0xAA55
51#define GPT_PART_NAME_LEN (72 / sizeof(uint16_t))
52#define GPT_NPARTITIONS 128
53
54/* Globally unique identifier */
55struct gpt_guid {
56 uint32_t time_low;
57 uint16_t time_mid;
58 uint16_t time_hi_and_version;
59 uint8_t clock_seq_hi;
60 uint8_t clock_seq_low;
61 uint8_t node[6];
62};
63
64
65/* only checking that the GUID is 0 is enough to verify an empty partition. */
66#define GPT_UNUSED_ENTRY_GUID \
67 ((struct gpt_guid) { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, \
68 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }})
69
70/* Linux native partition type */
71#define GPT_DEFAULT_ENTRY_TYPE "0FC63DAF-8483-4772-8E79-3D69D8477DE4"
72
73/*
74 * Attribute bits
75 */
76enum {
77 /* UEFI specific */
78 GPT_ATTRBIT_REQ = 0,
79 GPT_ATTRBIT_NOBLOCK = 1,
80 GPT_ATTRBIT_LEGACY = 2,
81
82 /* GUID specific (range 48..64)*/
83 GPT_ATTRBIT_GUID_FIRST = 48,
84 GPT_ATTRBIT_GUID_COUNT = 16
85};
86
87#define GPT_ATTRSTR_REQ "RequiredPartiton"
88#define GPT_ATTRSTR_NOBLOCK "NoBlockIOProtocol"
89#define GPT_ATTRSTR_LEGACY "LegacyBIOSBootable"
90
91/* The GPT Partition entry array contains an array of GPT entries. */
92struct gpt_entry {
93 struct gpt_guid type; /* purpose and type of the partition */
94 struct gpt_guid partition_guid;
95 uint64_t lba_start;
96 uint64_t lba_end;
97 uint64_t attrs;
98 uint16_t name[GPT_PART_NAME_LEN];
99} __attribute__ ((packed));
100
101/* GPT header */
102struct gpt_header {
103 uint64_t signature; /* header identification */
104 uint32_t revision; /* header version */
105 uint32_t size; /* in bytes */
106 uint32_t crc32; /* header CRC checksum */
107 uint32_t reserved1; /* must be 0 */
108 uint64_t my_lba; /* LBA of block that contains this struct (LBA 1) */
109 uint64_t alternative_lba; /* backup GPT header */
110 uint64_t first_usable_lba; /* first usable logical block for partitions */
111 uint64_t last_usable_lba; /* last usable logical block for partitions */
112 struct gpt_guid disk_guid; /* unique disk identifier */
113 uint64_t partition_entry_lba; /* LBA of start of partition entries array */
114 uint32_t npartition_entries; /* total partition entries - normally 128 */
115 uint32_t sizeof_partition_entry; /* bytes for each GUID pt */
116 uint32_t partition_entry_array_crc32; /* partition CRC checksum */
117 uint8_t reserved2[512 - 92]; /* must all be 0 */
118} __attribute__ ((packed));
119
120struct gpt_record {
121 uint8_t boot_indicator; /* unused by EFI, set to 0x80 for bootable */
122 uint8_t start_head; /* unused by EFI, pt start in CHS */
123 uint8_t start_sector; /* unused by EFI, pt start in CHS */
124 uint8_t start_track;
125 uint8_t os_type; /* EFI and legacy non-EFI OS types */
126 uint8_t end_head; /* unused by EFI, pt end in CHS */
127 uint8_t end_sector; /* unused by EFI, pt end in CHS */
128 uint8_t end_track; /* unused by EFI, pt end in CHS */
129 uint32_t starting_lba; /* used by EFI - start addr of the on disk pt */
130 uint32_t size_in_lba; /* used by EFI - size of pt in LBA */
131} __attribute__ ((packed));
132
133/* Protected MBR and legacy MBR share same structure */
134struct gpt_legacy_mbr {
135 uint8_t boot_code[440];
136 uint32_t unique_mbr_signature;
137 uint16_t unknown;
138 struct gpt_record partition_record[4];
139 uint16_t signature;
140} __attribute__ ((packed));
141
142/*
143 * Here be dragons!
144 * See: http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs
145 */
146#define DEF_GUID(_u, _n) \
147 { \
148 .typestr = (_u), \
149 .name = (_n), \
150 }
151
152static struct fdisk_parttype gpt_parttypes[] =
153{
154 /* Generic OS */
155 DEF_GUID("C12A7328-F81F-11D2-BA4B-00A0C93EC93B", N_("EFI System")),
156
157 DEF_GUID("024DEE41-33E7-11D3-9D69-0008C781F39F", N_("MBR partition scheme")),
158 DEF_GUID("D3BFE2DE-3DAF-11DF-BA40-E3A556D89593", N_("Intel Fast Flash")),
159
160 /* Hah!IdontneedEFI */
161 DEF_GUID("21686148-6449-6E6F-744E-656564454649", N_("BIOS boot")),
162
163 /* Windows */
164 DEF_GUID("E3C9E316-0B5C-4DB8-817D-F92DF00215AE", N_("Microsoft reserved")),
165 DEF_GUID("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", N_("Microsoft basic data")),
166 DEF_GUID("5808C8AA-7E8F-42E0-85D2-E1E90434CFB3", N_("Microsoft LDM metadata")),
167 DEF_GUID("AF9B60A0-1431-4F62-BC68-3311714A69AD", N_("Microsoft LDM data")),
168 DEF_GUID("DE94BBA4-06D1-4D40-A16A-BFD50179D6AC", N_("Windows recovery environment")),
169 DEF_GUID("37AFFC90-EF7D-4E96-91C3-2D7AE055B174", N_("IBM General Parallel Fs")),
170 DEF_GUID("E75CAF8F-F680-4CEE-AFA3-B001E56EFC2D", N_("Microsoft Storage Spaces")),
171
172 /* HP-UX */
173 DEF_GUID("75894C1E-3AEB-11D3-B7C1-7B03A0000000", N_("HP-UX data")),
174 DEF_GUID("E2A1E728-32E3-11D6-A682-7B03A0000000", N_("HP-UX service")),
175
176 /* Linux (http://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec) */
177 DEF_GUID("0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", N_("Linux swap")),
178 DEF_GUID("0FC63DAF-8483-4772-8E79-3D69D8477DE4", N_("Linux filesystem")),
179 DEF_GUID("3B8F8425-20E0-4F3B-907F-1A25A76F98E8", N_("Linux server data")),
180 DEF_GUID("44479540-F297-41B2-9AF7-D131D5F0458A", N_("Linux root (x86)")),
181 DEF_GUID("4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709", N_("Linux root (x86-64)")),
182 DEF_GUID("8DA63339-0007-60C0-C436-083AC8230908", N_("Linux reserved")),
183 DEF_GUID("933AC7E1-2EB4-4F13-B844-0E14E2AEF915", N_("Linux home")),
184 DEF_GUID("A19D880F-05FC-4D3B-A006-743F0F84911E", N_("Linux RAID")),
185 DEF_GUID("BC13C2FF-59E6-4262-A352-B275FD6F7172", N_("Linux extended boot")),
186 DEF_GUID("E6D6D379-F507-44C2-A23C-238F2A3DF928", N_("Linux LVM")),
187
188 /* FreeBSD */
189 DEF_GUID("516E7CB4-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD data")),
190 DEF_GUID("83BD6B9D-7F41-11DC-BE0B-001560B84F0F", N_("FreeBSD boot")),
191 DEF_GUID("516E7CB5-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD swap")),
192 DEF_GUID("516E7CB6-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD UFS")),
193 DEF_GUID("516E7CBA-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD ZFS")),
194 DEF_GUID("516E7CB8-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD Vinum")),
195
196 /* Apple OSX */
197 DEF_GUID("48465300-0000-11AA-AA11-00306543ECAC", N_("Apple HFS/HFS+")),
198 DEF_GUID("55465300-0000-11AA-AA11-00306543ECAC", N_("Apple UFS")),
199 DEF_GUID("52414944-0000-11AA-AA11-00306543ECAC", N_("Apple RAID")),
200 DEF_GUID("52414944-5F4F-11AA-AA11-00306543ECAC", N_("Apple RAID offline")),
201 DEF_GUID("426F6F74-0000-11AA-AA11-00306543ECAC", N_("Apple boot")),
202 DEF_GUID("4C616265-6C00-11AA-AA11-00306543ECAC", N_("Apple label")),
203 DEF_GUID("5265636F-7665-11AA-AA11-00306543ECAC", N_("Apple TV recovery")),
204 DEF_GUID("53746F72-6167-11AA-AA11-00306543ECAC", N_("Apple Core storage")),
205
206 /* Solaris */
207 DEF_GUID("6A82CB45-1DD2-11B2-99A6-080020736631", N_("Solaris boot")),
208 DEF_GUID("6A85CF4D-1DD2-11B2-99A6-080020736631", N_("Solaris root")),
209 /* same as Apple ZFS */
210 DEF_GUID("6A898CC3-1DD2-11B2-99A6-080020736631", N_("Solaris /usr & Apple ZFS")),
211 DEF_GUID("6A87C46F-1DD2-11B2-99A6-080020736631", N_("Solaris swap")),
212 DEF_GUID("6A8B642B-1DD2-11B2-99A6-080020736631", N_("Solaris backup")),
213 DEF_GUID("6A8EF2E9-1DD2-11B2-99A6-080020736631", N_("Solaris /var")),
214 DEF_GUID("6A90BA39-1DD2-11B2-99A6-080020736631", N_("Solaris /home")),
215 DEF_GUID("6A9283A5-1DD2-11B2-99A6-080020736631", N_("Solaris alternate sector")),
216 DEF_GUID("6A945A3B-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 1")),
217 DEF_GUID("6A9630D1-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 2")),
218 DEF_GUID("6A980767-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 3")),
219 DEF_GUID("6A96237F-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 4")),
220 DEF_GUID("6A8D2AC7-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 5")),
221
222 /* NetBSD */
223 DEF_GUID("49F48D32-B10E-11DC-B99B-0019D1879648", N_("NetBSD swap")),
224 DEF_GUID("49F48D5A-B10E-11DC-B99B-0019D1879648", N_("NetBSD FFS")),
225 DEF_GUID("49F48D82-B10E-11DC-B99B-0019D1879648", N_("NetBSD LFS")),
226 DEF_GUID("2DB519C4-B10E-11DC-B99B-0019D1879648", N_("NetBSD concatenated")),
227 DEF_GUID("2DB519EC-B10E-11DC-B99B-0019D1879648", N_("NetBSD encrypted")),
228 DEF_GUID("49F48DAA-B10E-11DC-B99B-0019D1879648", N_("NetBSD RAID")),
229
230 /* ChromeOS */
231 DEF_GUID("FE3A2A5D-4F32-41A7-B725-ACCC3285A309", N_("ChromeOS kernel")),
232 DEF_GUID("3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC", N_("ChromeOS root fs")),
233 DEF_GUID("2E0A753D-9E48-43B0-8337-B15192CB1B5E", N_("ChromeOS reserved")),
234
235 /* MidnightBSD */
236 DEF_GUID("85D5E45A-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD data")),
237 DEF_GUID("85D5E45E-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD boot")),
238 DEF_GUID("85D5E45B-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD swap")),
239 DEF_GUID("0394Ef8B-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD UFS")),
240 DEF_GUID("85D5E45D-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD ZFS")),
241 DEF_GUID("85D5E45C-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD Vinum")),
242};
243
244/* gpt_entry macros */
245#define gpt_partition_start(_e) le64_to_cpu((_e)->lba_start)
246#define gpt_partition_end(_e) le64_to_cpu((_e)->lba_end)
247
248/*
249 * in-memory fdisk GPT stuff
250 */
251struct fdisk_gpt_label {
252 struct fdisk_label head; /* generic part */
253
254 /* gpt specific part */
255 struct gpt_header *pheader; /* primary header */
256 struct gpt_header *bheader; /* backup header */
257 struct gpt_entry *ents; /* entries (partitions) */
258};
259
260static void gpt_deinit(struct fdisk_label *lb);
261
262static inline struct fdisk_gpt_label *self_label(struct fdisk_context *cxt)
263{
264 return (struct fdisk_gpt_label *) cxt->label;
265}
266
267/*
268 * Returns the partition length, or 0 if end is before beginning.
269 */
270static uint64_t gpt_partition_size(const struct gpt_entry *e)
271{
272 uint64_t start = gpt_partition_start(e);
273 uint64_t end = gpt_partition_end(e);
274
275 return start > end ? 0 : end - start + 1ULL;
276}
277
278/* prints UUID in the real byte order! */
279static void gpt_debug_uuid(const char *mesg, struct gpt_guid *guid)
280{
281 const unsigned char *uuid = (unsigned char *) guid;
282
283 fprintf(stderr, "%s: "
284 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
285 mesg,
286 uuid[0], uuid[1], uuid[2], uuid[3],
287 uuid[4], uuid[5],
288 uuid[6], uuid[7],
289 uuid[8], uuid[9],
290 uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]);
291}
292
293/*
294 * UUID is traditionally 16 byte big-endian array, except Intel EFI
295 * specification where the UUID is a structure of little-endian fields.
296 */
297static void swap_efi_guid(struct gpt_guid *uid)
298{
299 uid->time_low = swab32(uid->time_low);
300 uid->time_mid = swab16(uid->time_mid);
301 uid->time_hi_and_version = swab16(uid->time_hi_and_version);
302}
303
304static int string_to_guid(const char *in, struct gpt_guid *guid)
305{
306 if (uuid_parse(in, (unsigned char *) guid)) /* BE */
307 return -1;
308 swap_efi_guid(guid); /* LE */
309 return 0;
310}
311
312static char *guid_to_string(const struct gpt_guid *guid, char *out)
313{
314 struct gpt_guid u = *guid; /* LE */
315
316 swap_efi_guid(&u); /* BE */
317 uuid_unparse_upper((unsigned char *) &u, out);
318
319 return out;
320}
321
322static struct fdisk_parttype *gpt_partition_parttype(
323 struct fdisk_context *cxt,
324 const struct gpt_entry *e)
325{
326 struct fdisk_parttype *t;
327 char str[37];
328
329 guid_to_string(&e->type, str);
330 t = fdisk_label_get_parttype_from_string(cxt->label, str);
331 return t ? : fdisk_new_unknown_parttype(0, str);
332}
333
334static void gpt_entry_set_type(struct gpt_entry *e, struct gpt_guid *uuid)
335{
336 e->type = *uuid;
337 DBG(LABEL, gpt_debug_uuid("new type", &(e->type)));
338}
339
340static void gpt_entry_set_name(struct gpt_entry *e, char *str)
341{
342 char name[GPT_PART_NAME_LEN] = { 0 };
343 size_t i, sz = strlen(str);
344
345 if (sz) {
346 if (sz > GPT_PART_NAME_LEN)
347 sz = GPT_PART_NAME_LEN;
348 memcpy(name, str, sz);
349 }
350
351 for (i = 0; i < GPT_PART_NAME_LEN; i++)
352 e->name[i] = cpu_to_le16((uint16_t) name[i]);
353}
354
355static int gpt_entry_set_uuid(struct gpt_entry *e, char *str)
356{
357 struct gpt_guid uuid;
358 int rc;
359
360 rc = string_to_guid(str, &uuid);
361 if (rc)
362 return rc;
363
364 e->partition_guid = uuid;
365 return 0;
366}
367
368
369static const char *gpt_get_header_revstr(struct gpt_header *header)
370{
371 if (!header)
372 goto unknown;
373
374 switch (header->revision) {
375 case GPT_HEADER_REVISION_V1_02:
376 return "1.2";
377 case GPT_HEADER_REVISION_V1_00:
378 return "1.0";
379 case GPT_HEADER_REVISION_V0_99:
380 return "0.99";
381 default:
382 goto unknown;
383 }
384
385unknown:
386 return "unknown";
387}
388
389static inline int partition_unused(const struct gpt_entry *e)
390{
391 return !memcmp(&e->type, &GPT_UNUSED_ENTRY_GUID,
392 sizeof(struct gpt_guid));
393}
394
395/*
396 * Builds a clean new valid protective MBR - will wipe out any existing data.
397 * Returns 0 on success, otherwise < 0 on error.
398 */
399static int gpt_mknew_pmbr(struct fdisk_context *cxt)
400{
401 struct gpt_legacy_mbr *pmbr = NULL;
402 int rc;
403
404 if (!cxt || !cxt->firstsector)
405 return -ENOSYS;
406
407 rc = fdisk_init_firstsector_buffer(cxt);
408 if (rc)
409 return rc;
410
411 pmbr = (struct gpt_legacy_mbr *) cxt->firstsector;
412
413 pmbr->signature = cpu_to_le16(MSDOS_MBR_SIGNATURE);
414 pmbr->partition_record[0].os_type = EFI_PMBR_OSTYPE;
415 pmbr->partition_record[0].start_sector = 1;
416 pmbr->partition_record[0].end_head = 0xFE;
417 pmbr->partition_record[0].end_sector = 0xFF;
418 pmbr->partition_record[0].end_track = 0xFF;
419 pmbr->partition_record[0].starting_lba = cpu_to_le32(1);
420 pmbr->partition_record[0].size_in_lba =
421 cpu_to_le32(min((uint32_t) cxt->total_sectors - 1, 0xFFFFFFFF));
422
423 return 0;
424}
425
426/* some universal differences between the headers */
427static void gpt_mknew_header_common(struct fdisk_context *cxt,
428 struct gpt_header *header, uint64_t lba)
429{
430 if (!cxt || !header)
431 return;
432
433 header->my_lba = cpu_to_le64(lba);
434
435 if (lba == GPT_PRIMARY_PARTITION_TABLE_LBA) { /* primary */
436 header->alternative_lba = cpu_to_le64(cxt->total_sectors - 1);
437 header->partition_entry_lba = cpu_to_le64(2);
438 } else { /* backup */
439 uint64_t esz = le32_to_cpu(header->npartition_entries) * sizeof(struct gpt_entry);
440 uint64_t esects = (esz + cxt->sector_size - 1) / cxt->sector_size;
441
442 header->alternative_lba = cpu_to_le64(GPT_PRIMARY_PARTITION_TABLE_LBA);
443 header->partition_entry_lba = cpu_to_le64(cxt->total_sectors - 1 - esects);
444 }
445}
446
447/*
448 * Builds a new GPT header (at sector lba) from a backup header2.
449 * If building a primary header, then backup is the secondary, and vice versa.
450 *
451 * Always pass a new (zeroized) header to build upon as we don't
452 * explicitly zero-set some values such as CRCs and reserved.
453 *
454 * Returns 0 on success, otherwise < 0 on error.
455 */
456static int gpt_mknew_header_from_bkp(struct fdisk_context *cxt,
457 struct gpt_header *header,
458 uint64_t lba,
459 struct gpt_header *header2)
460{
461 if (!cxt || !header || !header2)
462 return -ENOSYS;
463
464 header->signature = header2->signature;
465 header->revision = header2->revision;
466 header->size = header2->size;
467 header->npartition_entries = header2->npartition_entries;
468 header->sizeof_partition_entry = header2->sizeof_partition_entry;
469 header->first_usable_lba = header2->first_usable_lba;
470 header->last_usable_lba = header2->last_usable_lba;
471
472 memcpy(&header->disk_guid,
473 &header2->disk_guid, sizeof(header2->disk_guid));
474 gpt_mknew_header_common(cxt, header, lba);
475
476 return 0;
477}
478
479static struct gpt_header *gpt_copy_header(struct fdisk_context *cxt,
480 struct gpt_header *src)
481{
482 struct gpt_header *res;
483
484 if (!cxt || !src)
485 return NULL;
486
487 res = calloc(1, sizeof(*res));
488 if (!res) {
489 fdisk_warn(cxt, _("failed to allocate GPT header"));
490 return NULL;
491 }
492
493 res->my_lba = src->alternative_lba;
494 res->alternative_lba = src->my_lba;
495
496 res->signature = src->signature;
497 res->revision = src->revision;
498 res->size = src->size;
499 res->npartition_entries = src->npartition_entries;
500 res->sizeof_partition_entry = src->sizeof_partition_entry;
501 res->first_usable_lba = src->first_usable_lba;
502 res->last_usable_lba = src->last_usable_lba;
503
504 memcpy(&res->disk_guid, &src->disk_guid, sizeof(src->disk_guid));
505
506
507 if (res->my_lba == GPT_PRIMARY_PARTITION_TABLE_LBA)
508 res->partition_entry_lba = cpu_to_le64(2);
509 else {
510 uint64_t esz = le32_to_cpu(src->npartition_entries) * sizeof(struct gpt_entry);
511 uint64_t esects = (esz + cxt->sector_size - 1) / cxt->sector_size;
512
513 res->partition_entry_lba = cpu_to_le64(cxt->total_sectors - 1 - esects);
514 }
515
516 return res;
517}
518
519static void count_first_last_lba(struct fdisk_context *cxt,
520 uint64_t *first, uint64_t *last)
521{
522 uint64_t esz = 0;
523
524 assert(cxt);
525
526 esz = sizeof(struct gpt_entry) * GPT_NPARTITIONS / cxt->sector_size;
527 *last = cxt->total_sectors - 2 - esz;
528 *first = esz + 2;
529
530 if (*first < cxt->first_lba && cxt->first_lba < *last)
531 /* Align according to topology */
532 *first = cxt->first_lba;
533}
534
535/*
536 * Builds a clean new GPT header (currently under revision 1.0).
537 *
538 * Always pass a new (zeroized) header to build upon as we don't
539 * explicitly zero-set some values such as CRCs and reserved.
540 *
541 * Returns 0 on success, otherwise < 0 on error.
542 */
543static int gpt_mknew_header(struct fdisk_context *cxt,
544 struct gpt_header *header, uint64_t lba)
545{
546 uint64_t first, last;
547 int has_id = 0;
548
549 if (!cxt || !header)
550 return -ENOSYS;
551
552 header->signature = cpu_to_le64(GPT_HEADER_SIGNATURE);
553 header->revision = cpu_to_le32(GPT_HEADER_REVISION_V1_00);
554 header->size = cpu_to_le32(sizeof(struct gpt_header));
555
556 /*
557 * 128 partitions are the default. It can go beyond that, but
558 * we're creating a de facto header here, so no funny business.
559 */
560 header->npartition_entries = cpu_to_le32(GPT_NPARTITIONS);
561 header->sizeof_partition_entry = cpu_to_le32(sizeof(struct gpt_entry));
562
563 count_first_last_lba(cxt, &first, &last);
564 header->first_usable_lba = cpu_to_le64(first);
565 header->last_usable_lba = cpu_to_le64(last);
566
567 gpt_mknew_header_common(cxt, header, lba);
568
569 if (cxt->script) {
570 const char *id = fdisk_script_get_header(cxt->script, "label-id");
571 if (id && string_to_guid(id, &header->disk_guid) == 0)
572 has_id = 1;
573 }
574
575 if (!has_id) {
576 uuid_generate_random((unsigned char *) &header->disk_guid);
577 swap_efi_guid(&header->disk_guid);
578 }
579 return 0;
580}
581
582/*
583 * Checks if there is a valid protective MBR partition table.
584 * Returns 0 if it is invalid or failure. Otherwise, return
585 * GPT_MBR_PROTECTIVE or GPT_MBR_HYBRID, depeding on the detection.
586 */
587static int valid_pmbr(struct fdisk_context *cxt)
588{
589 int i, part = 0, ret = 0; /* invalid by default */
590 struct gpt_legacy_mbr *pmbr = NULL;
591 uint32_t sz_lba = 0;
592
593 if (!cxt->firstsector)
594 goto done;
595
596 pmbr = (struct gpt_legacy_mbr *) cxt->firstsector;
597
598 if (le16_to_cpu(pmbr->signature) != MSDOS_MBR_SIGNATURE)
599 goto done;
600
601 /* LBA of the GPT partition header */
602 if (pmbr->partition_record[0].starting_lba !=
603 cpu_to_le32(GPT_PRIMARY_PARTITION_TABLE_LBA))
604 goto done;
605
606 /* seems like a valid MBR was found, check DOS primary partitions */
607 for (i = 0; i < 4; i++) {
608 if (pmbr->partition_record[i].os_type == EFI_PMBR_OSTYPE) {
609 /*
610 * Ok, we at least know that there's a protective MBR,
611 * now check if there are other partition types for
612 * hybrid MBR.
613 */
614 part = i;
615 ret = GPT_MBR_PROTECTIVE;
616 goto check_hybrid;
617 }
618 }
619
620 if (ret != GPT_MBR_PROTECTIVE)
621 goto done;
622check_hybrid:
623 for (i = 0 ; i < 4; i++) {
624 if ((pmbr->partition_record[i].os_type != EFI_PMBR_OSTYPE) &&
625 (pmbr->partition_record[i].os_type != 0x00))
626 ret = GPT_MBR_HYBRID;
627 }
628
629 /*
630 * Protective MBRs take up the lesser of the whole disk
631 * or 2 TiB (32bit LBA), ignoring the rest of the disk.
632 * Some partitioning programs, nonetheless, choose to set
633 * the size to the maximum 32-bit limitation, disregarding
634 * the disk size.
635 *
636 * Hybrid MBRs do not necessarily comply with this.
637 *
638 * Consider a bad value here to be a warning to support dd-ing
639 * an image from a smaller disk to a bigger disk.
640 */
641 if (ret == GPT_MBR_PROTECTIVE) {
642 sz_lba = le32_to_cpu(pmbr->partition_record[part].size_in_lba);
643 if (sz_lba != (uint32_t) cxt->total_sectors - 1 && sz_lba != 0xFFFFFFFF) {
644 fdisk_warnx(cxt, _("GPT PMBR size mismatch (%u != %u) "
645 "will be corrected by w(rite)."),
646 sz_lba,
647 (uint32_t) cxt->total_sectors - 1);
648 fdisk_label_set_changed(cxt->label, 1);
649 }
650 }
651done:
652 return ret;
653}
654
655static uint64_t last_lba(struct fdisk_context *cxt)
656{
657 struct stat s;
658 uint64_t sectors = 0;
659
660 memset(&s, 0, sizeof(s));
661 if (fstat(cxt->dev_fd, &s) == -1) {
662 fdisk_warn(cxt, _("gpt: stat() failed"));
663 return 0;
664 }
665
666 if (S_ISBLK(s.st_mode))
667 sectors = cxt->total_sectors - 1;
668 else if (S_ISREG(s.st_mode))
669 sectors = ((uint64_t) s.st_size /
670 (uint64_t) cxt->sector_size) - 1ULL;
671 else
672 fdisk_warnx(cxt, _("gpt: cannot handle files with mode %o"), s.st_mode);
673
674 DBG(LABEL, ul_debug("GPT last LBA: %ju", sectors));
675 return sectors;
676}
677
678static ssize_t read_lba(struct fdisk_context *cxt, uint64_t lba,
679 void *buffer, const size_t bytes)
680{
681 off_t offset = lba * cxt->sector_size;
682
683 if (lseek(cxt->dev_fd, offset, SEEK_SET) == (off_t) -1)
684 return -1;
685 return read(cxt->dev_fd, buffer, bytes) != bytes;
686}
687
688
689/* Returns the GPT entry array */
690static struct gpt_entry *gpt_read_entries(struct fdisk_context *cxt,
691 struct gpt_header *header)
692{
693 ssize_t sz;
694 struct gpt_entry *ret = NULL;
695 off_t offset;
696
697 assert(cxt);
698 assert(header);
699
700 sz = le32_to_cpu(header->npartition_entries) *
701 le32_to_cpu(header->sizeof_partition_entry);
702
703 ret = calloc(1, sz);
704 if (!ret)
705 return NULL;
706 offset = le64_to_cpu(header->partition_entry_lba) *
707 cxt->sector_size;
708
709 if (offset != lseek(cxt->dev_fd, offset, SEEK_SET))
710 goto fail;
711 if (sz != read(cxt->dev_fd, ret, sz))
712 goto fail;
713
714 return ret;
715
716fail:
717 free(ret);
718 return NULL;
719}
720
721static inline uint32_t count_crc32(const unsigned char *buf, size_t len)
722{
723 return (crc32(~0L, buf, len) ^ ~0L);
724}
725
726/*
727 * Recompute header and partition array 32bit CRC checksums.
728 * This function does not fail - if there's corruption, then it
729 * will be reported when checksuming it again (ie: probing or verify).
730 */
731static void gpt_recompute_crc(struct gpt_header *header, struct gpt_entry *ents)
732{
733 uint32_t crc = 0;
734 size_t entry_sz = 0;
735
736 if (!header)
737 return;
738
739 /* header CRC */
740 header->crc32 = 0;
741 crc = count_crc32((unsigned char *) header, le32_to_cpu(header->size));
742 header->crc32 = cpu_to_le32(crc);
743
744 /* partition entry array CRC */
745 header->partition_entry_array_crc32 = 0;
746 entry_sz = le32_to_cpu(header->npartition_entries) *
747 le32_to_cpu(header->sizeof_partition_entry);
748
749 crc = count_crc32((unsigned char *) ents, entry_sz);
750 header->partition_entry_array_crc32 = cpu_to_le32(crc);
751}
752
753/*
754 * Compute the 32bit CRC checksum of the partition table header.
755 * Returns 1 if it is valid, otherwise 0.
756 */
757static int gpt_check_header_crc(struct gpt_header *header, struct gpt_entry *ents)
758{
759 uint32_t crc, orgcrc = le32_to_cpu(header->crc32);
760
761 header->crc32 = 0;
762 crc = count_crc32((unsigned char *) header, le32_to_cpu(header->size));
763 header->crc32 = cpu_to_le32(orgcrc);
764
765 if (crc == le32_to_cpu(header->crc32))
766 return 1;
767
768 /*
769 * If we have checksum mismatch it may be due to stale data,
770 * like a partition being added or deleted. Recompute the CRC again
771 * and make sure this is not the case.
772 */
773 if (ents) {
774 gpt_recompute_crc(header, ents);
775 orgcrc = le32_to_cpu(header->crc32);
776 header->crc32 = 0;
777 crc = count_crc32((unsigned char *) header, le32_to_cpu(header->size));
778 header->crc32 = cpu_to_le32(orgcrc);
779
780 return crc == le32_to_cpu(header->crc32);
781 }
782
783 return 0;
784}
785
786/*
787 * It initializes the partition entry array.
788 * Returns 1 if the checksum is valid, otherwise 0.
789 */
790static int gpt_check_entryarr_crc(struct gpt_header *header,
791 struct gpt_entry *ents)
792{
793 int ret = 0;
794 ssize_t entry_sz;
795 uint32_t crc;
796
797 if (!header || !ents)
798 goto done;
799
800 entry_sz = le32_to_cpu(header->npartition_entries) *
801 le32_to_cpu(header->sizeof_partition_entry);
802
803 if (!entry_sz)
804 goto done;
805
806 crc = count_crc32((unsigned char *) ents, entry_sz);
807 ret = (crc == le32_to_cpu(header->partition_entry_array_crc32));
808done:
809 return ret;
810}
811
812static int gpt_check_lba_sanity(struct fdisk_context *cxt, struct gpt_header *header)
813{
814 int ret = 0;
815 uint64_t lu, fu, lastlba = last_lba(cxt);
816
817 fu = le64_to_cpu(header->first_usable_lba);
818 lu = le64_to_cpu(header->last_usable_lba);
819
820 /* check if first and last usable LBA make sense */
821 if (lu < fu) {
822 DBG(LABEL, ul_debug("error: header last LBA is before first LBA"));
823 goto done;
824 }
825
826 /* check if first and last usable LBAs with the disk's last LBA */
827 if (fu > lastlba || lu > lastlba) {
828 DBG(LABEL, ul_debug("error: header LBAs are after the disk's last LBA"));
829 goto done;
830 }
831
832 /* the header has to be outside usable range */
833 if (fu < GPT_PRIMARY_PARTITION_TABLE_LBA &&
834 GPT_PRIMARY_PARTITION_TABLE_LBA < lu) {
835 DBG(LABEL, ul_debug("error: header outside of usable range"));
836 goto done;
837 }
838
839 ret = 1; /* sane */
840done:
841 return ret;
842}
843
844/* Check if there is a valid header signature */
845static int gpt_check_signature(struct gpt_header *header)
846{
847 return header->signature == cpu_to_le64(GPT_HEADER_SIGNATURE);
848}
849
850/*
851 * Return the specified GPT Header, or NULL upon failure/invalid.
852 * Note that all tests must pass to ensure a valid header,
853 * we do not rely on only testing the signature for a valid probe.
854 */
855static struct gpt_header *gpt_read_header(struct fdisk_context *cxt,
856 uint64_t lba,
857 struct gpt_entry **_ents)
858{
859 struct gpt_header *header = NULL;
860 struct gpt_entry *ents = NULL;
861 uint32_t hsz;
862
863 if (!cxt)
864 return NULL;
865
866 header = calloc(1, sizeof(*header));
867 if (!header)
868 return NULL;
869
870 /* read and verify header */
871 if (read_lba(cxt, lba, header, sizeof(struct gpt_header)) != 0)
872 goto invalid;
873
874 if (!gpt_check_signature(header))
875 goto invalid;
876
877 if (!gpt_check_header_crc(header, NULL))
878 goto invalid;
879
880 /* read and verify entries */
881 ents = gpt_read_entries(cxt, header);
882 if (!ents)
883 goto invalid;
884
885 if (!gpt_check_entryarr_crc(header, ents))
886 goto invalid;
887
888 if (!gpt_check_lba_sanity(cxt, header))
889 goto invalid;
890
891 /* valid header must be at MyLBA */
892 if (le64_to_cpu(header->my_lba) != lba)
893 goto invalid;
894
895 /* make sure header size is between 92 and sector size bytes */
896 hsz = le32_to_cpu(header->size);
897 if (hsz < GPT_HEADER_MINSZ || hsz > cxt->sector_size)
898 goto invalid;
899
900 if (_ents)
901 *_ents = ents;
902 else
903 free(ents);
904
905 DBG(LABEL, ul_debug("found valid GPT Header on LBA %ju", lba));
906 return header;
907invalid:
908 free(header);
909 free(ents);
910
911 DBG(LABEL, ul_debug("read GPT Header on LBA %ju failed", lba));
912 return NULL;
913}
914
915
916static int gpt_locate_disklabel(struct fdisk_context *cxt, int n,
917 const char **name, off_t *offset, size_t *size)
918{
919 struct fdisk_gpt_label *gpt;
920
921 assert(cxt);
922
923 *name = NULL;
924 *offset = 0;
925 *size = 0;
926
927 switch (n) {
928 case 0:
929 *name = "PMBR";
930 *offset = 0;
931 *size = 512;
932 break;
933 case 1:
934 *name = _("GPT Header");
935 *offset = GPT_PRIMARY_PARTITION_TABLE_LBA * cxt->sector_size;
936 *size = sizeof(struct gpt_header);
937 break;
938 case 2:
939 *name = _("GPT Entries");
940 gpt = self_label(cxt);
941 *offset = le64_to_cpu(gpt->pheader->partition_entry_lba) * cxt->sector_size;
942 *size = le32_to_cpu(gpt->pheader->npartition_entries) *
943 le32_to_cpu(gpt->pheader->sizeof_partition_entry);
944 break;
945 default:
946 return 1; /* no more chunks */
947 }
948
949 return 0;
950}
951
952
953
954/*
955 * Returns the number of partitions that are in use.
956 */
957static unsigned partitions_in_use(struct gpt_header *header,
958 struct gpt_entry *ents)
959{
960 uint32_t i, used = 0;
961
962 if (!header || ! ents)
963 return 0;
964
965 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++)
966 if (!partition_unused(&ents[i]))
967 used++;
968 return used;
969}
970
971
972/*
973 * Check if a partition is too big for the disk (sectors).
974 * Returns the faulting partition number, otherwise 0.
975 */
976static uint32_t check_too_big_partitions(struct gpt_header *header,
977 struct gpt_entry *ents, uint64_t sectors)
978{
979 uint32_t i;
980
981 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
982 if (partition_unused(&ents[i]))
983 continue;
984 if (gpt_partition_end(&ents[i]) >= sectors)
985 return i + 1;
986 }
987
988 return 0;
989}
990
991/*
992 * Check if a partition ends before it begins
993 * Returns the faulting partition number, otherwise 0.
994 */
995static uint32_t check_start_after_end_paritions(struct gpt_header *header,
996 struct gpt_entry *ents)
997{
998 uint32_t i;
999
1000 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
1001 if (partition_unused(&ents[i]))
1002 continue;
1003 if (gpt_partition_start(&ents[i]) > gpt_partition_end(&ents[i]))
1004 return i + 1;
1005 }
1006
1007 return 0;
1008}
1009
1010/*
1011 * Check if partition e1 overlaps with partition e2.
1012 */
1013static inline int partition_overlap(struct gpt_entry *e1, struct gpt_entry *e2)
1014{
1015 uint64_t start1 = gpt_partition_start(e1);
1016 uint64_t end1 = gpt_partition_end(e1);
1017 uint64_t start2 = gpt_partition_start(e2);
1018 uint64_t end2 = gpt_partition_end(e2);
1019
1020 return (start1 && start2 && (start1 <= end2) != (end1 < start2));
1021}
1022
1023/*
1024 * Find any partitions that overlap.
1025 */
1026static uint32_t check_overlap_partitions(struct gpt_header *header,
1027 struct gpt_entry *ents)
1028{
1029 uint32_t i, j;
1030
1031 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++)
1032 for (j = 0; j < i; j++) {
1033 if (partition_unused(&ents[i]) ||
1034 partition_unused(&ents[j]))
1035 continue;
1036 if (partition_overlap(&ents[i], &ents[j])) {
1037 DBG(LABEL, ul_debug("GPT partitions overlap detected [%u vs. %u]", i, j));
1038 return i + 1;
1039 }
1040 }
1041
1042 return 0;
1043}
1044
1045/*
1046 * Find the first available block after the starting point; returns 0 if
1047 * there are no available blocks left, or error. From gdisk.
1048 */
1049static uint64_t find_first_available(struct gpt_header *header,
1050 struct gpt_entry *ents, uint64_t start)
1051{
1052 uint64_t first;
1053 uint32_t i, first_moved = 0;
1054
1055 uint64_t fu, lu;
1056
1057 if (!header || !ents)
1058 return 0;
1059
1060 fu = le64_to_cpu(header->first_usable_lba);
1061 lu = le64_to_cpu(header->last_usable_lba);
1062
1063 /*
1064 * Begin from the specified starting point or from the first usable
1065 * LBA, whichever is greater...
1066 */
1067 first = start < fu ? fu : start;
1068
1069 /*
1070 * Now search through all partitions; if first is within an
1071 * existing partition, move it to the next sector after that
1072 * partition and repeat. If first was moved, set firstMoved
1073 * flag; repeat until firstMoved is not set, so as to catch
1074 * cases where partitions are out of sequential order....
1075 */
1076 do {
1077 first_moved = 0;
1078 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
1079 if (partition_unused(&ents[i]))
1080 continue;
1081 if (first < gpt_partition_start(&ents[i]))
1082 continue;
1083 if (first <= gpt_partition_end(&ents[i])) {
1084 first = gpt_partition_end(&ents[i]) + 1;
1085 first_moved = 1;
1086 }
1087 }
1088 } while (first_moved == 1);
1089
1090 if (first > lu)
1091 first = 0;
1092
1093 return first;
1094}
1095
1096
1097/* Returns last available sector in the free space pointed to by start. From gdisk. */
1098static uint64_t find_last_free(struct gpt_header *header,
1099 struct gpt_entry *ents, uint64_t start)
1100{
1101 uint32_t i;
1102 uint64_t nearest_start;
1103
1104 if (!header || !ents)
1105 return 0;
1106
1107 nearest_start = le64_to_cpu(header->last_usable_lba);
1108
1109 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
1110 uint64_t ps = gpt_partition_start(&ents[i]);
1111
1112 if (nearest_start > ps && ps > start)
1113 nearest_start = ps - 1;
1114 }
1115
1116 return nearest_start;
1117}
1118
1119/* Returns the last free sector on the disk. From gdisk. */
1120static uint64_t find_last_free_sector(struct gpt_header *header,
1121 struct gpt_entry *ents)
1122{
1123 uint32_t i, last_moved;
1124 uint64_t last = 0;
1125
1126 if (!header || !ents)
1127 goto done;
1128
1129 /* start by assuming the last usable LBA is available */
1130 last = le64_to_cpu(header->last_usable_lba);
1131 do {
1132 last_moved = 0;
1133 for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
1134 if ((last >= gpt_partition_start(&ents[i])) &&
1135 (last <= gpt_partition_end(&ents[i]))) {
1136 last = gpt_partition_start(&ents[i]) - 1;
1137 last_moved = 1;
1138 }
1139 }
1140 } while (last_moved == 1);
1141done:
1142 return last;
1143}
1144
1145/*
1146 * Finds the first available sector in the largest block of unallocated
1147 * space on the disk. Returns 0 if there are no available blocks left.
1148 * From gdisk.
1149 */
1150static uint64_t find_first_in_largest(struct gpt_header *header,
1151 struct gpt_entry *ents)
1152{
1153 uint64_t start = 0, first_sect, last_sect;
1154 uint64_t segment_size, selected_size = 0, selected_segment = 0;
1155
1156 if (!header || !ents)
1157 goto done;
1158
1159 do {
1160 first_sect = find_first_available(header, ents, start);
1161 if (first_sect != 0) {
1162 last_sect = find_last_free(header, ents, first_sect);
1163 segment_size = last_sect - first_sect + 1;
1164
1165 if (segment_size > selected_size) {
1166 selected_size = segment_size;
1167 selected_segment = first_sect;
1168 }
1169 start = last_sect + 1;
1170 }
1171 } while (first_sect != 0);
1172
1173done:
1174 return selected_segment;
1175}
1176
1177/*
1178 * Find the total number of free sectors, the number of segments in which
1179 * they reside, and the size of the largest of those segments. From gdisk.
1180 */
1181static uint64_t get_free_sectors(struct fdisk_context *cxt, struct gpt_header *header,
1182 struct gpt_entry *ents, uint32_t *nsegments,
1183 uint64_t *largest_segment)
1184{
1185 uint32_t num = 0;
1186 uint64_t first_sect, last_sect;
1187 uint64_t largest_seg = 0, segment_sz;
1188 uint64_t totfound = 0, start = 0; /* starting point for each search */
1189
1190 if (!cxt->total_sectors)
1191 goto done;
1192
1193 do {
1194 first_sect = find_first_available(header, ents, start);
1195 if (first_sect) {
1196 last_sect = find_last_free(header, ents, first_sect);
1197 segment_sz = last_sect - first_sect + 1;
1198
1199 if (segment_sz > largest_seg)
1200 largest_seg = segment_sz;
1201 totfound += segment_sz;
1202 num++;
1203 start = last_sect + 1;
1204 }
1205 } while (first_sect);
1206
1207done:
1208 if (nsegments)
1209 *nsegments = num;
1210 if (largest_segment)
1211 *largest_segment = largest_seg;
1212
1213 return totfound;
1214}
1215
1216static int gpt_probe_label(struct fdisk_context *cxt)
1217{
1218 int mbr_type;
1219 struct fdisk_gpt_label *gpt;
1220
1221 assert(cxt);
1222 assert(cxt->label);
1223 assert(fdisk_is_label(cxt, GPT));
1224
1225 gpt = self_label(cxt);
1226
1227 /* TODO: it would be nice to support scenario when GPT headers are OK,
1228 * but PMBR is corrupt */
1229 mbr_type = valid_pmbr(cxt);
1230 if (!mbr_type)
1231 goto failed;
1232
1233 DBG(LABEL, ul_debug("found a %s MBR", mbr_type == GPT_MBR_PROTECTIVE ?
1234 "protective" : "hybrid"));
1235
1236 /* primary header */
1237 gpt->pheader = gpt_read_header(cxt, GPT_PRIMARY_PARTITION_TABLE_LBA,
1238 &gpt->ents);
1239
1240 if (gpt->pheader)
1241 /* primary OK, try backup from alternative LBA */
1242 gpt->bheader = gpt_read_header(cxt,
1243 le64_to_cpu(gpt->pheader->alternative_lba),
1244 NULL);
1245 else
1246 /* primary corrupted -- try last LBA */
1247 gpt->bheader = gpt_read_header(cxt, last_lba(cxt), &gpt->ents);
1248
1249 if (!gpt->pheader && !gpt->bheader)
1250 goto failed;
1251
1252 /* primary OK, backup corrupted -- recovery */
1253 if (gpt->pheader && !gpt->bheader) {
1254 fdisk_warnx(cxt, _("The backup GPT table is corrupt, but the "
1255 "primary appears OK, so that will be used."));
1256 gpt->bheader = gpt_copy_header(cxt, gpt->pheader);
1257 if (!gpt->bheader)
1258 goto failed;
1259 gpt_recompute_crc(gpt->bheader, gpt->ents);
1260
1261 /* primary corrupted, backup OK -- recovery */
1262 } else if (!gpt->pheader && gpt->bheader) {
1263 fdisk_warnx(cxt, _("The primary GPT table is corrupt, but the "
1264 "backup appears OK, so that will be used."));
1265 gpt->pheader = gpt_copy_header(cxt, gpt->bheader);
1266 if (!gpt->pheader)
1267 goto failed;
1268 gpt_recompute_crc(gpt->pheader, gpt->ents);
1269 }
1270
1271 cxt->label->nparts_max = le32_to_cpu(gpt->pheader->npartition_entries);
1272 cxt->label->nparts_cur = partitions_in_use(gpt->pheader, gpt->ents);
1273 return 1;
1274failed:
1275 DBG(LABEL, ul_debug("GPT probe failed"));
1276 gpt_deinit(cxt->label);
1277 return 0;
1278}
1279
1280/*
1281 * Stolen from libblkid - can be removed once partition semantics
1282 * are added to the fdisk API.
1283 */
1284static char *encode_to_utf8(unsigned char *src, size_t count)
1285{
1286 uint16_t c;
1287 char *dest;
1288 size_t i, j, len = count;
1289
1290 dest = calloc(1, count);
1291 if (!dest)
1292 return NULL;
1293
1294 for (j = i = 0; i + 2 <= count; i += 2) {
1295 /* always little endian */
1296 c = (src[i+1] << 8) | src[i];
1297 if (c == 0) {
1298 dest[j] = '\0';
1299 break;
1300 } else if (c < 0x80) {
1301 if (j+1 >= len)
1302 break;
1303 dest[j++] = (uint8_t) c;
1304 } else if (c < 0x800) {
1305 if (j+2 >= len)
1306 break;
1307 dest[j++] = (uint8_t) (0xc0 | (c >> 6));
1308 dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
1309 } else {
1310 if (j+3 >= len)
1311 break;
1312 dest[j++] = (uint8_t) (0xe0 | (c >> 12));
1313 dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
1314 dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
1315 }
1316 }
1317 dest[j] = '\0';
1318
1319 return dest;
1320}
1321
1322static int gpt_entry_attrs_to_string(struct gpt_entry *e, char **res)
1323{
1324 unsigned int n, count = 0;
1325 size_t l;
1326 char *bits, *p;
1327 uint64_t attrs;
1328
1329 assert(e);
1330 assert(res);
1331
1332 *res = NULL;
1333 attrs = le64_to_cpu(e->attrs);
1334 if (!attrs)
1335 return 0; /* no attributes at all */
1336
1337 bits = (char *) &attrs;
1338
1339 /* Note that sizeof() is correct here, we need separators between
1340 * the strings so also count \0 is correct */
1341 *res = calloc(1, sizeof(GPT_ATTRSTR_NOBLOCK) +
1342 sizeof(GPT_ATTRSTR_REQ) +
1343 sizeof(GPT_ATTRSTR_LEGACY) +
1344 sizeof("GUID:") + (GPT_ATTRBIT_GUID_COUNT * 3));
1345 if (!*res)
1346 return -errno;
1347
1348 p = *res;
1349 if (isset(bits, GPT_ATTRBIT_REQ)) {
1350 memcpy(p, GPT_ATTRSTR_REQ, (l = sizeof(GPT_ATTRSTR_REQ)));
1351 p += l - 1;
1352 }
1353 if (isset(bits, GPT_ATTRBIT_NOBLOCK)) {
1354 if (p > *res)
1355 *p++ = ' ';
1356 memcpy(p, GPT_ATTRSTR_NOBLOCK, (l = sizeof(GPT_ATTRSTR_NOBLOCK)));
1357 p += l - 1;
1358 }
1359 if (isset(bits, GPT_ATTRBIT_LEGACY)) {
1360 if (p > *res)
1361 *p++ = ' ';
1362 memcpy(p, GPT_ATTRSTR_LEGACY, (l = sizeof(GPT_ATTRSTR_LEGACY)));
1363 p += l - 1;
1364 }
1365
1366 for (n = GPT_ATTRBIT_GUID_FIRST;
1367 n < GPT_ATTRBIT_GUID_FIRST + GPT_ATTRBIT_GUID_COUNT; n++) {
1368
1369 if (!isset(bits, n))
1370 continue;
1371 if (!count) {
1372 if (p > *res)
1373 *p++ = ' ';
1374 p += sprintf(p, "GUID:%u", n);
1375 } else
1376 p += sprintf(p, ",%u", n);
1377 count++;
1378 }
1379
1380 return 0;
1381}
1382
1383static int gpt_entry_attrs_from_string(
1384 struct fdisk_context *cxt,
1385 struct gpt_entry *e,
1386 const char *str)
1387{
1388 const char *p = str;
1389 uint64_t attrs = 0;
1390 char *bits;
1391
1392 assert(e);
1393 assert(p);
1394
1395 DBG(LABEL, ul_debug("GPT: parsing string attributes '%s'", p));
1396
1397 bits = (char *) &attrs;
1398
1399 while (p && *p) {
1400 int bit = -1;
1401
1402 while (isblank(*p)) p++;
1403 if (!*p)
1404 break;
1405
1406 DBG(LABEL, ul_debug(" parsing item '%s'", p));
1407
1408 if (strncmp(p, "GUID:", 5) == 0) {
1409 p += 5;
1410 continue;
1411 } else if (strncmp(p, GPT_ATTRSTR_REQ,
1412 sizeof(GPT_ATTRSTR_REQ) - 1) == 0) {
1413 bit = GPT_ATTRBIT_REQ;
1414 p += sizeof(GPT_ATTRSTR_REQ) - 1;
1415 } else if (strncmp(p, GPT_ATTRSTR_LEGACY,
1416 sizeof(GPT_ATTRSTR_LEGACY) - 1) == 0) {
1417 bit = GPT_ATTRBIT_LEGACY;
1418 p += sizeof(GPT_ATTRSTR_LEGACY) - 1;
1419 } else if (strncmp(p, GPT_ATTRSTR_NOBLOCK,
1420 sizeof(GPT_ATTRSTR_NOBLOCK) - 1) == 0) {
1421 bit = GPT_ATTRBIT_NOBLOCK;
1422 p += sizeof(GPT_ATTRSTR_NOBLOCK) - 1;
1423 } else if (isdigit((unsigned int) *p)) {
1424 char *end = NULL;
1425
1426 errno = 0;
1427 bit = strtol(p, &end, 0);
1428 if (errno || !end || end == str
1429 || bit < GPT_ATTRBIT_GUID_FIRST
1430 || bit >= GPT_ATTRBIT_GUID_FIRST + GPT_ATTRBIT_GUID_COUNT)
1431 bit = -1;
1432 else
1433 p = end;
1434 }
1435
1436 if (bit < 0) {
1437 fdisk_warnx(cxt, _("unssuported GPT attribute bit '%s'"), p);
1438 return -EINVAL;
1439 }
1440
1441 setbit(bits, bit);
1442
1443 while (isblank(*p)) p++;
1444 if (*p == ',')
1445 p++;
1446 }
1447
1448 e->attrs = cpu_to_le64(attrs);
1449 return 0;
1450}
1451
1452static int gpt_get_partition(struct fdisk_context *cxt, size_t n,
1453 struct fdisk_partition *pa)
1454{
1455 struct fdisk_gpt_label *gpt;
1456 struct gpt_entry *e;
1457 char u_str[37];
1458 int rc = 0;
1459
1460 assert(cxt);
1461 assert(cxt->label);
1462 assert(fdisk_is_label(cxt, GPT));
1463
1464 gpt = self_label(cxt);
1465
1466 if ((uint32_t) n >= le32_to_cpu(gpt->pheader->npartition_entries))
1467 return -EINVAL;
1468
1469 gpt = self_label(cxt);
1470 e = &gpt->ents[n];
1471
1472 pa->used = !partition_unused(e) || gpt_partition_start(e);
1473 if (!pa->used)
1474 return 0;
1475
1476 pa->start = gpt_partition_start(e);
1477 pa->size = gpt_partition_size(e);
1478 pa->type = gpt_partition_parttype(cxt, e);
1479
1480 if (guid_to_string(&e->partition_guid, u_str)) {
1481 pa->uuid = strdup(u_str);
1482 if (!pa->uuid) {
1483 rc = -errno;
1484 goto done;
1485 }
1486 } else
1487 pa->uuid = NULL;
1488
1489 rc = gpt_entry_attrs_to_string(e, &pa->attrs);
1490 if (rc)
1491 goto done;
1492
1493 pa->name = encode_to_utf8((unsigned char *)e->name, sizeof(e->name));
1494 return 0;
1495done:
1496 fdisk_reset_partition(pa);
1497 return rc;
1498}
1499
1500
1501static int gpt_set_partition(struct fdisk_context *cxt, size_t n,
1502 struct fdisk_partition *pa)
1503{
1504 struct fdisk_gpt_label *gpt;
1505 struct gpt_entry *e;
1506 int rc = 0;
1507 uint64_t start, end;
1508
1509 assert(cxt);
1510 assert(cxt->label);
1511 assert(fdisk_is_label(cxt, GPT));
1512
1513 gpt = self_label(cxt);
1514
1515 if ((uint32_t) n >= le32_to_cpu(gpt->pheader->npartition_entries))
1516 return -EINVAL;
1517
1518 FDISK_INIT_UNDEF(start);
1519 FDISK_INIT_UNDEF(end);
1520
1521 gpt = self_label(cxt);
1522 e = &gpt->ents[n];
1523
1524 if (pa->uuid) {
1525 char new_u[37], old_u[37];
1526
1527 guid_to_string(&e->partition_guid, old_u);
1528 rc = gpt_entry_set_uuid(e, pa->uuid);
1529 if (rc)
1530 return rc;
1531 guid_to_string(&e->partition_guid, new_u);
1532 fdisk_info(cxt, _("Partition UUID changed from %s to %s."),
1533 old_u, new_u);
1534 }
1535
1536 if (pa->name) {
1537 char *old = encode_to_utf8((unsigned char *)e->name, sizeof(e->name));
1538 gpt_entry_set_name(e, pa->name);
1539
1540 fdisk_info(cxt, _("Partition name changed from '%s' to '%.*s'."),
1541 old, (int) GPT_PART_NAME_LEN, pa->name);
1542 free(old);
1543 }
1544
1545 if (pa->type && pa->type->typestr) {
1546 struct gpt_guid typeid;
1547
1548 rc = string_to_guid(pa->type->typestr, &typeid);
1549 if (rc)
1550 return rc;
1551 gpt_entry_set_type(e, &typeid);
1552 }
1553 if (pa->attrs) {
1554 rc = gpt_entry_attrs_from_string(cxt, e, pa->attrs);
1555 if (rc)
1556 return rc;
1557 }
1558
1559 if (fdisk_partition_has_start(pa))
1560 start = pa->start;
1561 if (fdisk_partition_has_size(pa))
1562 end = gpt_partition_start(e) + pa->size - 1ULL;
1563
1564 if (pa->end_follow_default) {
1565 /* enlarge */
1566 if (!FDISK_IS_UNDEF(start))
1567 start = gpt_partition_start(e);
1568 end = find_last_free(gpt->bheader, gpt->ents, start);
1569 if (!end)
1570 FDISK_INIT_UNDEF(end);
1571 }
1572
1573 if (!FDISK_IS_UNDEF(start))
1574 e->lba_start = cpu_to_le64(start);
1575 if (!FDISK_IS_UNDEF(end))
1576 e->lba_end = cpu_to_le64(end);
1577
1578 gpt_recompute_crc(gpt->pheader, gpt->ents);
1579 gpt_recompute_crc(gpt->bheader, gpt->ents);
1580
1581 fdisk_label_set_changed(cxt->label, 1);
1582 return rc;
1583}
1584
1585
1586/*
1587 * List label partitions.
1588 */
1589static int gpt_list_disklabel(struct fdisk_context *cxt)
1590{
1591 assert(cxt);
1592 assert(cxt->label);
1593 assert(fdisk_is_label(cxt, GPT));
1594
1595 if (fdisk_is_details(cxt)) {
1596 struct gpt_header *h = self_label(cxt)->pheader;
1597
1598 fdisk_info(cxt, _("First LBA: %ju"), h->first_usable_lba);
1599 fdisk_info(cxt, _("Last LBA: %ju"), h->last_usable_lba);
1600 /* TRANSLATORS: The LBA (Logical Block Address) of the backup GPT header. */
1601 fdisk_info(cxt, _("Alternative LBA: %ju"), h->alternative_lba);
1602 /* TRANSLATORS: The start of the array of partition entries. */
1603 fdisk_info(cxt, _("Partition entries LBA: %ju"), h->partition_entry_lba);
1604 fdisk_info(cxt, _("Allocated partition entries: %u"), h->npartition_entries);
1605 }
1606
1607 return 0;
1608}
1609
1610/*
1611 * Write partitions.
1612 * Returns 0 on success, or corresponding error otherwise.
1613 */
1614static int gpt_write_partitions(struct fdisk_context *cxt,
1615 struct gpt_header *header, struct gpt_entry *ents)
1616{
1617 off_t offset = le64_to_cpu(header->partition_entry_lba) * cxt->sector_size;
1618 uint32_t nparts = le32_to_cpu(header->npartition_entries);
1619 uint32_t totwrite = nparts * le32_to_cpu(header->sizeof_partition_entry);
1620 ssize_t rc;
1621
1622 if (offset != lseek(cxt->dev_fd, offset, SEEK_SET))
1623 goto fail;
1624
1625 rc = write(cxt->dev_fd, ents, totwrite);
1626 if (rc > 0 && totwrite == (uint32_t) rc)
1627 return 0;
1628fail:
1629 return -errno;
1630}
1631
1632/*
1633 * Write a GPT header to a specified LBA
1634 * Returns 0 on success, or corresponding error otherwise.
1635 */
1636static int gpt_write_header(struct fdisk_context *cxt,
1637 struct gpt_header *header, uint64_t lba)
1638{
1639 off_t offset = lba * cxt->sector_size;
1640
1641 if (offset != lseek(cxt->dev_fd, offset, SEEK_SET))
1642 goto fail;
1643 if (cxt->sector_size ==
1644 (size_t) write(cxt->dev_fd, header, cxt->sector_size))
1645 return 0;
1646fail:
1647 return -errno;
1648}
1649
1650/*
1651 * Write the protective MBR.
1652 * Returns 0 on success, or corresponding error otherwise.
1653 */
1654static int gpt_write_pmbr(struct fdisk_context *cxt)
1655{
1656 off_t offset;
1657 struct gpt_legacy_mbr *pmbr = NULL;
1658
1659 assert(cxt);
1660 assert(cxt->firstsector);
1661
1662 pmbr = (struct gpt_legacy_mbr *) cxt->firstsector;
1663
1664 /* zero out the legacy partitions */
1665 memset(pmbr->partition_record, 0, sizeof(pmbr->partition_record));
1666
1667 pmbr->signature = cpu_to_le16(MSDOS_MBR_SIGNATURE);
1668 pmbr->partition_record[0].os_type = EFI_PMBR_OSTYPE;
1669 pmbr->partition_record[0].start_sector = 1;
1670 pmbr->partition_record[0].end_head = 0xFE;
1671 pmbr->partition_record[0].end_sector = 0xFF;
1672 pmbr->partition_record[0].end_track = 0xFF;
1673 pmbr->partition_record[0].starting_lba = cpu_to_le32(1);
1674
1675 /*
1676 * Set size_in_lba to the size of the disk minus one. If the size of the disk
1677 * is too large to be represented by a 32bit LBA (2Tb), set it to 0xFFFFFFFF.
1678 */
1679 if (cxt->total_sectors - 1 > 0xFFFFFFFFULL)
1680 pmbr->partition_record[0].size_in_lba = cpu_to_le32(0xFFFFFFFF);
1681 else
1682 pmbr->partition_record[0].size_in_lba =
1683 cpu_to_le32(cxt->total_sectors - 1UL);
1684
1685 offset = GPT_PMBR_LBA * cxt->sector_size;
1686 if (offset != lseek(cxt->dev_fd, offset, SEEK_SET))
1687 goto fail;
1688
1689 /* pMBR covers the first sector (LBA) of the disk */
1690 if (write_all(cxt->dev_fd, pmbr, cxt->sector_size))
1691 goto fail;
1692 return 0;
1693fail:
1694 return -errno;
1695}
1696
1697/*
1698 * Writes in-memory GPT and pMBR data to disk.
1699 * Returns 0 if successful write, otherwise, a corresponding error.
1700 * Any indication of error will abort the operation.
1701 */
1702static int gpt_write_disklabel(struct fdisk_context *cxt)
1703{
1704 struct fdisk_gpt_label *gpt;
1705 int mbr_type;
1706
1707 assert(cxt);
1708 assert(cxt->label);
1709 assert(fdisk_is_label(cxt, GPT));
1710
1711 gpt = self_label(cxt);
1712 mbr_type = valid_pmbr(cxt);
1713
1714 /* check that disk is big enough to handle the backup header */
1715 if (le64_to_cpu(gpt->pheader->alternative_lba) > cxt->total_sectors)
1716 goto err0;
1717
1718 /* check that the backup header is properly placed */
1719 if (le64_to_cpu(gpt->pheader->alternative_lba) < cxt->total_sectors - 1)
1720 /* TODO: correct this (with user authorization) and write */
1721 goto err0;
1722
1723 if (check_overlap_partitions(gpt->pheader, gpt->ents))
1724 goto err0;
1725
1726 /* recompute CRCs for both headers */
1727 gpt_recompute_crc(gpt->pheader, gpt->ents);
1728 gpt_recompute_crc(gpt->bheader, gpt->ents);
1729
1730 /*
1731 * UEFI requires writing in this specific order:
1732 * 1) backup partition tables
1733 * 2) backup GPT header
1734 * 3) primary partition tables
1735 * 4) primary GPT header
1736 * 5) protective MBR
1737 *
1738 * If any write fails, we abort the rest.
1739 */
1740 if (gpt_write_partitions(cxt, gpt->bheader, gpt->ents) != 0)
1741 goto err1;
1742 if (gpt_write_header(cxt, gpt->bheader,
1743 le64_to_cpu(gpt->pheader->alternative_lba)) != 0)
1744 goto err1;
1745 if (gpt_write_partitions(cxt, gpt->pheader, gpt->ents) != 0)
1746 goto err1;
1747 if (gpt_write_header(cxt, gpt->pheader, GPT_PRIMARY_PARTITION_TABLE_LBA) != 0)
1748 goto err1;
1749
1750 if (mbr_type == GPT_MBR_HYBRID)
1751 fdisk_warnx(cxt, _("The device contains hybrid MBR -- writing GPT only. "
1752 "You have to sync the MBR manually."));
1753 else if (gpt_write_pmbr(cxt) != 0)
1754 goto err1;
1755
1756 DBG(LABEL, ul_debug("GPT write success"));
1757 return 0;
1758err0:
1759 DBG(LABEL, ul_debug("GPT write failed: incorrect input"));
1760 errno = EINVAL;
1761 return -EINVAL;
1762err1:
1763 DBG(LABEL, ul_debug("GPT write failed: %m"));
1764 return -errno;
1765}
1766
1767/*
1768 * Verify data integrity and report any found problems for:
1769 * - primary and backup header validations
1770 * - paritition validations
1771 */
1772static int gpt_verify_disklabel(struct fdisk_context *cxt)
1773{
1774 int nerror = 0;
1775 unsigned int ptnum;
1776 struct fdisk_gpt_label *gpt;
1777
1778 assert(cxt);
1779 assert(cxt->label);
1780 assert(fdisk_is_label(cxt, GPT));
1781
1782 gpt = self_label(cxt);
1783
1784 if (!gpt || !gpt->bheader) {
1785 nerror++;
1786 fdisk_warnx(cxt, _("Disk does not contain a valid backup header."));
1787 }
1788
1789 if (!gpt_check_header_crc(gpt->pheader, gpt->ents)) {
1790 nerror++;
1791 fdisk_warnx(cxt, _("Invalid primary header CRC checksum."));
1792 }
1793 if (gpt->bheader && !gpt_check_header_crc(gpt->bheader, gpt->ents)) {
1794 nerror++;
1795 fdisk_warnx(cxt, _("Invalid backup header CRC checksum."));
1796 }
1797
1798 if (!gpt_check_entryarr_crc(gpt->pheader, gpt->ents)) {
1799 nerror++;
1800 fdisk_warnx(cxt, _("Invalid partition entry checksum."));
1801 }
1802
1803 if (!gpt_check_lba_sanity(cxt, gpt->pheader)) {
1804 nerror++;
1805 fdisk_warnx(cxt, _("Invalid primary header LBA sanity checks."));
1806 }
1807 if (gpt->bheader && !gpt_check_lba_sanity(cxt, gpt->bheader)) {
1808 nerror++;
1809 fdisk_warnx(cxt, _("Invalid backup header LBA sanity checks."));
1810 }
1811
1812 if (le64_to_cpu(gpt->pheader->my_lba) != GPT_PRIMARY_PARTITION_TABLE_LBA) {
1813 nerror++;
1814 fdisk_warnx(cxt, _("MyLBA mismatch with real position at primary header."));
1815 }
1816 if (gpt->bheader && le64_to_cpu(gpt->bheader->my_lba) != last_lba(cxt)) {
1817 nerror++;
1818 fdisk_warnx(cxt, _("MyLBA mismatch with real position at backup header."));
1819
1820 }
1821 if (le64_to_cpu(gpt->pheader->alternative_lba) >= cxt->total_sectors) {
1822 nerror++;
1823 fdisk_warnx(cxt, _("Disk is too small to hold all data."));
1824 }
1825
1826 /*
1827 * if the GPT is the primary table, check the alternateLBA
1828 * to see if it is a valid GPT
1829 */
1830 if (gpt->bheader && (le64_to_cpu(gpt->pheader->my_lba) !=
1831 le64_to_cpu(gpt->bheader->alternative_lba))) {
1832 nerror++;
1833 fdisk_warnx(cxt, _("Primary and backup header mismatch."));
1834 }
1835
1836 ptnum = check_overlap_partitions(gpt->pheader, gpt->ents);
1837 if (ptnum) {
1838 nerror++;
1839 fdisk_warnx(cxt, _("Partition %u overlaps with partition %u."),
1840 ptnum, ptnum+1);
1841 }
1842
1843 ptnum = check_too_big_partitions(gpt->pheader, gpt->ents, cxt->total_sectors);
1844 if (ptnum) {
1845 nerror++;
1846 fdisk_warnx(cxt, _("Partition %u is too big for the disk."),
1847 ptnum);
1848 }
1849
1850 ptnum = check_start_after_end_paritions(gpt->pheader, gpt->ents);
1851 if (ptnum) {
1852 nerror++;
1853 fdisk_warnx(cxt, _("Partition %u ends before it starts."),
1854 ptnum);
1855 }
1856
1857 if (!nerror) { /* yay :-) */
1858 uint32_t nsegments = 0;
1859 uint64_t free_sectors = 0, largest_segment = 0;
1860 char *strsz = NULL;
1861
1862 fdisk_info(cxt, _("No errors detected."));
1863 fdisk_info(cxt, _("Header version: %s"), gpt_get_header_revstr(gpt->pheader));
1864 fdisk_info(cxt, _("Using %u out of %d partitions."),
1865 partitions_in_use(gpt->pheader, gpt->ents),
1866 le32_to_cpu(gpt->pheader->npartition_entries));
1867
1868 free_sectors = get_free_sectors(cxt, gpt->pheader, gpt->ents,
1869 &nsegments, &largest_segment);
1870 if (largest_segment)
1871 strsz = size_to_human_string(SIZE_SUFFIX_SPACE | SIZE_SUFFIX_3LETTER,
1872 largest_segment * cxt->sector_size);
1873
1874 fdisk_info(cxt,
1875 P_("A total of %ju free sectors is available in %u segment.",
1876 "A total of %ju free sectors is available in %u segments "
1877 "(the largest is %s).", nsegments),
1878 free_sectors, nsegments, strsz);
1879 free(strsz);
1880
1881 } else
1882 fdisk_warnx(cxt,
1883 P_("%d error detected.", "%d errors detected.", nerror),
1884 nerror);
1885
1886 return 0;
1887}
1888
1889/* Delete a single GPT partition, specified by partnum. */
1890static int gpt_delete_partition(struct fdisk_context *cxt,
1891 size_t partnum)
1892{
1893 struct fdisk_gpt_label *gpt;
1894
1895 assert(cxt);
1896 assert(cxt->label);
1897 assert(fdisk_is_label(cxt, GPT));
1898
1899 gpt = self_label(cxt);
1900
1901 if (partnum >= cxt->label->nparts_max
1902 || partition_unused(&gpt->ents[partnum]))
1903 return -EINVAL;
1904
1905 /* hasta la vista, baby! */
1906 memset(&gpt->ents[partnum], 0, sizeof(struct gpt_entry));
1907 if (!partition_unused(&gpt->ents[partnum]))
1908 return -EINVAL;
1909 else {
1910 gpt_recompute_crc(gpt->pheader, gpt->ents);
1911 gpt_recompute_crc(gpt->bheader, gpt->ents);
1912 cxt->label->nparts_cur--;
1913 fdisk_label_set_changed(cxt->label, 1);
1914 }
1915
1916 return 0;
1917}
1918
1919
1920/* Performs logical checks to add a new partition entry */
1921static int gpt_add_partition(
1922 struct fdisk_context *cxt,
1923 struct fdisk_partition *pa,
1924 size_t *partno)
1925{
1926 uint64_t user_f, user_l; /* user input ranges for first and last sectors */
1927 uint64_t disk_f, disk_l; /* first and last available sector ranges on device*/
1928 uint64_t dflt_f, dflt_l; /* largest segment (default) */
1929 struct gpt_guid typeid;
1930 struct fdisk_gpt_label *gpt;
1931 struct gpt_header *pheader;
1932 struct gpt_entry *e, *ents;
1933 struct fdisk_ask *ask = NULL;
1934 size_t partnum;
1935 int rc;
1936
1937 assert(cxt);
1938 assert(cxt->label);
1939 assert(fdisk_is_label(cxt, GPT));
1940
1941 gpt = self_label(cxt);
1942 pheader = gpt->pheader;
1943 ents = gpt->ents;
1944
1945 rc = fdisk_partition_next_partno(pa, cxt, &partnum);
1946 if (rc) {
1947 DBG(LABEL, ul_debug("GPT failed to get next partno"));
1948 return rc;
1949 }
1950 if (!partition_unused(&ents[partnum])) {
1951 fdisk_warnx(cxt, _("Partition %zu is already defined. "
1952 "Delete it before re-adding it."), partnum +1);
1953 return -ERANGE;
1954 }
1955 if (le32_to_cpu(pheader->npartition_entries) ==
1956 partitions_in_use(pheader, ents)) {
1957 fdisk_warnx(cxt, _("All partitions are already in use."));
1958 return -ENOSPC;
1959 }
1960 if (!get_free_sectors(cxt, pheader, ents, NULL, NULL)) {
1961 fdisk_warnx(cxt, _("No free sectors available."));
1962 return -ENOSPC;
1963 }
1964
1965 string_to_guid(pa && pa->type && pa->type->typestr ?
1966 pa->type->typestr:
1967 GPT_DEFAULT_ENTRY_TYPE, &typeid);
1968
1969 disk_f = find_first_available(pheader, ents, pheader->first_usable_lba);
1970
1971 /* if first sector no explicitly defined then ignore small gaps before
1972 * the first partition */
1973 if ((!pa || !fdisk_partition_has_start(pa))
1974 && !partition_unused(&ents[0])
1975 && disk_f < gpt_partition_start(&ents[0])) {
1976
1977 do {
1978 uint64_t x;
1979 DBG(LABEL, ul_debug("testing first sector %ju", disk_f));
1980 disk_f = find_first_available(pheader, ents, disk_f);
1981 if (!disk_f)
1982 break;
1983 x = find_last_free(pheader, ents, disk_f);
1984 if (x - disk_f >= cxt->grain / cxt->sector_size)
1985 break;
1986 DBG(LABEL, ul_debug("first sector %ju addresses to small space, continue...", disk_f));
1987 disk_f = x + 1;
1988 } while(1);
1989
1990 if (disk_f == 0)
1991 disk_f = find_first_available(pheader, ents, pheader->first_usable_lba);
1992 }
1993
1994 disk_l = find_last_free_sector(pheader, ents);
1995
1996 /* the default is the largest free space */
1997 dflt_f = find_first_in_largest(pheader, ents);
1998 dflt_l = find_last_free(pheader, ents, dflt_f);
1999
2000 /* align the default in range <dflt_f,dflt_l>*/
2001 dflt_f = fdisk_align_lba_in_range(cxt, dflt_f, dflt_f, dflt_l);
2002
2003 /* first sector */
2004 if (pa && pa->start_follow_default) {
2005 user_f = dflt_f;
2006
2007 } else if (pa && fdisk_partition_has_start(pa)) {
2008 DBG(LABEL, ul_debug("first sector defined: %ju", pa->start));
2009 if (pa->start != find_first_available(pheader, ents, pa->start)) {
2010 fdisk_warnx(cxt, _("Sector %ju already used."), pa->start);
2011 return -ERANGE;
2012 }
2013 user_f = pa->start;
2014 } else {
2015 /* ask by dialog */
2016 for (;;) {
2017 if (!ask)
2018 ask = fdisk_new_ask();
2019 else
2020 fdisk_reset_ask(ask);
2021
2022 /* First sector */
2023 fdisk_ask_set_query(ask, _("First sector"));
2024 fdisk_ask_set_type(ask, FDISK_ASKTYPE_NUMBER);
2025 fdisk_ask_number_set_low(ask, disk_f); /* minimal */
2026 fdisk_ask_number_set_default(ask, dflt_f); /* default */
2027 fdisk_ask_number_set_high(ask, disk_l); /* maximal */
2028
2029 rc = fdisk_do_ask(cxt, ask);
2030 if (rc)
2031 goto done;
2032
2033 user_f = fdisk_ask_number_get_result(ask);
2034 if (user_f != find_first_available(pheader, ents, user_f)) {
2035 fdisk_warnx(cxt, _("Sector %ju already used."), user_f);
2036 continue;
2037 }
2038 break;
2039 }
2040 }
2041
2042
2043 /* Last sector */
2044 dflt_l = find_last_free(pheader, ents, user_f);
2045
2046 if (pa && pa->end_follow_default) {
2047 user_l = dflt_l;
2048
2049 } else if (pa && fdisk_partition_has_size(pa)) {
2050 user_l = user_f + pa->size - 1;
2051 DBG(LABEL, ul_debug("size defined: %ju, end: %ju (last possible: %ju)",
2052 pa->size, user_l, dflt_l));
2053 if (user_l != dflt_l && !pa->size_explicit)
2054 user_l = fdisk_align_lba_in_range(cxt, user_l, user_f, dflt_l) - 1;
2055
2056 } else {
2057 for (;;) {
2058 if (!ask)
2059 ask = fdisk_new_ask();
2060 else
2061 fdisk_reset_ask(ask);
2062
2063 fdisk_ask_set_query(ask, _("Last sector, +sectors or +size{K,M,G,T,P}"));
2064 fdisk_ask_set_type(ask, FDISK_ASKTYPE_OFFSET);
2065 fdisk_ask_number_set_low(ask, user_f); /* minimal */
2066 fdisk_ask_number_set_default(ask, dflt_l); /* default */
2067 fdisk_ask_number_set_high(ask, dflt_l); /* maximal */
2068 fdisk_ask_number_set_base(ask, user_f); /* base for relative input */
2069 fdisk_ask_number_set_unit(ask, cxt->sector_size);
2070
2071 rc = fdisk_do_ask(cxt, ask);
2072 if (rc)
2073 goto done;
2074
2075 user_l = fdisk_ask_number_get_result(ask);
2076 if (fdisk_ask_number_is_relative(ask)) {
2077 user_l = fdisk_align_lba_in_range(cxt, user_l, user_f, dflt_l) - 1;
2078
2079 /* no space for anything useful, use all space
2080 if (user_l + (cxt->grain / cxt->sector_size) > dflt_l)
2081 user_l = dflt_l;
2082 */
2083 }
2084
2085 if (user_l > user_f && user_l <= disk_l)
2086 break;
2087 }
2088 }
2089
2090
2091 if (user_f > user_l || partnum >= cxt->label->nparts_max) {
2092 fdisk_warnx(cxt, _("Could not create partition %zu"), partnum + 1);
2093 rc = -EINVAL;
2094 goto done;
2095 }
2096
2097 assert(!FDISK_IS_UNDEF(user_l));
2098 assert(!FDISK_IS_UNDEF(user_f));
2099
2100 e = &ents[partnum];
2101 e->lba_end = cpu_to_le64(user_l);
2102 e->lba_start = cpu_to_le64(user_f);
2103
2104 gpt_entry_set_type(e, &typeid);
2105
2106 if (pa && pa->uuid) {
2107 /* Sometimes it's necessary to create a copy of the PT and
2108 * reuse already defined UUID
2109 */
2110 rc = gpt_entry_set_uuid(e, pa->uuid);
2111 if (rc)
2112 goto done;
2113 } else {
2114 /* Any time a new partition entry is created a new GUID must be
2115 * generated for that partition, and every partition is guaranteed
2116 * to have a unique GUID.
2117 */
2118 uuid_generate_random((unsigned char *) &e->partition_guid);
2119 swap_efi_guid(&e->partition_guid);
2120 }
2121
2122 if (pa && pa->name && *pa->name)
2123 gpt_entry_set_name(e, pa->name);
2124 if (pa && pa->attrs)
2125 gpt_entry_attrs_from_string(cxt, e, pa->attrs);
2126
2127 DBG(LABEL, ul_debug("GPT new partition: partno=%zu, start=%ju, end=%ju, size=%ju",
2128 partnum,
2129 gpt_partition_start(e),
2130 gpt_partition_end(e),
2131 gpt_partition_size(e)));
2132
2133 gpt_recompute_crc(gpt->pheader, ents);
2134 gpt_recompute_crc(gpt->bheader, ents);
2135
2136 /* report result */
2137 {
2138 struct fdisk_parttype *t;
2139
2140 cxt->label->nparts_cur++;
2141 fdisk_label_set_changed(cxt->label, 1);
2142
2143 t = gpt_partition_parttype(cxt, &ents[partnum]);
2144 fdisk_info_new_partition(cxt, partnum + 1, user_f, user_l, t);
2145 fdisk_unref_parttype(t);
2146 }
2147
2148 rc = 0;
2149 if (partno)
2150 *partno = partnum;
2151done:
2152 fdisk_unref_ask(ask);
2153 return rc;
2154}
2155
2156/*
2157 * Create a new GPT disklabel - destroys any previous data.
2158 */
2159static int gpt_create_disklabel(struct fdisk_context *cxt)
2160{
2161 int rc = 0;
2162 ssize_t esz = 0;
2163 char str[37];
2164 struct fdisk_gpt_label *gpt;
2165
2166 assert(cxt);
2167 assert(cxt->label);
2168 assert(fdisk_is_label(cxt, GPT));
2169
2170 gpt = self_label(cxt);
2171
2172 /* label private stuff has to be empty, see gpt_deinit() */
2173 assert(gpt->pheader == NULL);
2174 assert(gpt->bheader == NULL);
2175
2176 /*
2177 * When no header, entries or pmbr is set, we're probably
2178 * dealing with a new, empty disk - so always allocate memory
2179 * to deal with the data structures whatever the case is.
2180 */
2181 rc = gpt_mknew_pmbr(cxt);
2182 if (rc < 0)
2183 goto done;
2184
2185 /* primary */
2186 gpt->pheader = calloc(1, sizeof(*gpt->pheader));
2187 if (!gpt->pheader) {
2188 rc = -ENOMEM;
2189 goto done;
2190 }
2191 rc = gpt_mknew_header(cxt, gpt->pheader, GPT_PRIMARY_PARTITION_TABLE_LBA);
2192 if (rc < 0)
2193 goto done;
2194
2195 /* backup ("copy" primary) */
2196 gpt->bheader = calloc(1, sizeof(*gpt->bheader));
2197 if (!gpt->bheader) {
2198 rc = -ENOMEM;
2199 goto done;
2200 }
2201 rc = gpt_mknew_header_from_bkp(cxt, gpt->bheader,
2202 last_lba(cxt), gpt->pheader);
2203 if (rc < 0)
2204 goto done;
2205
2206 esz = le32_to_cpu(gpt->pheader->npartition_entries) *
2207 le32_to_cpu(gpt->pheader->sizeof_partition_entry);
2208 gpt->ents = calloc(1, esz);
2209 if (!gpt->ents) {
2210 rc = -ENOMEM;
2211 goto done;
2212 }
2213 gpt_recompute_crc(gpt->pheader, gpt->ents);
2214 gpt_recompute_crc(gpt->bheader, gpt->ents);
2215
2216 cxt->label->nparts_max = le32_to_cpu(gpt->pheader->npartition_entries);
2217 cxt->label->nparts_cur = 0;
2218
2219 guid_to_string(&gpt->pheader->disk_guid, str);
2220 fdisk_label_set_changed(cxt->label, 1);
2221 fdisk_info(cxt, _("Created a new GPT disklabel (GUID: %s)."), str);
2222done:
2223 return rc;
2224}
2225
2226static int gpt_get_disklabel_id(struct fdisk_context *cxt, char **id)
2227{
2228 struct fdisk_gpt_label *gpt;
2229 char str[37];
2230
2231 assert(cxt);
2232 assert(id);
2233 assert(cxt->label);
2234 assert(fdisk_is_label(cxt, GPT));
2235
2236 gpt = self_label(cxt);
2237 guid_to_string(&gpt->pheader->disk_guid, str);
2238
2239 *id = strdup(str);
2240 if (!*id)
2241 return -ENOMEM;
2242 return 0;
2243}
2244
2245static int gpt_set_disklabel_id(struct fdisk_context *cxt)
2246{
2247 struct fdisk_gpt_label *gpt;
2248 struct gpt_guid uuid;
2249 char *str, *old, *new;
2250 int rc;
2251
2252 assert(cxt);
2253 assert(cxt->label);
2254 assert(fdisk_is_label(cxt, GPT));
2255
2256 gpt = self_label(cxt);
2257 if (fdisk_ask_string(cxt,
2258 _("Enter new disk UUID (in 8-4-4-4-12 format)"), &str))
2259 return -EINVAL;
2260
2261 rc = string_to_guid(str, &uuid);
2262 free(str);
2263
2264 if (rc) {
2265 fdisk_warnx(cxt, _("Failed to parse your UUID."));
2266 return rc;
2267 }
2268
2269 gpt_get_disklabel_id(cxt, &old);
2270
2271 gpt->pheader->disk_guid = uuid;
2272 gpt->bheader->disk_guid = uuid;
2273
2274 gpt_recompute_crc(gpt->pheader, gpt->ents);
2275 gpt_recompute_crc(gpt->bheader, gpt->ents);
2276
2277 gpt_get_disklabel_id(cxt, &new);
2278
2279 fdisk_info(cxt, _("Disk identifier changed from %s to %s."), old, new);
2280
2281 free(old);
2282 free(new);
2283 fdisk_label_set_changed(cxt->label, 1);
2284 return 0;
2285}
2286
2287static int gpt_part_is_used(struct fdisk_context *cxt, size_t i)
2288{
2289 struct fdisk_gpt_label *gpt;
2290 struct gpt_entry *e;
2291
2292 assert(cxt);
2293 assert(cxt->label);
2294 assert(fdisk_is_label(cxt, GPT));
2295
2296 gpt = self_label(cxt);
2297
2298 if ((uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries))
2299 return 0;
2300 e = &gpt->ents[i];
2301
2302 return !partition_unused(e) || gpt_partition_start(e);
2303}
2304
2305/**
2306 * fdisk_gpt_is_hybrid:
2307 * @cxt: context
2308 *
2309 * The regular GPT contains PMBR (dummy protective MBR) where the protective
2310 * MBR does not address any partitions.
2311 *
2312 * Hybrid GPT contains regular MBR where this partition table addresses the
2313 * same partitions as GPT. It's recommended to not use hybrid GPT due to MBR
2314 * limits.
2315 *
2316 * The libfdisk does not provide functionality to sync GPT and MBR, you have to
2317 * directly access and modify (P)MBR (see fdisk_new_nested_context()).
2318 *
2319 * Returns: 1 if partition table detected as hybrid otherwise return 0
2320 */
2321int fdisk_gpt_is_hybrid(struct fdisk_context *cxt)
2322{
2323 assert(cxt);
2324 return valid_pmbr(cxt) == GPT_MBR_HYBRID;
2325}
2326
2327static int gpt_toggle_partition_flag(
2328 struct fdisk_context *cxt,
2329 size_t i,
2330 unsigned long flag)
2331{
2332 struct fdisk_gpt_label *gpt;
2333 uint64_t attrs, tmp;
2334 char *bits;
2335 const char *name = NULL;
2336 int bit = -1, rc;
2337
2338 assert(cxt);
2339 assert(cxt->label);
2340 assert(fdisk_is_label(cxt, GPT));
2341
2342 DBG(LABEL, ul_debug("GPT entry attribute change requested partno=%zu", i));
2343 gpt = self_label(cxt);
2344
2345 if ((uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries))
2346 return -EINVAL;
2347
2348 attrs = le64_to_cpu(gpt->ents[i].attrs);
2349 bits = (char *) &attrs;
2350
2351 switch (flag) {
2352 case GPT_FLAG_REQUIRED:
2353 bit = GPT_ATTRBIT_REQ;
2354 name = GPT_ATTRSTR_REQ;
2355 break;
2356 case GPT_FLAG_NOBLOCK:
2357 bit = GPT_ATTRBIT_NOBLOCK;
2358 name = GPT_ATTRSTR_NOBLOCK;
2359 break;
2360 case GPT_FLAG_LEGACYBOOT:
2361 bit = GPT_ATTRBIT_LEGACY;
2362 name = GPT_ATTRSTR_LEGACY;
2363 break;
2364 case GPT_FLAG_GUIDSPECIFIC:
2365 rc = fdisk_ask_number(cxt, 48, 48, 63, _("Enter GUID specific bit"), &tmp);
2366 if (rc)
2367 return rc;
2368 bit = tmp;
2369 break;
2370 default:
2371 /* already specified PT_FLAG_GUIDSPECIFIC bit */
2372 if (flag >= 48 && flag <= 63) {
2373 bit = flag;
2374 flag = GPT_FLAG_GUIDSPECIFIC;
2375 }
2376 break;
2377 }
2378
2379 if (bit < 0) {
2380 fdisk_warnx(cxt, _("failed to toggle unsupported bit %lu"), flag);
2381 return -EINVAL;
2382 }
2383
2384 if (!isset(bits, bit))
2385 setbit(bits, bit);
2386 else
2387 clrbit(bits, bit);
2388
2389 gpt->ents[i].attrs = cpu_to_le64(attrs);
2390
2391 if (flag == GPT_FLAG_GUIDSPECIFIC)
2392 fdisk_info(cxt, isset(bits, bit) ?
2393 _("The GUID specific bit %d on partition %zu is enabled now.") :
2394 _("The GUID specific bit %d on partition %zu is disabled now."),
2395 bit, i + 1);
2396 else
2397 fdisk_info(cxt, isset(bits, bit) ?
2398 _("The %s flag on partition %zu is enabled now.") :
2399 _("The %s flag on partition %zu is disabled now."),
2400 name, i + 1);
2401
2402 gpt_recompute_crc(gpt->pheader, gpt->ents);
2403 gpt_recompute_crc(gpt->bheader, gpt->ents);
2404 fdisk_label_set_changed(cxt->label, 1);
2405 return 0;
2406}
2407
2408static int gpt_entry_cmp_start(const void *a, const void *b)
2409{
2410 struct gpt_entry *ae = (struct gpt_entry *) a,
2411 *be = (struct gpt_entry *) b;
2412 int au = partition_unused(ae),
2413 bu = partition_unused(be);
2414
2415 if (au && bu)
2416 return 0;
2417 if (au)
2418 return 1;
2419 if (bu)
2420 return -1;
2421
2422 return cmp_numbers(gpt_partition_start(ae), gpt_partition_start(be));
2423}
2424
2425/* sort partition by start sector */
2426static int gpt_reorder(struct fdisk_context *cxt)
2427{
2428 struct fdisk_gpt_label *gpt;
2429 size_t nparts;
2430
2431 assert(cxt);
2432 assert(cxt->label);
2433 assert(fdisk_is_label(cxt, GPT));
2434
2435 gpt = self_label(cxt);
2436 nparts = le32_to_cpu(gpt->pheader->npartition_entries);
2437
2438 qsort(gpt->ents, nparts, sizeof(struct gpt_entry),
2439 gpt_entry_cmp_start);
2440
2441 gpt_recompute_crc(gpt->pheader, gpt->ents);
2442 gpt_recompute_crc(gpt->bheader, gpt->ents);
2443 fdisk_label_set_changed(cxt->label, 1);
2444
2445 fdisk_info(cxt, _("Done."));
2446 return 0;
2447}
2448
2449static int gpt_reset_alignment(struct fdisk_context *cxt)
2450{
2451 struct fdisk_gpt_label *gpt;
2452 struct gpt_header *h;
2453
2454 assert(cxt);
2455 assert(cxt->label);
2456 assert(fdisk_is_label(cxt, GPT));
2457
2458 gpt = self_label(cxt);
2459 h = gpt ? gpt->pheader : NULL;
2460
2461 if (h) {
2462 /* always follow existing table */
2463 cxt->first_lba = h->first_usable_lba;
2464 cxt->last_lba = h->last_usable_lba;
2465 } else {
2466 /* estimate ranges for GPT */
2467 uint64_t first, last;
2468
2469 count_first_last_lba(cxt, &first, &last);
2470
2471 if (cxt->first_lba < first)
2472 cxt->first_lba = first;
2473 if (cxt->last_lba > last)
2474 cxt->last_lba = last;
2475 }
2476
2477 return 0;
2478}
2479/*
2480 * Deinitialize fdisk-specific variables
2481 */
2482static void gpt_deinit(struct fdisk_label *lb)
2483{
2484 struct fdisk_gpt_label *gpt = (struct fdisk_gpt_label *) lb;
2485
2486 if (!gpt)
2487 return;
2488
2489 free(gpt->ents);
2490 free(gpt->pheader);
2491 free(gpt->bheader);
2492
2493 gpt->ents = NULL;
2494 gpt->pheader = NULL;
2495 gpt->bheader = NULL;
2496}
2497
2498static const struct fdisk_label_operations gpt_operations =
2499{
2500 .probe = gpt_probe_label,
2501 .write = gpt_write_disklabel,
2502 .verify = gpt_verify_disklabel,
2503 .create = gpt_create_disklabel,
2504 .list = gpt_list_disklabel,
2505 .locate = gpt_locate_disklabel,
2506 .reorder = gpt_reorder,
2507 .get_id = gpt_get_disklabel_id,
2508 .set_id = gpt_set_disklabel_id,
2509
2510 .get_part = gpt_get_partition,
2511 .set_part = gpt_set_partition,
2512 .add_part = gpt_add_partition,
2513 .del_part = gpt_delete_partition,
2514
2515 .part_is_used = gpt_part_is_used,
2516 .part_toggle_flag = gpt_toggle_partition_flag,
2517
2518 .deinit = gpt_deinit,
2519
2520 .reset_alignment = gpt_reset_alignment
2521};
2522
2523static const struct fdisk_field gpt_fields[] =
2524{
2525 /* basic */
2526 { FDISK_FIELD_DEVICE, N_("Device"), 10, 0 },
2527 { FDISK_FIELD_START, N_("Start"), 5, FDISK_FIELDFL_NUMBER },
2528 { FDISK_FIELD_END, N_("End"), 5, FDISK_FIELDFL_NUMBER },
2529 { FDISK_FIELD_SECTORS, N_("Sectors"), 5, FDISK_FIELDFL_NUMBER },
2530 { FDISK_FIELD_SIZE, N_("Size"), 5, FDISK_FIELDFL_NUMBER | FDISK_FIELDFL_EYECANDY },
2531 { FDISK_FIELD_TYPE, N_("Type"), 0.1, FDISK_FIELDFL_EYECANDY },
2532 /* expert */
2533 { FDISK_FIELD_TYPEID, N_("Type-UUID"), 36, FDISK_FIELDFL_DETAIL },
2534 { FDISK_FIELD_UUID, N_("UUID"), 36, FDISK_FIELDFL_DETAIL },
2535 { FDISK_FIELD_NAME, N_("Name"), 0.2, FDISK_FIELDFL_DETAIL },
2536 { FDISK_FIELD_ATTR, N_("Attrs"), 0, FDISK_FIELDFL_DETAIL }
2537};
2538
2539/*
2540 * allocates GPT in-memory stuff
2541 */
2542struct fdisk_label *fdisk_new_gpt_label(struct fdisk_context *cxt)
2543{
2544 struct fdisk_label *lb;
2545 struct fdisk_gpt_label *gpt;
2546
2547 assert(cxt);
2548
2549 gpt = calloc(1, sizeof(*gpt));
2550 if (!gpt)
2551 return NULL;
2552
2553 /* initialize generic part of the driver */
2554 lb = (struct fdisk_label *) gpt;
2555 lb->name = "gpt";
2556 lb->id = FDISK_DISKLABEL_GPT;
2557 lb->op = &gpt_operations;
2558 lb->parttypes = gpt_parttypes;
2559 lb->nparttypes = ARRAY_SIZE(gpt_parttypes);
2560
2561 lb->fields = gpt_fields;
2562 lb->nfields = ARRAY_SIZE(gpt_fields);
2563
2564 return lb;
2565}